Update to 2.0.0 tree from current Fremantle build
[opencv] / src / highgui / cvcap_ffmpeg.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
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.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
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.
25 //
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.
28 //
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.
39 //
40 //M*/
41
42 #include "_highgui.h"
43
44 #if defined _MSC_VER && _MSC_VER >= 1200
45 #pragma warning( disable: 4244 4510 4512 4610 )
46 #endif
47
48 extern "C" {
49 #if !defined(WIN32) || defined(__MINGW32__)
50 // some versions of FFMPEG assume a C99 compiler, and don't define INT64_C
51 #ifndef INT64_C
52 #define INT64_C
53 #define __STDC_CONSTANT_MACROS
54 // force re-inclusion of stdint.h to get INT64_C macro
55 #undef _STDINT_H
56 #include <stdint.h>
57 #endif
58 #include <errno.h>
59 #endif
60
61 #ifdef WIN32
62   #include <ffmpeg_/avformat.h>
63   #include <ffmpeg_/avcodec.h>
64   #include <ffmpeg_/imgconvert.h>
65 #else
66
67 // if the header path is not specified explicitly, let's deduce it
68 #if !defined HAVE_FFMPEG_AVCODEC_H && !defined HAVE_LIBAVCODEC_AVCODEC_H
69
70 #if defined(HAVE_GENTOO_FFMPEG)
71   #define HAVE_LIBAVCODEC_AVCODEC_H 1
72   #define HAVE_LIBAVFORMAT_AVFORMAT_H 1
73   #if defined(HAVE_FFMPEG_SWSCALE)
74     #define HAVE_LIBSWSCALE_SWSCALE_H 1
75   #endif
76 #elif defined HAVE_FFMPEG
77   #define HAVE_FFMPEG_AVCODEC_H 1
78   #define HAVE_FFMPEG_AVFORMAT_H 1
79   #if defined(HAVE_FFMPEG_SWSCALE)
80     #define HAVE_FFMPEG_SWSCALE_H 1
81   #endif
82 #endif
83
84 #endif
85
86 #if defined(HAVE_FFMPEG_AVCODEC_H)
87   #include <ffmpeg/avcodec.h>
88 #endif
89 #if defined(HAVE_FFMPEG_AVFORMAT_H)
90   #include <ffmpeg/avformat.h>
91 #endif
92 #if defined(HAVE_FFMPEG_SWSCALE_H)
93   #include <ffmpeg/swscale.h>
94 #endif
95
96 #if defined(HAVE_LIBAVFORMAT_AVFORMAT_H)
97   #include <libavformat/avformat.h>
98 #endif
99 #if defined(HAVE_LIBAVCODEC_AVCODEC_H)
100   #include <libavcodec/avcodec.h>
101 #endif
102 #if defined(HAVE_LIBSWSCALE_SWSCALE_H)
103   #include <libswscale/swscale.h>
104 #endif
105
106 #endif
107
108 }
109
110 #if defined _MSC_VER && _MSC_VER >= 1200
111 #pragma warning( default: 4244 4510 4512 4610 )
112 #endif
113
114 #ifdef NDEBUG
115 #define CV_WARN(message)
116 #else
117 #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
118 #endif
119
120
121 #ifndef MKTAG
122 #define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
123 #endif
124
125 /* PIX_FMT_RGBA32 macro changed in newer ffmpeg versions */
126 #ifndef PIX_FMT_RGBA32
127 #define PIX_FMT_RGBA32 PIX_FMT_RGB32
128 #endif
129
130
131
132 char * FOURCC2str( int fourcc )
133 {
134     char * mystr=(char*)malloc(5);
135     mystr[0]=(char)((fourcc    )&255);
136     mystr[1]=(char)((fourcc>> 8)&255);
137     mystr[2]=(char)((fourcc>>16)&255);
138     mystr[3]=(char)((fourcc>>24)&255);
139     mystr[4]=0;
140     return mystr;
141 }
142
143
144 // required to look up the correct codec ID depending on the FOURCC code,
145 // this is just a snipped from the file riff.c from ffmpeg/libavformat
146 typedef struct AVCodecTag {
147     int id;
148     unsigned int tag;
149 } AVCodecTag;
150
151 const AVCodecTag codec_bmp_tags[] = {
152     { CODEC_ID_H264, MKTAG('H', '2', '6', '4') },
153     { CODEC_ID_H264, MKTAG('h', '2', '6', '4') },
154     { CODEC_ID_H264, MKTAG('X', '2', '6', '4') },
155     { CODEC_ID_H264, MKTAG('x', '2', '6', '4') },
156     { CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') },
157     { CODEC_ID_H264, MKTAG('V', 'S', 'S', 'H') },
158
159     { CODEC_ID_H263, MKTAG('H', '2', '6', '3') },
160     { CODEC_ID_H263P, MKTAG('H', '2', '6', '3') },
161     { CODEC_ID_H263I, MKTAG('I', '2', '6', '3') }, /* intel h263 */
162     { CODEC_ID_H261, MKTAG('H', '2', '6', '1') },
163
164     /* added based on MPlayer */
165     { CODEC_ID_H263P, MKTAG('U', '2', '6', '3') },
166     { CODEC_ID_H263P, MKTAG('v', 'i', 'v', '1') },
167
168     { CODEC_ID_MPEG4, MKTAG('F', 'M', 'P', '4') },
169     { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') },
170     { CODEC_ID_MPEG4, MKTAG('D', 'X', '5', '0') },
171     { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
172     { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') },
173     { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') },
174     { CODEC_ID_MPEG4, MKTAG(0x04, 0, 0, 0) }, /* some broken avi use this */
175
176     /* added based on MPlayer */
177     { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', '1') },
178     { CODEC_ID_MPEG4, MKTAG('B', 'L', 'Z', '0') },
179     { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
180     { CODEC_ID_MPEG4, MKTAG('U', 'M', 'P', '4') },
181     { CODEC_ID_MPEG4, MKTAG('W', 'V', '1', 'F') },
182     { CODEC_ID_MPEG4, MKTAG('S', 'E', 'D', 'G') },
183
184     { CODEC_ID_MPEG4, MKTAG('R', 'M', 'P', '4') },
185
186     { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '3') }, /* default signature when using MSMPEG4 */
187     { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') },
188
189     /* added based on MPlayer */
190     { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', 'G', '3') },
191     { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '5') },
192     { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '6') },
193     { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '4') },
194     { CODEC_ID_MSMPEG4V3, MKTAG('A', 'P', '4', '1') },
195     { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '1') },
196     { CODEC_ID_MSMPEG4V3, MKTAG('C', 'O', 'L', '0') },
197
198     { CODEC_ID_MSMPEG4V2, MKTAG('M', 'P', '4', '2') },
199
200     /* added based on MPlayer */
201     { CODEC_ID_MSMPEG4V2, MKTAG('D', 'I', 'V', '2') },
202
203     { CODEC_ID_MSMPEG4V1, MKTAG('M', 'P', 'G', '4') },
204
205     { CODEC_ID_WMV1, MKTAG('W', 'M', 'V', '1') },
206
207     /* added based on MPlayer */
208     { CODEC_ID_WMV2, MKTAG('W', 'M', 'V', '2') },
209     { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'd') },
210     { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'd') },
211     { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'l') },
212     { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '2', '5') },
213     { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '1') },
214     { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') },
215     { CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', 'g', '2') },
216     { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'P', 'E', 'G') },
217     { CODEC_ID_MPEG1VIDEO, MKTAG('P', 'I', 'M', '1') },
218     { CODEC_ID_MPEG1VIDEO, MKTAG('V', 'C', 'R', '2') },
219     { CODEC_ID_MPEG1VIDEO, 0x10000001 },
220     { CODEC_ID_MPEG2VIDEO, 0x10000002 },
221     { CODEC_ID_MPEG2VIDEO, MKTAG('D', 'V', 'R', ' ') },
222     { CODEC_ID_MPEG2VIDEO, MKTAG('M', 'M', 'E', 'S') },
223     { CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') },
224     { CODEC_ID_MJPEG, MKTAG('L', 'J', 'P', 'G') },
225     { CODEC_ID_LJPEG, MKTAG('L', 'J', 'P', 'G') },
226     { CODEC_ID_MJPEG, MKTAG('J', 'P', 'G', 'L') }, /* Pegasus lossless JPEG */
227     { CODEC_ID_MJPEG, MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - decoder */
228     { CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') },
229     { CODEC_ID_MJPEG, MKTAG('I', 'J', 'P', 'G') },
230     { CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') },
231     { CODEC_ID_HUFFYUV, MKTAG('H', 'F', 'Y', 'U') },
232     { CODEC_ID_FFVHUFF, MKTAG('F', 'F', 'V', 'H') },
233     { CODEC_ID_CYUV, MKTAG('C', 'Y', 'U', 'V') },
234     { CODEC_ID_RAWVIDEO, 0 },
235     { CODEC_ID_RAWVIDEO, MKTAG('I', '4', '2', '0') },
236     { CODEC_ID_RAWVIDEO, MKTAG('Y', 'U', 'Y', '2') },
237     { CODEC_ID_RAWVIDEO, MKTAG('Y', '4', '2', '2') },
238     { CODEC_ID_RAWVIDEO, MKTAG('Y', 'V', '1', '2') },
239     { CODEC_ID_RAWVIDEO, MKTAG('U', 'Y', 'V', 'Y') },
240     { CODEC_ID_RAWVIDEO, MKTAG('I', 'Y', 'U', 'V') },
241     { CODEC_ID_RAWVIDEO, MKTAG('Y', '8', '0', '0') },
242     { CODEC_ID_RAWVIDEO, MKTAG('H', 'D', 'Y', 'C') },
243     { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '1') },
244     { CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '2') },
245     { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
246     { CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
247     { CODEC_ID_ASV1, MKTAG('A', 'S', 'V', '1') },
248     { CODEC_ID_ASV2, MKTAG('A', 'S', 'V', '2') },
249     { CODEC_ID_VCR1, MKTAG('V', 'C', 'R', '1') },
250     { CODEC_ID_FFV1, MKTAG('F', 'F', 'V', '1') },
251     { CODEC_ID_XAN_WC4, MKTAG('X', 'x', 'a', 'n') },
252     { CODEC_ID_MSRLE, MKTAG('m', 'r', 'l', 'e') },
253     { CODEC_ID_MSRLE, MKTAG(0x1, 0x0, 0x0, 0x0) },
254     { CODEC_ID_MSVIDEO1, MKTAG('M', 'S', 'V', 'C') },
255     { CODEC_ID_MSVIDEO1, MKTAG('m', 's', 'v', 'c') },
256     { CODEC_ID_MSVIDEO1, MKTAG('C', 'R', 'A', 'M') },
257     { CODEC_ID_MSVIDEO1, MKTAG('c', 'r', 'a', 'm') },
258     { CODEC_ID_MSVIDEO1, MKTAG('W', 'H', 'A', 'M') },
259     { CODEC_ID_MSVIDEO1, MKTAG('w', 'h', 'a', 'm') },
260     { CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') },
261     { CODEC_ID_TRUEMOTION1, MKTAG('D', 'U', 'C', 'K') },
262     { CODEC_ID_MSZH, MKTAG('M', 'S', 'Z', 'H') },
263     { CODEC_ID_ZLIB, MKTAG('Z', 'L', 'I', 'B') },
264     { CODEC_ID_SNOW, MKTAG('S', 'N', 'O', 'W') },
265     { CODEC_ID_4XM, MKTAG('4', 'X', 'M', 'V') },
266     { CODEC_ID_FLV1, MKTAG('F', 'L', 'V', '1') },
267     { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') },
268     { CODEC_ID_TSCC, MKTAG('t', 's', 'c', 'c') },
269     { CODEC_ID_ULTI, MKTAG('U', 'L', 'T', 'I') },
270     { CODEC_ID_VIXL, MKTAG('V', 'I', 'X', 'L') },
271     { CODEC_ID_QPEG, MKTAG('Q', 'P', 'E', 'G') },
272     { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '0') },
273     { CODEC_ID_QPEG, MKTAG('Q', '1', '.', '1') },
274     { CODEC_ID_WMV3, MKTAG('W', 'M', 'V', '3') },
275     { CODEC_ID_LOCO, MKTAG('L', 'O', 'C', 'O') },
276     { CODEC_ID_THEORA, MKTAG('t', 'h', 'e', 'o') },
277 #if LIBAVCODEC_VERSION_INT>0x000409
278     { CODEC_ID_WNV1, MKTAG('W', 'N', 'V', '1') },
279     { CODEC_ID_AASC, MKTAG('A', 'A', 'S', 'C') },
280     { CODEC_ID_INDEO2, MKTAG('R', 'T', '2', '1') },
281     { CODEC_ID_FRAPS, MKTAG('F', 'P', 'S', '1') },
282     { CODEC_ID_TRUEMOTION2, MKTAG('T', 'M', '2', '0') },
283 #endif
284 #if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
285     { CODEC_ID_FLASHSV, MKTAG('F', 'S', 'V', '1') },
286     { CODEC_ID_JPEGLS,MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - encoder */
287     { CODEC_ID_VC1, MKTAG('W', 'V', 'C', '1') },
288     { CODEC_ID_VC1, MKTAG('W', 'M', 'V', 'A') },
289     { CODEC_ID_CSCD, MKTAG('C', 'S', 'C', 'D') },
290     { CODEC_ID_ZMBV, MKTAG('Z', 'M', 'B', 'V') },
291     { CODEC_ID_KMVC, MKTAG('K', 'M', 'V', 'C') },
292 #endif
293 #if LIBAVCODEC_VERSION_INT>((51<<16)+(11<<8)+0)
294     { CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
295     { CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') },
296     { CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') },
297     { CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
298     { CODEC_ID_VP6F, MKTAG('V', 'P', '6', 'F') },
299     { CODEC_ID_JPEG2000, MKTAG('M', 'J', '2', 'C') },
300     { CODEC_ID_VMNC, MKTAG('V', 'M', 'n', 'c') },
301 #endif
302 #if LIBAVCODEC_VERSION_INT>=((51<<16)+(49<<8)+0)
303 // this tag seems not to exist in older versions of FFMPEG
304     { CODEC_ID_TARGA, MKTAG('t', 'g', 'a', ' ') },
305 #endif
306     { CODEC_ID_NONE, 0 },
307 };
308
309
310 class CvCapture_FFMPEG : public CvCapture
311 {
312 public:
313     CvCapture_FFMPEG() { init(); }
314     virtual ~CvCapture_FFMPEG() { close(); }
315
316     virtual bool open( const char* filename );
317     virtual void close();
318
319     virtual double getProperty(int);
320     virtual bool setProperty(int, double);
321     virtual bool grabFrame();
322     virtual IplImage* retrieveFrame(int);
323
324 protected:
325     void init();
326     bool reopen();
327     bool slowSeek( int framenumber );
328
329     AVFormatContext   * ic;
330     int                 video_stream;
331     AVStream          * video_st;
332     AVFrame           * picture;
333     int64_t             picture_pts;
334     AVFrame             rgb_picture;
335     AVPacket            packet;
336     IplImage            frame;
337 #if defined(HAVE_FFMPEG_SWSCALE)
338     struct SwsContext *img_convert_ctx;
339 #endif
340 /*
341    'filename' contains the filename of the videosource,
342    'filename==NULL' indicates that ffmpeg's seek support works
343    for the particular file.
344    'filename!=NULL' indicates that the slow fallback function is used for seeking,
345    and so the filename is needed to reopen the file on backward seeking.
346 */
347     char              * filename;
348 };
349
350
351 void CvCapture_FFMPEG::init()
352 {
353     ic = 0;
354     video_stream = -1;
355     video_st = 0;
356     picture = 0;
357     picture_pts = 0;
358     memset( &rgb_picture, 0, sizeof(rgb_picture) );
359     memset( &frame, 0, sizeof(frame) );
360     filename = 0;
361     packet.data = NULL;
362 #if defined(HAVE_FFMPEG_SWSCALE)
363     img_convert_ctx = 0;
364 #endif    
365 }
366
367
368 void CvCapture_FFMPEG::close()
369 {
370     if( picture )
371     av_free(picture);
372
373     if( video_st )
374     {
375 #if LIBAVFORMAT_BUILD > 4628
376         avcodec_close( video_st->codec );
377 #else
378         avcodec_close( &video_st->codec );
379 #endif
380         video_st = NULL;
381     }
382
383     if( ic )
384     {
385         av_close_input_file(ic);
386         ic = NULL;
387     }
388
389     if( rgb_picture.data[0] )
390         cvFree( &rgb_picture.data[0] );
391
392     // free last packet if exist
393     if (packet.data) {
394         av_free_packet (&packet);
395     }
396
397
398     init();
399 }
400
401
402 /*
403     Used to reopen a video if the slower fallback function for seeking is used.
404 */
405 bool CvCapture_FFMPEG::reopen()
406 {
407     if ( filename==NULL ) return false;
408
409 #if LIBAVFORMAT_BUILD > 4628
410     avcodec_close( video_st->codec );
411 #else
412     avcodec_close( &video_st->codec );
413 #endif
414     av_close_input_file(ic);
415
416     // reopen video
417     av_open_input_file(&ic, filename, NULL, 0, NULL);
418     av_find_stream_info(ic);
419 #if LIBAVFORMAT_BUILD > 4628
420     AVCodecContext *enc = ic->streams[video_stream]->codec;
421 #else
422     AVCodecContext *enc = &ic->streams[video_stream]->codec;
423 #endif
424     AVCodec *codec = avcodec_find_decoder(enc->codec_id);
425     avcodec_open(enc, codec);
426     video_st = ic->streams[video_stream];
427
428     // reset framenumber to zero
429     picture_pts=0;
430
431     return true;
432 }
433
434
435
436 bool CvCapture_FFMPEG::open( const char* _filename )
437 {
438     unsigned i;
439     bool valid = false;
440
441     close();
442
443     /* register all codecs, demux and protocols */
444     av_register_all();
445
446 #ifndef _DEBUG
447     // av_log_level = AV_LOG_QUIET;
448 #endif
449
450     int err = av_open_input_file(&ic, _filename, NULL, 0, NULL);
451     if (err < 0) {
452             CV_WARN("Error opening file");
453             goto exit_func;
454     }
455     err = av_find_stream_info(ic);
456     if (err < 0) {
457             CV_WARN("Could not find codec parameters");
458             goto exit_func;
459     }
460     for(i = 0; i < ic->nb_streams; i++) {
461 #if LIBAVFORMAT_BUILD > 4628
462         AVCodecContext *enc = ic->streams[i]->codec;
463 #else
464         AVCodecContext *enc = &ic->streams[i]->codec;
465 #endif
466
467         if( CODEC_TYPE_VIDEO == enc->codec_type && video_stream < 0) {
468             AVCodec *codec = avcodec_find_decoder(enc->codec_id);
469             if (!codec ||
470             avcodec_open(enc, codec) < 0)
471             goto exit_func;
472             video_stream = i;
473             video_st = ic->streams[i];
474             picture = avcodec_alloc_frame();
475
476             rgb_picture.data[0] = (uint8_t*)cvAlloc(
477                                     avpicture_get_size( PIX_FMT_BGR24,
478                                     enc->width, enc->height ));
479             avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0],
480                     PIX_FMT_BGR24, enc->width, enc->height );
481
482             cvInitImageHeader( &frame, cvSize( enc->width,
483                                        enc->height ), 8, 3, 0, 4 );
484             cvSetData( &frame, rgb_picture.data[0],
485                                rgb_picture.linesize[0] );
486             break;
487         }
488     }
489
490     if(video_stream >= 0) valid = true;
491
492     // perform check if source is seekable via ffmpeg's seek function av_seek_frame(...)
493     err = av_seek_frame(ic, video_stream, 10, 0);
494     if (err < 0)
495     {
496         filename=(char*)malloc(strlen(_filename)+1);
497         strcpy(filename, _filename);
498         // reopen videofile to 'seek' back to first frame
499         reopen();
500     }
501     else
502     {
503         // seek seems to work, so we don't need the filename,
504         // but we still need to seek back to filestart
505         filename=NULL;
506         av_seek_frame(ic, video_stream, 0, 0);
507     }
508 exit_func:
509
510     if( !valid )
511         close();
512
513     return valid;
514 }
515
516
517 bool CvCapture_FFMPEG::grabFrame()
518 {
519     bool valid = false;
520     static bool bFirstTime = true;
521     int got_picture;
522
523     // First time we're called, set packet.data to NULL to indicate it
524     // doesn't have to be freed
525     if (bFirstTime) {
526         bFirstTime = false;
527         packet.data = NULL;
528     }
529
530     if( !ic || !video_st )
531         return false;
532
533     // free last packet if exist
534     if (packet.data != NULL) {
535         av_free_packet (&packet);
536     }
537
538     // get the next frame
539     while (!valid && (av_read_frame(ic, &packet) >= 0)) {
540                 if( packet.stream_index != video_stream ) {
541                         av_free_packet (&packet);
542                         continue;
543                 }
544
545 #if LIBAVFORMAT_BUILD > 4628
546         avcodec_decode_video(video_st->codec,
547                              picture, &got_picture,
548                              packet.data, packet.size);
549 #else
550         avcodec_decode_video(&video_st->codec,
551                              picture, &got_picture,
552                              packet.data, packet.size);
553 #endif
554
555         if (got_picture) {
556             // we have a new picture, so memorize it
557             picture_pts = packet.pts;
558             valid = 1;
559         }
560     }
561
562     // return if we have a new picture or not
563     return valid;
564 }
565
566
567 IplImage* CvCapture_FFMPEG::retrieveFrame(int)
568 {
569     if( !video_st || !picture->data[0] )
570         return 0;
571
572 #if !defined(HAVE_FFMPEG_SWSCALE)
573 #if LIBAVFORMAT_BUILD > 4628
574     img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24,
575                  (AVPicture*)picture,
576                  video_st->codec->pix_fmt,
577                  video_st->codec->width,
578                  video_st->codec->height );
579 #else
580     img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24,
581                  (AVPicture*)picture,
582                  video_st->codec.pix_fmt,
583                  video_st->codec.width,
584                  video_st->codec.height );
585 #endif
586 #else
587     img_convert_ctx = sws_getContext(video_st->codec->width,
588                   video_st->codec->height,
589                   video_st->codec->pix_fmt,
590                   video_st->codec->width,
591                   video_st->codec->height,
592                   PIX_FMT_BGR24,
593                   SWS_BICUBIC,
594                   NULL, NULL, NULL);
595
596          sws_scale(img_convert_ctx, picture->data,
597              picture->linesize, 0,
598              video_st->codec->height,
599              rgb_picture.data, rgb_picture.linesize);
600     sws_freeContext(img_convert_ctx);
601 #endif
602     return &frame;
603 }
604
605 #if defined(__APPLE__)
606 #define AV_NOPTS_VALUE_ ((int64_t)0x8000000000000000LL)
607 #else
608 #define AV_NOPTS_VALUE_ ((int64_t)AV_NOPTS_VALUE)
609 #endif
610
611 double CvCapture_FFMPEG::getProperty( int property_id )
612 {
613     // if( !capture || !video_st || !picture->data[0] ) return 0;
614     if( !video_st ) return 0;
615
616
617     int64_t timestamp;
618     timestamp = picture_pts;
619
620     switch( property_id )
621     {
622     case CV_CAP_PROP_POS_MSEC:
623         if(video_st->cur_dts != AV_NOPTS_VALUE_)
624             return (((double)video_st->cur_dts-1) *1000) / av_q2d (video_st->r_frame_rate);
625         break;
626     case CV_CAP_PROP_POS_FRAMES:
627         if(video_st->cur_dts != AV_NOPTS_VALUE_)
628             return (double)video_st->cur_dts-1;
629         break;
630     case CV_CAP_PROP_POS_AVI_RATIO:
631         if(video_st->cur_dts != AV_NOPTS_VALUE_ && video_st->duration != AV_NOPTS_VALUE_)
632             return (double)(video_st->cur_dts-1)/(double)video_st->duration;
633         break;
634         case CV_CAP_PROP_FRAME_COUNT:
635             if(video_st->duration != AV_NOPTS_VALUE_)
636                     return (double)video_st->duration;
637             break;
638     case CV_CAP_PROP_FRAME_WIDTH:
639         return (double)frame.width;
640     case CV_CAP_PROP_FRAME_HEIGHT:
641         return (double)frame.height;
642     case CV_CAP_PROP_FPS:
643 #if LIBAVCODEC_BUILD > 4753
644         return av_q2d (video_st->r_frame_rate);
645 #else
646         return (double)video_st->codec.frame_rate
647             / (double)video_st->codec.frame_rate_base;
648 #endif
649     case CV_CAP_PROP_FOURCC:
650 #if LIBAVFORMAT_BUILD > 4628
651         return (double)video_st->codec->codec_tag;
652 #else
653         return (double)video_st->codec.codec_tag;
654 #endif
655     }
656     return 0;
657 }
658
659
660
661 // this is a VERY slow fallback function, ONLY used if ffmpeg's av_seek_frame delivers no correct result!
662 bool CvCapture_FFMPEG::slowSeek( int framenumber )
663 {
664     if ( framenumber>picture_pts )
665     {
666         while ( picture_pts<framenumber )
667             if ( !grabFrame() ) return false;
668     }
669     else if ( framenumber<picture_pts )
670     {
671         reopen();
672         while ( picture_pts<framenumber )
673             if ( !grabFrame() ) return false;
674     }
675     return true;
676 }
677
678
679 bool CvCapture_FFMPEG::setProperty( int property_id, double value )
680 {
681     if( !video_st ) return false;
682
683     switch( property_id )
684     {
685     case CV_CAP_PROP_POS_MSEC:
686     case CV_CAP_PROP_POS_FRAMES:
687     case CV_CAP_PROP_POS_AVI_RATIO:
688         {
689             int64_t timestamp = 0;
690             AVRational time_base;
691             switch( property_id )
692             {
693             case CV_CAP_PROP_POS_FRAMES:
694                 timestamp=(int64_t)value;
695                 if(ic->start_time != AV_NOPTS_VALUE_)
696                     timestamp += ic->start_time;
697                 break;
698
699             case CV_CAP_PROP_POS_MSEC:
700                 time_base=ic->streams[video_stream]->time_base;
701                 timestamp=(int64_t)(value*(float(time_base.den)/float(time_base.num))/1000);
702                 if(ic->start_time != AV_NOPTS_VALUE_)
703                     timestamp += ic->start_time;
704                 break;
705
706             case CV_CAP_PROP_POS_AVI_RATIO:
707                 timestamp=(int64_t)(value*ic->duration);
708                 if(ic->start_time != AV_NOPTS_VALUE_ && ic->duration != AV_NOPTS_VALUE_)
709                     timestamp += ic->start_time;
710                 break;
711             }
712
713             if ( filename )
714             {
715                 // ffmpeg's seek doesn't work...
716                 if (!slowSeek((int)timestamp))
717                 {
718                     fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n",
719                         (double)timestamp / AV_TIME_BASE);
720                     return false;
721                 }
722             }
723             else
724             {
725                 int ret = av_seek_frame(ic, video_stream, timestamp, 0);
726                 if (ret < 0)
727                 {
728                     fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n",
729                             (double)timestamp / AV_TIME_BASE);
730                     return false;
731                 }
732             }
733             picture_pts=(int64_t)value;
734         }
735         break;
736
737     default:
738         return false;
739     }
740
741     return true;
742 }
743
744
745
746 CvCapture* cvCreateFileCapture_FFMPEG( const char* filename )
747 {
748     CvCapture_FFMPEG* capture = new CvCapture_FFMPEG;
749     if( capture->open( filename ))
750         return capture;
751     delete capture;
752     return 0;
753 }
754
755
756 ///////////////// FFMPEG CvVideoWriter implementation //////////////////////////
757 class CvVideoWriter_FFMPEG : public CvVideoWriter
758 {
759 public:
760     CvVideoWriter_FFMPEG() { init(); }
761     virtual ~CvVideoWriter_FFMPEG() { close(); }
762
763     virtual bool open( const char* filename, int fourcc,
764         double fps, CvSize frameSize, bool isColor );
765     virtual void close();
766     virtual bool writeFrame( const IplImage* image );
767
768 protected:
769     void init();
770
771     AVOutputFormat *fmt;
772     AVFormatContext *oc;
773     uint8_t         * outbuf;
774     uint32_t          outbuf_size;
775     FILE            * outfile;
776     AVFrame         * picture;
777     AVFrame         * input_picture;
778     uint8_t         * picbuf;
779     AVStream        * video_st;
780     int               input_pix_fmt;
781     IplImage        * temp_image;
782 #if defined(HAVE_FFMPEG_SWSCALE)
783     struct SwsContext *img_convert_ctx;
784 #endif
785 };
786
787 static const char * icvFFMPEGErrStr(int err)
788 {
789     switch(err) {
790     case AVERROR_NUMEXPECTED:
791                 return "Incorrect filename syntax";
792     case AVERROR_INVALIDDATA:
793                 return "Invalid data in header";
794     case AVERROR_NOFMT:
795                 return "Unknown format";
796     case AVERROR_IO:
797                 return "I/O error occurred";
798     case AVERROR_NOMEM:
799                 return "Memory allocation error";
800     default:
801                 break;
802     }
803         return "Unspecified error";
804 }
805
806 /* function internal to FFMPEG (libavformat/riff.c) to lookup codec id by fourcc tag*/
807 extern "C" {
808         enum CodecID codec_get_bmp_id(unsigned int tag);
809 }
810
811 void CvVideoWriter_FFMPEG::init()
812 {
813     fmt = 0;
814     oc = 0;
815     outbuf = 0;
816     outbuf_size = 0;
817     outfile = 0;
818     picture = 0;
819     input_picture = 0;
820     picbuf = 0;
821     video_st = 0;
822     input_pix_fmt = 0;
823     temp_image = 0;
824 #if defined(HAVE_FFMPEG_SWSCALE)
825     img_convert_ctx = 0;
826 #endif    
827 }
828
829 /**
830  * the following function is a modified version of code
831  * found in ffmpeg-0.4.9-pre1/output_example.c
832  */
833 static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bool alloc)
834 {
835         AVFrame * picture;
836         uint8_t * picture_buf;
837         int size;
838
839         picture = avcodec_alloc_frame();
840         if (!picture)
841                 return NULL;
842         size = avpicture_get_size( (PixelFormat) pix_fmt, width, height);
843         if(alloc){
844                 picture_buf = (uint8_t *) cvAlloc(size);
845                 if (!picture_buf)
846                 {
847                         av_free(picture);
848                         return NULL;
849                 }
850                 avpicture_fill((AVPicture *)picture, picture_buf,
851                                 (PixelFormat) pix_fmt, width, height);
852         }
853         else {
854         }
855         return picture;
856 }
857
858 /* add a video output stream to the container */
859 static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
860                                                      CodecID codec_id,
861                                                                                          int w, int h, int bitrate,
862                                                                                          double fps, int pixel_format)
863 {
864         AVCodecContext *c;
865         AVStream *st;
866         int frame_rate, frame_rate_base;
867         AVCodec *codec;
868
869
870         st = av_new_stream(oc, 0);
871         if (!st) {
872                 CV_WARN("Could not allocate stream");
873                 return NULL;
874         }
875
876 #if LIBAVFORMAT_BUILD > 4628
877         c = st->codec;
878 #else
879         c = &(st->codec);
880 #endif
881
882 #if LIBAVFORMAT_BUILD > 4621
883         c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_VIDEO);
884 #else
885         c->codec_id = oc->oformat->video_codec;
886 #endif
887
888         if(codec_id != CODEC_ID_NONE){
889                 c->codec_id = codec_id;
890         }
891
892     //if(codec_tag) c->codec_tag=codec_tag;
893         codec = avcodec_find_encoder(c->codec_id);
894
895         c->codec_type = CODEC_TYPE_VIDEO;
896
897         /* put sample parameters */
898         c->bit_rate = bitrate;
899
900         /* resolution must be a multiple of two */
901         c->width = w;
902         c->height = h;
903
904         /* time base: this is the fundamental unit of time (in seconds) in terms
905        of which frame timestamps are represented. for fixed-fps content,
906        timebase should be 1/framerate and timestamp increments should be
907        identically 1. */
908         frame_rate=cvRound(fps);
909         frame_rate_base=1;
910         while (fabs((double)frame_rate/frame_rate_base) - fps > 0.001){
911                 frame_rate_base*=10;
912                 frame_rate=cvRound(fps*frame_rate_base);
913         }
914 #if LIBAVFORMAT_BUILD > 4752
915     c->time_base.den = frame_rate;
916     c->time_base.num = frame_rate_base;
917         /* adjust time base for supported framerates */
918         if(codec && codec->supported_framerates){
919                 const AVRational *p= codec->supported_framerates;
920         AVRational req = {frame_rate, frame_rate_base};
921                 const AVRational *best=NULL;
922                 AVRational best_error= {INT_MAX, 1};
923                 for(; p->den!=0; p++){
924                         AVRational error= av_sub_q(req, *p);
925                         if(error.num <0) error.num *= -1;
926                         if(av_cmp_q(error, best_error) < 0){
927                                 best_error= error;
928                                 best= p;
929                         }
930                 }
931                 c->time_base.den= best->num;
932                 c->time_base.num= best->den;
933         }
934 #else
935         c->frame_rate = frame_rate;
936         c->frame_rate_base = frame_rate_base;
937 #endif
938
939         c->gop_size = 12; /* emit one intra frame every twelve frames at most */
940         c->pix_fmt = (PixelFormat) pixel_format;
941
942         if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
943         c->max_b_frames = 2;
944     }
945     if (c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MSMPEG4V3){
946         /* needed to avoid using macroblocks in which some coeffs overflow
947            this doesnt happen with normal video, it just happens here as the
948            motion of the chroma plane doesnt match the luma plane */
949                 /* avoid FFMPEG warning 'clipping 1 dct coefficients...' */
950         c->mb_decision=2;
951     }
952 #if LIBAVCODEC_VERSION_INT>0x000409
953     // some formats want stream headers to be seperate
954     if(oc->oformat->flags & AVFMT_GLOBALHEADER)
955     {
956         c->flags |= CODEC_FLAG_GLOBAL_HEADER;
957     }
958 #endif
959
960     return st;
961 }
962
963 int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_t * outbuf, uint32_t outbuf_size, AVFrame * picture ){
964         CV_FUNCNAME("icv_av_write_frame_FFMPEG");
965
966 #if LIBAVFORMAT_BUILD > 4628
967         AVCodecContext * c = video_st->codec;
968 #else
969         AVCodecContext * c = &(video_st->codec);
970 #endif
971         int out_size;
972         int ret;
973
974         __BEGIN__;
975
976     if (oc->oformat->flags & AVFMT_RAWPICTURE) {
977         /* raw video case. The API will change slightly in the near
978            futur for that */
979         AVPacket pkt;
980         av_init_packet(&pkt);
981
982         pkt.flags |= PKT_FLAG_KEY;
983         pkt.stream_index= video_st->index;
984         pkt.data= (uint8_t *)picture;
985         pkt.size= sizeof(AVPicture);
986
987         ret = av_write_frame(oc, &pkt);
988     } else {
989         /* encode the image */
990         out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
991         /* if zero size, it means the image was buffered */
992         if (out_size > 0) {
993             AVPacket pkt;
994             av_init_packet(&pkt);
995
996 #if LIBAVFORMAT_BUILD > 4752
997             pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base);
998 #else
999                         pkt.pts = c->coded_frame->pts;
1000 #endif
1001             if(c->coded_frame->key_frame)
1002                 pkt.flags |= PKT_FLAG_KEY;
1003             pkt.stream_index= video_st->index;
1004             pkt.data= outbuf;
1005             pkt.size= out_size;
1006
1007             /* write the compressed frame in the media file */
1008             ret = av_write_frame(oc, &pkt);
1009         } else {
1010             ret = 0;
1011         }
1012     }
1013     if (ret != 0) {
1014                 CV_ERROR(CV_StsError, "Error while writing video frame");
1015         }
1016
1017         __END__;
1018         return CV_StsOk;
1019 }
1020
1021 /// write a frame with FFMPEG
1022 bool CvVideoWriter_FFMPEG::writeFrame( const IplImage * image )
1023 {
1024         bool ret = false;
1025
1026     CV_FUNCNAME("CvVideoWriter_FFMPEG::writerFrame");
1027
1028         __BEGIN__;
1029
1030         // typecast from opaque data type to implemented struct
1031 #if LIBAVFORMAT_BUILD > 4628
1032     AVCodecContext *c = video_st->codec;
1033 #else
1034         AVCodecContext *c = &(video_st->codec);
1035 #endif
1036
1037 #if LIBAVFORMAT_BUILD < 5231
1038     // It is not needed in the latest versions of the ffmpeg
1039     if( c->codec_id == CODEC_ID_RAWVIDEO && image->origin != IPL_ORIGIN_BL )
1040     {
1041         if( !temp_image )
1042             temp_image = cvCreateImage( cvGetSize(image),
1043                                     image->depth, image->nChannels );
1044         cvFlip( image, temp_image, 0 );
1045         image = temp_image;
1046     }
1047 #endif
1048
1049     // check parameters
1050     if (input_pix_fmt == PIX_FMT_BGR24) {
1051         if (image->nChannels != 3 || image->depth != IPL_DEPTH_8U) {
1052             CV_ERROR(CV_StsUnsupportedFormat, "cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 3.");
1053         }
1054     }
1055         else if (input_pix_fmt == PIX_FMT_GRAY8) {
1056         if (image->nChannels != 1 || image->depth != IPL_DEPTH_8U) {
1057             CV_ERROR(CV_StsUnsupportedFormat, "cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 1.");
1058         }
1059     }
1060         else {
1061         assert(false);
1062     }
1063
1064         // check if buffer sizes match, i.e. image has expected format (size, channels, bitdepth, alignment)
1065         assert (image->imageSize == avpicture_get_size( input_pix_fmt, image->width, image->height ));
1066
1067         if ( c->pix_fmt != input_pix_fmt ) {
1068                 assert( input_picture );
1069                 // let input_picture point to the raw data buffer of 'image'
1070                 avpicture_fill((AVPicture *)input_picture, (uint8_t *) image->imageData,
1071                                 (PixelFormat)input_pix_fmt, image->width, image->height);
1072
1073 #if !defined(HAVE_FFMPEG_SWSCALE)
1074                 // convert to the color format needed by the codec
1075                 if( img_convert((AVPicture *)picture, c->pix_fmt,
1076                                         (AVPicture *)input_picture, (PixelFormat)input_pix_fmt,
1077                                         image->width, image->height) < 0){
1078                         CV_ERROR(CV_StsUnsupportedFormat, "FFMPEG::img_convert pixel format conversion from BGR24 not handled");
1079                 }
1080 #else
1081                 img_convert_ctx = sws_getContext(image->width,
1082                              image->height,
1083                              PIX_FMT_BGR24,
1084                              c->width,
1085                              c->height,
1086                              c->pix_fmt,
1087                              SWS_BICUBIC,
1088                              NULL, NULL, NULL);
1089
1090                     if ( sws_scale(img_convert_ctx, input_picture->data,
1091                              input_picture->linesize, 0,
1092                              image->height,
1093                              picture->data, picture->linesize) < 0 )
1094                     {
1095                       CV_ERROR(CV_StsUnsupportedFormat, "FFMPEG::img_convert pixel format conversion from BGR24 not handled");
1096                     }
1097                 sws_freeContext(img_convert_ctx);
1098 #endif
1099         }
1100         else{
1101                 avpicture_fill((AVPicture *)picture, (uint8_t *) image->imageData,
1102                                 (PixelFormat)input_pix_fmt, image->width, image->height);
1103         }
1104
1105         ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0;
1106
1107         __END__;
1108         return ret;
1109 }
1110
1111 /// close video output stream and free associated memory
1112 void CvVideoWriter_FFMPEG::close()
1113 {
1114         unsigned i;
1115
1116         // nothing to do if already released
1117         if ( !picture )
1118                 return;
1119
1120         /* no more frame to compress. The codec has a latency of a few
1121            frames if using B frames, so we get the last frames by
1122            passing the same picture again */
1123         // TODO -- do we need to account for latency here?
1124
1125         /* write the trailer, if any */
1126         av_write_trailer(oc);
1127
1128         // free pictures
1129 #if LIBAVFORMAT_BUILD > 4628
1130         if( video_st->codec->pix_fmt != input_pix_fmt){
1131 #else
1132         if( video_st->codec.pix_fmt != input_pix_fmt){
1133 #endif
1134                 cvFree(&(picture->data[0]));
1135         }
1136         av_free(picture);
1137
1138     if (input_picture) {
1139         av_free(input_picture);
1140     }
1141
1142         /* close codec */
1143 #if LIBAVFORMAT_BUILD > 4628
1144         avcodec_close(video_st->codec);
1145 #else
1146         avcodec_close(&(video_st->codec));
1147 #endif
1148
1149         av_free(outbuf);
1150
1151         /* free the streams */
1152         for(i = 0; i < oc->nb_streams; i++) {
1153                 av_freep(&oc->streams[i]->codec);
1154                 av_freep(&oc->streams[i]);
1155         }
1156
1157         if (!(fmt->flags & AVFMT_NOFILE)) {
1158                 /* close the output file */
1159
1160
1161 #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)
1162                 url_fclose(oc->pb);
1163 #else
1164                 url_fclose(&oc->pb);
1165 #endif
1166
1167         }
1168
1169         /* free the stream */
1170         av_free(oc);
1171
1172     cvReleaseImage( &temp_image );
1173
1174         init();
1175 }
1176
1177 /// Create a video writer object that uses FFMPEG
1178 bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
1179                 double fps, CvSize frameSize, bool is_color )
1180 {
1181     CV_FUNCNAME("CvVideoWriter_FFMPEG::open");
1182
1183         CodecID codec_id = CODEC_ID_NONE;
1184         int err, codec_pix_fmt, bitrate_scale=64;
1185
1186         __BEGIN__;
1187
1188     close();
1189
1190         // check arguments
1191         assert (filename);
1192         assert (fps > 0);
1193         assert (frameSize.width > 0  &&  frameSize.height > 0);
1194
1195         // tell FFMPEG to register codecs
1196         av_register_all ();
1197
1198         /* auto detect the output format from the name and fourcc code. */
1199         fmt = guess_format(NULL, filename, NULL);
1200         if (!fmt) {
1201                 CV_ERROR( CV_StsUnsupportedFormat, "FFMPEG does not recognize the given file extension");
1202         }
1203
1204         /* determine optimal pixel format */
1205     if (is_color) {
1206         input_pix_fmt = PIX_FMT_BGR24;
1207     }
1208         else {
1209         input_pix_fmt = PIX_FMT_GRAY8;
1210     }
1211
1212         // alloc memory for context
1213         oc = av_alloc_format_context();
1214         assert (oc);
1215
1216         /* set file name */
1217         oc->oformat = fmt;
1218         snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
1219
1220         /* set some options */
1221         oc->max_delay = (int)(0.7*AV_TIME_BASE);  /* This reduces buffer underrun warnings with MPEG */
1222
1223         /* Lookup codec_id for given fourcc */
1224 #if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)
1225         if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ){
1226                         CV_ERROR( CV_StsUnsupportedFormat,
1227                                 "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." );
1228                 }
1229 #else
1230         {
1231         const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL};
1232         if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE ){
1233                         CV_ERROR( CV_StsUnsupportedFormat,
1234                                 "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." );
1235                 }
1236         }
1237 #endif
1238
1239     // set a few optimal pixel formats for lossless codecs of interest..
1240     switch (codec_id) {
1241 #if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
1242     case CODEC_ID_JPEGLS:
1243         // BGR24 or GRAY8 depending on is_color...
1244         codec_pix_fmt = input_pix_fmt;
1245         break;
1246 #endif
1247     case CODEC_ID_HUFFYUV:
1248         codec_pix_fmt = PIX_FMT_YUV422P;
1249         break;
1250     case CODEC_ID_MJPEG:
1251     case CODEC_ID_LJPEG:
1252       codec_pix_fmt = PIX_FMT_YUVJ420P;
1253       bitrate_scale = 128;
1254       break;
1255     case CODEC_ID_RAWVIDEO:
1256     default:
1257         // good for lossy formats, MPEG, etc.
1258         codec_pix_fmt = PIX_FMT_YUV420P;
1259         break;
1260     }
1261
1262         // TODO -- safe to ignore output audio stream?
1263         video_st = icv_add_video_stream_FFMPEG(oc, codec_id,
1264                         frameSize.width, frameSize.height, frameSize.width*frameSize.height*bitrate_scale,
1265             fps, codec_pix_fmt);
1266
1267
1268         /* set the output parameters (must be done even if no
1269        parameters). */
1270     if (av_set_parameters(oc, NULL) < 0) {
1271                 CV_ERROR(CV_StsBadArg, "Invalid output format parameters");
1272     }
1273
1274     dump_format(oc, 0, filename, 1);
1275
1276     /* now that all the parameters are set, we can open the audio and
1277        video codecs and allocate the necessary encode buffers */
1278     if (!video_st){
1279                 CV_ERROR(CV_StsBadArg, "Couldn't open video stream");
1280         }
1281
1282     AVCodec *codec;
1283     AVCodecContext *c;
1284
1285 #if LIBAVFORMAT_BUILD > 4628
1286     c = (video_st->codec);
1287 #else
1288     c = &(video_st->codec);
1289 #endif
1290
1291     c->codec_tag = fourcc;
1292     /* find the video encoder */
1293     codec = avcodec_find_encoder(c->codec_id);
1294     if (!codec) {
1295                 CV_ERROR(CV_StsBadArg, "codec not found");
1296     }
1297
1298     /* open the codec */
1299     if ( (err=avcodec_open(c, codec)) < 0) {
1300                 char errtext[256];
1301                 sprintf(errtext, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err));
1302                 CV_ERROR(CV_StsBadArg, errtext);
1303     }
1304
1305     outbuf = NULL;
1306
1307     if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
1308         /* allocate output buffer */
1309                 /* assume we will never get codec output with more than 4 bytes per pixel... */
1310                 outbuf_size = frameSize.width*frameSize.height*4;
1311         outbuf = (uint8_t *) av_malloc(outbuf_size);
1312     }
1313
1314         bool need_color_convert;
1315         need_color_convert = (c->pix_fmt != input_pix_fmt);
1316
1317     /* allocate the encoded raw picture */
1318     picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert);
1319     if (!picture) {
1320                 CV_ERROR(CV_StsNoMem, "Could not allocate picture");
1321     }
1322
1323     /* if the output format is not our input format, then a temporary
1324        picture of the input format is needed too. It is then converted
1325            to the required output format */
1326         input_picture = NULL;
1327     if ( need_color_convert ) {
1328         input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false);
1329         if (!input_picture) {
1330                         CV_ERROR(CV_StsNoMem, "Could not allocate picture");
1331         }
1332     }
1333
1334         /* open the output file, if needed */
1335     if (!(fmt->flags & AVFMT_NOFILE)) {
1336         if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
1337                         CV_ERROR(CV_StsBadArg, "Couldn't open output file for writing");
1338         }
1339     }
1340
1341     /* write the stream header, if any */
1342     av_write_header( oc );
1343
1344
1345         __END__;
1346
1347         return true;
1348 }
1349
1350 CvVideoWriter* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps,
1351                                            CvSize frameSize, int isColor )
1352 {
1353     CvVideoWriter_FFMPEG* writer = new CvVideoWriter_FFMPEG;
1354     if( writer->open( filename, fourcc, fps, frameSize, isColor != 0 ))
1355         return writer;
1356     delete writer;
1357     return 0;
1358 }