--- src/highgui/cvcap_ffmpeg.cpp.orig 2010-09-02 21:16:44.000000000 -0400 +++ src/highgui/cvcap_ffmpeg.cpp 2010-09-02 22:09:32.000000000 -0400 @@ -345,6 +345,9 @@ and so the filename is needed to reopen the file on backward seeking. */ char * filename; + +private: + bool seekKeyAndRunOverFrames(int framenumber); }; @@ -686,73 +689,57 @@ return true; } - -bool CvCapture_FFMPEG::setProperty( int property_id, double value ) -{ - 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: - { - int64_t timestamp = 0; - AVRational time_base; - switch( property_id ) - { - case CV_CAP_PROP_POS_FRAMES: - timestamp=(int64_t)value; - if(ic->start_time != AV_NOPTS_VALUE_) - timestamp += ic->start_time; - break; - - 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(ic->start_time != AV_NOPTS_VALUE_) - timestamp += ic->start_time; - break; - - 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 ( filename ) - { - // ffmpeg's seek doesn't work... - if (!slowSeek((int)timestamp)) - { - fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n", - (double)timestamp / AV_TIME_BASE); - return false; - } - } - else - { - 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 false; - } - } - picture_pts=(int64_t)value; - } - break; - - default: - return false; - } - - return true; +#define short_seek_dist 25 +bool CvCapture_FFMPEG::seekKeyAndRunOverFrames(int framenumber) +{ + int ret; + if (framenumber > video_st->cur_dts-1) + { + if (framenumber-(video_st->cur_dts-1) > short_seek_dist) { + ret=av_seek_frame(ic, video_stream, framenumber, 1); + assert(ret>=0); + if(ret<0) + return false; + } + grabFrame(); + while ((video_st->cur_dts-1) < framenumber) + if ( !grabFrame() ) return false; + } + else if ( framenumber < (video_st->cur_dts-1) ) + { + ret=av_seek_frame(ic, video_stream, framenumber, 1); + assert(ret>=0); + if(ret<0) + return false; + grabFrame(); + while ((video_st->cur_dts-1) < framenumber ) + if ( !grabFrame() ) return false; + } + return(true); } - +bool CvCapture_FFMPEG::setProperty( int property_id, double value ) +{ + if( !video_st ) return false; + int ret; + int framenumber; + AVRational time_base; + switch( property_id ) + { + case CV_CAP_PROP_POS_FRAMES: + framenumber=(int)value; + return seekKeyAndRunOverFrames(framenumber); + break; + case CV_CAP_PROP_POS_MSEC: + framenumber=value/(1000.0f * av_q2d (video_st->time_base)); + return seekKeyAndRunOverFrames(framenumber); + break; + + default: + return false; + } + return false; +} CvCapture* cvCreateFileCapture_FFMPEG( const char* filename ) {