Update the trunk to the OpenCV's CVS (2008-07-14)
[opencv] / otherlibs / highgui / cvcap_ffmpeg.cpp
index 8012097..3c84214 100644 (file)
 
 #include "_highgui.h"
 
+#if defined _MSC_VER && _MSC_VER >= 1200
+#pragma warning( disable: 4244 4510 4512 4610 )
+#endif
+
 extern "C" {
-#include <ffmpeg/avformat.h>
-#include <ffmpeg/avcodec.h>
 #ifndef WIN32
+#define INT64_C
+#define __STDC_CONSTANT_MACROS
+#include <stdint.h>
 #include <errno.h>
 #endif
-}
 
+#include <ffmpeg/avformat.h>
+#include <ffmpeg/avcodec.h>
+}
 
-#define INT64_C (long long)
+#if defined _MSC_VER && _MSC_VER >= 1200
+#pragma warning( default: 4244 4510 4512 4610 )
+#endif
 
 #ifdef NDEBUG
-#define CV_WARN(message) 
+#define CV_WARN(message)
 #else
 #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
 #endif
 
 
-#if LIBAVCODEC_VERSION_INT<=0x000409
+#ifndef MKTAG
 #define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
 #endif
 
@@ -69,10 +78,10 @@ extern "C" {
 char * FOURCC2str( int fourcc )
 {
     char * mystr=(char*)malloc(5);
-    mystr[0]=(fourcc    )&255;
-    mystr[1]=(fourcc>> 8)&255;
-    mystr[2]=(fourcc>>16)&255;
-    mystr[3]=(fourcc>>24)&255;
+    mystr[0]=(char)((fourcc    )&255);
+    mystr[1]=(char)((fourcc>> 8)&255);
+    mystr[2]=(char)((fourcc>>16)&255);
+    mystr[3]=(char)((fourcc>>24)&255);
     mystr[4]=0;
     return mystr;
 }
@@ -212,15 +221,17 @@ const AVCodecTag codec_bmp_tags[] = {
     { CODEC_ID_LOCO, MKTAG('L', 'O', 'C', 'O') },
     { CODEC_ID_THEORA, MKTAG('t', 'h', 'e', 'o') },
 #if LIBAVCODEC_VERSION_INT>0x000409
-    { CODEC_ID_JPEGLS,MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - encoder */
-    { CODEC_ID_FLASHSV, MKTAG('F', 'S', 'V', '1') },
-    { CODEC_ID_VC1, MKTAG('W', 'V', 'C', '1') },
-    { CODEC_ID_VC1, MKTAG('W', 'M', 'V', 'A') },
     { CODEC_ID_WNV1, MKTAG('W', 'N', 'V', '1') },
     { CODEC_ID_AASC, MKTAG('A', 'A', 'S', 'C') },
     { CODEC_ID_INDEO2, MKTAG('R', 'T', '2', '1') },
     { CODEC_ID_FRAPS, MKTAG('F', 'P', 'S', '1') },
     { CODEC_ID_TRUEMOTION2, MKTAG('T', 'M', '2', '0') },
+#endif
+#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
+    { CODEC_ID_FLASHSV, MKTAG('F', 'S', 'V', '1') },
+    { CODEC_ID_JPEGLS,MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - encoder */
+    { CODEC_ID_VC1, MKTAG('W', 'V', 'C', '1') },
+    { CODEC_ID_VC1, MKTAG('W', 'M', 'V', 'A') },
     { CODEC_ID_CSCD, MKTAG('C', 'S', 'C', 'D') },
     { CODEC_ID_ZMBV, MKTAG('Z', 'M', 'B', 'V') },
     { CODEC_ID_KMVC, MKTAG('K', 'M', 'V', 'C') },
@@ -242,9 +253,24 @@ const AVCodecTag codec_bmp_tags[] = {
 };
 
 
-typedef struct CvCaptureAVI_FFMPEG
+class CvCapture_FFMPEG : public CvCapture
 {
-    CvCaptureVTable   * vtable;
+public:
+    CvCapture_FFMPEG() { init(); }
+    virtual ~CvCapture_FFMPEG() { close(); }
+
+    virtual bool open( const char* filename );
+    virtual void close();
+    
+    virtual double getProperty(int);
+    virtual bool setProperty(int, double);
+    virtual bool grabFrame();
+    virtual IplImage* retrieveFrame();
+
+protected:
+    void init();
+    bool reopen();
+    bool slowSeek( int framenumber );
 
     AVFormatContext   * ic;
     int                 video_stream;
@@ -259,85 +285,93 @@ typedef struct CvCaptureAVI_FFMPEG
    for the particular file.
    'filename!=NULL' indicates that the slow fallback function is used for seeking,
    and so the filename is needed to reopen the file on backward seeking.
-*/ 
+*/
     char              * filename;
-} CvCaptureAVI_FFMPEG;
+};
+
+
+void CvCapture_FFMPEG::init()
+{
+    ic = 0;
+    video_stream = -1;
+    video_st = 0;
+    picture = 0;
+    picture_pts = 0;
+    memset( &rgb_picture, 0, sizeof(rgb_picture) );
+    memset( &frame, 0, sizeof(frame) );
+    filename = 0;
+}
 
 
-static void icvCloseAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture )
+void CvCapture_FFMPEG::close()
 {
-    //cvFree( (void**)&(capture->entries) );
-    if( capture->picture )
-    av_free(capture->picture);
+    if( picture )
+    av_free(picture);
 
-    if( capture->video_st )
+    if( video_st )
     {
 #if LIBAVFORMAT_BUILD > 4628
-        avcodec_close( capture->video_st->codec );
+        avcodec_close( video_st->codec );
 #else
-        avcodec_close( &capture->video_st->codec );
+        avcodec_close( &video_st->codec );
 #endif
-        capture->video_st = NULL;
+        video_st = NULL;
     }
 
-    if( capture->ic )
+    if( ic )
     {
-        av_close_input_file(capture->ic);
-        capture->ic = NULL;
+        av_close_input_file(ic);
+        ic = NULL;
     }
 
-    if( capture->rgb_picture.data[0] )
-        cvFree( &capture->rgb_picture.data[0] );
+    if( rgb_picture.data[0] )
+        cvFree( &rgb_picture.data[0] );
 
-    memset( &capture->frame, 0, sizeof(capture->frame));
+    init();
 }
 
 
 /*
     Used to reopen a video if the slower fallback function for seeking is used.
 */
-static int icvReopenFileAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture )
+bool CvCapture_FFMPEG::reopen()
 {
-    if ( capture->filename==NULL ) return 0;
+    if ( filename==NULL ) return false;
 
 #if LIBAVFORMAT_BUILD > 4628
-    avcodec_close( capture->video_st->codec );
+    avcodec_close( video_st->codec );
 #else
-    avcodec_close( &capture->video_st->codec );
+    avcodec_close( &video_st->codec );
 #endif
-    av_close_input_file(capture->ic);
+    av_close_input_file(ic);
 
     // reopen video
-    av_open_input_file(&capture->ic, capture->filename, NULL, 0, NULL);
-    av_find_stream_info(capture->ic);
+    av_open_input_file(&ic, filename, NULL, 0, NULL);
+    av_find_stream_info(ic);
 #if LIBAVFORMAT_BUILD > 4628
-    AVCodecContext *enc = capture->ic->streams[capture->video_stream]->codec;
+    AVCodecContext *enc = ic->streams[video_stream]->codec;
 #else
-    AVCodecContext *enc = &capture->ic->streams[capture->video_stream]->codec;
+    AVCodecContext *enc = &ic->streams[video_stream]->codec;
 #endif
     AVCodec *codec = avcodec_find_decoder(enc->codec_id);
     avcodec_open(enc, codec);
-    capture->video_st = capture->ic->streams[capture->video_stream];
+    video_st = ic->streams[video_stream];
 
     // reset framenumber to zero
-    capture->picture_pts=0;
+    picture_pts=0;
 
-    return 1;
+    return true;
 }
 
 
 
-// forward
-static int icvCheckSeekAVI_FFMPEG( CvCaptureAVI_FFMPEG *capture);
-
-static int icvOpenAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture, const char* filename )
+bool CvCapture_FFMPEG::open( const char* _filename )
 {
-    int err, valid = 0, video_index = -1, i;
-    AVFormatContext *ic;
+    unsigned i;
+    bool valid = false;
+
+    close();
 
-    capture->ic = NULL;
-    capture->video_stream = -1;
-    capture->video_st = NULL;
     /* register all codecs, demux and protocols */
     av_register_all();
 
@@ -345,12 +379,11 @@ static int icvOpenAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture, const char* filename
     // av_log_level = AV_LOG_QUIET;
 #endif
 
-    err = av_open_input_file(&ic, filename, NULL, 0, NULL);
+    int err = av_open_input_file(&ic, _filename, NULL, 0, NULL);
     if (err < 0) {
            CV_WARN("Error opening file");
            goto exit_func;
     }
-    capture->ic = ic;
     err = av_find_stream_info(ic);
     if (err < 0) {
            CV_WARN("Could not find codec parameters");
@@ -362,66 +395,60 @@ static int icvOpenAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture, const char* filename
 #else
         AVCodecContext *enc = &ic->streams[i]->codec;
 #endif
-        AVCodec *codec;
-    if( CODEC_TYPE_VIDEO == enc->codec_type && video_index < 0) {
-        video_index = i;
-        codec = avcodec_find_decoder(enc->codec_id);
-        if (!codec ||
-        avcodec_open(enc, codec) < 0)
-        goto exit_func;
-        capture->video_stream = i;
-        capture->video_st = ic->streams[i];
-        capture->picture = avcodec_alloc_frame();
-
-        capture->rgb_picture.data[0] = (uint8_t*)cvAlloc(
-                                avpicture_get_size( PIX_FMT_BGR24,
-                                enc->width, enc->height ));
-        avpicture_fill( (AVPicture*)&capture->rgb_picture, capture->rgb_picture.data[0],
-                PIX_FMT_BGR24, enc->width, enc->height );
-
-        cvInitImageHeader( &capture->frame, cvSize( enc->width,
-                                   enc->height ), 8, 3, 0, 4 );
-        cvSetData( &capture->frame, capture->rgb_picture.data[0],
-                           capture->rgb_picture.linesize[0] );
-        break;
-    }
+        
+        if( CODEC_TYPE_VIDEO == enc->codec_type && video_stream < 0) {
+            AVCodec *codec = avcodec_find_decoder(enc->codec_id);
+            if (!codec ||
+            avcodec_open(enc, codec) < 0)
+            goto exit_func;
+            video_stream = i;
+            video_st = ic->streams[i];
+            picture = avcodec_alloc_frame();
+
+            rgb_picture.data[0] = (uint8_t*)cvAlloc(
+                                    avpicture_get_size( PIX_FMT_BGR24,
+                                    enc->width, enc->height ));
+            avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0],
+                    PIX_FMT_BGR24, enc->width, enc->height );
+
+            cvInitImageHeader( &frame, cvSize( enc->width,
+                                       enc->height ), 8, 3, 0, 4 );
+            cvSetData( &frame, rgb_picture.data[0],
+                               rgb_picture.linesize[0] );
+            break;
+        }
     }
 
