1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
44 #if defined _MSC_VER && _MSC_VER >= 1200
45 #pragma warning( disable: 4244 4510 4512 4610 )
51 #define __STDC_CONSTANT_MACROS
56 #include <ffmpeg/avformat.h>
57 #include <ffmpeg/avcodec.h>
60 #if defined _MSC_VER && _MSC_VER >= 1200
61 #pragma warning( default: 4244 4510 4512 4610 )
65 #define CV_WARN(message)
67 #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
72 #define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
78 char * FOURCC2str( int fourcc )
80 char * mystr=(char*)malloc(5);
81 mystr[0]=(char)((fourcc )&255);
82 mystr[1]=(char)((fourcc>> 8)&255);
83 mystr[2]=(char)((fourcc>>16)&255);
84 mystr[3]=(char)((fourcc>>24)&255);
90 // required to look up the correct codec ID depending on the FOURCC code,
91 // this is just a snipped from the file riff.c from ffmpeg/libavformat
92 typedef struct AVCodecTag {
97 const AVCodecTag codec_bmp_tags[] = {
98 { CODEC_ID_H264, MKTAG('H', '2', '6', '4') },
99 { CODEC_ID_H264, MKTAG('h', '2', '6', '4') },
100 { CODEC_ID_H264, MKTAG('X', '2', '6', '4') },
101 { CODEC_ID_H264, MKTAG('x', '2', '6', '4') },
102 { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
103 { CODEC_ID_H264, MKTAG('V', 'S', 'S', 'H') },
105 { CODEC_ID_H263, MKTAG('H', '2', '6', '3') },
106 { CODEC_ID_H263P, MKTAG('H', '2', '6', '3') },
107 { CODEC_ID_H263I, MKTAG('I', '2', '6', '3') }, /* intel h263 */
108 { CODEC_ID_H261, MKTAG('H', '2', '6', '1') },
110 /* added based on MPlayer */
111 { CODEC_ID_H263P, MKTAG('U', '2', '6', '3') },
112 { CODEC_ID_H263P, MKTAG('v', 'i', 'v', '1') },
114 { CODEC_ID_MPEG4, MKTAG('F', 'M', 'P', '4') },
115 { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') },
116 { CODEC_ID_MPEG4, MKTAG('D', 'X', '5', '0') },
117 { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
118 { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') },
119 { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') },
120 { CODEC_ID_MPEG4, MKTAG(0x04, 0, 0, 0) }, /* some broken avi use this */
122 /* added based on MPlayer */
123 { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', '1') },
124 { CODEC_ID_MPEG4, MKTAG('B', 'L', 'Z', '0') },
125 { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
126 { CODEC_ID_MPEG4, MKTAG('U', 'M', 'P', '4') },
127 { CODEC_ID_MPEG4, MKTAG('W', 'V', '1', 'F') },
128 { CODEC_ID_MPEG4, MKTAG('S', 'E', 'D', 'G') },
130 { CODEC_ID_MPEG4, MKTAG('R', 'M', 'P', '4') },
132 { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '3') }, /* default signature when using MSMPEG4 */
133 { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') },
135 /* added based on MPlayer */
136 { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', 'G', '3') },
137 { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '5') },
138 { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '6') },
139 { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '4') },
140 { CODEC_ID_MSMPEG4V3, MKTAG('A', 'P', '4', '1') },
141 { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '1') },
142 { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '0') },
144 { CODEC_ID_MSMPEG4V2, MKTAG('M', 'P', '4', '2') },
146 /* added based on MPlayer */
147 { CODEC_ID_MSMPEG4V2, MKTAG('D', 'I', 'V', '2') },
149 { CODEC_ID_MSMPEG4V1, MKTAG('M', 'P', 'G', '4') },
151 { CODEC_ID_WMV1, MKTAG('W', 'M', 'V', '1') },
153 /* added based on MPlayer */
154 { CODEC_ID_WMV2, MKTAG('W', 'M', 'V', '2') },
155 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'd') },
156 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'd') },
157 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'l') },
158 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '2', '5') },
159 { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '1') },
160 { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') },
161 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', 'g', '2') },
162 { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'P', 'E', 'G') },
163 { CODEC_ID_MPEG1VIDEO, MKTAG('P', 'I', 'M', '1') },
164 { CODEC_ID_MPEG1VIDEO, MKTAG('V', 'C', 'R', '2') },
165 { CODEC_ID_MPEG1VIDEO, 0x10000001 },
166 { CODEC_ID_MPEG2VIDEO, 0x10000002 },
167 { CODEC_ID_MPEG2VIDEO, MKTAG('D', 'V', 'R', ' ') },
168 { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'M', 'E', 'S') },
169 { CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') },
170 { CODEC_ID_MJPEG, MKTAG('L', 'J', 'P', 'G') },
171 { CODEC_ID_LJPEG, MKTAG('L', 'J', 'P', 'G') },
172 { CODEC_ID_MJPEG, MKTAG('J', 'P', 'G', 'L') }, /* Pegasus lossless JPEG */
173 { CODEC_ID_MJPEG, MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - decoder */
174 { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') },
175 { CODEC_ID_MJPEG, MKTAG('I', 'J', 'P', 'G') },
176 { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') },
177 { CODEC_ID_HUFFYUV, MKTAG('H', 'F', 'Y', 'U') },
178 { CODEC_ID_FFVHUFF, MKTAG('F', 'F', 'V', 'H') },
179 { CODEC_ID_CYUV, MKTAG('C', 'Y', 'U', 'V') },
180 { CODEC_ID_RAWVIDEO, 0 },
181 { CODEC_ID_RAWVIDEO, MKTAG('I', '4', '2', '0') },
182 { CODEC_ID_RAWVIDEO, MKTAG('Y', 'U', 'Y', '2') },
183 { CODEC_ID_RAWVIDEO, MKTAG('Y', '4', '2', '2') },
184 { CODEC_ID_RAWVIDEO, MKTAG('Y', 'V', '1', '2') },
185 { CODEC_ID_RAWVIDEO, MKTAG('U', 'Y', 'V', 'Y') },
186 { CODEC_ID_RAWVIDEO, MKTAG('I', 'Y', 'U', 'V') },
187 { CODEC_ID_RAWVIDEO, MKTAG('Y', '8', '0', '0') },
188 { CODEC_ID_RAWVIDEO, MKTAG('H', 'D', 'Y', 'C') },
189 { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '1') },
190 { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '2') },
191 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
192 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
193 { CODEC_ID_ASV1, MKTAG('A', 'S', 'V', '1') },
194 { CODEC_ID_ASV2, MKTAG('A', 'S', 'V', '2') },
195 { CODEC_ID_VCR1, MKTAG('V', 'C', 'R', '1') },
196 { CODEC_ID_FFV1, MKTAG('F', 'F', 'V', '1') },
197 { CODEC_ID_XAN_WC4, MKTAG('X', 'x', 'a', 'n') },
198 { CODEC_ID_MSRLE, MKTAG('m', 'r', 'l', 'e') },
199 { CODEC_ID_MSRLE, MKTAG(0x1, 0x0, 0x0, 0x0) },
200 { CODEC_ID_MSVIDEO1, MKTAG('M', 'S', 'V', 'C') },
201 { CODEC_ID_MSVIDEO1, MKTAG('m', 's', 'v', 'c') },
202 { CODEC_ID_MSVIDEO1, MKTAG('C', 'R', 'A', 'M') },
203 { CODEC_ID_MSVIDEO1, MKTAG('c', 'r', 'a', 'm') },
204 { CODEC_ID_MSVIDEO1, MKTAG('W', 'H', 'A', 'M') },
205 { CODEC_ID_MSVIDEO1, MKTAG('w', 'h', 'a', 'm') },
206 { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') },
207 { CODEC_ID_TRUEMOTION1, MKTAG('D', 'U', 'C', 'K') },
208 { CODEC_ID_MSZH, MKTAG('M', 'S', 'Z', 'H') },
209 { CODEC_ID_ZLIB, MKTAG('Z', 'L', 'I', 'B') },
210 { CODEC_ID_SNOW, MKTAG('S', 'N', 'O', 'W') },
211 { CODEC_ID_4XM, MKTAG('4', 'X', 'M', 'V') },
212 { CODEC_ID_FLV1, MKTAG('F', 'L', 'V', '1') },
213 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') },
214 { CODEC_ID_TSCC, MKTAG('t', 's', 'c', 'c') },
215 { CODEC_ID_ULTI, MKTAG('U', 'L', 'T', 'I') },
216 { CODEC_ID_VIXL, MKTAG('V', 'I', 'X', 'L') },
217 { CODEC_ID_QPEG, MKTAG('Q', 'P', 'E', 'G') },
218 { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '0') },
219 { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '1') },
220 { CODEC_ID_WMV3, MKTAG('W', 'M', 'V', '3') },
221 { CODEC_ID_LOCO, MKTAG('L', 'O', 'C', 'O') },
222 { CODEC_ID_THEORA, MKTAG('t', 'h', 'e', 'o') },
223 #if LIBAVCODEC_VERSION_INT>0x000409
224 { CODEC_ID_WNV1, MKTAG('W', 'N', 'V', '1') },
225 { CODEC_ID_AASC, MKTAG('A', 'A', 'S', 'C') },
226 { CODEC_ID_INDEO2, MKTAG('R', 'T', '2', '1') },
227 { CODEC_ID_FRAPS, MKTAG('F', 'P', 'S', '1') },
228 { CODEC_ID_TRUEMOTION2, MKTAG('T', 'M', '2', '0') },
230 #if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
231 { CODEC_ID_FLASHSV, MKTAG('F', 'S', 'V', '1') },
232 { CODEC_ID_JPEGLS,MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - encoder */
233 { CODEC_ID_VC1, MKTAG('W', 'V', 'C', '1') },
234 { CODEC_ID_VC1, MKTAG('W', 'M', 'V', 'A') },
235 { CODEC_ID_CSCD, MKTAG('C', 'S', 'C', 'D') },
236 { CODEC_ID_ZMBV, MKTAG('Z', 'M', 'B', 'V') },
237 { CODEC_ID_KMVC, MKTAG('K', 'M', 'V', 'C') },
239 #if LIBAVCODEC_VERSION_INT>((51<<16)+(11<<8)+0)
240 { CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
241 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') },
242 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') },
243 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
244 { CODEC_ID_VP6F, MKTAG('V', 'P', '6', 'F') },
245 { CODEC_ID_JPEG2000, MKTAG('M', 'J', '2', 'C') },
246 { CODEC_ID_VMNC, MKTAG('V', 'M', 'n', 'c') },
248 #if LIBAVCODEC_VERSION_INT>=((51<<16)+(49<<8)+0)
249 // this tag seems not to exist in older versions of FFMPEG
250 { CODEC_ID_TARGA, MKTAG('t', 'g', 'a', ' ') },
252 { CODEC_ID_NONE, 0 },
256 class CvCapture_FFMPEG : public CvCapture
259 CvCapture_FFMPEG() { init(); }
260 virtual ~CvCapture_FFMPEG() { close(); }
262 virtual bool open( const char* filename );
263 virtual void close();
265 virtual double getProperty(int);
266 virtual bool setProperty(int, double);
267 virtual bool grabFrame();
268 virtual IplImage* retrieveFrame();
273 bool slowSeek( int framenumber );
275 AVFormatContext * ic;
283 'filename' contains the filename of the videosource,
284 'filename==NULL' indicates that ffmpeg's seek support works
285 for the particular file.
286 'filename!=NULL' indicates that the slow fallback function is used for seeking,
287 and so the filename is needed to reopen the file on backward seeking.
293 void CvCapture_FFMPEG::init()
300 memset( &rgb_picture, 0, sizeof(rgb_picture) );
301 memset( &frame, 0, sizeof(frame) );
306 void CvCapture_FFMPEG::close()
313 #if LIBAVFORMAT_BUILD > 4628
314 avcodec_close( video_st->codec );
316 avcodec_close( &video_st->codec );
323 av_close_input_file(ic);
327 if( rgb_picture.data[0] )
328 cvFree( &rgb_picture.data[0] );
335 Used to reopen a video if the slower fallback function for seeking is used.
337 bool CvCapture_FFMPEG::reopen()
339 if ( filename==NULL ) return false;
341 #if LIBAVFORMAT_BUILD > 4628
342 avcodec_close( video_st->codec );
344 avcodec_close( &video_st->codec );
346 av_close_input_file(ic);
349 av_open_input_file(&ic, filename, NULL, 0, NULL);
350 av_find_stream_info(ic);
351 #if LIBAVFORMAT_BUILD > 4628
352 AVCodecContext *enc = ic->streams[video_stream]->codec;
354 AVCodecContext *enc = &ic->streams[video_stream]->codec;
356 AVCodec *codec = avcodec_find_decoder(enc->codec_id);
357 avcodec_open(enc, codec);
358 video_st = ic->streams[video_stream];
360 // reset framenumber to zero
368 bool CvCapture_FFMPEG::open( const char* _filename )
375 /* register all codecs, demux and protocols */
379 // av_log_level = AV_LOG_QUIET;
382 int err = av_open_input_file(&ic, _filename, NULL, 0, NULL);
384 CV_WARN("Error opening file");
387 err = av_find_stream_info(ic);
389 CV_WARN("Could not find codec parameters");
392 for(i = 0; i < ic->nb_streams; i++) {
393 #if LIBAVFORMAT_BUILD > 4628
394 AVCodecContext *enc = ic->streams[i]->codec;
396 AVCodecContext *enc = &ic->streams[i]->codec;
399 if( CODEC_TYPE_VIDEO == enc->codec_type && video_stream < 0) {
400 AVCodec *codec = avcodec_find_decoder(enc->codec_id);
402 avcodec_open(enc, codec) < 0)
405 video_st = ic->streams[i];
406 picture = avcodec_alloc_frame();
408 rgb_picture.data[0] = (uint8_t*)cvAlloc(
409 avpicture_get_size( PIX_FMT_BGR24,
410 enc->width, enc->height ));
411 avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0],
412 PIX_FMT_BGR24, enc->width, enc->height );
414 cvInitImageHeader( &frame, cvSize( enc->width,
415 enc->height ), 8, 3, 0, 4 );
416 cvSetData( &frame, rgb_picture.data[0],
417 rgb_picture.linesize[0] );
422 if(video_stream >= 0) valid = true;
424 // perform check if source is seekable via ffmpeg's seek function av_seek_frame(...)
425 err = av_seek_frame(ic, video_stream, 10, 0);
428 filename=(char*)malloc(strlen(_filename)+1);
429 strcpy(filename, _filename);
430 // reopen videofile to 'seek' back to first frame
435 // seek seems to work, so we don't need the filename,
436 // but we still need to seek back to filestart
438 av_seek_frame(ic, video_stream, 0, 0);
449 bool CvCapture_FFMPEG::grabFrame()
452 static bool bFirstTime = true;
456 // First time we're called, set packet.data to NULL to indicate it
457 // doesn't have to be freed
463 if( !ic || !video_st )
466 // free last packet if exist
467 if (pkt.data != NULL) {
468 av_free_packet (&pkt);
471 // get the next frame
472 while (!valid && (av_read_frame(ic, &pkt) >= 0)) {
473 if( pkt.stream_index != video_stream ) continue;
474 #if LIBAVFORMAT_BUILD > 4628
475 avcodec_decode_video(video_st->codec,
476 picture, &got_picture,
479 avcodec_decode_video(&video_st->codec,
480 picture, &got_picture,
485 // we have a new picture, so memorize it
486 picture_pts = pkt.pts;
491 // return if we have a new picture or not
496 IplImage* CvCapture_FFMPEG::retrieveFrame()
498 if( !video_st || !picture->data[0] )
502 #if LIBAVFORMAT_BUILD > 4628
503 img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24,
505 video_st->codec->pix_fmt,
506 video_st->codec->width,
507 video_st->codec->height );
509 img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24,
511 video_st->codec.pix_fmt,
512 video_st->codec.width,
513 video_st->codec.height );
519 double CvCapture_FFMPEG::getProperty( int property_id )
521 // if( !capture || !video_st || !picture->data[0] ) return 0;
522 if( !video_st ) return 0;
526 timestamp = picture_pts;
528 switch( property_id )
530 case CV_CAP_PROP_POS_MSEC:
531 // if(ic->start_time != static_cast<double>(AV_NOPTS_VALUE))
532 if(ic->start_time != AV_NOPTS_VALUE)
533 return (double)(timestamp - ic->start_time)*1000/(double)AV_TIME_BASE;
535 case CV_CAP_PROP_POS_FRAMES:
536 //if(video_st->cur_dts != static_cast<double>(AV_NOPTS_VALUE))
537 if(video_st->cur_dts != AV_NOPTS_VALUE)
538 return (double)video_st->cur_dts-1;
540 case CV_CAP_PROP_POS_AVI_RATIO:
541 // if(ic->start_time != static_cast<double>(AV_NOPTS_VALUE) && ic->duration != static_cast<double>(AV_NOPTS_VALUE))
542 if(ic->start_time != AV_NOPTS_VALUE && ic->duration != AV_NOPTS_VALUE)
543 return (double)(timestamp-ic->start_time)/(double)ic->duration;
545 case CV_CAP_PROP_FRAME_WIDTH:
546 return (double)frame.width;
548 case CV_CAP_PROP_FRAME_HEIGHT:
549 return (double)frame.height;
551 case CV_CAP_PROP_FPS:
552 #if LIBAVCODEC_BUILD > 4753
553 return av_q2d (video_st->r_frame_rate);
555 return (double)video_st->codec.frame_rate
556 / (double)video_st->codec.frame_rate_base;
559 case CV_CAP_PROP_FOURCC:
560 #if LIBAVFORMAT_BUILD > 4628
561 return (double)video_st->codec->codec_tag;
563 return (double)video_st->codec.codec_tag;
572 // this is a VERY slow fallback function, ONLY used if ffmpeg's av_seek_frame delivers no correct result!
573 bool CvCapture_FFMPEG::slowSeek( int framenumber )
575 if ( framenumber>picture_pts )
577 while ( picture_pts<framenumber )
578 if ( !grabFrame() ) return false;
580 else if ( framenumber<picture_pts )
583 while ( picture_pts<framenumber )
584 if ( !grabFrame() ) return false;
590 bool CvCapture_FFMPEG::setProperty( int property_id, double value )
592 if( !video_st ) return false;
594 switch( property_id )
596 case CV_CAP_PROP_POS_MSEC:
597 case CV_CAP_PROP_POS_FRAMES:
598 case CV_CAP_PROP_POS_AVI_RATIO:
600 int64_t timestamp = 0;
601 AVRational time_base;
602 switch( property_id )
604 case CV_CAP_PROP_POS_FRAMES:
605 timestamp=(int64_t)value;
606 if(ic->start_time != AV_NOPTS_VALUE)
607 timestamp += ic->start_time;
610 case CV_CAP_PROP_POS_MSEC:
611 time_base=ic->streams[video_stream]->time_base;
612 timestamp=(int64_t)(value*(float(time_base.den)/float(time_base.num))/1000);
613 if(ic->start_time != AV_NOPTS_VALUE)
614 timestamp += ic->start_time;
617 case CV_CAP_PROP_POS_AVI_RATIO:
618 timestamp=(int64_t)(value*ic->duration);
619 if(ic->start_time != AV_NOPTS_VALUE && ic->duration != AV_NOPTS_VALUE)
620 timestamp += ic->start_time;
626 // ffmpeg's seek doesn't work...
627 if (!slowSeek((int)timestamp))
629 fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n",
630 (double)timestamp / AV_TIME_BASE);
636 int ret = av_seek_frame(ic, video_stream, timestamp, 0);
639 fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n",
640 (double)timestamp / AV_TIME_BASE);
644 picture_pts=(int64_t)value;
657 CvCapture* cvCreateFileCapture_FFMPEG( const char* filename )
659 CvCapture_FFMPEG* capture = new CvCapture_FFMPEG;
660 if( capture->open( filename ))
667 ///////////////// FFMPEG CvVideoWriter implementation //////////////////////////
668 class CvVideoWriter_FFMPEG : public CvVideoWriter
671 CvVideoWriter_FFMPEG() { init(); }
672 virtual ~CvVideoWriter_FFMPEG() { close(); }
674 virtual bool open( const char* filename, int fourcc,
675 double fps, CvSize frameSize, bool isColor );
676 virtual void close();
677 virtual bool writeFrame( const IplImage* image );
685 uint32_t outbuf_size;
688 AVFrame * input_picture;
692 IplImage * temp_image;
695 static const char * icvFFMPEGErrStr(int err)
698 case AVERROR_NUMEXPECTED:
699 return "Incorrect filename syntax";
700 case AVERROR_INVALIDDATA:
701 return "Invalid data in header";
703 return "Unknown format";
705 return "I/O error occurred";
707 return "Memory allocation error";
711 return "Unspecified error";
714 /* function internal to FFMPEG (libavformat/riff.c) to lookup codec id by fourcc tag*/
716 enum CodecID codec_get_bmp_id(unsigned int tag);
719 void CvVideoWriter_FFMPEG::init()
735 * the following function is a modified version of code
736 * found in ffmpeg-0.4.9-pre1/output_example.c
738 static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bool alloc)
741 uint8_t * picture_buf;
744 picture = avcodec_alloc_frame();
747 size = avpicture_get_size(pix_fmt, width, height);
749 picture_buf = (uint8_t *) cvAlloc(size);
755 avpicture_fill((AVPicture *)picture, picture_buf,
756 pix_fmt, width, height);
763 /* add a video output stream to the container */
764 static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
766 int w, int h, int bitrate,
767 double fps, int pixel_format)
771 int frame_rate, frame_rate_base;
775 st = av_new_stream(oc, 0);
777 CV_WARN("Could not allocate stream");
781 #if LIBAVFORMAT_BUILD > 4628
787 #if LIBAVFORMAT_BUILD > 4621
788 c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_VIDEO);
790 c->codec_id = oc->oformat->video_codec;
793 if(codec_id != CODEC_ID_NONE){
794 c->codec_id = codec_id;
797 //if(codec_tag) c->codec_tag=codec_tag;
798 codec = avcodec_find_encoder(c->codec_id);
800 c->codec_type = CODEC_TYPE_VIDEO;
802 /* put sample parameters */
803 c->bit_rate = bitrate;
805 /* resolution must be a multiple of two */
809 /* time base: this is the fundamental unit of time (in seconds) in terms
810 of which frame timestamps are represented. for fixed-fps content,
811 timebase should be 1/framerate and timestamp increments should be
813 frame_rate=cvRound(fps);
815 while (fabs((double)frame_rate/frame_rate_base) - fps > 0.001){
817 frame_rate=cvRound(fps*frame_rate_base);
819 #if LIBAVFORMAT_BUILD > 4752
820 c->time_base.den = frame_rate;
821 c->time_base.num = frame_rate_base;
822 /* adjust time base for supported framerates */
823 if(codec && codec->supported_framerates){
824 const AVRational *p= codec->supported_framerates;
825 AVRational req = {frame_rate, frame_rate_base};
826 const AVRational *best=NULL;
827 AVRational best_error= {INT_MAX, 1};
828 for(; p->den!=0; p++){
829 AVRational error= av_sub_q(req, *p);
830 if(error.num <0) error.num *= -1;
831 if(av_cmp_q(error, best_error) < 0){
836 c->time_base.den= best->num;
837 c->time_base.num= best->den;
840 c->frame_rate = frame_rate;
841 c->frame_rate_base = frame_rate_base;
844 c->gop_size = 12; /* emit one intra frame every twelve frames at most */
845 c->pix_fmt = (PixelFormat) pixel_format;
847 if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
850 if (c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MSMPEG4V3){
851 /* needed to avoid using macroblocks in which some coeffs overflow
852 this doesnt happen with normal video, it just happens here as the
853 motion of the chroma plane doesnt match the luma plane */
854 /* avoid FFMPEG warning 'clipping 1 dct coefficients...' */
857 #if LIBAVCODEC_VERSION_INT>0x000409
858 // some formats want stream headers to be seperate
859 if(oc->oformat->flags & AVFMT_GLOBALHEADER)
861 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
868 int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_t * outbuf, uint32_t outbuf_size, AVFrame * picture ){
869 CV_FUNCNAME("icv_av_write_frame_FFMPEG");
871 #if LIBAVFORMAT_BUILD > 4628
872 AVCodecContext * c = video_st->codec;
874 AVCodecContext * c = &(video_st->codec);
881 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
882 /* raw video case. The API will change slightly in the near
885 av_init_packet(&pkt);
887 pkt.flags |= PKT_FLAG_KEY;
888 pkt.stream_index= video_st->index;
889 pkt.data= (uint8_t *)picture;
890 pkt.size= sizeof(AVPicture);
892 ret = av_write_frame(oc, &pkt);
894 /* encode the image */
895 out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
896 /* if zero size, it means the image was buffered */
899 av_init_packet(&pkt);
901 #if LIBAVFORMAT_BUILD > 4752
902 pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base);
904 pkt.pts = c->coded_frame->pts;
906 if(c->coded_frame->key_frame)
907 pkt.flags |= PKT_FLAG_KEY;
908 pkt.stream_index= video_st->index;
912 /* write the compressed frame in the media file */
913 ret = av_write_frame(oc, &pkt);
919 CV_ERROR(CV_StsError, "Error while writing video frame");
926 /// write a frame with FFMPEG
927 bool CvVideoWriter_FFMPEG::writeFrame( const IplImage * image )
931 CV_FUNCNAME("CvVideoWriter_FFMPEG::writerFrame");
935 // typecast from opaque data type to implemented struct
936 #if LIBAVFORMAT_BUILD > 4628
937 AVCodecContext *c = video_st->codec;
939 AVCodecContext *c = &(video_st->codec);
942 if( c->codec_id == CODEC_ID_RAWVIDEO && image->origin != IPL_ORIGIN_BL )
945 temp_image = cvCreateImage( cvGetSize(image),
946 image->depth, image->nChannels );
947 cvFlip( image, temp_image, 0 );
952 if (input_pix_fmt == PIX_FMT_BGR24) {
953 if (image->nChannels != 3 || image->depth != IPL_DEPTH_8U) {
954 CV_ERROR(CV_StsUnsupportedFormat, "cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 3.");
957 else if (input_pix_fmt == PIX_FMT_GRAY8) {
958 if (image->nChannels != 1 || image->depth != IPL_DEPTH_8U) {
959 CV_ERROR(CV_StsUnsupportedFormat, "cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 1.");
966 // check if buffer sizes match, i.e. image has expected format (size, channels, bitdepth, alignment)
967 assert (image->imageSize == avpicture_get_size( input_pix_fmt, image->width, image->height ));
969 if ( c->pix_fmt != input_pix_fmt ) {
970 assert( input_picture );
971 // let input_picture point to the raw data buffer of 'image'
972 avpicture_fill((AVPicture *)input_picture, (uint8_t *) image->imageData,
973 input_pix_fmt, image->width, image->height);
975 // convert to the color format needed by the codec
976 if( img_convert((AVPicture *)picture, c->pix_fmt,
977 (AVPicture *)input_picture, input_pix_fmt,
978 image->width, image->height) < 0){
979 CV_ERROR(CV_StsUnsupportedFormat, "FFMPEG::img_convert pixel format conversion from BGR24 not handled");
983 avpicture_fill((AVPicture *)picture, (uint8_t *) image->imageData,
984 input_pix_fmt, image->width, image->height);
987 ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0;
993 /// close video output stream and free associated memory
994 void CvVideoWriter_FFMPEG::close()
998 // nothing to do if already released
1002 /* no more frame to compress. The codec has a latency of a few
1003 frames if using B frames, so we get the last frames by
1004 passing the same picture again */
1005 // TODO -- do we need to account for latency here?
1007 /* write the trailer, if any */
1008 av_write_trailer(oc);
1011 #if LIBAVFORMAT_BUILD > 4628
1012 if( video_st->codec->pix_fmt != input_pix_fmt){
1014 if( video_st->codec.pix_fmt != input_pix_fmt){
1016 cvFree(&(picture->data[0]));
1020 if (input_picture) {
1021 av_free(input_picture);
1025 #if LIBAVFORMAT_BUILD > 4628
1026 avcodec_close(video_st->codec);
1028 avcodec_close(&(video_st->codec));
1033 /* free the streams */
1034 for(i = 0; i < oc->nb_streams; i++) {
1035 av_freep(&oc->streams[i]->codec);
1036 av_freep(&oc->streams[i]);
1039 if (!(fmt->flags & AVFMT_NOFILE)) {
1040 /* close the output file */
1043 #if LIBAVCODEC_VERSION_INT==((51<<16)+(49<<8)+0)
1046 url_fclose(&oc->pb);
1051 /* free the stream */
1054 cvReleaseImage( &temp_image );
1059 /// Create a video writer object that uses FFMPEG
1060 bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
1061 double fps, CvSize frameSize, bool is_color )
1063 CV_FUNCNAME("CvVideoWriter_FFMPEG::open");
1065 CodecID codec_id = CODEC_ID_NONE;
1075 assert (frameSize.width > 0 && frameSize.height > 0);
1077 // tell FFMPEG to register codecs
1080 /* auto detect the output format from the name and fourcc code. */
1081 fmt = guess_format(NULL, filename, NULL);
1083 CV_ERROR( CV_StsUnsupportedFormat, "FFMPEG does not recognize the given file extension");
1086 /* determine optimal pixel format */
1088 input_pix_fmt = PIX_FMT_BGR24;
1091 input_pix_fmt = PIX_FMT_GRAY8;
1094 // alloc memory for context
1095 oc = av_alloc_format_context();
1100 snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
1102 /* set some options */
1103 oc->max_delay = (int)(0.7*AV_TIME_BASE); /* This reduces buffer underrun warnings with MPEG */
1105 /* Lookup codec_id for given fourcc */
1106 if(fourcc!=CV_FOURCC_DEFAULT){
1107 #if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)
1108 if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ){
1109 CV_ERROR( CV_StsUnsupportedFormat,
1110 "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." );
1114 if( (codec_id = av_codec_get_id((const AVCodecTag**)(&codec_bmp_tags), fourcc)) == CODEC_ID_NONE ){
1115 CV_ERROR( CV_StsUnsupportedFormat,
1116 "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." );
1121 // set a few optimal pixel formats for lossless codecs of interest..
1124 #if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
1125 case CODEC_ID_JPEGLS:
1126 // BGR24 or GRAY8 depending on is_color...
1127 codec_pix_fmt = input_pix_fmt;
1131 // no choice... other supported formats are YUV only
1132 codec_pix_fmt = PIX_FMT_RGBA32;
1134 case CODEC_ID_MJPEG:
1135 case CODEC_ID_LJPEG:
1136 codec_pix_fmt = PIX_FMT_YUVJ420P;
1138 case CODEC_ID_RAWVIDEO:
1140 // good for lossy formats, MPEG, etc.
1141 codec_pix_fmt = PIX_FMT_YUV420P;
1145 // TODO -- safe to ignore output audio stream?
1146 video_st = icv_add_video_stream_FFMPEG(oc, codec_id,
1147 frameSize.width, frameSize.height, frameSize.width*frameSize.height*64,
1148 fps, codec_pix_fmt);
1151 /* set the output parameters (must be done even if no
1153 if (av_set_parameters(oc, NULL) < 0) {
1154 CV_ERROR(CV_StsBadArg, "Invalid output format parameters");
1157 dump_format(oc, 0, filename, 1);
1159 /* now that all the parameters are set, we can open the audio and
1160 video codecs and allocate the necessary encode buffers */
1162 CV_ERROR(CV_StsBadArg, "Couldn't open video stream");
1168 #if LIBAVFORMAT_BUILD > 4628
1169 c = (video_st->codec);
1171 c = &(video_st->codec);
1174 c->codec_tag = fourcc;
1175 /* find the video encoder */
1176 codec = avcodec_find_encoder(c->codec_id);
1178 CV_ERROR(CV_StsBadArg, "codec not found");
1181 /* open the codec */
1182 if ( (err=avcodec_open(c, codec)) < 0) {
1184 sprintf(errtext, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err));
1185 CV_ERROR(CV_StsBadArg, errtext);
1190 if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
1191 /* allocate output buffer */
1192 /* assume we will never get codec output with more than 4 bytes per pixel... */
1193 outbuf_size = frameSize.width*frameSize.height*4;
1194 outbuf = (uint8_t *) av_malloc(outbuf_size);
1197 bool need_color_convert;
1198 need_color_convert = (c->pix_fmt != input_pix_fmt);
1200 /* allocate the encoded raw picture */
1201 picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert);
1203 CV_ERROR(CV_StsNoMem, "Could not allocate picture");
1206 /* if the output format is not our input format, then a temporary
1207 picture of the input format is needed too. It is then converted
1208 to the required output format */
1209 input_picture = NULL;
1210 if ( need_color_convert ) {
1211 input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false);
1212 if (!input_picture) {
1213 CV_ERROR(CV_StsNoMem, "Could not allocate picture");
1217 /* open the output file, if needed */
1218 if (!(fmt->flags & AVFMT_NOFILE)) {
1219 if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
1220 CV_ERROR(CV_StsBadArg, "Couldn't open output file for writing");
1224 /* write the stream header, if any */
1225 av_write_header( oc );
1233 CvVideoWriter* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps,
1234 CvSize frameSize, int isColor )
1236 CvVideoWriter_FFMPEG* writer = new CvVideoWriter_FFMPEG;
1237 if( writer->open( filename, fourcc, fps, frameSize, isColor != 0 ))