345 |
345 |
and so the filename is needed to reopen the file on backward seeking.
|
346 |
346 |
*/
|
347 |
347 |
char * filename;
|
|
348 |
|
|
349 |
private:
|
|
350 |
bool seekKeyAndRunOverFrames(int framenumber);
|
348 |
351 |
};
|
349 |
352 |
|
350 |
353 |
|
... | ... | |
686 |
689 |
return true;
|
687 |
690 |
}
|
688 |
691 |
|
689 |
|
|
690 |
|
bool CvCapture_FFMPEG::setProperty( int property_id, double value )
|
691 |
|
{
|
692 |
|
if( !video_st ) return false;
|
693 |
|
|
694 |
|
switch( property_id )
|
695 |
|
{
|
696 |
|
case CV_CAP_PROP_POS_MSEC:
|
697 |
|
case CV_CAP_PROP_POS_FRAMES:
|
698 |
|
case CV_CAP_PROP_POS_AVI_RATIO:
|
699 |
|
{
|
700 |
|
int64_t timestamp = 0;
|
701 |
|
AVRational time_base;
|
702 |
|
switch( property_id )
|
703 |
|
{
|
704 |
|
case CV_CAP_PROP_POS_FRAMES:
|
705 |
|
timestamp=(int64_t)value;
|
706 |
|
if(ic->start_time != AV_NOPTS_VALUE_)
|
707 |
|
timestamp += ic->start_time;
|
708 |
|
break;
|
709 |
|
|
710 |
|
case CV_CAP_PROP_POS_MSEC:
|
711 |
|
time_base=ic->streams[video_stream]->time_base;
|
712 |
|
timestamp=(int64_t)(value*(float(time_base.den)/float(time_base.num))/1000);
|
713 |
|
if(ic->start_time != AV_NOPTS_VALUE_)
|
714 |
|
timestamp += ic->start_time;
|
715 |
|
break;
|
716 |
|
|
717 |
|
case CV_CAP_PROP_POS_AVI_RATIO:
|
718 |
|
timestamp=(int64_t)(value*ic->duration);
|
719 |
|
if(ic->start_time != AV_NOPTS_VALUE_ && ic->duration != AV_NOPTS_VALUE_)
|
720 |
|
timestamp += ic->start_time;
|
721 |
|
break;
|
722 |
|
}
|
723 |
|
|
724 |
|
if ( filename )
|
725 |
|
{
|
726 |
|
// ffmpeg's seek doesn't work...
|
727 |
|
if (!slowSeek((int)timestamp))
|
728 |
|
{
|
729 |
|
fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n",
|
730 |
|
(double)timestamp / AV_TIME_BASE);
|
731 |
|
return false;
|
732 |
|
}
|
733 |
|
}
|
734 |
|
else
|
735 |
|
{
|
736 |
|
int ret = av_seek_frame(ic, video_stream, timestamp, 0);
|
737 |
|
if (ret < 0)
|
738 |
|
{
|
739 |
|
fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n",
|
740 |
|
(double)timestamp / AV_TIME_BASE);
|
741 |
|
return false;
|
742 |
|
}
|
743 |
|
}
|
744 |
|
picture_pts=(int64_t)value;
|
745 |
|
}
|
746 |
|
break;
|
747 |
|
|
748 |
|
default:
|
749 |
|
return false;
|
750 |
|
}
|
751 |
|
|
752 |
|
return true;
|
|
692 |
#define short_seek_dist 25
|
|
693 |
bool CvCapture_FFMPEG::seekKeyAndRunOverFrames(int framenumber)
|
|
694 |
{
|
|
695 |
int ret;
|
|
696 |
if (framenumber > video_st->cur_dts-1)
|
|
697 |
{
|
|
698 |
if (framenumber-(video_st->cur_dts-1) > short_seek_dist) {
|
|
699 |
ret=av_seek_frame(ic, video_stream, framenumber, 1);
|
|
700 |
assert(ret>=0);
|
|
701 |
if(ret<0)
|
|
702 |
return false;
|
|
703 |
}
|
|
704 |
grabFrame();
|
|
705 |
while ((video_st->cur_dts-1) < framenumber)
|
|
706 |
if ( !grabFrame() ) return false;
|
|
707 |
}
|
|
708 |
else if ( framenumber < (video_st->cur_dts-1) )
|
|
709 |
{
|
|
710 |
ret=av_seek_frame(ic, video_stream, framenumber, 1);
|
|
711 |
assert(ret>=0);
|
|
712 |
if(ret<0)
|
|
713 |
return false;
|
|
714 |
grabFrame();
|
|
715 |
while ((video_st->cur_dts-1) < framenumber )
|
|
716 |
if ( !grabFrame() ) return false;
|
|
717 |
}
|
|
718 |
return(true);
|
753 |
719 |
}
|
754 |
720 |
|
755 |
|
|
|
721 |
bool CvCapture_FFMPEG::setProperty( int property_id, double value )
|
|
722 |
{
|
|
723 |
if( !video_st ) return false;
|
|
724 |
int ret;
|
|
725 |
int framenumber;
|
|
726 |
AVRational time_base;
|
|
727 |
switch( property_id )
|
|
728 |
{
|
|
729 |
case CV_CAP_PROP_POS_FRAMES:
|
|
730 |
framenumber=(int)value;
|
|
731 |
return seekKeyAndRunOverFrames(framenumber);
|
|
732 |
break;
|
|
733 |
case CV_CAP_PROP_POS_MSEC:
|
|
734 |
framenumber=value/(1000.0f * av_q2d (video_st->time_base));
|
|
735 |
return seekKeyAndRunOverFrames(framenumber);
|
|
736 |
break;
|
|
737 |
|
|
738 |
default:
|
|
739 |
return false;
|
|
740 |
}
|
|
741 |
return false;
|
|
742 |
}
|
756 |
743 |
|
757 |
744 |
CvCapture* cvCreateFileCapture_FFMPEG( const char* filename )
|
758 |
745 |
{
|