-    if(video_index >= 0) valid = 1;
+    if(video_stream >= 0) valid = true;
 
     // perform check if source is seekable via ffmpeg's seek function av_seek_frame(...)
-    err = av_seek_frame(capture->ic, capture->video_stream, 10, 0);
+    err = av_seek_frame(ic, video_stream, 10, 0);
     if (err < 0)
     {
-        int length=0;
-        while ( filename[length] ) length++;
-        // remark filename
-        capture->filename=(char*)malloc(length+1);
-        for ( int i=0; i<length+1; i++ ) capture->filename[i]=filename[i];
+        filename=(char*)malloc(strlen(_filename)+1);
+        strcpy(filename, _filename);
         // reopen videofile to 'seek' back to first frame
-        icvReopenFileAVI_FFMPEG( capture );
+        reopen();
     }
     else
     {
         // seek seems to work, so we don't need the filename,
         // but we still need to seek back to filestart
-        capture->filename=NULL;
-        av_seek_frame(capture->ic, capture->video_stream, 0, 0);
+        filename=NULL;
+        av_seek_frame(ic, video_stream, 0, 0);
     }
 exit_func:
 
     if( !valid )
-        icvCloseAVI_FFMPEG( capture );
+        close();
 
     return valid;
 }
 
 
-
-
-static int icvGrabFrameAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture )
+bool CvCapture_FFMPEG::grabFrame()
 {
-    int valid=0;
+    bool valid = false;
     static bool bFirstTime = true;
     static AVPacket pkt;
     int got_picture;
@@ -433,8 +460,8 @@ static int icvGrabFrameAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture )
         pkt.data = NULL;
     }
 
