Bug 1033137 - Fix image lifetime issues in libav backend; r=edwin

This commit is contained in:
Anthony Jones 2014-07-03 14:43:17 +12:00
Родитель 441cb860ec
Коммит 7905911bfd
3 изменённых файлов: 17 добавлений и 16 удалений

Просмотреть файл

@ -12,6 +12,7 @@
#include "FFmpegLibs.h"
#include "FFmpegLog.h"
#include "FFmpegDataDecoder.h"
#include "prsystem.h"
namespace mozilla
{
@ -83,6 +84,10 @@ FFmpegDataDecoder<LIBAV_VER>::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();

Просмотреть файл

@ -42,6 +42,7 @@ FFmpegH264Decoder<LIBAV_VER>::Init()
NS_ENSURE_SUCCESS(rv, rv);
mCodecContext.get_buffer = AllocateBufferCb;
mCodecContext.release_buffer = ReleaseBufferCb;
return NS_OK;
}
@ -82,8 +83,8 @@ FFmpegH264Decoder<LIBAV_VER>::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<Image*>(frame->opaque), aSample->is_sync_point, -1,
gfx::IntRect(0, 0, mCodecContext.width, mCodecContext.height));
mCallback->Output(data.forget());
@ -132,6 +133,13 @@ FFmpegH264Decoder<LIBAV_VER>::AllocateBufferCb(AVCodecContext* aCodecContext,
}
}
/* static */ void
FFmpegH264Decoder<LIBAV_VER>::ReleaseBufferCb(AVCodecContext* aCodecContext,
AVFrame* aFrame)
{
reinterpret_cast<Image*>(aFrame->opaque)->Release();
}
int
FFmpegH264Decoder<LIBAV_VER>::AllocateYUV420PVideoBuffer(
AVCodecContext* aCodecContext, AVFrame* aFrame)
@ -194,7 +202,7 @@ FFmpegH264Decoder<LIBAV_VER>::AllocateYUV420PVideoBuffer(
PlanarYCbCrDataFromAVFrame(data, aFrame);
ycbcr->SetDataNoCopy(data);
mCurrentImage.swap(image);
aFrame->opaque = reinterpret_cast<void*>(image.forget().take());
return 0;
}

Просмотреть файл

@ -49,22 +49,10 @@ private:
AVFrame* aFrame);
static int AllocateBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame);
static void ReleaseBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame);
MediaDataDecoderCallback* mCallback;
nsRefPtr<ImageContainer> 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<Image>, but
* currently we have to support older versions of ffmpeg which lack
* refcounting.
*/
nsRefPtr<Image> mCurrentImage;
};
} // namespace mozilla