Have specialized AVCodecContext initialization

A common initialization procedure is too restrictive, and we end up setting up audio configuration for video decoding and vice-versa.
This commit is contained in:
trav90
2016-12-14 03:30:40 -06:00
committed by roytam1
parent 4d1ef4248d
commit 95a8f149db
6 changed files with 65 additions and 46 deletions
@@ -35,6 +35,22 @@ FFmpegAudioDecoder<LIBAV_VER>::Init()
return NS_OK;
}
void
FFmpegAudioDecoder<LIBAV_VER>::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)
{
@@ -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:
@@ -27,13 +27,8 @@ FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FlushableMediaTaskQueue* aTaskQu
, mFrame(NULL)
, mExtraData(nullptr)
, mCodecID(aCodecID)
, mCodecParser(nullptr)
{
MOZ_COUNT_CTOR(FFmpegDataDecoder);
if (mCodecParser) {
av_parser_close(mCodecParser);
mCodecParser = nullptr;
}
}
FFmpegDataDecoder<LIBAV_VER>::~FFmpegDataDecoder()
@@ -41,27 +36,6 @@ FFmpegDataDecoder<LIBAV_VER>::~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<LIBAV_VER>::Init()
{
@@ -82,19 +56,7 @@ FFmpegDataDecoder<LIBAV_VER>::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<LIBAV_VER>::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;
}
@@ -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<MediaByteBuffer> mExtraData;
AVCodecID mCodecID;
AVCodecParserContext* mCodecParser;
private:
static bool sFFmpegInitDone;
@@ -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<LIBAV_VER>::PtsCorrectionContext::PtsCorrectionContext()
: mNumFaultyPts(0)
, mNumFaultyDts(0)
@@ -71,6 +92,7 @@ FFmpegH264Decoder<LIBAV_VER>::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<LIBAV_VER>::Init()
nsresult rv = FFmpegDataDecoder::Init();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
void
FFmpegH264Decoder<LIBAV_VER>::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<LIBAV_VER>::DecodeResult
@@ -292,6 +329,10 @@ FFmpegH264Decoder<LIBAV_VER>::Flush()
FFmpegH264Decoder<LIBAV_VER>::~FFmpegH264Decoder()
{
MOZ_COUNT_DTOR(FFmpegH264Decoder);
if (mCodecParser) {
av_parser_close(mCodecParser);
mCodecParser = nullptr;
}
}
AVCodecID
@@ -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();