-    if( !capture || !capture->ic || !capture->video_st )
-        return 0;
+    if( !ic || !video_st )
+        return false;
 
     // free last packet if exist
     if (pkt.data != NULL) {
@@ -442,21 +469,21 @@ static int icvGrabFrameAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture )
     }
 
     // get the next frame
-    while ((0 == valid) && (av_read_frame(capture->ic, &pkt) >= 0)) {
-        if( pkt.stream_index != capture->video_stream ) continue;
+    while (!valid && (av_read_frame(ic, &pkt) >= 0)) {
+               if( pkt.stream_index != video_stream ) continue;
 #if LIBAVFORMAT_BUILD > 4628
-        avcodec_decode_video(capture->video_st->codec, 
-                             capture->picture, &got_picture, 
+        avcodec_decode_video(video_st->codec,
+                             picture, &got_picture,
                              pkt.data, pkt.size);
 #else
-        avcodec_decode_video(&capture->video_st->codec, 
-                             capture->picture, &got_picture, 
+        avcodec_decode_video(&video_st->codec,
+                             picture, &got_picture,
                              pkt.data, pkt.size);
 #endif
 
         if (got_picture) {
             // we have a new picture, so memorize it
-            capture->picture_pts = pkt.pts;
+            picture_pts = pkt.pts;
             valid = 1;
         }
     }
@@ -466,74 +493,74 @@ static int icvGrabFrameAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture )
 }
 
 
-static const IplImage* icvRetrieveFrameAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture )
+IplImage* CvCapture_FFMPEG::retrieveFrame()
 {
-    if( !capture || !capture->video_st || !capture->picture->data[0] )
-    return 0;
+    if( !video_st || !picture->data[0] )
+        return 0;
 
 
 #if LIBAVFORMAT_BUILD > 4628
-    img_convert( (AVPicture*)&capture->rgb_picture, PIX_FMT_BGR24,
-                 (AVPicture*)capture->picture,
-                 capture->video_st->codec->pix_fmt,
-                 capture->video_st->codec->width,
-                 capture->video_st->codec->height );
+    img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24,
+                 (AVPicture*)picture,
+                 video_st->codec->pix_fmt,
+                 video_st->codec->width,
+                 video_st->codec->height );
 #else
-    img_convert( (AVPicture*)&capture->rgb_picture, PIX_FMT_BGR24,
-                 (AVPicture*)capture->picture,
-                 capture->video_st->codec.pix_fmt,
-                 capture->video_st->codec.width,
-                 capture->video_st->codec.height );
+    img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24,
+                 (AVPicture*)picture,
+                 video_st->codec.pix_fmt,
+                 video_st->codec.width,
+                 video_st->codec.height );
 #endif
-    return &capture->frame;
+    return &frame;
 }
 
 
-static double icvGetPropertyAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture, int property_id )
+double CvCapture_FFMPEG::getProperty( int property_id )
 {
-    // if( !capture || !capture->video_st || !capture->picture->data[0] ) return 0;
-    if( !capture || !capture->video_st ) return 0;
+    // if( !capture || !video_st || !picture->data[0] ) return 0;
+    if( !video_st ) return 0;
 
 
     int64_t timestamp;
-    timestamp = capture->picture_pts;
+    timestamp = picture_pts;
 
     switch( property_id )
     {
     case CV_CAP_PROP_POS_MSEC:
-        // if(capture->ic->start_time != static_cast<double>(AV_NOPTS_VALUE))
-        if(capture->ic->start_time != AV_NOPTS_VALUE)
-        return (double)(timestamp - capture->ic->start_time)*1000/(double)AV_TIME_BASE;
+        // if(ic->start_time != static_cast<double>(AV_NOPTS_VALUE))
+        if(ic->start_time != AV_NOPTS_VALUE)
+        return (double)(timestamp - ic->start_time)*1000/(double)AV_TIME_BASE;
         break;
     case CV_CAP_PROP_POS_FRAMES:
-    //if(capture->video_st->cur_dts != static_cast<double>(AV_NOPTS_VALUE))
-    if(capture->video_st->cur_dts != AV_NOPTS_VALUE)
-        return (double)capture->video_st->cur_dts-1;
+    //if(video_st->cur_dts != static_cast<double>(AV_NOPTS_VALUE))
+    if(video_st->cur_dts != AV_NOPTS_VALUE)
+        return (double)video_st->cur_dts-1;
     break;
     case CV_CAP_PROP_POS_AVI_RATIO:
-    //  if(capture->ic->start_time != static_cast<double>(AV_NOPTS_VALUE) && capture->ic->duration != static_cast<double>(AV_NOPTS_VALUE))
-    if(capture->ic->start_time != AV_NOPTS_VALUE && capture->ic->duration != AV_NOPTS_VALUE)
-        return (double)(timestamp-capture->ic->start_time)/(double)capture->ic->duration;
+    //  if(ic->start_time != static_cast<double>(AV_NOPTS_VALUE) && ic->duration != static_cast<double>(AV_NOPTS_VALUE))
+    if(ic->start_time != AV_NOPTS_VALUE && ic->duration != AV_NOPTS_VALUE)
+        return (double)(timestamp-ic->start_time)/(double)ic->duration;
     break;
     case CV_CAP_PROP_FRAME_WIDTH:
-        return (double)capture->frame.width;
+        return (double)frame.width;
     break;
     case CV_CAP_PROP_FRAME_HEIGHT:
-        return (double)capture->frame.height;
+        return (double)frame.height;
     break;
     case CV_CAP_PROP_FPS:
 #if LIBAVCODEC_BUILD > 4753
-        return av_q2d (capture->video_st->r_frame_rate);
+        return av_q2d (video_st->r_frame_rate);
 #else
-        return (double)capture->video_st->codec.frame_rate
-            / (double)capture->video_st->codec.frame_rate_base;
+        return (double)video_st->codec.frame_rate
+            / (double)video_st->codec.frame_rate_base;
 #endif
     break;
     case CV_CAP_PROP_FOURCC:
 #if LIBAVFORMAT_BUILD > 4628
-        return (double)capture->video_st->codec->codec_tag;
+        return (double)video_st->codec->codec_tag;
 #else
-        return (double)capture->video_st->codec.codec_tag;
+        return (double)video_st->codec.codec_tag;
 #endif
     break;
     }
@@ -543,144 +570,129 @@ static double icvGetPropertyAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture, int proper
 
 
 // this is a VERY slow fallback function, ONLY used if ffmpeg's av_seek_frame delivers no correct result!
-static int icvSlowSeekAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture, const int framenumber )
+bool CvCapture_FFMPEG::slowSeek( int framenumber )
 {
-    if ( framenumber>capture->picture_pts )
+    if ( framenumber>picture_pts )
     {
-        while ( capture->picture_pts<framenumber )
-            if ( icvGrabFrameAVI_FFMPEG( capture )<0 ) return 0;
+        while ( picture_pts<framenumber )
+            if ( !grabFrame() ) return false;
     }
-    else if ( framenumber<capture->picture_pts )
+    else if ( framenumber<picture_pts )
     {
-        icvReopenFileAVI_FFMPEG(capture);
-        while ( capture->picture_pts<framenumber )
-            if ( icvGrabFrameAVI_FFMPEG( capture )<0 ) return 0;
+        reopen();
+        while ( picture_pts<framenumber )
+            if ( !grabFrame() ) return false;
     }
-    return 1;
+    return true;
 }
 
 
