Revision: 27146
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=27146
Author:   ben2610
Date:     2010-02-25 23:12:16 +0100 (Thu, 25 Feb 2010)

Log Message:
-----------
VideoTexture: fix a bug with AV sync that was causing a loss of sync in case of 
rewind to the begining of the file.

Modified Paths:
--------------
    trunk/blender/source/gameengine/VideoTexture/VideoFFmpeg.cpp

Modified: trunk/blender/source/gameengine/VideoTexture/VideoFFmpeg.cpp
===================================================================
--- trunk/blender/source/gameengine/VideoTexture/VideoFFmpeg.cpp        
2010-02-25 21:20:00 UTC (rev 27145)
+++ trunk/blender/source/gameengine/VideoTexture/VideoFFmpeg.cpp        
2010-02-25 22:12:16 UTC (rev 27146)
@@ -304,6 +304,10 @@
        CachePacket *cachePacket;
        bool endOfFile = false;
        int frameFinished = 0;
+       double timeBase = 
av_q2d(video->m_formatCtx->streams[video->m_videoStream]->time_base);
+       int64_t startTs = 
video->m_formatCtx->streams[video->m_videoStream]->start_time;
+       if (startTs == AV_NOPTS_VALUE)
+               startTs = 0;
 
        while (!video->m_stopThread)
        {
@@ -390,7 +394,8 @@
                                                        
currentFrame->frame->data,
                                                        
currentFrame->frame->linesize);
                                                // move frame to queue, this 
frame is necessarily the next one
-                                               currentFrame->framePosition = 
++video->m_curPosition;
+                                               video->m_curPosition = 
(long)((cachePacket->packet.dts-startTs) * (video->m_baseFrameRate*timeBase) + 
0.5);
+                                               currentFrame->framePosition = 
video->m_curPosition;
                                                
pthread_mutex_lock(&video->m_cacheMutex);
                                                
BLI_addtail(&video->m_frameCacheBase, currentFrame);
                                                
pthread_mutex_unlock(&video->m_cacheMutex);
@@ -731,14 +736,15 @@
                // get actual time
                double startTime = PIL_check_seconds_timer();
                double actTime;
-               if (m_isFile && ts >= 0.0)
+               // timestamp passed from audio actuators can sometimes be 
slightly negative
+               if (m_isFile && ts >= -0.5)
                {
                        // allow setting timestamp only when not streaming
                        actTime = ts;
-                       if (m_eof && actTime * actFrameRate() < m_lastFrame) 
+                       if (actTime * actFrameRate() < m_lastFrame) 
                        {
-                               // user is asking to rewind while the playback 
is already finished in the cache.
-                               // we must clean the cache otherwise the eof 
condition will prevent any further reading.
+                               // user is asking to rewind, force a cache 
clear to make sure we will do a seek
+                               // note that this does not decrement m_repeat 
if ts didn't reach m_range[1]
                                stopCache();
                        }
                }
@@ -840,8 +846,9 @@
        int frameFinished;
        int posFound = 1;
        bool frameLoaded = false;
-       long long targetTs = 0;
+       int64_t targetTs = 0;
        CacheFrame *frame;
+       int64_t dts = 0;
 
        if (m_cacheStarted)
        {
@@ -875,6 +882,10 @@
                        {
                                return frame->frame;
                        }
+                       if (frame->framePosition > position)
+                               // this can happen after rewind if the seek 
didn't find the first frame
+                               // the frame in the buffer is ahead of time, 
just leave it there
+                               return NULL;
                        // this frame is not useful, release it
                        pthread_mutex_lock(&m_cacheMutex);
                        BLI_remlink(&m_frameCacheBase, frame);
@@ -882,6 +893,11 @@
                        pthread_mutex_unlock(&m_cacheMutex);
                } while (true);
        }
+       double timeBase = 
av_q2d(m_formatCtx->streams[m_videoStream]->time_base);
+       int64_t startTs = m_formatCtx->streams[m_videoStream]->start_time;
+       if (startTs == AV_NOPTS_VALUE)
+               startTs = 0;
+
        // come here when there is no cache or cache has been stopped
        // locate the frame, by seeking if necessary (seeking is only possible 
for files)
        if (m_isFile)
@@ -901,7 +917,9 @@
                                                m_frame, &frameFinished, 
                                                packet.data, packet.size);
                                        if (frameFinished)
-                                               m_curPosition++;
+                                       {
+                                               m_curPosition = 
(long)((packet.dts-startTs) * (m_baseFrameRate*timeBase) + 0.5);
+                                       }
                                }
                                av_free_packet(&packet);
                                if (position == m_curPosition+1)
@@ -911,16 +929,13 @@
                // if the position is not in preseek, do a direct jump
                if (position != m_curPosition + 1) 
                { 
-                       double timeBase = 
av_q2d(m_formatCtx->streams[m_videoStream]->time_base);
                        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 += startTs;
+                       pos += startTs;
 
                        if (position <= m_curPosition || !m_eof)
                        {
@@ -952,9 +967,7 @@
                                }
                        }
                        // this is the timestamp of the frame we're looking for
-                       targetTs = (int64_t)(position / (m_baseFrameRate * 
timeBase));
-                       if (startTs != AV_NOPTS_VALUE)
-                               targetTs += startTs;
+                       targetTs = (int64_t)(position / (m_baseFrameRate * 
timeBase)) + startTs;
 
                        posFound = 0;
                        avcodec_flush_buffers(m_codecCtx);
@@ -978,14 +991,17 @@
                        avcodec_decode_video(m_codecCtx, 
                                m_frame, &frameFinished, 
                                packet.data, packet.size);
-
+                       // remember dts to compute exact frame number
+                       dts = packet.dts;
                        if (frameFinished && !posFound) 
                        {
-                               if (packet.dts >= targetTs)
+                               if (dts >= targetTs)
+                               {
                                        posFound = 1;
+                               }
                        } 
 
-                       if(frameFinished && posFound == 1) 
+                       if (frameFinished && posFound == 1) 
                        {
                                AVFrame * input = m_frame;
 
@@ -1028,7 +1044,7 @@
        m_eof = m_isFile && !frameLoaded;
        if (frameLoaded)
        {
-               m_curPosition = position;
+               m_curPosition = (long)((dts-startTs) * 
(m_baseFrameRate*timeBase) + 0.5);
                if (m_isThreaded)
                {
                        // normal case for file: first locate, then start cache


_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to