From 1099a9dd0ead817deb47f5321f40b4a867e957df Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 4 Jan 2012 18:49:11 -0600 Subject: [PATCH] seek/play/pause improvements Since decoding is going on in different threads, there may be delay (beyond just re-order queue) for frames to start popping out. To avoid build up of decoded frames, pop out as many decoded frames as possible before decoding more bitstream. --- xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 2 +- .../Video/DVDVideoCodecGStreamer.cpp | 43 +++++++------------ .../DVDCodecs/Video/DVDVideoCodecGStreamer.h | 1 - .../dvdplayer/DVDCodecs/Video/GstDecoder.cpp | 4 +- xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 17 +++----- 5 files changed, 26 insertions(+), 41 deletions(-) diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h index 20a1c0f80..295aa2dc1 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h @@ -44,7 +44,7 @@ namespace Shaders { class BaseYUV2RGBShader; } namespace Shaders { class BaseVideoFilterShader; } class COpenMaxVideo; -#define NUM_BUFFERS 5 +#define NUM_BUFFERS 3 #undef ALIGN diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecGStreamer.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecGStreamer.cpp index fda5fdd6a..c15a8b788 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecGStreamer.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecGStreamer.cpp @@ -62,7 +62,7 @@ class GSTEGLImageHandle : public EGLImageHandle : EGLImageHandle() { this->eglImage = NULL; - this->buf = gst_buffer_ref(buf); + this->buf = buf; this->width = width; this->height = height; this->format = format; @@ -136,10 +136,9 @@ CDVDVideoCodecGStreamer::CDVDVideoCodecGStreamer() } m_initialized = false; - m_pictureBuffer = NULL; m_decoder = NULL; - m_needData = false; + m_needData = true; m_AppSrc = NULL; m_AppSrcCaps = NULL; m_AppSinkCaps = NULL; @@ -185,12 +184,6 @@ void CDVDVideoCodecGStreamer::Flush() gst_buffer_unref(m_pictureQueue.front()); m_pictureQueue.pop(); } - - if (m_pictureBuffer) - { - gst_buffer_unref(m_pictureBuffer); - m_pictureBuffer = NULL; - } } void CDVDVideoCodecGStreamer::Dispose() @@ -233,6 +226,9 @@ void CDVDVideoCodecGStreamer::Dispose() int CDVDVideoCodecGStreamer::Decode(BYTE* pData, int iSize, double dts, double pts) { + while (pData && !(m_needData||m_reset||m_error)) + usleep(1000); + CSingleLock lock(m_monitorLock); GstBuffer *buffer = NULL; @@ -275,12 +271,6 @@ int CDVDVideoCodecGStreamer::Decode(BYTE* pData, int iSize, double dts, double p } } - if (m_pictureBuffer) - { - gst_buffer_unref(m_pictureBuffer); - m_pictureBuffer = NULL; - } - if (m_pictureQueue.size()) return VC_PICTURE; else @@ -295,18 +285,20 @@ void CDVDVideoCodecGStreamer::Reset() bool CDVDVideoCodecGStreamer::GetPicture(DVDVideoPicture* pDvdVideoPicture) { CSingleLock lock(m_monitorLock); + GstBuffer *buf; if (m_pictureQueue.size()) { - m_pictureBuffer = m_pictureQueue.front(); + buf = m_pictureQueue.front(); m_pictureQueue.pop(); } else return false; - GstCaps *caps = gst_buffer_get_caps(m_pictureBuffer); + GstCaps *caps = gst_buffer_get_caps(buf); if (caps == NULL) { ERR("No caps on decoded buffer"); + gst_buffer_unref(buf); return false; } @@ -326,6 +318,7 @@ bool CDVDVideoCodecGStreamer::GetPicture(DVDVideoPicture* pDvdVideoPicture) ERR("invalid caps on decoded buffer"); gst_caps_unref(m_AppSinkCaps); m_AppSinkCaps = NULL; + gst_buffer_unref(buf); return false; } @@ -344,6 +337,7 @@ bool CDVDVideoCodecGStreamer::GetPicture(DVDVideoPicture* pDvdVideoPicture) ERR("invalid color format on decoded buffer"); gst_caps_unref(m_AppSinkCaps); m_AppSinkCaps = NULL; + gst_buffer_unref(buf); return false; } } @@ -370,11 +364,11 @@ bool CDVDVideoCodecGStreamer::GetPicture(DVDVideoPicture* pDvdVideoPicture) pDvdVideoPicture->iDisplayY = 0; } - pDvdVideoPicture->eglImageHandle = new GSTEGLImageHandle(m_pictureBuffer, m_width, m_height, m_format); + pDvdVideoPicture->eglImageHandle = new GSTEGLImageHandle(buf, m_width, m_height, m_format); pDvdVideoPicture->format = DVDVideoPicture::FMT_EGLIMG; - pDvdVideoPicture->pts = (double)GST_BUFFER_TIMESTAMP(m_pictureBuffer) / 1000.0; + pDvdVideoPicture->pts = (double)GST_BUFFER_TIMESTAMP(buf) / 1000.0; pDvdVideoPicture->dts = DVD_NOPTS_VALUE; - pDvdVideoPicture->iDuration = (double)GST_BUFFER_DURATION(m_pictureBuffer) / 1000.0; + pDvdVideoPicture->iDuration = (double)GST_BUFFER_DURATION(buf) / 1000.0; DBG("create %p (%f)", pDvdVideoPicture->eglImageHandle, pDvdVideoPicture->pts); @@ -409,13 +403,6 @@ void CDVDVideoCodecGStreamer::OnDecodedBuffer(GstBuffer *buffer) return; } - /* throttle decoding if rendering is not keeping up.. */ - while (m_pictureQueue.size() > 4) - { - DBG("throttling: %d", m_pictureQueue.size()); - usleep(1000); - } - if (buffer) { CSingleLock lock(m_monitorLock); @@ -427,11 +414,13 @@ void CDVDVideoCodecGStreamer::OnDecodedBuffer(GstBuffer *buffer) void CDVDVideoCodecGStreamer::OnNeedData() { + DBG("need-data"); m_needData = true; } void CDVDVideoCodecGStreamer::OnEnoughData() { + DBG("enough-data"); m_needData = false; } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecGStreamer.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecGStreamer.h index 75ec4c115..c2883d591 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecGStreamer.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecGStreamer.h @@ -70,7 +70,6 @@ class CDVDVideoCodecGStreamer : public CDVDVideoCodec, public IGstDecoderCallbac GstCaps *m_AppSinkCaps; std::queue m_pictureQueue; - GstBuffer *m_pictureBuffer; CCriticalSection m_needBuffer; CCriticalSection m_monitorLock; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/GstDecoder.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/GstDecoder.cpp index fae6f78f7..bf3dfdc7a 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/GstDecoder.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/GstDecoder.cpp @@ -49,9 +49,9 @@ GstElement *CGstDecoder::Open(GstCaps *sourceCapabilities) DBG("The capabilities from source are %s", capsString); gchar *pipelineString = g_strdup_printf( - "appsrc caps=\"%s\" name=\"AppSrc\" stream-type=seekable format=time block=(boolean)true ! " + "appsrc caps=\"%s\" name=\"AppSrc\" stream-type=seekable format=time max-bytes=4096 ! " "decodebin2 ! ffmpegcolorspace ! " - "appsink caps=\"video/x-raw-yuv,format=(fourcc){I420,NV12}\" name=\"AppSink\" max-buffers=3", + "appsink caps=\"video/x-raw-yuv,format=(fourcc){I420,NV12}\" name=\"AppSink\"", capsString); DBG("Entire pipeline is %s", pipelineString); diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp index 6ae32fa3e..d38887c5a 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp @@ -573,11 +573,13 @@ void CDVDPlayerVideo::Process() // check for a new picture if (iDecoderState & VC_PICTURE) { + do { + // note: decoder may have multiple buffers to return to us, so + // keep popping out buffers until there are no more: + m_pVideoCodec->ClearPicture(&picture); + if (! m_pVideoCodec->GetPicture(&picture)) + break; - // try to retrieve the picture (should never fail!), unless there is a demuxer bug ofcours - m_pVideoCodec->ClearPicture(&picture); - if (m_pVideoCodec->GetPicture(&picture)) - { sPostProcessType.clear(); picture.iGroupId = pPacket->iGroupId; @@ -699,12 +701,7 @@ void CDVDPlayerVideo::Process() iDropped = 0; bRequestDrop = (iResult & EOS_VERYLATE) == EOS_VERYLATE; - } - else - { - CLog::Log(LOGWARNING, "Decoder Error getting videoPicture."); - m_pVideoCodec->Reset(); - } + } while (true); } /*