-
-
-static int icvSetPropertyAVI_FFMPEG( CvCaptureAVI_FFMPEG* capture,
-                                     int property_id, double value )
+bool CvCapture_FFMPEG::setProperty( int property_id, double value )
 {
-    if( !capture || !capture->video_st ) return 0;
+    if( !video_st ) return false;
 
     switch( property_id )
     {
-        case CV_CAP_PROP_POS_MSEC:
-        case CV_CAP_PROP_POS_FRAMES:
-        case CV_CAP_PROP_POS_AVI_RATIO:
+    case CV_CAP_PROP_POS_MSEC:
+    case CV_CAP_PROP_POS_FRAMES:
+    case CV_CAP_PROP_POS_AVI_RATIO:
         {
-            int64_t timestamp;
+            int64_t timestamp = 0;
             AVRational time_base;
             switch( property_id )
             {
-                case CV_CAP_PROP_POS_FRAMES:
+            case CV_CAP_PROP_POS_FRAMES:
                 timestamp=(int64_t)value;
-                if(capture->ic->start_time != AV_NOPTS_VALUE)
-                    timestamp += capture->ic->start_time;
+                if(ic->start_time != AV_NOPTS_VALUE)
+                    timestamp += ic->start_time;
                 break;
 
-                case CV_CAP_PROP_POS_MSEC:
-                time_base=capture->ic->streams[capture->video_stream]->time_base;
+            case CV_CAP_PROP_POS_MSEC:
+                time_base=ic->streams[video_stream]->time_base;
                 timestamp=(int64_t)(value*(float(time_base.den)/float(time_base.num))/1000);
-                if(capture->ic->start_time != AV_NOPTS_VALUE)
-                    timestamp += capture->ic->start_time;
+                if(ic->start_time != AV_NOPTS_VALUE)
+                    timestamp += ic->start_time;
                 break;
 
-                case CV_CAP_PROP_POS_AVI_RATIO:
-                timestamp=(int64_t)(value*capture->ic->duration);
-                if(capture->ic->start_time != AV_NOPTS_VALUE && capture->ic->duration != AV_NOPTS_VALUE)
-                    timestamp += capture->ic->start_time;
+            case CV_CAP_PROP_POS_AVI_RATIO:
+                timestamp=(int64_t)(value*ic->duration);
+                if(ic->start_time != AV_NOPTS_VALUE && ic->duration != AV_NOPTS_VALUE)
+                    timestamp += ic->start_time;
                 break;
             }
 
-            if ( capture->filename )
+            if ( filename )
             {
                 // ffmpeg's seek doesn't work...
-                if (icvSlowSeekAVI_FFMPEG(capture, timestamp) < 0)
+                if (!slowSeek((int)timestamp))
                 {
-                    fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n", 
+                    fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n",
                         (double)timestamp / AV_TIME_BASE);
-                    return 0;
+                    return false;
                 }
             }
             else
             {
-                int ret = av_seek_frame(capture->ic, capture->video_stream, timestamp, 0);
+                int ret = av_seek_frame(ic, video_stream, timestamp, 0);
                 if (ret < 0)
                 {
-                    fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n", 
-                        (double)timestamp / AV_TIME_BASE);
-                    return 0;
+                    fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n",
+                            (double)timestamp / AV_TIME_BASE);
+                    return false;
                 }
             }
-            capture->picture_pts=value;
+            picture_pts=(int64_t)value;
         }
         break;
 
-        default:
-            return 0;
+    default:
+        return false;
     }
 
-    return 1;
+    return true;
 }
 
 
 
