Skip to content

Commit

Permalink
seek/play/pause improvements
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Rob Clark committed Jan 5, 2012
1 parent 601c3cd commit 1099a9d
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 41 deletions.
2 changes: 1 addition & 1 deletion xbmc/cores/VideoRenderers/LinuxRendererGLES.h
Expand Up @@ -44,7 +44,7 @@ namespace Shaders { class BaseYUV2RGBShader; }
namespace Shaders { class BaseVideoFilterShader; } namespace Shaders { class BaseVideoFilterShader; }
class COpenMaxVideo; class COpenMaxVideo;


#define NUM_BUFFERS 5 #define NUM_BUFFERS 3




#undef ALIGN #undef ALIGN
Expand Down
43 changes: 16 additions & 27 deletions xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecGStreamer.cpp
Expand Up @@ -62,7 +62,7 @@ class GSTEGLImageHandle : public EGLImageHandle
: EGLImageHandle() : EGLImageHandle()
{ {
this->eglImage = NULL; this->eglImage = NULL;
this->buf = gst_buffer_ref(buf); this->buf = buf;
this->width = width; this->width = width;
this->height = height; this->height = height;
this->format = format; this->format = format;
Expand Down Expand Up @@ -136,10 +136,9 @@ CDVDVideoCodecGStreamer::CDVDVideoCodecGStreamer()
} }


m_initialized = false; m_initialized = false;
m_pictureBuffer = NULL;


m_decoder = NULL; m_decoder = NULL;
m_needData = false; m_needData = true;
m_AppSrc = NULL; m_AppSrc = NULL;
m_AppSrcCaps = NULL; m_AppSrcCaps = NULL;
m_AppSinkCaps = NULL; m_AppSinkCaps = NULL;
Expand Down Expand Up @@ -185,12 +184,6 @@ void CDVDVideoCodecGStreamer::Flush()
gst_buffer_unref(m_pictureQueue.front()); gst_buffer_unref(m_pictureQueue.front());
m_pictureQueue.pop(); m_pictureQueue.pop();
} }

if (m_pictureBuffer)
{
gst_buffer_unref(m_pictureBuffer);
m_pictureBuffer = NULL;
}
} }


void CDVDVideoCodecGStreamer::Dispose() void CDVDVideoCodecGStreamer::Dispose()
Expand Down Expand Up @@ -233,6 +226,9 @@ void CDVDVideoCodecGStreamer::Dispose()


int CDVDVideoCodecGStreamer::Decode(BYTE* pData, int iSize, double dts, double pts) 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); CSingleLock lock(m_monitorLock);


GstBuffer *buffer = NULL; GstBuffer *buffer = NULL;
Expand Down Expand Up @@ -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()) if (m_pictureQueue.size())
return VC_PICTURE; return VC_PICTURE;
else else
Expand All @@ -295,18 +285,20 @@ void CDVDVideoCodecGStreamer::Reset()
bool CDVDVideoCodecGStreamer::GetPicture(DVDVideoPicture* pDvdVideoPicture) bool CDVDVideoCodecGStreamer::GetPicture(DVDVideoPicture* pDvdVideoPicture)
{ {
CSingleLock lock(m_monitorLock); CSingleLock lock(m_monitorLock);
GstBuffer *buf;
if (m_pictureQueue.size()) if (m_pictureQueue.size())
{ {
m_pictureBuffer = m_pictureQueue.front(); buf = m_pictureQueue.front();
m_pictureQueue.pop(); m_pictureQueue.pop();
} }
else else
return false; return false;


GstCaps *caps = gst_buffer_get_caps(m_pictureBuffer); GstCaps *caps = gst_buffer_get_caps(buf);
if (caps == NULL) if (caps == NULL)
{ {
ERR("No caps on decoded buffer"); ERR("No caps on decoded buffer");
gst_buffer_unref(buf);
return false; return false;
} }


Expand All @@ -326,6 +318,7 @@ bool CDVDVideoCodecGStreamer::GetPicture(DVDVideoPicture* pDvdVideoPicture)
ERR("invalid caps on decoded buffer"); ERR("invalid caps on decoded buffer");
gst_caps_unref(m_AppSinkCaps); gst_caps_unref(m_AppSinkCaps);
m_AppSinkCaps = NULL; m_AppSinkCaps = NULL;
gst_buffer_unref(buf);
return false; return false;
} }


