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.
45 #include <ffmpeg/avformat.h>
46 #include <ffmpeg/avcodec.h>
53 #define INT64_C (long long)
56 #define CV_WARN(message)
58 #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
62 #if LIBAVCODEC_VERSION_INT<=0x000409
63 #define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
69 char * FOURCC2str( int fourcc )
71 char * mystr=(char*)malloc(5);
72 mystr[0]=(fourcc )&255;
73 mystr[1]=(fourcc>> 8)&255;
74 mystr[2]=(fourcc>>16)&255;
75 mystr[3]=(fourcc>>24)&255;
81 // required to look up the correct codec ID depending on the FOURCC code,
82 // this is just a snipped from the file riff.c from ffmpeg/libavformat
83 typedef struct AVCodecTag {
88 const AVCodecTag codec_bmp_tags[] = {
89 { CODEC_ID_H264, MKTAG('H', '2', '6', '4') },
90 { CODEC_ID_H264, MKTAG('h', '2', '6', '4') },
91 { CODEC_ID_H264, MKTAG('X', '2', '6', '4') },
92 { CODEC_ID_H264, MKTAG('x', '2', '6', '4') },
93 { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
94 { CODEC_ID_H264, MKTAG('V', 'S', 'S', 'H') },
96 { CODEC_ID_H263, MKTAG('H', '2', '6', '3') },
97 { CODEC_ID_H263P, MKTAG('H', '2', '6', '3') },
98 { CODEC_ID_H263I, MKTAG('I', '2', '6', '3') }, /* intel h263 */
99 { CODEC_ID_H261, MKTAG('H', '2', '6', '1') },
101 /* added based on MPlayer */
102 { CODEC_ID_H263P, MKTAG('U', '2', '6', '3') },
103 { CODEC_ID_H263P, MKTAG('v', 'i', 'v', '1') },
105 { CODEC_ID_MPEG4, MKTAG('F', 'M', 'P', '4') },
106 { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') },
107 { CODEC_ID_MPEG4, MKTAG('D', 'X', '5', '0') },
108 { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
109 { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') },
110 { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') },
111 { CODEC_ID_MPEG4, MKTAG(0x04, 0, 0, 0) }, /* some broken avi use this */
113 /* added based on MPlayer */
114 { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', '1') },
115 { CODEC_ID_MPEG4, MKTAG('B', 'L', 'Z', '0') },
116 { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
117 { CODEC_ID_MPEG4, MKTAG('U', 'M', 'P', '4') },
118 { CODEC_ID_MPEG4, MKTAG('W', 'V', '1', 'F') },
119 { CODEC_ID_MPEG4, MKTAG('S', 'E', 'D', 'G') },
121 { CODEC_ID_MPEG4, MKTAG('R', 'M', 'P', '4') },
123 { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '3') }, /* default signature when using MSMPEG4 */
124 { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') },
126 /* added based on MPlayer */
127 { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', 'G', '3') },
128 { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '5') },
129 { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '6') },
130 { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '4') },
131 { CODEC_ID_MSMPEG4V3, MKTAG('A', 'P', '4', '1') },
132 { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '1') },
133 { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '0') },
135 { CODEC_ID_MSMPEG4V2, MKTAG('M', 'P', '4', '2') },
137 /* added based on MPlayer */
138 { CODEC_ID_MSMPEG4V2, MKTAG('D', 'I', 'V', '2') },
140 { CODEC_ID_MSMPEG4V1, MKTAG('M', 'P', 'G', '4') },
142 { CODEC_ID_WMV1, MKTAG('W', 'M', 'V', '1') },
144 /* added based on MPlayer */
145 { CODEC_ID_WMV2, MKTAG('W', 'M', 'V', '2') },
146 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'd') },
147 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'd') },
148 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'l') },
149 { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '2', '5') },
150 { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '1') },
151 { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') },
152 { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', 'g', '2') },
153 { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'P', 'E', 'G') },
154 { CODEC_ID_MPEG1VIDEO, MKTAG('P', 'I', 'M', '1') },
155 { CODEC_ID_MPEG1VIDEO, MKTAG('V', 'C', 'R', '2') },
156 { CODEC_ID_MPEG1VIDEO, 0x10000001 },
157 { CODEC_ID_MPEG2VIDEO, 0x10000002 },
158 { CODEC_ID_MPEG2VIDEO, MKTAG('D', 'V', 'R', ' ') },
159 { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'M', 'E', 'S') },
160 { CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') },
161 { CODEC_ID_MJPEG, MKTAG('L', 'J', 'P', 'G') },
162 { CODEC_ID_LJPEG, MKTAG('L', 'J', 'P', 'G') },
163 { CODEC_ID_MJPEG, MKTAG('J', 'P', 'G', 'L') }, /* Pegasus lossless JPEG */
164 { CODEC_ID_MJPEG, MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - decoder */
165 { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') },
166 { CODEC_ID_MJPEG, MKTAG('I', 'J', 'P', 'G') },
167 { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') },
168 { CODEC_ID_HUFFYUV, MKTAG('H', 'F', 'Y', 'U') },
169 { CODEC_ID_FFVHUFF, MKTAG('F', 'F', 'V', 'H') },
170 { CODEC_ID_CYUV, MKTAG('C', 'Y', 'U', 'V') },
171 { CODEC_ID_RAWVIDEO, 0 },
172 { CODEC_ID_RAWVIDEO, MKTAG('I', '4', '2', '0') },
173 { CODEC_ID_RAWVIDEO, MKTAG('Y', 'U', 'Y', '2') },
174 { CODEC_ID_RAWVIDEO, MKTAG('Y', '4', '2', '2') },
175 { CODEC_ID_RAWVIDEO, MKTAG('Y', 'V', '1', '2') },
176 { CODEC_ID_RAWVIDEO, MKTAG('U', 'Y', 'V', 'Y') },
177 { CODEC_ID_RAWVIDEO, MKTAG('I', 'Y', 'U', 'V') },
178 { CODEC_ID_RAWVIDEO, MKTAG('Y', '8', '0', '0') },
179 { CODEC_ID_RAWVIDEO, MKTAG('H', 'D', 'Y', 'C') },
180 { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '1') },
181 { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '2') },
182 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
183 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
184 { CODEC_ID_ASV1, MKTAG('A', 'S', 'V', '1') },
185 { CODEC_ID_ASV2, MKTAG('A', 'S', 'V', '2') },
186 { CODEC_ID_VCR1, MKTAG('V', 'C', 'R', '1') },
187 { CODEC_ID_FFV1, MKTAG('F', 'F', 'V', '1') },
188 { CODEC_ID_XAN_WC4, MKTAG('X', 'x', 'a', 'n') },
189 { CODEC_ID_MSRLE, MKTAG('m', 'r', 'l', 'e') },
190 { CODEC_ID_MSRLE, MKTAG(0x1, 0x0, 0x0, 0x0) },
191 { CODEC_ID_MSVIDEO1, MKTAG('M', 'S', 'V', 'C') },
192 { CODEC_ID_MSVIDEO1, MKTAG('m', 's', 'v', 'c') },
193 { CODEC_ID_MSVIDEO1, MKTAG('C', 'R', 'A', 'M') },
194 { CODEC_ID_MSVIDEO1, MKTAG('c', 'r', 'a', 'm') },
195 { CODEC_ID_MSVIDEO1, MKTAG('W', 'H', 'A', 'M') },
196 { CODEC_ID_MSVIDEO1, MKTAG('w', 'h', 'a', 'm') },
197 { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') },
198 { CODEC_ID_TRUEMOTION1, MKTAG('D', 'U', 'C', 'K') },
199 { CODEC_ID_MSZH, MKTAG('M', 'S', 'Z', 'H') },
200 { CODEC_ID_ZLIB, MKTAG('Z', 'L', 'I', 'B') },
201 { CODEC_ID_SNOW, MKTAG('S', 'N', 'O', 'W') },
202 { CODEC_ID_4XM, MKTAG('4', 'X', 'M', 'V') },
203 { CODEC_ID_FLV1, MKTAG('F', 'L', 'V', '1') },
204 { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') },
205 { CODEC_ID_TSCC, MKTAG('t', 's', 'c', 'c') },
206 { CODEC_ID_ULTI, MKTAG('U', 'L', 'T', 'I') },
207 { CODEC_ID_VIXL, MKTAG('V', 'I', 'X', 'L') },
208 { CODEC_ID_QPEG, MKTAG('Q', 'P', 'E', 'G') },
209 { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '0') },
210 { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '1') },
211 { CODEC_ID_WMV3, MKTAG('W', 'M', 'V', '3') },
212 { CODEC_ID_LOCO, MKTAG('L', 'O', 'C', 'O') },
213 { CODEC_ID_THEORA, MKTAG('t', 'h', 'e', 'o') },
214 #if LIBAVCODEC_VERSION_INT>0x000409
215 { CODEC_ID_JPEGLS,MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - encoder */
216 { CODEC_ID_FLASHSV, MKTAG('F', 'S', 'V', '1') },
217 { CODEC_ID_VC1, MKTAG('W', 'V', 'C', '1') },
218 { CODEC_ID_VC1, MKTAG('W', 'M', 'V', 'A') },
219 { CODEC_ID_WNV1, MKTAG('W', 'N', 'V', '1') },
220 { CODEC_ID_AASC, MKTAG('A', 'A', 'S', 'C') },
221 { CODEC_ID_INDEO2, MKTAG('R', 'T', '2', '1') },
222 { CODEC_ID_FRAPS, MKTAG('F', 'P', 'S', '1') },
223 { CODEC_ID_TRUEMOTION2, MKTAG('T', 'M', '2', '0') },
224 { CODEC_ID_CSCD, MKTAG('C', 'S', 'C', 'D') },
225 { CODEC_ID_ZMBV, MKTAG('Z', 'M', 'B', 'V') },
226 { CODEC_ID_KMVC, MKTAG('K', 'M', 'V', 'C') },
228 #if LIBAVCODEC_VERSION_INT>((51<<16)+(11<<8)+0)
229 { CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
230 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') },
231 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') },
232 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
233 { CODEC_ID_VP6F, MKTAG('V', 'P', '6', 'F') },
234 { CODEC_ID_JPEG2000, MKTAG('M', 'J', '2', 'C') },
235 { CODEC_ID_VMNC, MKTAG('V', 'M', 'n', 'c') },
237 #if LIBAVCODEC_VERSION_INT>=((51<<16)+(49<<8)+0)
238 // this tag seems not to exist in older versions of FFMPEG
239 { CODEC_ID_TARGA, MKTAG('t', 'g', 'a', ' ') },
241 { CODEC_ID_NONE, 0 },
245 typedef struct CvCaptureAVI_FFMPEG
247 CvCaptureVTable * vtable;
249 AVFormatContext * ic;
257 'filename' contains the filename of the videosource,
258 'filename==NULL' indicates that ffmpeg's seek support works
259 for the particular file.
260 'filename!=NULL' indicates that the slow fallback function is used for seeking,
261 and so the filename is needed to reopen the file on backward seeking.
264 } CvCaptureAVI_FFMPEG;
267 static void icvCloseAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture )
269 //cvFree( (void**)&(capture->entries) );
270 if( capture->picture )
271 av_free(capture->picture);
273 if( capture->video_st )
275 #if LIBAVFORMAT_BUILD > 4628
276 avcodec_close( capture->video_st->codec );
278 avcodec_close( &capture->video_st->codec );
280 capture->video_st = NULL;
285 av_close_input_file(capture->ic);
289 if( capture->rgb_picture.data[0] )
290 cvFree( &capture->rgb_picture.data[0] );
292 memset( &capture->frame, 0, sizeof(capture->frame));
297 Used to reopen a video if the slower fallback function for seeking is used.
299 static int icvReopenFileAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture )
301 if ( capture->filename==NULL ) return 0;
303 #if LIBAVFORMAT_BUILD > 4628
304 avcodec_close( capture->video_st->codec );
306 avcodec_close( &capture->video_st->codec );
308 av_close_input_file(capture->ic);
311 av_open_input_file(&capture->ic, capture->filename, NULL, 0, NULL);
312 av_find_stream_info(capture->ic);
313 #if LIBAVFORMAT_BUILD > 4628
314 AVCodecContext *enc = capture->ic->streams[capture->video_stream]->codec;
316 AVCodecContext *enc = &capture->ic->streams[capture->video_stream]->codec;
318 AVCodec *codec = avcodec_find_decoder(enc->codec_id);
319 avcodec_open(enc, codec);
320 capture->video_st = capture->ic->streams[capture->video_stream];
322 // reset framenumber to zero
323 capture->picture_pts=0;
331 static int icvCheckSeekAVI_FFMPEG( CvCaptureAVI_FFMPEG *capture);
333 static int icvOpenAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture, const char* filename )
335 int err, valid = 0, video_index = -1, i;
339 capture->video_stream = -1;
340 capture->video_st = NULL;
341 /* register all codecs, demux and protocols */
345 // av_log_level = AV_LOG_QUIET;
348 err = av_open_input_file(&ic, filename, NULL, 0, NULL);
350 CV_WARN("Error opening file");
354 err = av_find_stream_info(ic);
356 CV_WARN("Could not find codec parameters");
359 for(i = 0; i < ic->nb_streams; i++) {
360 #if LIBAVFORMAT_BUILD > 4628
361 AVCodecContext *enc = ic->streams[i]->codec;
363 AVCodecContext *enc = &ic->streams[i]->codec;
366 if( CODEC_TYPE_VIDEO == enc->codec_type && video_index < 0) {
368 codec = avcodec_find_decoder(enc->codec_id);
370 avcodec_open(enc, codec) < 0)
372 capture->video_stream = i;
373 capture->video_st = ic->streams[i];
374 capture->picture = avcodec_alloc_frame();
376 capture->rgb_picture.data[0] = (uint8_t*)cvAlloc(
377 avpicture_get_size( PIX_FMT_BGR24,
378 enc->width, enc->height ));
379 avpicture_fill( (AVPicture*)&capture->rgb_picture, capture->rgb_picture.data[0],
380 PIX_FMT_BGR24, enc->width, enc->height );
382 cvInitImageHeader( &capture->frame, cvSize( enc->width,
383 enc->height ), 8, 3, 0, 4 );
384 cvSetData( &capture->frame, capture->rgb_picture.data[0],
385 capture->rgb_picture.linesize[0] );
390 if(video_index >= 0) valid = 1;
392 // perform check if source is seekable via ffmpeg's seek function av_seek_frame(...)
393 err = av_seek_frame(capture->ic, capture->video_stream, 10, 0);
397 while ( filename[length] ) length++;
399 capture->filename=(char*)malloc(length+1);
400 for ( int i=0; i<length+1; i++ ) capture->filename[i]=filename[i];
401 // reopen videofile to 'seek' back to first frame
402 icvReopenFileAVI_FFMPEG( capture );
406 // seek seems to work, so we don't need the filename,
407 // but we still need to seek back to filestart
408 capture->filename=NULL;
409 av_seek_frame(capture->ic, capture->video_stream, 0, 0);
414 icvCloseAVI_FFMPEG( capture );
422 static int icvGrabFrameAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture )
425 static bool bFirstTime = true;
429 // First time we're called, set packet.data to NULL to indicate it
430 // doesn't have to be freed
436 if( !capture || !capture->ic || !capture->video_st )
439 // free last packet if exist
440 if (pkt.data != NULL) {
441 av_free_packet (&pkt);
444 // get the next frame
445 while ((0 == valid) && (av_read_frame(capture->ic, &pkt) >= 0)) {
446 if( pkt.stream_index != capture->video_stream ) continue;
447 #if LIBAVFORMAT_BUILD > 4628
448 avcodec_decode_video(capture->video_st->codec,
449 capture->picture, &got_picture,
452 avcodec_decode_video(&capture->video_st->codec,
453 capture->picture, &got_picture,
458 // we have a new picture, so memorize it
459 capture->picture_pts = pkt.pts;
464 // return if we have a new picture or not
469 static const IplImage* icvRetrieveFrameAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture )
471 if( !capture || !capture->video_st || !capture->picture->data[0] )
475 #if LIBAVFORMAT_BUILD > 4628
476 img_convert( (AVPicture*)&capture->rgb_picture, PIX_FMT_BGR24,
477 (AVPicture*)capture->picture,
478 capture->video_st->codec->pix_fmt,
479 capture->video_st->codec->width,
480 capture->video_st->codec->height );
482 img_convert( (AVPicture*)&capture->rgb_picture, PIX_FMT_BGR24,
483 (AVPicture*)capture->picture,
484 capture->video_st->codec.pix_fmt,
485 capture->video_st->codec.width,
486 capture->video_st->codec.height );
488 return &capture->frame;
492 static double icvGetPropertyAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture, int property_id )
494 // if( !capture || !capture->video_st || !capture->picture->data[0] ) return 0;
495 if( !capture || !capture->video_st ) return 0;
499 timestamp = capture->picture_pts;
501 switch( property_id )
503 case CV_CAP_PROP_POS_MSEC:
504 // if(capture->ic->start_time != static_cast<double>(AV_NOPTS_VALUE))
505 if(capture->ic->start_time != AV_NOPTS_VALUE)
506 return (double)(timestamp - capture->ic->start_time)*1000/(double)AV_TIME_BASE;
508 case CV_CAP_PROP_POS_FRAMES:
509 //if(capture->video_st->cur_dts != static_cast<double>(AV_NOPTS_VALUE))
510 if(capture->video_st->cur_dts != AV_NOPTS_VALUE)
511 return (double)capture->video_st->cur_dts-1;
513 case CV_CAP_PROP_POS_AVI_RATIO:
514 // if(capture->ic->start_time != static_cast<double>(AV_NOPTS_VALUE) && capture->ic->duration != static_cast<double>(AV_NOPTS_VALUE))
515 if(capture->ic->start_time != AV_NOPTS_VALUE && capture->ic->duration != AV_NOPTS_VALUE)
516 return (double)(timestamp-capture->ic->start_time)/(double)capture->ic->duration;
518 case CV_CAP_PROP_FRAME_WIDTH:
519 return (double)capture->frame.width;
521 case CV_CAP_PROP_FRAME_HEIGHT:
522 return (double)capture->frame.height;
524 case CV_CAP_PROP_FPS:
525 #if LIBAVCODEC_BUILD > 4753
526 return av_q2d (capture->video_st->r_frame_rate);
528 return (double)capture->video_st->codec.frame_rate
529 / (double)capture->video_st->codec.frame_rate_base;
532 case CV_CAP_PROP_FOURCC:
533 #if LIBAVFORMAT_BUILD > 4628
534 return (double)capture->video_st->codec->codec_tag;
536 return (double)capture->video_st->codec.codec_tag;
545 // this is a VERY slow fallback function, ONLY used if ffmpeg's av_seek_frame delivers no correct result!
546 static int icvSlowSeekAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture, const int framenumber )
548 if ( framenumber>capture->picture_pts )
550 while ( capture->picture_pts<framenumber )
551 if ( icvGrabFrameAVI_FFMPEG( capture )<0 ) return 0;
553 else if ( framenumber<capture->picture_pts )
555 icvReopenFileAVI_FFMPEG(capture);
556 while ( capture->picture_pts<framenumber )
557 if ( icvGrabFrameAVI_FFMPEG( capture )<0 ) return 0;
565 static int icvSetPropertyAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture,
566 int property_id, double value )
568 if( !capture || !capture->video_st ) return 0;
570 switch( property_id )
572 case CV_CAP_PROP_POS_MSEC:
573 case CV_CAP_PROP_POS_FRAMES:
574 case CV_CAP_PROP_POS_AVI_RATIO:
577 AVRational time_base;
578 switch( property_id )
580 case CV_CAP_PROP_POS_FRAMES:
581 timestamp=(int64_t)value;
582 if(capture->ic->start_time != AV_NOPTS_VALUE)
583 timestamp += capture->ic->start_time;
586 case CV_CAP_PROP_POS_MSEC:
587 time_base=capture->ic->streams[capture->video_stream]->time_base;
588 timestamp=(int64_t)(value*(float(time_base.den)/float(time_base.num))/1000);
589 if(capture->ic->start_time != AV_NOPTS_VALUE)
590 timestamp += capture->ic->start_time;
593 case CV_CAP_PROP_POS_AVI_RATIO:
594 timestamp=(int64_t)(value*capture->ic->duration);
595 if(capture->ic->start_time != AV_NOPTS_VALUE && capture->ic->duration != AV_NOPTS_VALUE)
596 timestamp += capture->ic->start_time;
600 if ( capture->filename )
602 // ffmpeg's seek doesn't work...
603 if (icvSlowSeekAVI_FFMPEG(capture, timestamp) < 0)
605 fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n",
606 (double)timestamp / AV_TIME_BASE);
612 int ret = av_seek_frame(capture->ic, capture->video_stream, timestamp, 0);
615 fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n",
616 (double)timestamp / AV_TIME_BASE);
620 capture->picture_pts=value;
633 static CvCaptureVTable captureAVI_FFMPEG_vtable =
636 (CvCaptureCloseFunc)icvCloseAVI_FFMPEG,
637 (CvCaptureGrabFrameFunc)icvGrabFrameAVI_FFMPEG,
638 (CvCaptureRetrieveFrameFunc)icvRetrieveFrameAVI_FFMPEG,
639 (CvCaptureGetPropertyFunc)icvGetPropertyAVI_FFMPEG,
640 (CvCaptureSetPropertyFunc)icvSetPropertyAVI_FFMPEG,
641 (CvCaptureGetDescriptionFunc)0
645 CvCapture* cvCaptureFromFile_FFMPEG( const char* filename )
647 CvCaptureAVI_FFMPEG* capture = 0;
651 capture = (CvCaptureAVI_FFMPEG*)cvAlloc( sizeof(*capture));
652 memset( capture, 0, sizeof(*capture));
654 capture->vtable = &captureAVI_FFMPEG_vtable;
656 if( !icvOpenAVI_FFMPEG( capture, filename ))
658 capture->vtable->close((CvCapture*)capture);
663 return (CvCapture*)capture;
667 ///////////////// FFMPEG CvVideoWriter implementation //////////////////////////
668 typedef struct CvAVI_FFMPEG_Writer
673 uint32_t outbuf_size;
676 AVFrame * input_picture;
680 IplImage * temp_image;
681 } CvAVI_FFMPEG_Writer;
683 const char * icv_FFMPEG_ErrStr(int err)
686 case AVERROR_NUMEXPECTED:
687 return "Incorrect filename syntax";
688 case AVERROR_INVALIDDATA:
689 return "Invalid data in header";
691 return "Unknown format";
693 return "I/O error occurred";
695 return "Memory allocation error";
699 return "Unspecified error";
702 /* function internal to FFMPEG (libavformat/riff.c) to lookup codec id by fourcc tag*/
704 enum CodecID codec_get_bmp_id(unsigned int tag);
708 * the following function is a modified version of code
709 * found in ffmpeg-0.4.9-pre1/output_example.c
711 static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bool alloc)
714 uint8_t * picture_buf;
717 picture = avcodec_alloc_frame();
720 size = avpicture_get_size(pix_fmt, width, height);
722 picture_buf = (uint8_t *) cvAlloc(size);
728 avpicture_fill((AVPicture *)picture, picture_buf,
729 pix_fmt, width, height);
736 /* add a video output stream to the container */
737 static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
739 int w, int h, int bitrate,
740 double fps, int pixel_format)
744 int frame_rate, frame_rate_base;
748 st = av_new_stream(oc, 0);
750 CV_WARN("Could not allocate stream");
754 #if LIBAVFORMAT_BUILD > 4628
760 #if LIBAVFORMAT_BUILD > 4621
761 c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_VIDEO);
763 c->codec_id = oc->oformat->video_codec;
766 if(codec_id != CODEC_ID_NONE){
767 c->codec_id = codec_id;
770 //if(codec_tag) c->codec_tag=codec_tag;
771 codec = avcodec_find_encoder(c->codec_id);
773 c->codec_type = CODEC_TYPE_VIDEO;
775 /* put sample parameters */
776 c->bit_rate = bitrate;
778 /* resolution must be a multiple of two */
782 /* time base: this is the fundamental unit of time (in seconds) in terms
783 of which frame timestamps are represented. for fixed-fps content,
784 timebase should be 1/framerate and timestamp increments should be
786 frame_rate=cvRound(fps);
788 while (fabs((double)frame_rate/frame_rate_base) - fps > 0.001){
790 frame_rate=cvRound(fps*frame_rate_base);
792 #if LIBAVFORMAT_BUILD > 4752
793 c->time_base.den = frame_rate;
794 c->time_base.num = frame_rate_base;
795 /* adjust time base for supported framerates */
796 if(codec && codec->supported_framerates){
797 const AVRational *p= codec->supported_framerates;
798 AVRational req = {frame_rate, frame_rate_base};
799 const AVRational *best=NULL;
800 AVRational best_error= {INT_MAX, 1};
801 for(; p->den!=0; p++){
802 AVRational error= av_sub_q(req, *p);
803 if(error.num <0) error.num *= -1;
804 if(av_cmp_q(error, best_error) < 0){
809 c->time_base.den= best->num;
810 c->time_base.num= best->den;
813 c->frame_rate = frame_rate;
814 c->frame_rate_base = frame_rate_base;
817 c->gop_size = 12; /* emit one intra frame every twelve frames at most */
818 c->pix_fmt = (PixelFormat) pixel_format;
820 if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
823 if (c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MSMPEG4V3){
824 /* needed to avoid using macroblocks in which some coeffs overflow
825 this doesnt happen with normal video, it just happens here as the
826 motion of the chroma plane doesnt match the luma plane */
827 /* avoid FFMPEG warning 'clipping 1 dct coefficients...' */
830 #if LIBAVCODEC_VERSION_INT>0x000409
831 // some formats want stream headers to be seperate
832 if(oc->oformat->flags & AVFMT_GLOBALHEADER)
834 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
841 /// Create a video writer object that uses FFMPEG
842 CV_IMPL CvVideoWriter* cvCreateVideoWriter( const char * filename, int fourcc,
843 double fps, CvSize frameSize, int is_color )
845 CV_FUNCNAME("cvCreateVideoWriter");
847 CvAVI_FFMPEG_Writer * writer = NULL;
848 CodecID codec_id = CODEC_ID_NONE;
856 assert (frameSize.width > 0 && frameSize.height > 0);
858 // allocate memory for structure...
859 writer = (CvAVI_FFMPEG_Writer *) cvAlloc( sizeof(CvAVI_FFMPEG_Writer));
860 memset (writer, 0, sizeof (*writer));
862 // tell FFMPEG to register codecs
865 /* auto detect the output format from the name and fourcc code. */
866 writer->fmt = guess_format(NULL, filename, NULL);
868 CV_ERROR( CV_StsUnsupportedFormat, "FFMPEG does not recognize the given file extension");
871 /* determine optimal pixel format */
873 writer->input_pix_fmt = PIX_FMT_BGR24;
876 writer->input_pix_fmt = PIX_FMT_GRAY8;
879 // alloc memory for context
880 writer->oc = av_alloc_format_context();
884 writer->oc->oformat = writer->fmt;
885 snprintf(writer->oc->filename, sizeof(writer->oc->filename), "%s", filename);
887 /* set some options */
888 writer->oc->max_delay = (int)(0.7*AV_TIME_BASE); /* This reduces buffer underrun warnings with MPEG */
890 /* Lookup codec id for given fourcc */
891 if(fourcc!=CV_FOURCC_DEFAULT){
892 #if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)
893 if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ){
894 CV_ERROR( CV_StsUnsupportedFormat,
895 "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." );
899 if( (codec_id = av_codec_get_id((const AVCodecTag**)(&codec_bmp_tags), fourcc)) == CODEC_ID_NONE ){
900 CV_ERROR( CV_StsUnsupportedFormat,
901 "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." );
906 // set a few optimal pixel formats for lossless codecs of interest..
909 #if LIBAVCODEC_VERSION_INT>0x000409
910 case CODEC_ID_JPEGLS:
911 // BGR24 or GRAY8 depending on is_color...
912 codec_pix_fmt = writer->input_pix_fmt;
916 // no choice... other supported formats are YUV only
917 codec_pix_fmt = PIX_FMT_RGBA32;
921 codec_pix_fmt = PIX_FMT_YUVJ420P;
923 case CODEC_ID_RAWVIDEO:
925 // good for lossy formats, MPEG, etc.
926 codec_pix_fmt = PIX_FMT_YUV420P;
930 // TODO -- safe to ignore output audio stream?
931 writer->video_st = icv_add_video_stream_FFMPEG(writer->oc, codec_id,
932 frameSize.width, frameSize.height, frameSize.width*frameSize.height*64,
936 /* set the output parameters (must be done even if no
938 if (av_set_parameters(writer->oc, NULL) < 0) {
939 CV_ERROR(CV_StsBadArg, "Invalid output format parameters");
942 dump_format(writer->oc, 0, filename, 1);
944 /* now that all the parameters are set, we can open the audio and
945 video codecs and allocate the necessary encode buffers */
946 if (!writer->video_st){
947 CV_ERROR(CV_StsBadArg, "Couldn't open video stream");
953 #if LIBAVFORMAT_BUILD > 4628
954 c = (writer->video_st->codec);
956 c = &(writer->video_st->codec);
959 c->codec_tag = fourcc;
960 /* find the video encoder */
961 codec = avcodec_find_encoder(c->codec_id);
963 CV_ERROR(CV_StsBadArg, "codec not found");
967 if ( (err=avcodec_open(c, codec)) < 0) {
969 sprintf(errtext, "Could not open codec '%s': %s", codec->name, icv_FFMPEG_ErrStr(err));
970 CV_ERROR(CV_StsBadArg, errtext);
973 writer->outbuf = NULL;
975 if (!(writer->oc->oformat->flags & AVFMT_RAWPICTURE)) {
976 /* allocate output buffer */
977 /* assume we will never get codec output with more than 4 bytes per pixel... */
978 writer->outbuf_size = frameSize.width*frameSize.height*4;
979 writer->outbuf = (uint8_t *) av_malloc(writer->outbuf_size);
982 bool need_color_convert;
983 need_color_convert = (c->pix_fmt != writer->input_pix_fmt);
985 /* allocate the encoded raw picture */
986 writer->picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert);
987 if (!writer->picture) {
988 CV_ERROR(CV_StsNoMem, "Could not allocate picture");
991 /* if the output format is not our input format, then a temporary
992 picture of the input format is needed too. It is then converted
993 to the required output format */
994 writer->input_picture = NULL;
995 if ( need_color_convert ) {
996 writer->input_picture = icv_alloc_picture_FFMPEG(writer->input_pix_fmt, c->width, c->height, false);
997 if (!writer->input_picture) {
998 CV_ERROR(CV_StsNoMem, "Could not allocate picture");
1002 /* open the output file, if needed */
1003 if (!(writer->fmt->flags & AVFMT_NOFILE)) {
1004 if (url_fopen(&writer->oc->pb, filename, URL_WRONLY) < 0) {
1005 CV_ERROR(CV_StsBadArg, "Couldn't open output file for writing");
1009 /* write the stream header, if any */
1010 av_write_header( writer->oc );
1015 // return what we got
1016 return (CvVideoWriter *) writer;
1019 int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_t * outbuf, uint32_t outbuf_size, AVFrame * picture ){
1020 CV_FUNCNAME("icv_av_write_frame_FFMPEG");
1022 #if LIBAVFORMAT_BUILD > 4628
1023 AVCodecContext * c = video_st->codec;
1025 AVCodecContext * c = &(video_st->codec);
1032 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
1033 /* raw video case. The API will change slightly in the near
1036 av_init_packet(&pkt);
1038 pkt.flags |= PKT_FLAG_KEY;
1039 pkt.stream_index= video_st->index;
1040 pkt.data= (uint8_t *)picture;
1041 pkt.size= sizeof(AVPicture);
1043 ret = av_write_frame(oc, &pkt);
1045 /* encode the image */
1046 out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
1047 /* if zero size, it means the image was buffered */
1050 av_init_packet(&pkt);
1052 #if LIBAVFORMAT_BUILD > 4752
1053 pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base);
1055 pkt.pts = c->coded_frame->pts;
1057 if(c->coded_frame->key_frame)
1058 pkt.flags |= PKT_FLAG_KEY;
1059 pkt.stream_index= video_st->index;
1063 /* write the compressed frame in the media file */
1064 ret = av_write_frame(oc, &pkt);
1070 CV_ERROR(CV_StsError, "Error while writing video frame");
1077 /// write a frame with FFMPEG
1078 CV_IMPL int cvWriteFrame( CvVideoWriter * writer, const IplImage * image )
1082 CV_FUNCNAME("cvWriteFrame");
1086 // typecast from opaque data type to implemented struct
1087 CvAVI_FFMPEG_Writer * mywriter = (CvAVI_FFMPEG_Writer*) writer;
1088 #if LIBAVFORMAT_BUILD > 4628
1089 AVCodecContext *c = mywriter->video_st->codec;
1091 AVCodecContext *c = &(mywriter->video_st->codec);
1094 if( c->codec_id == CODEC_ID_RAWVIDEO && image->origin != IPL_ORIGIN_BL )
1096 if( !mywriter->temp_image )
1097 mywriter->temp_image = cvCreateImage( cvGetSize(image),
1098 image->depth, image->nChannels );
1099 cvFlip( image, mywriter->temp_image, 0 );
1100 image = mywriter->temp_image;
1104 if (mywriter->input_pix_fmt == PIX_FMT_BGR24) {
1105 if (image->nChannels != 3 || image->depth != IPL_DEPTH_8U) {
1106 CV_ERROR(CV_StsUnsupportedFormat, "cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 3.");
1109 else if (mywriter->input_pix_fmt == PIX_FMT_GRAY8) {
1110 if (image->nChannels != 1 || image->depth != IPL_DEPTH_8U) {
1111 CV_ERROR(CV_StsUnsupportedFormat, "cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 1.");
1118 // check if buffer sizes match, i.e. image has expected format (size, channels, bitdepth, alignment)
1119 assert (image->imageSize == avpicture_get_size( mywriter->input_pix_fmt, image->width, image->height ));
1121 if ( c->pix_fmt != mywriter->input_pix_fmt ) {
1122 assert( mywriter->input_picture );
1123 // let input_picture point to the raw data buffer of 'image'
1124 avpicture_fill((AVPicture *)mywriter->input_picture, (uint8_t *) image->imageData,
1125 mywriter->input_pix_fmt, image->width, image->height);
1127 // convert to the color format needed by the codec
1128 if( img_convert((AVPicture *)mywriter->picture, c->pix_fmt,
1129 (AVPicture *)mywriter->input_picture, mywriter->input_pix_fmt,
1130 image->width, image->height) < 0){
1131 CV_ERROR(CV_StsUnsupportedFormat, "FFMPEG::img_convert pixel format conversion from BGR24 not handled");
1135 avpicture_fill((AVPicture *)mywriter->picture, (uint8_t *) image->imageData,
1136 mywriter->input_pix_fmt, image->width, image->height);
1139 ret = icv_av_write_frame_FFMPEG( mywriter->oc, mywriter->video_st, mywriter->outbuf, mywriter->outbuf_size, mywriter->picture);
1145 /// close video output stream and free associated memory
1146 CV_IMPL void cvReleaseVideoWriter( CvVideoWriter ** writer )
1150 // nothing to do if already released
1154 // release data structures in reverse order
1155 CvAVI_FFMPEG_Writer * mywriter = (CvAVI_FFMPEG_Writer*)(*writer);
1157 /* no more frame to compress. The codec has a latency of a few
1158 frames if using B frames, so we get the last frames by
1159 passing the same picture again */
1160 // TODO -- do we need to account for latency here?
1162 /* write the trailer, if any */
1163 av_write_trailer(mywriter->oc);
1166 #if LIBAVFORMAT_BUILD > 4628
1167 if( mywriter->video_st->codec->pix_fmt != mywriter->input_pix_fmt){
1169 if( mywriter->video_st->codec.pix_fmt != mywriter->input_pix_fmt){
1171 cvFree(&(mywriter->picture->data[0]));
1173 av_free(mywriter->picture);
1175 if (mywriter->input_picture) {
1176 av_free(mywriter->input_picture);
1180 #if LIBAVFORMAT_BUILD > 4628
1181 avcodec_close(mywriter->video_st->codec);
1183 avcodec_close(&(mywriter->video_st->codec));
1186 av_free(mywriter->outbuf);
1188 /* free the streams */
1189 for(i = 0; i < mywriter->oc->nb_streams; i++) {
1190 av_freep(&mywriter->oc->streams[i]->codec);
1191 av_freep(&mywriter->oc->streams[i]);
1194 if (!(mywriter->fmt->flags & AVFMT_NOFILE)) {
1195 /* close the output file */
1198 #if LIBAVCODEC_VERSION_INT==((51<<16)+(49<<8)+0)
1199 url_fclose(mywriter->oc->pb);
1201 url_fclose(&mywriter->oc->pb);
1206 /* free the stream */
1207 av_free(mywriter->oc);
1209 cvReleaseImage( &mywriter->temp_image );
1211 /* free cvVideoWriter */