Skip to content

Commit

Permalink
videoplayer: adapt lateness detection and dropping to buffering
Browse files Browse the repository at this point in the history
  • Loading branch information
FernetMenta committed Nov 2, 2014
1 parent a693300 commit 4715730
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 48 deletions.
16 changes: 15 additions & 1 deletion xbmc/cores/VideoRenderers/RenderManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi
m_bIsStarted = true;
m_bReconfigured = true;
m_presentstep = PRESENT_IDLE;
m_presentpts = DVD_NOPTS_VALUE;
m_sleeptime = 1.0;
m_presentevent.notifyAll();

m_firstFlipPage = false; // tempfix
Expand Down Expand Up @@ -646,7 +648,7 @@ void CXBMCRenderManager::SetViewMode(int iViewMode)
m_pRenderer->SetViewMode(iViewMode);
}

void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/)
void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, double pts /* = 0 */, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/)
{
{ CSharedLock lock(m_sharedSection);

Expand Down Expand Up @@ -714,6 +716,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L
m.timestamp = timestamp;
m.presentfield = sync;
m.presentmethod = presentmethod;
m.pts = pts;
requeue(m_queued, m_free);

/* signal to any waiters to check state */
Expand Down Expand Up @@ -1105,6 +1108,8 @@ void CXBMCRenderManager::PrepareNextRender()
m_discard.push_back(m_presentsource);
m_presentsource = idx;
m_queued.pop_front();
m_sleeptime = m_Queue[idx].timestamp - clocktime;
m_presentpts = m_Queue[idx].pts;
m_presentevent.notifyAll();
}
}
Expand All @@ -1121,3 +1126,12 @@ void CXBMCRenderManager::DiscardBuffer()
m_presentstep = PRESENT_IDLE;
m_presentevent.notifyAll();
}

bool CXBMCRenderManager::GetStats(double &sleeptime, double &pts, int &bufferLevel)
{
CSingleLock lock(m_presentlock);
sleeptime = m_sleeptime;
pts = m_presentpts;
bufferLevel = m_queued.size() + m_discard.size();
return true;
}
12 changes: 11 additions & 1 deletion xbmc/cores/VideoRenderers/RenderManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,11 @@ class CXBMCRenderManager
*
* @param bStop reference to stop flag of calling thread
* @param timestamp of frame delivered with AddVideoPicture
* @param pts used for lateness detection
* @param source depreciated
* @param sync signals frame, top, or bottom field
*/
void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE);
void FlipPage(volatile bool& bStop, double timestamp = 0.0, double pts = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE);
unsigned int PreInit();
void UnInit();
bool Flush();
Expand Down Expand Up @@ -178,6 +179,12 @@ class CXBMCRenderManager
*/
int WaitForBuffer(volatile bool& bStop, int timeout = 100);

/**
* Can be called by player for lateness detection. This is done best by
* looking at the end of the queue.
*/
bool GetStats(double &sleeptime, double &pts, int &bufferLevel);

/**
* Video player call this on flush in oder to discard any queued frames
*/
Expand Down Expand Up @@ -225,6 +232,7 @@ class CXBMCRenderManager

