diff --git a/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp index e0c20557db..a0de21915d 100644 --- a/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp @@ -35,6 +35,22 @@ FFmpegAudioDecoder::Init() return NS_OK; } +void +FFmpegAudioDecoder::InitCodecContext() +{ + MOZ_ASSERT(mCodecContext); + // We do not want to set this value to 0 as FFmpeg by default will + // use the number of cores, which with our mozlibavutil get_cpu_count + // isn't implemented. + mCodecContext->thread_count = 1; + // FFmpeg takes this as a suggestion for what format to use for audio samples. + uint32_t major, minor; + FFmpegRuntimeLinker::GetVersion(major, minor); + // LibAV 0.8 produces rubbish float interleaved samples, request 16 bits audio. + mCodecContext->request_sample_fmt = + (major == 53) ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLT; +} + static AudioDataValue* CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumAFrames) { diff --git a/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.h b/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.h index d0934fcda5..5f8f81788b 100644 --- a/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.h +++ b/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.h @@ -28,6 +28,7 @@ public: virtual nsresult Init() override; virtual nsresult Input(MediaRawData* aSample) override; virtual nsresult Drain() override; + void InitCodecContext() override; static AVCodecID GetCodecId(const nsACString& aMimeType); private: diff --git a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp index 29689ce6fb..ad794c02fb 100644 --- a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp @@ -27,13 +27,8 @@ FFmpegDataDecoder::FFmpegDataDecoder(FlushableMediaTaskQueue* aTaskQu , mFrame(NULL) , mExtraData(nullptr) , mCodecID(aCodecID) - , mCodecParser(nullptr) { MOZ_COUNT_CTOR(FFmpegDataDecoder); - if (mCodecParser) { - av_parser_close(mCodecParser); - mCodecParser = nullptr; - } } FFmpegDataDecoder::~FFmpegDataDecoder() @@ -41,27 +36,6 @@ FFmpegDataDecoder::~FFmpegDataDecoder() MOZ_COUNT_DTOR(FFmpegDataDecoder); } -/** - * FFmpeg calls back to this function with a list of pixel formats it supports. - * We choose a pixel format that we support and return it. - * For now, we just look for YUV420P as it is the only non-HW accelerated format - * supported by FFmpeg's H264 decoder. - */ -static PixelFormat -ChoosePixelFormat(AVCodecContext* aCodecContext, const PixelFormat* aFormats) -{ - FFMPEG_LOG("Choosing FFmpeg pixel format for video decoding."); - for (; *aFormats > -1; aFormats++) { - if (*aFormats == PIX_FMT_YUV420P || *aFormats == PIX_FMT_YUVJ420P) { - FFMPEG_LOG("Requesting pixel format YUV420P."); - return PIX_FMT_YUV420P; - } - } - - NS_WARNING("FFmpeg does not share any supported pixel formats."); - return PIX_FMT_NONE; -} - nsresult FFmpegDataDecoder::Init() { @@ -82,19 +56,7 @@ FFmpegDataDecoder::Init() mCodecContext->opaque = this; - // FFmpeg takes this as a suggestion for what format to use for audio samples. - uint32_t major, minor; - FFmpegRuntimeLinker::GetVersion(major, minor); - // LibAV 0.8 produces rubbish float interleaved samples, request 16 bits audio. - mCodecContext->request_sample_fmt = major == 53 ? - AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLT; - - // 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_SLICE | FF_THREAD_FRAME; - mCodecContext->thread_safe_callbacks = false; + InitCodecContext(); if (mExtraData) { mCodecContext->extradata_size = mExtraData->Length(); @@ -126,11 +88,6 @@ FFmpegDataDecoder::Init() return NS_ERROR_FAILURE; } - mCodecParser = av_parser_init(mCodecID); - if (mCodecParser) { - mCodecParser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - } - FFMPEG_LOG("FFmpeg init successful."); return NS_OK; } diff --git a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h index 6e88747ca4..4ff360bf4a 100644 --- a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h +++ b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h @@ -38,6 +38,7 @@ public: static AVCodec* FindAVCodec(AVCodecID aCodec); protected: + virtual void InitCodecContext() {} AVFrame* PrepareFrame(); FlushableMediaTaskQueue* mTaskQueue; @@ -45,7 +46,6 @@ protected: AVFrame* mFrame; nsRefPtr mExtraData; AVCodecID mCodecID; - AVCodecParserContext* mCodecParser; private: static bool sFFmpegInitDone; diff --git a/dom/media/platforms/ffmpeg/FFmpegH264Decoder.cpp b/dom/media/platforms/ffmpeg/FFmpegH264Decoder.cpp index 23951996b1..64458934ee 100644 --- a/dom/media/platforms/ffmpeg/FFmpegH264Decoder.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegH264Decoder.cpp @@ -21,6 +21,27 @@ typedef mozilla::layers::PlanarYCbCrImage PlanarYCbCrImage; namespace mozilla { +/** + * FFmpeg calls back to this function with a list of pixel formats it supports. + * We choose a pixel format that we support and return it. + * For now, we just look for YUV420P as it is the only non-HW accelerated format + * supported by FFmpeg's H264 decoder. + */ +static PixelFormat +ChoosePixelFormat(AVCodecContext* aCodecContext, const PixelFormat* aFormats) +{ + FFMPEG_LOG("Choosing FFmpeg pixel format for video decoding."); + for (; *aFormats > -1; aFormats++) { + if (*aFormats == PIX_FMT_YUV420P || *aFormats == PIX_FMT_YUVJ420P) { + FFMPEG_LOG("Requesting pixel format YUV420P."); + return PIX_FMT_YUV420P; + } + } + + NS_WARNING("FFmpeg does not share any supported pixel formats."); + return PIX_FMT_NONE; +} + FFmpegH264Decoder::PtsCorrectionContext::PtsCorrectionContext() : mNumFaultyPts(0) , mNumFaultyDts(0) @@ -71,6 +92,7 @@ FFmpegH264Decoder::FFmpegH264Decoder( , mPictureHeight(aConfig.mImage.height) , mDisplayWidth(aConfig.mDisplay.width) , mDisplayHeight(aConfig.mDisplay.height) + , mCodecParser(nullptr) { MOZ_COUNT_CTOR(FFmpegH264Decoder); // Use a new MediaByteBuffer as the object will be modified during initialization. @@ -84,10 +106,25 @@ FFmpegH264Decoder::Init() nsresult rv = FFmpegDataDecoder::Init(); NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; +} + +void +FFmpegH264Decoder::InitCodecContext() +{ mCodecContext->width = mPictureWidth; mCodecContext->height = mPictureHeight; - return NS_OK; + mCodecContext->thread_count = PR_GetNumberOfProcessors(); + mCodecContext->thread_type = FF_THREAD_SLICE | FF_THREAD_FRAME; + + // FFmpeg will call back to this to negotiate a video pixel format. + mCodecContext->get_format = ChoosePixelFormat; + + mCodecParser = av_parser_init(mCodecID); + if (mCodecParser) { + mCodecParser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + } } FFmpegH264Decoder::DecodeResult @@ -292,6 +329,10 @@ FFmpegH264Decoder::Flush() FFmpegH264Decoder::~FFmpegH264Decoder() { MOZ_COUNT_DTOR(FFmpegH264Decoder); + if (mCodecParser) { + av_parser_close(mCodecParser); + mCodecParser = nullptr; + } } AVCodecID diff --git a/dom/media/platforms/ffmpeg/FFmpegH264Decoder.h b/dom/media/platforms/ffmpeg/FFmpegH264Decoder.h index e9deb4f45b..34ae89edb9 100644 --- a/dom/media/platforms/ffmpeg/FFmpegH264Decoder.h +++ b/dom/media/platforms/ffmpeg/FFmpegH264Decoder.h @@ -42,6 +42,7 @@ public: virtual nsresult Input(MediaRawData* aSample) override; virtual nsresult Drain() override; virtual nsresult Flush() override; + void InitCodecContext() override; static AVCodecID GetCodecId(const nsACString& aMimeType); private: @@ -67,6 +68,9 @@ private: uint32_t mDisplayWidth; uint32_t mDisplayHeight; + // Parser used for VP8 and VP9 decoding. + AVCodecParserContext* mCodecParser; + class PtsCorrectionContext { public: PtsCorrectionContext();