Updated by Andrey Kamaev about 13 years ago
@CvCapture_FFMPEG::setProperty( [[CvCapture]]_FFMPEG::setProperty( int property_id, double value )@ )
is incorrect.
it uses FFMPEG "@av_seek_frame@" "av_seek_frame" incorrectly because:
# 1) it give it wrong parameters
# @av_seek_frame@ 2) av_seek_frame return only key frames, and so you can not use setProperty function to set the capture to a non-key frame.
h1. FIX:
i written a function that seek for the nearest key frame and from there it grab frames until it reach the desired frame.
<pre><code class="cpp">
#DEFINE SHORTER_DISTANCE_FOR_SEEK_TO_MAKE_IT_FASTER
bool seekKeyAndRunOverFrames(int framenumber)
{
int ret;
if (framenumber > video_st->cur_dts-1)
{
if (framenumber-(video_st->cur_dts-1) > SHORTER_DISTANCE_FOR_SEEK_TO_MAKE_IT_FASTER) {
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);
}
</code></pre>
and it is called by @setProperty@:
<pre><code class="cpp">
setProperty:
bool CvCapture_FFMPEG::setProperty( [[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;
}
</code></pre>
@CV_CAP_PROP_POS_RATIO@
CV_CAP_PROP_POS_RATIO should throw an "not implemented" exception as for many captures we can not get the correct number of frames per stream.
is incorrect.
it uses FFMPEG "@av_seek_frame@" "av_seek_frame" incorrectly because:
# 1) it give it wrong parameters
# @av_seek_frame@ 2) av_seek_frame return only key frames, and so you can not use setProperty function to set the capture to a non-key frame.
h1. FIX:
i written a function that seek for the nearest key frame and from there it grab frames until it reach the desired frame.
<pre><code class="cpp">
#DEFINE SHORTER_DISTANCE_FOR_SEEK_TO_MAKE_IT_FASTER
bool seekKeyAndRunOverFrames(int framenumber)
{
int ret;
if (framenumber > video_st->cur_dts-1)
{
if (framenumber-(video_st->cur_dts-1) > SHORTER_DISTANCE_FOR_SEEK_TO_MAKE_IT_FASTER) {
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);
}
</code></pre>
and it is called by @setProperty@:
<pre><code class="cpp">
setProperty:
bool CvCapture_FFMPEG::setProperty( [[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;
}
</code></pre>
@CV_CAP_PROP_POS_RATIO@
CV_CAP_PROP_POS_RATIO should throw an "not implemented" exception as for many captures we can not get the correct number of frames per stream.