diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-06-09 00:08:19 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-06-09 00:08:19 +0400 |
commit | c8b4cf92067ffeb625aa39003baf5d8f7c3f0025 (patch) | |
tree | c6c50dbc3d90a65fca6c1ca56a93e4a57cf7e154 /source/gameengine/VideoTexture | |
parent | e93db433a086a3e739c0f4026cd500f0b595b0f1 (diff) | |
parent | d76a6f5231c015c35123d22e1f5c3ffcdfbf9bbd (diff) |
2.50:
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r19820:HEAD
Notes:
* Game and sequencer RNA, and sequencer header are now out of date
a bit after changes in trunk.
* I didn't know how to port these bugfixes, most likely they are
not needed anymore.
* Fix "duplicate strip" always increase the user count for ipo.
* IPO pinning on sequencer strips was lost during Undo.
Diffstat (limited to 'source/gameengine/VideoTexture')
-rw-r--r-- | source/gameengine/VideoTexture/BlendType.h | 6 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/FilterBlueScreen.cpp | 7 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/FilterColor.cpp | 21 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/FilterNormal.cpp | 7 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/FilterSource.cpp | 21 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/ImageBase.cpp | 8 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/ImageBuff.cpp | 10 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/ImageMix.cpp | 15 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/ImageRender.cpp | 71 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/ImageViewport.cpp | 7 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/PyTypeList.cpp | 1 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/Texture.cpp | 16 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/VideoBase.cpp | 7 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/VideoBase.h | 13 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/VideoFFmpeg.cpp | 86 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/VideoFFmpeg.h | 5 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/blendVideoTex.cpp | 46 |
17 files changed, 263 insertions, 84 deletions
diff --git a/source/gameengine/VideoTexture/BlendType.h b/source/gameengine/VideoTexture/BlendType.h index ac3ed8812a6..8b243c43912 100644 --- a/source/gameengine/VideoTexture/BlendType.h +++ b/source/gameengine/VideoTexture/BlendType.h @@ -25,6 +25,7 @@ http://www.gnu.org/copyleft/lesser.txt. /// class allows check type of blender python object and access its contained object +/// MUST ONLY BE USED FOR KX classes that are descendent of PyObjectPlus template <class PyObj> class BlendType { public: @@ -48,8 +49,9 @@ public: // if pointer to type is set and don't match to type of provided object, return NULL else if (obj->ob_type != m_objType) return NULL; - // return pointer to object - return (PyObj*)obj; + // return pointer to object, this class can only be used for KX object => + // the Py object is actually a proxy + return (PyObj*)BGE_PROXY_REF(obj); } /// parse arguments to get object diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp index 43d7566102a..6b23105a278 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp +++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp @@ -135,8 +135,13 @@ static PyGetSetDef filterBSGetSets[] = // define python type PyTypeObject FilterBlueScreenType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterBlueScreen", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp index 22ee729b200..5ff1f7f11ce 100644 --- a/source/gameengine/VideoTexture/FilterColor.cpp +++ b/source/gameengine/VideoTexture/FilterColor.cpp @@ -41,8 +41,13 @@ static PyGetSetDef filterGrayGetSets[] = // define python type PyTypeObject FilterGrayType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterGray", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -173,8 +178,13 @@ static PyGetSetDef filterColorGetSets[] = // define python type PyTypeObject FilterColorType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterColor", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -307,8 +317,13 @@ static PyGetSetDef filterLevelGetSets[] = // define python type PyTypeObject FilterLevelType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterLevel", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp index a7266967efb..9a2b1e90d5a 100644 --- a/source/gameengine/VideoTexture/FilterNormal.cpp +++ b/source/gameengine/VideoTexture/FilterNormal.cpp @@ -124,8 +124,13 @@ static PyGetSetDef filterNormalGetSets[] = // define python type PyTypeObject FilterNormalType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterNormal", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/FilterSource.cpp b/source/gameengine/VideoTexture/FilterSource.cpp index f3676e93a6d..4c75e14bbac 100644 --- a/source/gameengine/VideoTexture/FilterSource.cpp +++ b/source/gameengine/VideoTexture/FilterSource.cpp @@ -36,8 +36,13 @@ http://www.gnu.org/copyleft/lesser.txt. // define python type PyTypeObject FilterRGB24Type = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterRGB24", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -82,8 +87,13 @@ PyTypeObject FilterRGB24Type = // define python type PyTypeObject FilterRGBA32Type = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterRGBA32", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -128,8 +138,13 @@ PyTypeObject FilterRGBA32Type = // define python type PyTypeObject FilterBGR24Type = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterBGR24", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp index dcca20de24a..5e2841271a6 100644 --- a/source/gameengine/VideoTexture/ImageBase.cpp +++ b/source/gameengine/VideoTexture/ImageBase.cpp @@ -437,7 +437,9 @@ PyObject * Image_getSource (PyImage * self, PyObject * args) { // get arguments char * id; - if (self->m_image != NULL && PyArg_ParseTuple(args, "s", &id)) + if (!PyArg_ParseTuple(args, "s:getSource", &id)) + return NULL; + if (self->m_image != NULL) { // get source object PyObject * src = reinterpret_cast<PyObject*>(self->m_image->getSource(id)); @@ -460,7 +462,9 @@ PyObject * Image_setSource (PyImage * self, PyObject * args) // get arguments char * id; PyObject * obj; - if (self->m_image != NULL && PyArg_ParseTuple(args, "sO", &id, &obj)) + if (!PyArg_ParseTuple(args, "sO:setSource", &id, &obj)) + return NULL; + if (self->m_image != NULL) { // check type of object if (pyImageTypes.in(obj->ob_type)) diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp index 19ad17ac643..c7185660e83 100644 --- a/source/gameengine/VideoTexture/ImageBuff.cpp +++ b/source/gameengine/VideoTexture/ImageBuff.cpp @@ -71,10 +71,9 @@ static PyObject * load (PyImage * self, PyObject * args) short width; short height; // parse parameters - if (!PyArg_ParseTuple(args, "s#hh", &buff, &buffSize, &width, &height)) + if (!PyArg_ParseTuple(args, "s#hh:load", &buff, &buffSize, &width, &height)) { // report error - PyErr_SetString(PyExc_TypeError, "Parameters are not correct"); return NULL; } // else check buffer size @@ -123,8 +122,13 @@ static PyGetSetDef imageBuffGetSets[] = // define python type PyTypeObject ImageBuffType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageBuff", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp index b07b362818c..067143e57bb 100644 --- a/source/gameengine/VideoTexture/ImageMix.cpp +++ b/source/gameengine/VideoTexture/ImageMix.cpp @@ -109,7 +109,9 @@ PyObject * getWeight (PyImage * self, PyObject * args) short weight = 0; // get arguments char * id; - if (self->m_image != NULL && PyArg_ParseTuple(args, "s", &id)) + if (!PyArg_ParseTuple(args, "s:getWeight", &id)) + return NULL; + if (self->m_image != NULL) // get weight weight = getImageMix(self)->getWeight(id); // return weight @@ -123,7 +125,9 @@ PyObject * setWeight (PyImage * self, PyObject * args) // get arguments char * id; short weight = 0; - if (self->m_image != NULL && PyArg_ParseTuple(args, "sh", &id, &weight)) + if (!PyArg_ParseTuple(args, "sh:setWeight", &id, &weight)) + return NULL; + if (self->m_image != NULL) // set weight if (!getImageMix(self)->setWeight(id, weight)) { @@ -162,8 +166,13 @@ static PyGetSetDef imageMixGetSets[] = // define python type PyTypeObject ImageMixType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageMix", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 09c3c22f258..c4fb1fefd9c 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -181,7 +181,6 @@ void ImageRender::Render() frustrum.camnear = -mirrorOffset[2]; frustrum.camfar = -mirrorOffset[2]+m_clip; } - const float ortho = 100.0; const RAS_IRasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode(); // The screen area that ImageViewport will copy is also the rendering zone @@ -214,44 +213,48 @@ void ImageRender::Render() float farfrust = m_camera->GetCameraFar(); float aspect_ratio = 1.0f; Scene *blenderScene = m_scene->GetBlenderScene(); + MT_Matrix4x4 projmat; - if (orthographic) { - lens *= ortho; - nearfrust = (nearfrust + 1.0)*ortho; - farfrust *= ortho; - } // compute the aspect ratio from frame blender scene settings so that render to texture // works the same in Blender and in Blender player if (blenderScene->r.ysch != 0) - aspect_ratio = float(blenderScene->r.xsch) / float(blenderScene->r.ysch); - - RAS_FramingManager::ComputeDefaultFrustum( - nearfrust, - farfrust, - lens, - aspect_ratio, - frustrum); - - MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( - frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); - + aspect_ratio = float(blenderScene->r.xsch*blenderScene->r.xasp) / float(blenderScene->r.ysch*blenderScene->r.yasp); + + if (orthographic) { + + RAS_FramingManager::ComputeDefaultOrtho( + nearfrust, + farfrust, + m_camera->GetScale(), + aspect_ratio, + frustrum + ); + + projmat = m_rasterizer->GetOrthoMatrix( + frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + } else + { + RAS_FramingManager::ComputeDefaultFrustum( + nearfrust, + farfrust, + lens, + aspect_ratio, + frustrum); + + projmat = m_rasterizer->GetFrustumMatrix( + frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + } m_camera->SetProjectionMatrix(projmat); } MT_Transform camtrans(m_camera->GetWorldToCamera()); - if (!m_camera->GetCameraData()->m_perspective) - camtrans.getOrigin()[2] *= ortho; MT_Matrix4x4 viewmat(camtrans); - m_rasterizer->SetViewMatrix(viewmat, m_camera->NodeGetWorldPosition(), - m_camera->GetCameraLocation(), m_camera->GetCameraOrientation()); + m_rasterizer->SetViewMatrix(viewmat, m_camera->NodeGetWorldOrientation(), m_camera->NodeGetWorldPosition(), m_camera->GetCameraData()->m_perspective); m_camera->SetModelviewMatrix(viewmat); // restore the stereo mode now that the matrix is computed m_rasterizer->SetStereoMode(stereomode); - // do not update the mesh transform, we don't want to do it more than once per frame - //m_scene->UpdateMeshTransformations(); - m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera); m_scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools); @@ -373,8 +376,13 @@ static PyGetSetDef imageRenderGetSets[] = // define python type PyTypeObject ImageRenderType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageRender", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -553,8 +561,8 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj float yaxis[3] = {0.f, 1.f, 0.f}; float mirrorMat[3][3]; float left, right, top, bottom, back; - - m_camera= new KX_Camera(scene, KX_Scene::m_callbacks, camdata); + // make sure this camera will delete its node + m_camera= new KX_Camera(scene, KX_Scene::m_callbacks, camdata, true, true); m_camera->SetName("__mirror__cam__"); // don't add the camera to the scene object list, it doesn't need to be accessible m_owncamera = true; @@ -707,8 +715,13 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj // define python type PyTypeObject ImageMirrorType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageMirror", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index a4e36b5948c..d2c23e758f6 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -289,8 +289,13 @@ static PyGetSetDef imageViewportGetSets[] = // define python type PyTypeObject ImageViewportType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageViewport", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp index 6d2676dce09..2d571675dbd 100644 --- a/source/gameengine/VideoTexture/PyTypeList.cpp +++ b/source/gameengine/VideoTexture/PyTypeList.cpp @@ -45,7 +45,6 @@ bool PyTypeList::in (PyTypeObject * type) /// add type to list void PyTypeList::add (PyTypeObject * type, const char * name) { - PyTypeListItem * typeItem; // if list doesn't exist, create it if (m_list.get() == NULL) m_list.reset(new PyTypeListType()); diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index 3533cee0f7f..f4105652f80 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -50,7 +50,7 @@ http://www.gnu.org/copyleft/lesser.txt. // macro for exception handling and logging #define CATCH_EXCP catch (Exception & exp) \ -{ exp.report(); } +{ exp.report(); return NULL; } // Blender GameObject type @@ -162,11 +162,12 @@ void Texture_dealloc (Texture * self) // release renderer Py_XDECREF(self->m_source); // close texture - Texture_close(self); + PyObject* ret = Texture_close(self); + Py_DECREF(ret); // release scaled image buffer delete [] self->m_scaledImg; // release object - self->ob_type->tp_free((PyObject*)self); + ((PyObject *)self)->ob_type->tp_free((PyObject*)self); } @@ -278,7 +279,7 @@ PyObject * Texture_refresh (Texture * self, PyObject * args) { // get parameter - refresh source PyObject * param; - if (!PyArg_ParseTuple(args, "O", ¶m) || !PyBool_Check(param)) + if (!PyArg_ParseTuple(args, "O:refresh", ¶m) || !PyBool_Check(param)) { // report error PyErr_SetString(PyExc_TypeError, "The value must be a bool"); @@ -433,8 +434,13 @@ static PyGetSetDef textureGetSets[] = // class Texture declaration PyTypeObject TextureType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.Texture", /*tp_name*/ sizeof(Texture), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp index 3c703d75cda..5d449a158d8 100644 --- a/source/gameengine/VideoTexture/VideoBase.cpp +++ b/source/gameengine/VideoTexture/VideoBase.cpp @@ -113,7 +113,10 @@ void Video_open (VideoBase * self, char * file, short captureID) PyObject * Video_play (PyImage * self) { 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) { if (getVideo(self)->stop()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } @@ -146,7 +149,7 @@ int Video_setRange (PyImage * self, PyObject * value, void * closure) || !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 0)) || !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 1))) { - PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 longs"); + PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 float"); return -1; } // set range diff --git a/source/gameengine/VideoTexture/VideoBase.h b/source/gameengine/VideoTexture/VideoBase.h index 15ecb7a78f4..0c8668ee0bc 100644 --- a/source/gameengine/VideoTexture/VideoBase.h +++ b/source/gameengine/VideoTexture/VideoBase.h @@ -80,7 +80,17 @@ public: } 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) { if (m_status == SourcePlaying) @@ -170,6 +180,7 @@ template <class T> void Video_init (PyImage * self) // video functions void Video_open (VideoBase * self, char * file, short captureID); PyObject * Video_play (PyImage * self); +PyObject * Video_pause (PyImage * self); PyObject * Video_stop (PyImage * self); PyObject * Video_refresh (PyImage * self); PyObject * Video_getStatus (PyImage * self, void * closure); diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 5265b0ecb93..1a5481488c0 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -117,6 +117,7 @@ bool VideoFFmpeg::release() } m_codec = NULL; m_status = SourceStopped; + m_lastFrame = -1; return true; } @@ -669,12 +670,12 @@ bool VideoFFmpeg::play (void) } -// stop video -bool VideoFFmpeg::stop (void) +// pause video +bool VideoFFmpeg::pause (void) { try { - if (VideoBase::stop()) + if (VideoBase::pause()) { return true; } @@ -683,6 +684,20 @@ bool VideoFFmpeg::stop (void) return false; } +// stop video +bool VideoFFmpeg::stop (void) +{ + try + { + VideoBase::stop(); + // force restart when play + m_lastFrame = -1; + return true; + } + CATCH_EXCP; + return false; +} + // set video range void VideoFFmpeg::setRange (double start, double stop) @@ -721,6 +736,8 @@ void VideoFFmpeg::loadFrame (void) { // get actual time double startTime = PIL_check_seconds_timer(); + if (m_lastFrame == -1 && !m_isFile) + m_startTime = startTime; double actTime = startTime - m_startTime; // if video has ended if (m_isFile && actTime * m_frameRate >= m_range[1]) @@ -886,28 +903,47 @@ AVFrame *VideoFFmpeg::grabFrame(long position) if (position != m_curPosition + 1) { double timeBase = av_q2d(m_formatCtx->streams[m_videoStream]->time_base); - long long pos = (long long) - ((long long) (position - m_preseek) * AV_TIME_BASE / m_baseFrameRate); - long long startTs = m_formatCtx->streams[m_videoStream]->start_time; + int64_t pos = (int64_t)((position - m_preseek) / (m_baseFrameRate*timeBase)); + int64_t startTs = m_formatCtx->streams[m_videoStream]->start_time; + int seekres; if (pos < 0) pos = 0; if (startTs != AV_NOPTS_VALUE) - pos += (long long)(startTs * AV_TIME_BASE * timeBase); + pos += startTs; if (position <= m_curPosition || !m_eof) { - // no need to seek past the end of the file - if (av_seek_frame(m_formatCtx, -1, pos, AVSEEK_FLAG_BACKWARD) >= 0) +#if 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. - // It's not important because it will be set at this end of this function - m_curPosition = position - m_preseek - 1; + if (av_seek_frame(m_formatCtx, m_videoStream, pos, AVSEEK_FLAG_BACKWARD) >= 0) + { + // 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 - targetTs = (long long)(((double) position) / m_baseFrameRate / timeBase); + targetTs = (int64_t)(position / (m_baseFrameRate * timeBase)); if (startTs != AV_NOPTS_VALUE) targetTs += startTs; @@ -1097,8 +1133,9 @@ int VideoFFmpeg_setDeinterlace (PyImage * self, PyObject * value, void * closure // methods structure static PyMethodDef videoMethods[] = { // methods from VideoBase class - {"play", (PyCFunction)Video_play, METH_NOARGS, "Play video"}, - {"stop", (PyCFunction)Video_stop, METH_NOARGS, "Stop (pause) video"}, + {"play", (PyCFunction)Video_play, METH_NOARGS, "Play (restart) 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"}, {NULL} }; @@ -1123,8 +1160,13 @@ static PyGetSetDef videoGetSets[] = // python type declaration PyTypeObject VideoFFmpegType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.VideoFFmpeg", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -1173,7 +1215,7 @@ static int ImageFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds char * file = NULL; // get parameters - if (!PyArg_ParseTuple(args, "s", &file)) + if (!PyArg_ParseTuple(args, "s:ImageFFmpeg", &file)) return -1; try @@ -1198,8 +1240,9 @@ static int ImageFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds PyObject * Image_reload (PyImage * self, PyObject *args) { char * newname = NULL; - - if (self->m_image != NULL && PyArg_ParseTuple(args, "|s", &newname)) + if (!PyArg_ParseTuple(args, "|s:reload", &newname)) + return NULL; + if (self->m_image != NULL) { VideoFFmpeg* video = getFFmpeg(self); // check type of object @@ -1241,8 +1284,13 @@ static PyGetSetDef imageGetSets[] = // python type declaration PyTypeObject ImageFFmpegType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageFFmpeg", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h index 51f1067c466..fbd04e7e1fc 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.h +++ b/source/gameengine/VideoTexture/VideoFFmpeg.h @@ -83,9 +83,10 @@ public: /// play video virtual bool play (void); - /// stop/pause video + /// pause video + virtual bool pause (void); + /// stop video virtual bool stop (void); - /// set play range virtual void setRange (double start, double stop); /// set frame rate diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp index c11e7fffecd..1dcc72c8f7d 100644 --- a/source/gameengine/VideoTexture/blendVideoTex.cpp +++ b/source/gameengine/VideoTexture/blendVideoTex.cpp @@ -74,7 +74,7 @@ static PyObject * getLastError (PyObject *self, PyObject *args) static PyObject * setLogFile (PyObject *self, PyObject *args) { // get parameters - if (!PyArg_ParseTuple(args, "s", &Exception::m_logFile)) + if (!PyArg_ParseTuple(args, "s:setLogFile", &Exception::m_logFile)) return Py_BuildValue("i", -1); // log file was loaded return Py_BuildValue("i", 0); @@ -86,7 +86,7 @@ static PyObject * imageToArray (PyObject * self, PyObject *args) { // parameter is Image object PyObject * pyImg; - if (!PyArg_ParseTuple(args, "O", &pyImg) || !pyImageTypes.in(pyImg->ob_type)) + if (!PyArg_ParseTuple(args, "O:imageToArray", &pyImg) || !pyImageTypes.in(pyImg->ob_type)) { // if object is incorect, report error PyErr_SetString(PyExc_TypeError, "VideoTexture.imageToArray(image): The value must be a image source object"); @@ -159,8 +159,25 @@ static void registerAllTypes(void) pyFilterTypes.add(&FilterBGR24Type, "FilterBGR24"); } + +#if (PY_VERSION_HEX >= 0x03000000) +static struct PyModuleDef VideoTexture_module_def = { + {}, /* m_base */ + "VideoTexture", /* m_name */ + "Module that allows to play video files on textures in GameBlender.", /* m_doc */ + 0, /* m_size */ + moduleMethods, /* m_methods */ + 0, /* m_reload */ + 0, /* m_traverse */ + 0, /* m_clear */ + 0, /* m_free */ +}; +#endif + PyObject* initVideoTexture(void) { + PyObject * m; + // initialize GL extensions //bgl::InitExtensions(0); @@ -175,9 +192,25 @@ PyObject* initVideoTexture(void) if (PyType_Ready(&TextureType) < 0) return NULL; - PyObject * m = Py_InitModule4("VideoTexture", moduleMethods, - "Module that allows to play video files on textures in GameBlender.", - (PyObject*)NULL,PYTHON_API_VERSION); + /* Use existing module where possible + * be careful not to init any runtime vars after this */ + m = PyImport_ImportModule( "VideoTexture" ); + if(m) { + Py_DECREF(m); + return m; + } + else { + PyErr_Clear(); + +#if (PY_VERSION_HEX >= 0x03000000) + m = PyModule_Create(&VideoTexture_module_def); +#else + m = Py_InitModule4("VideoTexture", moduleMethods, + "Module that allows to play video files on textures in GameBlender.", + (PyObject*)NULL,PYTHON_API_VERSION); +#endif + } + if (m == NULL) return NULL; @@ -187,9 +220,10 @@ PyObject* initVideoTexture(void) Py_INCREF(&TextureType); PyModule_AddObject(m, (char*)"Texture", (PyObject*)&TextureType); - + // init last error description Exception::m_lastError[0] = '\0'; + return m; } |