-static CvCaptureVTable captureAVI_FFMPEG_vtable = 
+CvCapture* cvCreateFileCapture_FFMPEG( const char* filename )
 {
-    6,
-    (CvCaptureCloseFunc)icvCloseAVI_FFMPEG,
-    (CvCaptureGrabFrameFunc)icvGrabFrameAVI_FFMPEG,
-    (CvCaptureRetrieveFrameFunc)icvRetrieveFrameAVI_FFMPEG,
-    (CvCaptureGetPropertyFunc)icvGetPropertyAVI_FFMPEG,
-    (CvCaptureSetPropertyFunc)icvSetPropertyAVI_FFMPEG,
-    (CvCaptureGetDescriptionFunc)0
-};
+    CvCapture_FFMPEG* capture = new CvCapture_FFMPEG;
+    if( capture->open( filename ))
+        return capture;
+    delete capture;
+    return 0;
+}
 
 
-CvCapture* cvCaptureFromFile_FFMPEG( const char* filename )
+///////////////// FFMPEG CvVideoWriter implementation //////////////////////////
+class CvVideoWriter_FFMPEG : public CvVideoWriter
 {
-    CvCaptureAVI_FFMPEG* capture = 0;
+public:
+    CvVideoWriter_FFMPEG() { init(); }
+    virtual ~CvVideoWriter_FFMPEG() { close(); }
 
-    if( filename )
-    {
-        capture = (CvCaptureAVI_FFMPEG*)cvAlloc( sizeof(*capture));
-        memset( capture, 0, sizeof(*capture));
+    virtual bool open( const char* filename, int fourcc,
+        double fps, CvSize frameSize, bool isColor );
+    virtual void close();
+    virtual bool writeFrame( const IplImage* image );
 
-        capture->vtable = &captureAVI_FFMPEG_vtable;
+protected:
+    void init();
 
-        if( !icvOpenAVI_FFMPEG( capture, filename ))
-        {
-            capture->vtable->close((CvCapture*)capture);
-            cvFree( &capture );
-        }
-    }
-
-    return (CvCapture*)capture;
-}
-
-
-///////////////// FFMPEG CvVideoWriter implementation //////////////////////////
-typedef struct CvAVI_FFMPEG_Writer
-{
-       AVOutputFormat *fmt;
-       AVFormatContext *oc;
+    AVOutputFormat *fmt;
+    AVFormatContext *oc;
     uint8_t         * outbuf;
     uint32_t          outbuf_size;
     FILE            * outfile;
     AVFrame         * picture;
     AVFrame         * input_picture;
     uint8_t         * picbuf;
-       AVStream        * video_st;
-       int                       input_pix_fmt;
+    AVStream        * video_st;
+    int               input_pix_fmt;
     IplImage        * temp_image;
-} CvAVI_FFMPEG_Writer;
+};
 