struct SPresent
{
double pts;
double timestamp;
EFIELDSYNC presentfield;
EPRESENTMETHOD presentmethod;
Expand All @@ -236,6 +244,8 @@ class CXBMCRenderManager

ERenderFormat m_format;

double m_sleeptime;
double m_presentpts;
double m_presentcorr;
double m_presenterr;
double m_errorbuff[ERRORBUFFSIZE];
Expand Down
40 changes: 39 additions & 1 deletion xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ struct DVDVideoUserData
#define DVP_FLAG_NOSKIP 0x00000010 // indicate this picture should never be dropped
#define DVP_FLAG_DROPPED 0x00000020 // indicate that this picture has been dropped in decoder stage, will have no data

#define DVD_CODEC_CTRL_SKIPDEINT 0x01000000 // indicate that this picture was requested to have been dropped in deint stage
#define DVD_CODEC_CTRL_NO_POSTPROC 0x02000000 // see GetCodecStats
#define DVD_CODEC_CTRL_DRAIN 0x04000000 // see GetCodecStats

// DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2!

#define DVP_QSCALE_UNKNOWN 0
Expand All @@ -166,6 +170,8 @@ class CDVDCodecOptions;
#define VC_PICTURE 0x00000004 // the decoder got a picture, call Decode(NULL, 0) again to parse the rest of the data
#define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data
#define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again
#define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped

class CDVDVideoCodec
{
public:
Expand Down Expand Up @@ -283,7 +289,6 @@ class CDVDVideoCodec
return 0;
}


/**
* Number of references to old pictures that are allowed to
* be retained when calling decode on the next demux packet
Expand All @@ -300,4 +305,37 @@ class CDVDVideoCodec
* Interact with user settings so that user disabled codecs are disabled
*/
static bool IsCodecDisabled(DVDCodecAvailableType* map, unsigned int size, AVCodecID id);

/* For calculation of dropping requirements player asks for some information.
*
* - pts : right after decoder, used to detect gaps (dropped frames in decoder)
* - droppedPics : indicates if decoder has dropped a picture
* -1 means that decoder has no info on this.
*
* If codec does not implement this method, pts of decoded frame at input
* video player is used. In case decoder does post-proc and de-interlacing there
* may be quite some frames queued up between exit decoder and entry player.
*/
virtual bool GetCodecStats(double &pts, int &droppedPics)
{
droppedPics= -1;
return false;
}

/**
* Codec can be informed by player with the following flags:
*
* DVD_CODEC_CTRL_NO_POSTPROC :
* if speed is not normal the codec can switch off
* postprocessing and de-interlacing
*
* DVD_CODEC_CTRL_DRAIN :
* codecs may do postprocessing and de-interlacing.
* If video buffers in RenderManager are about to run dry,
* this is signaled to codec. Codec can wait for post-proc
* to be finished instead of returning empty and getting another
* packet.
*
*/
virtual void SetCodecControl(int flags) {}
};
41 changes: 41 additions & 0 deletions xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec()
m_iLastKeyframe = 0;
m_dts = DVD_NOPTS_VALUE;
m_started = false;
m_decoderPts = DVD_NOPTS_VALUE;
}

CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg()
Expand Down Expand Up @@ -342,6 +343,14 @@ void CDVDVideoCodecFFmpeg::SetDropState(bool bDrop)
{
if( m_pCodecContext )
{
if (bDrop && m_pHardware && m_pHardware->CanSkipDeint())
{
m_requestSkipDeint = true;
bDrop = false;
}
else
m_requestSkipDeint = false;

// i don't know exactly how high this should be set
// couldn't find any good docs on it. think it varies
// from codec to codec on what it does
Expand Down Expand Up @@ -543,6 +552,7 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p
void CDVDVideoCodecFFmpeg::Reset()
{
m_started = false;
m_decoderPts = DVD_NOPTS_VALUE;
m_iLastKeyframe = m_pCodecContext->has_b_frames;
avcodec_flush_buffers(m_pCodecContext);

Expand Down Expand Up @@ -640,6 +650,22 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture)
else
pDvdVideoPicture->pts = DVD_NOPTS_VALUE;

if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE)
m_decoderPts = pDvdVideoPicture->pts;
else
m_decoderPts = m_dts;

if (m_requestSkipDeint)
{
pDvdVideoPicture->iFlags |= DVD_CODEC_CTRL_SKIPDEINT;
m_skippedDeint = 1;
}
else
m_skippedDeint = 0;

m_requestSkipDeint = false;
pDvdVideoPicture->iFlags |= m_codecControlFlags;

if(!m_started)
pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;

Expand Down Expand Up @@ -821,3 +847,18 @@ unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences()
else
return 0;
}

bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &droppedPics)
{
pts = m_decoderPts;
if (m_skippedDeint)
droppedPics = m_skippedDeint;
else
droppedPics = -1;
return true;
}

void CDVDVideoCodecFFmpeg::SetCodecControl(int flags)
{
m_codecControlFlags = flags;
}
7 changes: 7 additions & 0 deletions xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
virtual int Check (AVCodecContext* avctx) = 0;
virtual void Reset () {}
virtual unsigned GetAllowedReferences() { return 0; }
virtual bool CanSkipDeint() {return false; }
virtual const std::string Name() = 0;
virtual CCriticalSection* Section() { return NULL; }
};
Expand All @@ -67,6 +68,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open
virtual unsigned GetConvergeCount();
virtual unsigned GetAllowedReferences();
virtual bool GetCodecStats(double &pts, int &droppedPics);
virtual void SetCodecControl(int flags);

bool IsHardwareAllowed() { return !m_bSoftware; }
IHardwareDecoder * GetHardware() { return m_pHardware; };
Expand Down Expand Up @@ -122,4 +125,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
double m_dts;
bool m_started;
std::vector<PixelFormat> m_formats;
double m_decoderPts, m_decoderInterval;
int m_skippedDeint;
bool m_requestSkipDeint;
int m_codecControlFlags;
};

0 comments on commit 4715730

Please sign in to comment.