forked from bartvdbraak/blender
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:
parent
25569b0f7d
commit
328d3128a5
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user