-const char * icv_FFMPEG_ErrStr(int err)
+static const char * icvFFMPEGErrStr(int err)
 {
     switch(err) {
     case AVERROR_NUMEXPECTED:
@@ -704,6 +716,21 @@ extern "C" {
        enum CodecID codec_get_bmp_id(unsigned int tag);
 }
 
+void CvVideoWriter_FFMPEG::init()
+{
+    fmt = 0;
+    oc = 0;
+    outbuf = 0;
+    outbuf_size = 0;
+    outfile = 0;
+    picture = 0;
+    input_picture = 0;
+    picbuf = 0;
+    video_st = 0;
+    input_pix_fmt = 0;
+    temp_image = 0;
+}
+
 /**
  * the following function is a modified version of code
  * found in ffmpeg-0.4.9-pre1/output_example.c
@@ -720,12 +747,12 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo
        size = avpicture_get_size(pix_fmt, width, height);
        if(alloc){
                picture_buf = (uint8_t *) cvAlloc(size);
-               if (!picture_buf) 
+               if (!picture_buf)
                {
                        av_free(picture);
                        return NULL;
                }
-               avpicture_fill((AVPicture *)picture, picture_buf, 
+               avpicture_fill((AVPicture *)picture, picture_buf,
                                pix_fmt, width, height);
        }
        else {
@@ -734,16 +761,16 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo
 }
 
 /* add a video output stream to the container */
-static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, 
-                                                    CodecID codec_id, 
-                                                                                        int w, int h, int bitrate, 
+static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
+                                                    CodecID codec_id,
+                                                                                        int w, int h, int bitrate,
                                                                                         double fps, int pixel_format)
 {
        AVCodecContext *c;
        AVStream *st;
        int frame_rate, frame_rate_base;
        AVCodec *codec;
-       
+
 
        st = av_new_stream(oc, 0);
        if (!st) {
@@ -757,7 +784,7 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
        c = &(st->codec);
 #endif
 
-#if LIBAVFORMAT_BUILD > 4621 
+#if LIBAVFORMAT_BUILD > 4621
        c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_VIDEO);
 #else
        c->codec_id = oc->oformat->video_codec;
@@ -838,184 +865,6 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
     return st;
 }
 
-/// Create a video writer object that uses FFMPEG
-CV_IMPL CvVideoWriter* cvCreateVideoWriter( const char * filename, int fourcc,
-               double fps, CvSize frameSize, int is_color )
-{
-       CV_FUNCNAME("cvCreateVideoWriter");
-
-       CvAVI_FFMPEG_Writer * writer = NULL;
-       CodecID codec_id = CODEC_ID_NONE;
-       int err;
-       
-       __BEGIN__;
-
-       // check arguments
-       assert (filename);
-       assert (fps > 0);
-       assert (frameSize.width > 0  &&  frameSize.height > 0);
-
-       // allocate memory for structure...
-       writer = (CvAVI_FFMPEG_Writer *) cvAlloc( sizeof(CvAVI_FFMPEG_Writer));
-       memset (writer, 0, sizeof (*writer));
-
-       // tell FFMPEG to register codecs
-       av_register_all ();
-
-       /* auto detect the output format from the name and fourcc code. */
-       writer->fmt = guess_format(NULL, filename, NULL);
-       if (!writer->fmt) {
-               CV_ERROR( CV_StsUnsupportedFormat, "FFMPEG does not recognize the given file extension");
-       }
-
-       /* determine optimal pixel format */
-    if (is_color) {
-        writer->input_pix_fmt = PIX_FMT_BGR24;
-    } 
-       else {
-        writer->input_pix_fmt = PIX_FMT_GRAY8;
-    }
-
-       // alloc memory for context 
-       writer->oc = av_alloc_format_context();
-       assert (writer->oc);
-
-       /* set file name */
-       writer->oc->oformat = writer->fmt;
-       snprintf(writer->oc->filename, sizeof(writer->oc->filename), "%s", filename);
-
-       /* set some options */
-       writer->oc->max_delay = (int)(0.7*AV_TIME_BASE);  /* This reduces buffer underrun warnings with MPEG */
-
-       /* Lookup codec id for given fourcc */
-       if(fourcc!=CV_FOURCC_DEFAULT){
-#if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)
-        if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ){
-                       CV_ERROR( CV_StsUnsupportedFormat, 
-                               "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." );
-               }
-       }
-#else
-        if( (codec_id = av_codec_get_id((const AVCodecTag**)(&codec_bmp_tags), fourcc)) == CODEC_ID_NONE ){
-                       CV_ERROR( CV_StsUnsupportedFormat, 
-                               "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." );
-               }
-       }
-#endif
-
-    // set a few optimal pixel formats for lossless codecs of interest..
-    int codec_pix_fmt;
-    switch (codec_id) {
-#if LIBAVCODEC_VERSION_INT>0x000409
-    case CODEC_ID_JPEGLS:
-        // BGR24 or GRAY8 depending on is_color...
-        codec_pix_fmt = writer->input_pix_fmt;
-        break;
-#endif
-    case CODEC_ID_FFV1:
-        // no choice... other supported formats are YUV only
-        codec_pix_fmt = PIX_FMT_RGBA32;
-        break;
-       case CODEC_ID_MJPEG:
-       case CODEC_ID_LJPEG:
-               codec_pix_fmt = PIX_FMT_YUVJ420P;
-               break;
-    case CODEC_ID_RAWVIDEO:
-    default:
-        // good for lossy formats, MPEG, etc.
-        codec_pix_fmt = PIX_FMT_YUV420P;
-        break;
-    }
-
-       // TODO -- safe to ignore output audio stream?
-       writer->video_st = icv_add_video_stream_FFMPEG(writer->oc, codec_id, 
-                       frameSize.width, frameSize.height, frameSize.width*frameSize.height*64,
-            fps, codec_pix_fmt);
-
-
-       /* set the output parameters (must be done even if no
-       parameters). */
-    if (av_set_parameters(writer->oc, NULL) < 0) {
-               CV_ERROR(CV_StsBadArg, "Invalid output format parameters");
-    }
-
-    dump_format(writer->oc, 0, filename, 1);
-
-    /* now that all the parameters are set, we can open the audio and
-       video codecs and allocate the necessary encode buffers */
-    if (!writer->video_st){
-               CV_ERROR(CV_StsBadArg, "Couldn't open video stream");
-       }
-
-    AVCodec *codec;
-    AVCodecContext *c;
-
-#if LIBAVFORMAT_BUILD > 4628
-    c = (writer->video_st->codec);
-#else
-    c = &(writer->video_st->codec);
-#endif
-
-    c->codec_tag = fourcc;
-    /* find the video encoder */
-    codec = avcodec_find_encoder(c->codec_id);
-    if (!codec) {
-               CV_ERROR(CV_StsBadArg, "codec not found");
-    }
-
-    /* open the codec */
-    if ( (err=avcodec_open(c, codec)) < 0) {
-               char errtext[256];
-               sprintf(errtext, "Could not open codec '%s': %s", codec->name, icv_FFMPEG_ErrStr(err));
-               CV_ERROR(CV_StsBadArg, errtext);
-    }
-
-    writer->outbuf = NULL;
-
-    if (!(writer->oc->oformat->flags & AVFMT_RAWPICTURE)) {
-        /* allocate output buffer */
-               /* assume we will never get codec output with more than 4 bytes per pixel... */
-               writer->outbuf_size = frameSize.width*frameSize.height*4; 
-        writer->outbuf = (uint8_t *) av_malloc(writer->outbuf_size);
-    }
-
-       bool need_color_convert;
-       need_color_convert = (c->pix_fmt != writer->input_pix_fmt);
-
-    /* allocate the encoded raw picture */
-    writer->picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert);
-    if (!writer->picture) {
-               CV_ERROR(CV_StsNoMem, "Could not allocate picture");
-    }
-
-    /* if the output format is not our input format, then a temporary
-       picture of the input format is needed too. It is then converted 
-          to the required output format */
-       writer->input_picture = NULL;
-    if ( need_color_convert ) {
-        writer->input_picture = icv_alloc_picture_FFMPEG(writer->input_pix_fmt, c->width, c->height, false);
-        if (!writer->input_picture) {
-                       CV_ERROR(CV_StsNoMem, "Could not allocate picture");
-        }
-    }
-
-       /* open the output file, if needed */
-    if (!(writer->fmt->flags & AVFMT_NOFILE)) {
-        if (url_fopen(&writer->oc->pb, filename, URL_WRONLY) < 0) {
-                       CV_ERROR(CV_StsBadArg, "Couldn't open output file for writing");
-        }
-    }
-
-    /* write the stream header, if any */
-    av_write_header( writer->oc );
-       
-
-       __END__;
-
-       // return what we got
-       return (CvVideoWriter *) writer;
-}
-
 int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_t * outbuf, uint32_t outbuf_size, AVFrame * picture ){
        CV_FUNCNAME("icv_av_write_frame_FFMPEG");
 
@@ -1049,9 +898,9 @@ int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_
             AVPacket pkt;
             av_init_packet(&pkt);
 
-#if LIBAVFORMAT_BUILD > 4752 
+#if LIBAVFORMAT_BUILD > 4752
             pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base);
-#else 
+#else
                        pkt.pts = c->coded_frame->pts;
 #endif
             if(c->coded_frame->key_frame)
@@ -1075,142 +924,318 @@ int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_
 }
 
 /// write a frame with FFMPEG
