Skip to content
Permalink
Browse files

VideoPlayer: fix false positive drop detection for ffmpeg decoder

  • Loading branch information...
FernetMenta authored and popcornmix committed Aug 13, 2016
1 parent 7ff57ab commit e2de38e28d8711373cf2787d8696f52dc47da554
@@ -89,6 +89,60 @@ enum EFilterFlags {
FILTER_ROTATE = 0x40, //< rotate image according to the codec hints
};

CDVDVideoCodecFFmpeg::CDropControl::CDropControl()
{
Reset(true);
}

void CDVDVideoCodecFFmpeg::CDropControl::Reset(bool init)
{
m_lastPTS = AV_NOPTS_VALUE;

if (init || m_state != VALID)
{
m_count = 0;
m_diffPTS = 0;
m_state = INIT;
}
}

void CDVDVideoCodecFFmpeg::CDropControl::Process(int64_t pts, bool drop)
{
if (m_state == INIT)
{
if (pts != AV_NOPTS_VALUE && m_lastPTS != AV_NOPTS_VALUE)
{
m_diffPTS += pts - m_lastPTS;
m_count++;
}
if (m_count > 10)
{
m_diffPTS = m_diffPTS / m_count;
if (m_diffPTS > 0)
{
CLog::Log(LOGNOTICE, "CDVDVideoCodecFFmpeg::CDropControl: calculated diff time: %lld", m_diffPTS);
m_state = CDropControl::VALID;
m_count = 0;
}
}
}
else if (m_state == VALID && !drop)
{
if (std::abs(pts - m_lastPTS - m_diffPTS) > m_diffPTS * 0.2)
{
m_count++;
if (m_count > 5)
{
CLog::Log(LOGNOTICE, "CDVDVideoCodecFFmpeg::CDropControl: lost diff");
Reset(true);
}
}
else
m_count = 0;
}
m_lastPTS = pts;
}

enum AVPixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx, const AVPixelFormat * fmt)
{
CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
@@ -409,6 +463,7 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
UpdateName();

m_processInfo.SetVideoDimensions(m_pCodecContext->coded_width, m_pCodecContext->coded_height);
m_dropCtrl.Reset(true);
return true;
}

@@ -620,13 +675,6 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p

if (!iGotPicture)
{
if (pData && m_pCodecContext->skip_frame > AVDISCARD_DEFAULT)
{
m_droppedFrames++;
if (m_interlaced)
m_droppedFrames++;
}

if (m_pHardware && (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN))
{
int result;
@@ -637,6 +685,22 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p
return VC_BUFFER;
}

int64_t framePTS = av_frame_get_best_effort_timestamp(m_pDecodedFrame);

if (m_pCodecContext->skip_frame > AVDISCARD_DEFAULT)
{
if (m_dropCtrl.m_state == CDropControl::VALID &&
m_dropCtrl.m_lastPTS != AV_NOPTS_VALUE &&
framePTS != AV_NOPTS_VALUE &&
framePTS > (m_dropCtrl.m_lastPTS + m_dropCtrl.m_diffPTS * 1.5))
{
m_droppedFrames++;
if (m_interlaced)
m_droppedFrames++;
}
}
m_dropCtrl.Process(framePTS, m_pCodecContext->skip_frame > AVDISCARD_DEFAULT);

if (m_pDecodedFrame->key_frame)
{
m_started = true;
@@ -730,6 +794,7 @@ void CDVDVideoCodecFFmpeg::Reset()

m_filters = "";
FilterClose();
m_dropCtrl.Reset(false);
}

void CDVDVideoCodecFFmpeg::Reopen()
@@ -122,4 +122,20 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
double m_DAR;
CDVDStreamInfo m_hints;
CDVDCodecOptions m_options;

struct CDropControl
{
CDropControl();
void Reset(bool init);
void Process(int64_t pts, bool drop);

int64_t m_lastPTS;
int64_t m_diffPTS;
int m_count;
enum
{
INIT,
VALID
} m_state;
} m_dropCtrl;
};

0 comments on commit e2de38e

Please sign in to comment.
You can’t perform that action at this time.