BGE VideoTexture: VideoFFmpeg was missing a rewind function: rename stop() to pause() and add stop() that will also reset the frame counter.

This commit is contained in:
Benoit Bolsee 2009-05-26 18:37:46 +00:00
parent 25569b0f7d
commit 328d3128a5
4 changed files with 70 additions and 19 deletions

@ -113,7 +113,10 @@ void Video_open (VideoBase * self, char * file, short captureID)
PyObject * Video_play (PyImage * self) PyObject * Video_play (PyImage * self)
{ if (getVideo(self)->play()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } { if (getVideo(self)->play()) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
// stop video // pause video
PyObject * Video_pause (PyImage * self)
{ if (getVideo(self)->pause()) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
PyObject * Video_stop (PyImage * self) PyObject * Video_stop (PyImage * self)
{ if (getVideo(self)->stop()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } { if (getVideo(self)->stop()) Py_RETURN_TRUE; else Py_RETURN_FALSE; }

@ -80,7 +80,17 @@ public:
} }
return false; return false;
} }
/// stop/pause video /// pause video
virtual bool pause (void)
{
if (m_status == SourcePlaying)
{
m_status = SourceStopped;
return true;
}
return false;
}
/// stop video
virtual bool stop (void) virtual bool stop (void)
{ {
if (m_status == SourcePlaying) if (m_status == SourcePlaying)
@ -170,6 +180,7 @@ template <class T> void Video_init (PyImage * self)
// video functions // video functions
void Video_open (VideoBase * self, char * file, short captureID); void Video_open (VideoBase * self, char * file, short captureID);
PyObject * Video_play (PyImage * self); PyObject * Video_play (PyImage * self);
PyObject * Video_pause (PyImage * self);
PyObject * Video_stop (PyImage * self); PyObject * Video_stop (PyImage * self);
PyObject * Video_refresh (PyImage * self); PyObject * Video_refresh (PyImage * self);
PyObject * Video_getStatus (PyImage * self, void * closure); PyObject * Video_getStatus (PyImage * self, void * closure);

@ -669,15 +669,29 @@ bool VideoFFmpeg::play (void)
} }
// pause video
bool VideoFFmpeg::pause (void)
{
try
{
if (VideoBase::pause())
{
return true;
}
}
CATCH_EXCP;
return false;
}
// stop video // stop video
bool VideoFFmpeg::stop (void) bool VideoFFmpeg::stop (void)
{ {
try try
{ {
if (VideoBase::stop()) VideoBase::stop();
{ // force restart when play
return true; m_lastFrame = -1;
} return true;
} }
CATCH_EXCP; CATCH_EXCP;
return false; return false;
@ -721,6 +735,8 @@ void VideoFFmpeg::loadFrame (void)
{ {
// get actual time // get actual time
double startTime = PIL_check_seconds_timer(); double startTime = PIL_check_seconds_timer();
if (m_lastFrame == -1)
m_startTime = startTime;
double actTime = startTime - m_startTime; double actTime = startTime - m_startTime;
// if video has ended // if video has ended
if (m_isFile && actTime * m_frameRate >= m_range[1]) if (m_isFile && actTime * m_frameRate >= m_range[1])
@ -886,28 +902,47 @@ AVFrame *VideoFFmpeg::grabFrame(long position)
if (position != m_curPosition + 1) if (position != m_curPosition + 1)
{ {
double timeBase = av_q2d(m_formatCtx->streams[m_videoStream]->time_base); double timeBase = av_q2d(m_formatCtx->streams[m_videoStream]->time_base);
long long pos = (long long) int64_t pos = (int64_t)((position - m_preseek) / (m_baseFrameRate*timeBase));
((long long) (position - m_preseek) * AV_TIME_BASE / m_baseFrameRate); int64_t startTs = m_formatCtx->streams[m_videoStream]->start_time;
long long startTs = m_formatCtx->streams[m_videoStream]->start_time; int seekres;
if (pos < 0) if (pos < 0)
pos = 0; pos = 0;
if (startTs != AV_NOPTS_VALUE) if (startTs != AV_NOPTS_VALUE)
pos += (long long)(startTs * AV_TIME_BASE * timeBase); pos += startTs;
if (position <= m_curPosition || !m_eof) if (position <= m_curPosition || !m_eof)
{ {
// no need to seek past the end of the file #if 0
if (av_seek_frame(m_formatCtx, -1, pos, AVSEEK_FLAG_BACKWARD) >= 0) // Tried to make this work but couldn't: seeking on byte is ignored by the
// format plugin and it will generally continue to read from last timestamp.
// Too bad because frame seek is not always able to get the first frame
// of the file.
if (position <= m_preseek)
{
// we can safely go the begining of the file
if (av_seek_frame(m_formatCtx, m_videoStream, 0, AVSEEK_FLAG_BYTE) >= 0)
{
// binary seek does not reset the timestamp, must do it now
av_update_cur_dts(m_formatCtx, m_formatCtx->streams[m_videoStream], startTs);
m_curPosition = 0;
}
}
else
#endif
{ {
// current position is now lost, guess a value. // current position is now lost, guess a value.
// It's not important because it will be set at this end of this function if (av_seek_frame(m_formatCtx, m_videoStream, pos, AVSEEK_FLAG_BACKWARD) >= 0)
m_curPosition = position - m_preseek - 1; {
// current position is now lost, guess a value.
// It's not important because it will be set at this end of this function
m_curPosition = position - m_preseek - 1;
}
} }
} }
// this is the timestamp of the frame we're looking for // this is the timestamp of the frame we're looking for
targetTs = (long long)(((double) position) / m_baseFrameRate / timeBase); targetTs = (int64_t)(position / (m_baseFrameRate * timeBase));
if (startTs != AV_NOPTS_VALUE) if (startTs != AV_NOPTS_VALUE)
targetTs += startTs; targetTs += startTs;
@ -1097,8 +1132,9 @@ int VideoFFmpeg_setDeinterlace (PyImage * self, PyObject * value, void * closure
// methods structure // methods structure
static PyMethodDef videoMethods[] = static PyMethodDef videoMethods[] =
{ // methods from VideoBase class { // methods from VideoBase class
{"play", (PyCFunction)Video_play, METH_NOARGS, "Play video"}, {"play", (PyCFunction)Video_play, METH_NOARGS, "Play (restart) video"},
{"stop", (PyCFunction)Video_stop, METH_NOARGS, "Stop (pause) video"}, {"pause", (PyCFunction)Video_pause, METH_NOARGS, "pause video"},
{"stop", (PyCFunction)Video_stop, METH_NOARGS, "stop video (play will replay it from start)"},
{"refresh", (PyCFunction)Video_refresh, METH_NOARGS, "Refresh video - get its status"}, {"refresh", (PyCFunction)Video_refresh, METH_NOARGS, "Refresh video - get its status"},
{NULL} {NULL}
}; };

@ -83,9 +83,10 @@ public:
/// play video /// play video
virtual bool play (void); virtual bool play (void);
/// stop/pause video /// pause video
virtual bool pause (void);
/// stop video
virtual bool stop (void); virtual bool stop (void);
/// set play range /// set play range
virtual void setRange (double start, double stop); virtual void setRange (double start, double stop);
/// set frame rate /// set frame rate