From 7905911bfde90df5f9d7b9ddce2dbc553bf29479 Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Thu, 3 Jul 2014 14:43:17 +1200 Subject: [PATCH] Bug 1033137 - Fix image lifetime issues in libav backend; r=edwin --- content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp | 5 +++++ content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp | 14 +++++++++++--- content/media/fmp4/ffmpeg/FFmpegH264Decoder.h | 14 +------------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp b/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp index c6ba598f17b0..15773a1fa5d0 100644 --- a/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp +++ b/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp @@ -12,6 +12,7 @@ #include "FFmpegLibs.h" #include "FFmpegLog.h" #include "FFmpegDataDecoder.h" +#include "prsystem.h" namespace mozilla { @@ -83,6 +84,10 @@ FFmpegDataDecoder::Init() // FFmpeg will call back to this to negotiate a video pixel format. mCodecContext.get_format = ChoosePixelFormat; + mCodecContext.thread_count = PR_GetNumberOfProcessors(); + mCodecContext.thread_type = FF_THREAD_FRAME; + mCodecContext.thread_safe_callbacks = false; + mCodecContext.extradata = mExtraData.begin(); mCodecContext.extradata_size = mExtraData.length(); diff --git a/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp b/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp index 2fe03703eb8a..781764419a89 100644 --- a/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp +++ b/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp @@ -42,6 +42,7 @@ FFmpegH264Decoder::Init() NS_ENSURE_SUCCESS(rv, rv); mCodecContext.get_buffer = AllocateBufferCb; + mCodecContext.release_buffer = ReleaseBufferCb; return NS_OK; } @@ -82,8 +83,8 @@ FFmpegH264Decoder::DecodeFrame(mp4_demuxer::MP4Sample* aSample) data = VideoData::CreateFromImage( info, mImageContainer, aSample->byte_offset, - aSample->composition_timestamp, aSample->duration, mCurrentImage, - aSample->is_sync_point, -1, + aSample->composition_timestamp, aSample->duration, + reinterpret_cast(frame->opaque), aSample->is_sync_point, -1, gfx::IntRect(0, 0, mCodecContext.width, mCodecContext.height)); mCallback->Output(data.forget()); @@ -132,6 +133,13 @@ FFmpegH264Decoder::AllocateBufferCb(AVCodecContext* aCodecContext, } } +/* static */ void +FFmpegH264Decoder::ReleaseBufferCb(AVCodecContext* aCodecContext, + AVFrame* aFrame) +{ + reinterpret_cast(aFrame->opaque)->Release(); +} + int FFmpegH264Decoder::AllocateYUV420PVideoBuffer( AVCodecContext* aCodecContext, AVFrame* aFrame) @@ -194,7 +202,7 @@ FFmpegH264Decoder::AllocateYUV420PVideoBuffer( PlanarYCbCrDataFromAVFrame(data, aFrame); ycbcr->SetDataNoCopy(data); - mCurrentImage.swap(image); + aFrame->opaque = reinterpret_cast(image.forget().take()); return 0; } diff --git a/content/media/fmp4/ffmpeg/FFmpegH264Decoder.h b/content/media/fmp4/ffmpeg/FFmpegH264Decoder.h index 9947b8ab30a5..f81aa89218bf 100644 --- a/content/media/fmp4/ffmpeg/FFmpegH264Decoder.h +++ b/content/media/fmp4/ffmpeg/FFmpegH264Decoder.h @@ -49,22 +49,10 @@ private: AVFrame* aFrame); static int AllocateBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame); + static void ReleaseBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame); MediaDataDecoderCallback* mCallback; nsRefPtr mImageContainer; - - /** - * Pass Image back from the allocator to our DoDecode method. - * We *should* return the image back through ffmpeg wrapped in an AVFrame like - * we're meant to. However, if avcodec_decode_video2 fails, it returns a - * completely different frame from the one holding our image and it will be - * leaked. - * This could be handled in the future by wrapping our Image in a reference - * counted AVBuffer and letting ffmpeg hold the nsAutoPtr, but - * currently we have to support older versions of ffmpeg which lack - * refcounting. - */ - nsRefPtr mCurrentImage; }; } // namespace mozilla