Expand All @@ -344,6 +337,7 @@ bool CDVDVideoCodecGStreamer::GetPicture(DVDVideoPicture* pDvdVideoPicture)
ERR("invalid color format on decoded buffer"); ERR("invalid color format on decoded buffer");
gst_caps_unref(m_AppSinkCaps); gst_caps_unref(m_AppSinkCaps);
m_AppSinkCaps = NULL; m_AppSinkCaps = NULL;
gst_buffer_unref(buf);
return false; return false;
} }
} }
Expand All @@ -370,11 +364,11 @@ bool CDVDVideoCodecGStreamer::GetPicture(DVDVideoPicture* pDvdVideoPicture)
pDvdVideoPicture->iDisplayY = 0; 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->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->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); DBG("create %p (%f)", pDvdVideoPicture->eglImageHandle, pDvdVideoPicture->pts);


Expand Down Expand Up @@ -409,13 +403,6 @@ void CDVDVideoCodecGStreamer::OnDecodedBuffer(GstBuffer *buffer)
return; return;
} }


/* throttle decoding if rendering is not keeping up.. */
while (m_pictureQueue.size() > 4)
{
DBG("throttling: %d", m_pictureQueue.size());
usleep(1000);
}

if (buffer) if (buffer)
{ {
CSingleLock lock(m_monitorLock); CSingleLock lock(m_monitorLock);
Expand All @@ -427,11 +414,13 @@ void CDVDVideoCodecGStreamer::OnDecodedBuffer(GstBuffer *buffer)


void CDVDVideoCodecGStreamer::OnNeedData() void CDVDVideoCodecGStreamer::OnNeedData()
{ {
DBG("need-data");
m_needData = true; m_needData = true;
} }


void CDVDVideoCodecGStreamer::OnEnoughData() void CDVDVideoCodecGStreamer::OnEnoughData()
{ {
DBG("enough-data");
m_needData = false; m_needData = false;
} }


Expand Down
Expand Up @@ -70,7 +70,6 @@ class CDVDVideoCodecGStreamer : public CDVDVideoCodec, public IGstDecoderCallbac
GstCaps *m_AppSinkCaps; GstCaps *m_AppSinkCaps;


std::queue<GstBuffer *> m_pictureQueue; std::queue<GstBuffer *> m_pictureQueue;
GstBuffer *m_pictureBuffer;


CCriticalSection m_needBuffer; CCriticalSection m_needBuffer;
CCriticalSection m_monitorLock; CCriticalSection m_monitorLock;
Expand Down
4 changes: 2 additions & 2 deletions xbmc/cores/dvdplayer/DVDCodecs/Video/GstDecoder.cpp
Expand Up @@ -49,9 +49,9 @@ GstElement *CGstDecoder::Open(GstCaps *sourceCapabilities)
DBG("The capabilities from source are %s", capsString); DBG("The capabilities from source are %s", capsString);


gchar *pipelineString = g_strdup_printf( 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 ! " "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); capsString);


DBG("Entire pipeline is %s", pipelineString); DBG("Entire pipeline is %s", pipelineString);
Expand Down
17 changes: 7 additions & 10 deletions xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
Expand Up @@ -573,11 +573,13 @@ void CDVDPlayerVideo::Process()
// check for a new picture // check for a new picture
if (iDecoderState & VC_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(); sPostProcessType.clear();


picture.iGroupId = pPacket->iGroupId; picture.iGroupId = pPacket->iGroupId;
Expand Down Expand Up @@ -699,12 +701,7 @@ void CDVDPlayerVideo::Process()
iDropped = 0; iDropped = 0;


bRequestDrop = (iResult & EOS_VERYLATE) == EOS_VERYLATE; bRequestDrop = (iResult & EOS_VERYLATE) == EOS_VERYLATE;
} } while (true);
else
{
CLog::Log(LOGWARNING, "Decoder Error getting videoPicture.");
m_pVideoCodec->Reset();
}
} }


/* /*
Expand Down

0 comments on commit 1099a9d

Please sign in to comment.