-CV_IMPL int cvWriteFrame( CvVideoWriter * writer, const IplImage * image )
+bool CvVideoWriter_FFMPEG::writeFrame( const IplImage * image )
 {
-       int ret = 0;
+       bool ret = false;
 
-       CV_FUNCNAME("cvWriteFrame");
+    CV_FUNCNAME("CvVideoWriter_FFMPEG::writerFrame");
 
        __BEGIN__;
 
        // typecast from opaque data type to implemented struct
-       CvAVI_FFMPEG_Writer * mywriter = (CvAVI_FFMPEG_Writer*) writer;
 #if LIBAVFORMAT_BUILD > 4628
-    AVCodecContext *c = mywriter->video_st->codec;
+    AVCodecContext *c = video_st->codec;
 #else
-       AVCodecContext *c = &(mywriter->video_st->codec);
+       AVCodecContext *c = &(video_st->codec);
 #endif
-    
+
     if( c->codec_id == CODEC_ID_RAWVIDEO && image->origin != IPL_ORIGIN_BL )
     {
-        if( !mywriter->temp_image )
-            mywriter->temp_image = cvCreateImage( cvGetSize(image),
+        if( !temp_image )
+            temp_image = cvCreateImage( cvGetSize(image),
                                     image->depth, image->nChannels );
-        cvFlip( image, mywriter->temp_image, 0 );
-        image = mywriter->temp_image;
+        cvFlip( image, temp_image, 0 );
+        image = temp_image;
     }
 
     // check parameters
-    if (mywriter->input_pix_fmt == PIX_FMT_BGR24) {
+    if (input_pix_fmt == PIX_FMT_BGR24) {
         if (image->nChannels != 3 || image->depth != IPL_DEPTH_8U) {
             CV_ERROR(CV_StsUnsupportedFormat, "cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 3.");
         }
-    } 
-       else if (mywriter->input_pix_fmt == PIX_FMT_GRAY8) {
+    }
+       else if (input_pix_fmt == PIX_FMT_GRAY8) {
         if (image->nChannels != 1 || image->depth != IPL_DEPTH_8U) {
             CV_ERROR(CV_StsUnsupportedFormat, "cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 1.");
         }
-    } 
+    }
        else {
         assert(false);
     }
 
        // check if buffer sizes match, i.e. image has expected format (size, channels, bitdepth, alignment)
-       assert (image->imageSize == avpicture_get_size( mywriter->input_pix_fmt, image->width, image->height ));
+       assert (image->imageSize == avpicture_get_size( input_pix_fmt, image->width, image->height ));
 
-       if ( c->pix_fmt != mywriter->input_pix_fmt ) {
-               assert( mywriter->input_picture );
+       if ( c->pix_fmt != input_pix_fmt ) {
+               assert( input_picture );
                // let input_picture point to the raw data buffer of 'image'
-               avpicture_fill((AVPicture *)mywriter->input_picture, (uint8_t *) image->imageData, 
-                               mywriter->input_pix_fmt, image->width, image->height);
+               avpicture_fill((AVPicture *)input_picture, (uint8_t *) image->imageData,
+                               input_pix_fmt, image->width, image->height);
 
                // convert to the color format needed by the codec
-               if( img_convert((AVPicture *)mywriter->picture, c->pix_fmt,
-                                       (AVPicture *)mywriter->input_picture, mywriter->input_pix_fmt, 
+               if( img_convert((AVPicture *)picture, c->pix_fmt,
+                                       (AVPicture *)input_picture, input_pix_fmt,
                                        image->width, image->height) < 0){
                        CV_ERROR(CV_StsUnsupportedFormat, "FFMPEG::img_convert pixel format conversion from BGR24 not handled");
                }
        }
        else{
-               avpicture_fill((AVPicture *)mywriter->picture, (uint8_t *) image->imageData,
-                               mywriter->input_pix_fmt, image->width, image->height);
+               avpicture_fill((AVPicture *)picture, (uint8_t *) image->imageData,
+                               input_pix_fmt, image->width, image->height);
        }
 
-       ret = icv_av_write_frame_FFMPEG( mywriter->oc, mywriter->video_st, mywriter->outbuf, mywriter->outbuf_size, mywriter->picture);
+       ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0;
 
        __END__;
        return ret;
 }
 
 /// close video output stream and free associated memory
-CV_IMPL void cvReleaseVideoWriter( CvVideoWriter ** writer )
+void CvVideoWriter_FFMPEG::close()
 {
-       int i;
+       unsigned i;
 
        // nothing to do if already released
-       if ( !(*writer) )
+       if ( !picture )
                return;
-       
-       // release data structures in reverse order
-       CvAVI_FFMPEG_Writer * mywriter = (CvAVI_FFMPEG_Writer*)(*writer);
 
        /* no more frame to compress. The codec has a latency of a few
           frames if using B frames, so we get the last frames by
           passing the same picture again */
-       // TODO -- do we need to account for latency here? 
+       // TODO -- do we need to account for latency here?
 
        /* write the trailer, if any */
-       av_write_trailer(mywriter->oc);
+       av_write_trailer(oc);
 
        // free pictures
 #if LIBAVFORMAT_BUILD > 4628
-       if( mywriter->video_st->codec->pix_fmt != mywriter->input_pix_fmt){
+       if( video_st->codec->pix_fmt != input_pix_fmt){
 #else
-       if( mywriter->video_st->codec.pix_fmt != mywriter->input_pix_fmt){
+       if( video_st->codec.pix_fmt != input_pix_fmt){
 #endif
-               cvFree(&(mywriter->picture->data[0]));
+               cvFree(&(picture->data[0]));
        }
-       av_free(mywriter->picture);
+       av_free(picture);
 
-    if (mywriter->input_picture) {
-        av_free(mywriter->input_picture);
+    if (input_picture) {
+        av_free(input_picture);
     }
 
        /* close codec */
 #if LIBAVFORMAT_BUILD > 4628
-       avcodec_close(mywriter->video_st->codec);
+       avcodec_close(video_st->codec);
 #else
-       avcodec_close(&(mywriter->video_st->codec));
+       avcodec_close(&(video_st->codec));
 #endif
-    
-       av_free(mywriter->outbuf);
+
+       av_free(outbuf);
 
        /* free the streams */
-       for(i = 0; i < mywriter->oc->nb_streams; i++) {
-               av_freep(&mywriter->oc->streams[i]->codec);
-               av_freep(&mywriter->oc->streams[i]);
+       for(i = 0; i < oc->nb_streams; i++) {
+               av_freep(&oc->streams[i]->codec);
+               av_freep(&oc->streams[i]);
        }
 
-       if (!(mywriter->fmt->flags & AVFMT_NOFILE)) {
+       if (!(fmt->flags & AVFMT_NOFILE)) {
                /* close the output file */
 
 
 #if LIBAVCODEC_VERSION_INT==((51<<16)+(49<<8)+0)
-               url_fclose(mywriter->oc->pb);
+               url_fclose(oc->pb);
 #else
-               url_fclose(&mywriter->oc->pb);
+               url_fclose(&oc->pb);
 #endif
 
        }
 
        /* free the stream */
-       av_free(mywriter->oc);
+       av_free(oc);
 
-    cvReleaseImage( &mywriter->temp_image );
+    cvReleaseImage( &temp_image );
+
+       init();
+}
+
+/// Create a video writer object that uses FFMPEG
+bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
+               double fps, CvSize frameSize, bool is_color )
+{
+    CV_FUNCNAME("CvVideoWriter_FFMPEG::open");
+
+       CodecID codec_id = CODEC_ID_NONE;
+       int err;
+
+       __BEGIN__;
 
-       /* free cvVideoWriter */
-       cvFree ( writer );
+    close();
 
-       // mark as released
-       (*writer) = 0;
+       // check arguments
+       assert (filename);
+       assert (fps > 0);
+       assert (frameSize.width > 0  &&  frameSize.height > 0);
+
+       // tell FFMPEG to register codecs
+       av_register_all ();
+
+       /* auto detect the output format from the name and fourcc code. */
+       fmt = guess_format(NULL, filename, NULL);
+       if (!fmt) {
+               CV_ERROR( CV_StsUnsupportedFormat, "FFMPEG does not recognize the given file extension");
+       }
+
+       /* determine optimal pixel format */
+    if (is_color) {
+        input_pix_fmt = PIX_FMT_BGR24;
+    }
+       else {
+        input_pix_fmt = PIX_FMT_GRAY8;
+    }
+
+       // alloc memory for context
+       oc = av_alloc_format_context();
+       assert (oc);
+
+       /* set file name */
+       oc->oformat = fmt;
+       snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
+
+       /* set some options */
+       oc->max_delay = (int)(0.7*AV_TIME_BASE);  /* This reduces buffer underrun warnings with MPEG */
+
+       /* Lookup codec_id for given fourcc */
+       if(fourcc!=CV_FOURCC_DEFAULT){
+#if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)
+        if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ){
+                       CV_ERROR( CV_StsUnsupportedFormat,
+                               "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." );
+               }
+       }
+#else
+        if( (codec_id = av_codec_get_id((const AVCodecTag**)(&codec_bmp_tags), fourcc)) == CODEC_ID_NONE ){
+                       CV_ERROR( CV_StsUnsupportedFormat,
+                               "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." );
+               }
+       }
+#endif
+
+    // set a few optimal pixel formats for lossless codecs of interest..
+    int codec_pix_fmt;
+    switch (codec_id) {
+#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
+    case CODEC_ID_JPEGLS:
+        // BGR24 or GRAY8 depending on is_color...
+        codec_pix_fmt = input_pix_fmt;
+        break;
+#endif
+    case CODEC_ID_FFV1:
+        // no choice... other supported formats are YUV only
+        codec_pix_fmt = PIX_FMT_RGBA32;
+        break;
+       case CODEC_ID_MJPEG:
+       case CODEC_ID_LJPEG:
+               codec_pix_fmt = PIX_FMT_YUVJ420P;
+               break;
+    case CODEC_ID_RAWVIDEO:
+    default:
+        // good for lossy formats, MPEG, etc.
+        codec_pix_fmt = PIX_FMT_YUV420P;
+        break;
+    }
+
+       // TODO -- safe to ignore output audio stream?
+       video_st = icv_add_video_stream_FFMPEG(oc, codec_id,
+                       frameSize.width, frameSize.height, frameSize.width*frameSize.height*64,
+            fps, codec_pix_fmt);
+
+
+       /* set the output parameters (must be done even if no
+       parameters). */
+    if (av_set_parameters(oc, NULL) < 0) {
+               CV_ERROR(CV_StsBadArg, "Invalid output format parameters");
+    }
+
+    dump_format(oc, 0, filename, 1);
+
+    /* now that all the parameters are set, we can open the audio and
+       video codecs and allocate the necessary encode buffers */
+    if (!video_st){
+               CV_ERROR(CV_StsBadArg, "Couldn't open video stream");
+       }
+
+    AVCodec *codec;
+    AVCodecContext *c;
+
+#if LIBAVFORMAT_BUILD > 4628
+    c = (video_st->codec);
+#else
+    c = &(video_st->codec);
+#endif
+
+    c->codec_tag = fourcc;
+    /* find the video encoder */
+    codec = avcodec_find_encoder(c->codec_id);
+    if (!codec) {
+               CV_ERROR(CV_StsBadArg, "codec not found");
+    }
+
+    /* open the codec */
+    if ( (err=avcodec_open(c, codec)) < 0) {
+               char errtext[256];
+               sprintf(errtext, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err));
+               CV_ERROR(CV_StsBadArg, errtext);
+    }
+
+    outbuf = NULL;
+
+    if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
+        /* allocate output buffer */
+               /* assume we will never get codec output with more than 4 bytes per pixel... */
+               outbuf_size = frameSize.width*frameSize.height*4;
+        outbuf = (uint8_t *) av_malloc(outbuf_size);
+    }
+
+       bool need_color_convert;
+       need_color_convert = (c->pix_fmt != input_pix_fmt);
+
+    /* allocate the encoded raw picture */
+    picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert);
+    if (!picture) {
+               CV_ERROR(CV_StsNoMem, "Could not allocate picture");
+    }
+
+    /* if the output format is not our input format, then a temporary
+       picture of the input format is needed too. It is then converted
+          to the required output format */
+       input_picture = NULL;
+    if ( need_color_convert ) {
+        input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false);
+        if (!input_picture) {
+                       CV_ERROR(CV_StsNoMem, "Could not allocate picture");
+        }
+    }
+
+       /* open the output file, if needed */
+    if (!(fmt->flags & AVFMT_NOFILE)) {
+        if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
+                       CV_ERROR(CV_StsBadArg, "Couldn't open output file for writing");
+        }
+    }
+
+    /* write the stream header, if any */
+    av_write_header( oc );
+
+
+       __END__;
+
+       return true;
+}
+
+CvVideoWriter* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps,
+                                           CvSize frameSize, int isColor )
+{
+    CvVideoWriter_FFMPEG* writer = new CvVideoWriter_FFMPEG;
+    if( writer->open( filename, fourcc, fps, frameSize, isColor != 0 ))
+        return writer;
+    delete writer;
+    return 0;
 }