diff options
author | Benoit Bolsee <benoit.bolsee@online.be> | 2010-03-28 21:50:45 +0400 |
---|---|---|
committer | Benoit Bolsee <benoit.bolsee@online.be> | 2010-03-28 21:50:45 +0400 |
commit | a99d584008f80f6f5361e1af507d8ed6bdd2fffd (patch) | |
tree | bbebe029271a6a3d9f0e6d0634aadf49475707f1 /source/gameengine | |
parent | 8ba96eb1ae5ccfb3cc61f4f8d692dd271964c1af (diff) |
VideoTexture: fix video capture lagging when CPU is busy. This problem was caused by special frame handling that was appropriate for video streaming but not for video capture: drift compensation and no frame skipping. Disable that for video capture to take into account the realtime nature of video.
Diffstat (limited to 'source/gameengine')
-rw-r--r-- | source/gameengine/VideoTexture/VideoFFmpeg.cpp | 22 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/VideoFFmpeg.h | 5 |
2 files changed, 20 insertions, 7 deletions
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 6f7e9b82911..939cd54500a 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -56,7 +56,7 @@ m_frame(NULL), m_frameDeinterlaced(NULL), m_frameRGB(NULL), m_imgConvertCtx(NULL m_deinterlace(false), m_preseek(0), m_videoStream(-1), m_baseFrameRate(25.0), m_lastFrame(-1), m_eof(false), m_externTime(false), m_curPosition(-1), m_startTime(0), m_captWidth(0), m_captHeight(0), m_captRate(0.f), m_isImage(false), -m_isThreaded(false), m_stopThread(false), m_cacheStarted(false) +m_isThreaded(false), m_isStreaming(false), m_stopThread(false), m_cacheStarted(false) { // set video format m_format = RGB24; @@ -298,6 +298,7 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV */ void *VideoFFmpeg::cacheThread(void *data) { + static int count=0; VideoFFmpeg* video = (VideoFFmpeg*)data; // holds the frame that is being decoded CacheFrame *currentFrame = NULL; @@ -306,6 +307,8 @@ void *VideoFFmpeg::cacheThread(void *data) 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; + long pts; + if (startTs == AV_NOPTS_VALUE) startTs = 0; @@ -396,6 +399,7 @@ void *VideoFFmpeg::cacheThread(void *data) // move frame to queue, this frame is necessarily the next one video->m_curPosition = (long)((cachePacket->packet.dts-startTs) * (video->m_baseFrameRate*timeBase) + 0.5); currentFrame->framePosition = video->m_curPosition; + pts = (long)((cachePacket->packet.pts-startTs) * (video->m_baseFrameRate*timeBase) + 0.5); pthread_mutex_lock(&video->m_cacheMutex); BLI_addtail(&video->m_frameCacheBase, currentFrame); pthread_mutex_unlock(&video->m_cacheMutex); @@ -544,8 +548,10 @@ void VideoFFmpeg::openFile (char * filename) #endif ) { - // the file is in fact a streaming source, prevent seeking + // the file is in fact a streaming source, treat as cam to prevent seeking m_isFile = false; + // but it's not handled exactly like a camera. + m_isStreaming = true; // for streaming it is important to do non blocking read m_formatCtx->flags |= AVFMT_FLAG_NONBLOCK; } @@ -811,12 +817,12 @@ void VideoFFmpeg::calcImage (unsigned int texId, double ts) // close the file as we don't need it anymore release(); } - } else if (!m_isFile) + } else if (m_isStreaming) { // we didn't get a frame and we are streaming, this may be due to // a delay in the network or because we are getting the frame too fast. // In the later case, shift time by a small amount to compensate for a drift - m_startTime += 0.01; + m_startTime += 0.001; } } } @@ -878,14 +884,18 @@ AVFrame *VideoFFmpeg::grabFrame(long position) } // for streaming, always return the next frame, // that's what grabFrame does in non cache mode anyway. - if (!m_isFile || frame->framePosition == position) + if (m_isStreaming || frame->framePosition == position) { return frame->frame; } - if (frame->framePosition > position) + // for cam, skip old frames to keep image realtime. + // There should be no risk of clock drift since it all happens on the same CPU + 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); diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h index b9bf69039c7..a19d8969b40 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.h +++ b/source/gameengine/VideoTexture/VideoFFmpeg.h @@ -61,7 +61,7 @@ static inline AVCodecContext* get_codec_from_stream(AVStream* stream) #include "VideoBase.h" -#define CACHE_FRAME_SIZE 5 +#define CACHE_FRAME_SIZE 10 #define CACHE_PACKET_SIZE 30 // type VideoFFmpeg declaration @@ -153,6 +153,9 @@ protected: /// is image loading done in a separate thread? bool m_isThreaded; + /// is streaming or camera? + bool m_isStreaming; + /// keep last image name STR_String m_imageName; |