Use LibAV/FFmpeg logic to detect invalid pts

The logic was extracted from LibAV cmdutils.c. FFmpeg provides an API for that (av_frame_get_best_effort_timestamp()) unfortunately this isn't provided by LibAV.
So copy the logic instead in order to keep compatibility with the two forks.
This commit is contained in:
trav90
2016-12-04 05:24:46 -06:00
committed by roytam1
parent 61c7b38e08
commit 0a7eb3d9c0
2 changed files with 56 additions and 16 deletions
@@ -21,6 +21,45 @@ typedef mozilla::layers::PlanarYCbCrImage PlanarYCbCrImage;
namespace mozilla
{
FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::PtsCorrectionContext()
: mNumFaultyPts(0)
, mNumFaultyDts(0)
, mLastPts(INT64_MIN)
, mLastDts(INT64_MIN)
{
}
int64_t
FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::GuessCorrectPts(int64_t aPts, int64_t aDts)
{
int64_t pts = AV_NOPTS_VALUE;
if (aDts != int64_t(AV_NOPTS_VALUE)) {
mNumFaultyDts += aDts <= mLastDts;
mLastDts = aDts;
}
if (aPts != int64_t(AV_NOPTS_VALUE)) {
mNumFaultyPts += aPts <= mLastPts;
mLastPts = aPts;
}
if ((mNumFaultyPts <= mNumFaultyDts || aDts == int64_t(AV_NOPTS_VALUE)) &&
aPts != int64_t(AV_NOPTS_VALUE)) {
pts = aPts;
} else {
pts = aDts;
}
return pts;
}
void
FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::Reset()
{
mNumFaultyPts = 0;
mNumFaultyDts = 0;
mLastPts = INT64_MIN;
mLastDts = INT64_MIN;
}
FFmpegH264Decoder<LIBAV_VER>::FFmpegH264Decoder(
FlushableMediaTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
const VideoInfo& aConfig,
@@ -53,20 +92,6 @@ FFmpegH264Decoder<LIBAV_VER>::Init()
return NS_OK;
}
int64_t
FFmpegH264Decoder<LIBAV_VER>::GetPts(const AVPacket& packet)
{
#if LIBAVCODEC_VERSION_MAJOR == 53
if (mFrame->pkt_pts == 0) {
return mFrame->pkt_dts;
} else {
return mFrame->pkt_pts;
}
#else
return mFrame->pkt_pts;
#endif
}
FFmpegH264Decoder<LIBAV_VER>::DecodeResult
FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
{
@@ -107,7 +132,7 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
// If we've decoded a frame then we need to output it
if (decoded) {
int64_t pts = GetPts(packet);
int64_t pts = mPtsContext.GuessCorrectPts(mFrame->pkt_pts, mFrame->pkt_dts);
FFMPEG_LOG("Got one frame output with pts=%lld opaque=%lld",
pts, mCodecContext->reordered_opaque);
@@ -310,6 +335,7 @@ FFmpegH264Decoder<LIBAV_VER>::Drain()
nsresult
FFmpegH264Decoder<LIBAV_VER>::Flush()
{
mPtsContext.Reset();
nsresult rv = FFmpegDataDecoder::Flush();
// Even if the above fails we may as well clear our frame queue.
return rv;
+15 -1
View File
@@ -59,7 +59,6 @@ private:
static int AllocateBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame);
static void ReleaseBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame);
int64_t GetPts(const AVPacket& packet);
MediaDataDecoderCallback* mCallback;
nsRefPtr<ImageContainer> mImageContainer;
@@ -67,6 +66,21 @@ private:
uint32_t mPictureHeight;
uint32_t mDisplayWidth;
uint32_t mDisplayHeight;
class PtsCorrectionContext {
public:
PtsCorrectionContext();
int64_t GuessCorrectPts(int64_t aPts, int64_t aDts);
void Reset();
private:
int64_t mNumFaultyPts; /// Number of incorrect PTS values so far
int64_t mNumFaultyDts; /// Number of incorrect DTS values so far
int64_t mLastPts; /// PTS of the last frame
int64_t mLastDts; /// DTS of the last frame
};
PtsCorrectionContext mPtsContext;
};
} // namespace mozilla