Commit ec97683d authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

fixed positioning in ffmpeg wrapper (thanks to mike_at_nrec for the patch).…

fixed positioning in ffmpeg wrapper (thanks to mike_at_nrec for the patch). Added frame positioning feature to laplace demo to test the feature
parent 2e520b05
...@@ -505,7 +505,9 @@ bool CvCapture_FFMPEG::open( const char* _filename ) ...@@ -505,7 +505,9 @@ bool CvCapture_FFMPEG::open( const char* _filename )
// seek seems to work, so we don't need the filename, // seek seems to work, so we don't need the filename,
// but we still need to seek back to filestart // but we still need to seek back to filestart
filename=NULL; filename=NULL;
av_seek_frame(ic, video_stream, 0, 0); int64_t ts = video_st->first_dts;
int flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD;
av_seek_frame(ic, video_stream, ts, flags);
} }
exit_func: exit_func:
...@@ -621,7 +623,7 @@ double CvCapture_FFMPEG::getProperty( int property_id ) ...@@ -621,7 +623,7 @@ double CvCapture_FFMPEG::getProperty( int property_id )
// if( !capture || !video_st || !picture->data[0] ) return 0; // if( !capture || !video_st || !picture->data[0] ) return 0;
if( !video_st ) return 0; if( !video_st ) return 0;
double frameScale = av_q2d (video_st->time_base) * av_q2d (video_st->r_frame_rate);
int64_t timestamp; int64_t timestamp;
timestamp = picture_pts; timestamp = picture_pts;
...@@ -631,24 +633,23 @@ double CvCapture_FFMPEG::getProperty( int property_id ) ...@@ -631,24 +633,23 @@ double CvCapture_FFMPEG::getProperty( int property_id )
if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_) if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_)
return (((double)video_st->parser->dts-1) *1000.0f) * av_q2d (video_st->time_base); return (((double)video_st->parser->dts-1) *1000.0f) * av_q2d (video_st->time_base);
if(video_st->cur_dts != AV_NOPTS_VALUE_) if(video_st->cur_dts != AV_NOPTS_VALUE_)
return (((double)video_st->cur_dts-1) *1000.0f * av_q2d (video_st->time_base)); return ((video_st->cur_dts-video_st->first_dts) * 1000.0 * av_q2d (video_st->time_base));
// return (((double)video_st->cur_dts-1) *1000) / av_q2d (video_st->r_frame_rate);
break; break;
case CV_CAP_PROP_POS_FRAMES: case CV_CAP_PROP_POS_FRAMES:
if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_) if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_)
return (double)video_st->parser->dts-1; return (double)video_st->parser->dts-1;
if(video_st->cur_dts != AV_NOPTS_VALUE_) if(video_st->cur_dts != AV_NOPTS_VALUE_)
return (double)video_st->cur_dts-1; return((video_st->cur_dts-video_st->first_dts) * frameScale);
break; break;
case CV_CAP_PROP_POS_AVI_RATIO: case CV_CAP_PROP_POS_AVI_RATIO:
if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_) if(video_st->parser && video_st->parser->dts != AV_NOPTS_VALUE_)
return (double)(video_st->parser->dts-1)/(double)video_st->duration; return (double)(video_st->parser->dts-1)/(double)video_st->duration;
if(video_st->cur_dts != AV_NOPTS_VALUE_ && video_st->duration != AV_NOPTS_VALUE_) if(video_st->cur_dts != AV_NOPTS_VALUE_ && video_st->duration != AV_NOPTS_VALUE_)
return (double)(video_st->cur_dts-1)/(double)video_st->duration; return(((video_st->cur_dts-video_st->first_dts)+(1.0/frameScale)) / (double)video_st->duration);
break; break;
case CV_CAP_PROP_FRAME_COUNT: case CV_CAP_PROP_FRAME_COUNT:
if(video_st->duration != AV_NOPTS_VALUE_) if(video_st->duration != AV_NOPTS_VALUE_)
return (double)video_st->duration; return (double)video_st->duration * frameScale;
break; break;
case CV_CAP_PROP_FRAME_WIDTH: case CV_CAP_PROP_FRAME_WIDTH:
return (double)frame.width; return (double)frame.width;
...@@ -705,25 +706,26 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value ) ...@@ -705,25 +706,26 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value )
case CV_CAP_PROP_POS_FRAMES: case CV_CAP_PROP_POS_FRAMES:
case CV_CAP_PROP_POS_AVI_RATIO: case CV_CAP_PROP_POS_AVI_RATIO:
{ {
int64_t timestamp = 0; int64_t timestamp = ic->streams[video_stream]->first_dts;
AVRational time_base; AVRational time_base = ic->streams[video_stream]->time_base;
AVRational frame_base = ic->streams[video_stream]->r_frame_rate;
double timeScale = (time_base.den / (double)time_base.num) / (frame_base.num / frame_base.den);
switch( property_id ) switch( property_id )
{ {
case CV_CAP_PROP_POS_FRAMES: case CV_CAP_PROP_POS_FRAMES:
timestamp=(int64_t)value; timestamp += (int64_t)(value * timeScale);
if(ic->start_time != AV_NOPTS_VALUE_) if(ic->start_time != AV_NOPTS_VALUE_)
timestamp += ic->start_time; timestamp += ic->start_time;
break; break;
case CV_CAP_PROP_POS_MSEC: 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);
timestamp=(int64_t)(value*(float(time_base.den)/float(time_base.num))/1000);
if(ic->start_time != AV_NOPTS_VALUE_) if(ic->start_time != AV_NOPTS_VALUE_)
timestamp += ic->start_time; timestamp += ic->start_time;
break; break;
case CV_CAP_PROP_POS_AVI_RATIO: case CV_CAP_PROP_POS_AVI_RATIO:
timestamp=(int64_t)(value*ic->duration); timestamp += (int64_t)(value*ic->duration);
if(ic->start_time != AV_NOPTS_VALUE_ && ic->duration != AV_NOPTS_VALUE_) if(ic->start_time != AV_NOPTS_VALUE_ && ic->duration != AV_NOPTS_VALUE_)
timestamp += ic->start_time; timestamp += ic->start_time;
break; break;
...@@ -741,7 +743,10 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value ) ...@@ -741,7 +743,10 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value )
} }
else else
{ {
int ret = av_seek_frame(ic, video_stream, timestamp, 0); int flags = AVSEEK_FLAG_FRAME;
if (timestamp < ic->streams[video_stream]->cur_dts)
flags |= AVSEEK_FLAG_BACKWARD;
int ret = av_seek_frame(ic, video_stream, timestamp, flags);
if (ret < 0) if (ret < 0)
{ {
fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n", fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment