Bug 1208917: Fix VP9 decoding with recent version of libav. r=kentuckyfriedtakahe
authorJean-Yves Avenard <jyavenard@mozilla.com>
Mon, 28 Sep 2015 09:48:42 +1000
changeset 607014 10db198e218b83f0637a2ba59667d22ad2521119
parent 607013 0123f6fe9832325693b692f1b9e1ede0fbf5f63e
child 607015 2b03bc846310350c4fed031b72f01edfe832cf94
push id93006
push userjyavenard@mozilla.com
push dateThu, 15 Oct 2015 05:15:33 +0000
treeherdertry@45ea2a01301e [default view] [failures only]
reviewerskentuckyfriedtakahe
bugs1208917
milestone43.0a2
Bug 1208917: Fix VP9 decoding with recent version of libav. r=kentuckyfriedtakahe Recent libav do not require a codec parser to decode VP9.
dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp
dom/media/platforms/ffmpeg/FFmpegDataDecoder.h
dom/media/platforms/ffmpeg/FFmpegH264Decoder.cpp
dom/media/platforms/ffmpeg/FFmpegH264Decoder.h
--- a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp
@@ -26,23 +26,28 @@ FFmpegDataDecoder<LIBAV_VER>::FFmpegData
   : mTaskQueue(aTaskQueue)
   , mCallback(aCallback)
   , mCodecContext(nullptr)
   , mFrame(NULL)
   , mExtraData(nullptr)
   , mCodecID(aCodecID)
   , mMonitor("FFMpegaDataDecoder")
   , mIsFlushing(false)
+  , mCodecParser(nullptr)
 {
   MOZ_COUNT_CTOR(FFmpegDataDecoder);
 }
 
 FFmpegDataDecoder<LIBAV_VER>::~FFmpegDataDecoder()
 {
   MOZ_COUNT_DTOR(FFmpegDataDecoder);
+  if (mCodecParser) {
+    av_parser_close(mCodecParser);
+    mCodecParser = nullptr;
+  }
 }
 
 /**
  * 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.
  */
@@ -122,16 +127,21 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecode
       mCodecContext->sample_fmt != AV_SAMPLE_FMT_FLT &&
       mCodecContext->sample_fmt != AV_SAMPLE_FMT_FLTP &&
       mCodecContext->sample_fmt != AV_SAMPLE_FMT_S16 &&
       mCodecContext->sample_fmt != AV_SAMPLE_FMT_S16P) {
     NS_WARNING("FFmpeg audio decoder outputs unsupported audio format.");
     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;
 }
 
 nsresult
 FFmpegDataDecoder<LIBAV_VER>::Shutdown()
 {
   if (mTaskQueue) {
--- a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h
+++ b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h
@@ -54,16 +54,17 @@ protected:
 
   // For wait on mIsFlushing during Shutdown() process.
   // Protects mReorderQueue.
   Monitor mMonitor;
   // Set on reader/decode thread calling Flush() to indicate that output is
   // not required and so input samples on mTaskQueue need not be processed.
   // Cleared on mTaskQueue in ProcessDrain().
   Atomic<bool> mIsFlushing;
+  AVCodecParserContext* mCodecParser;
 
 private:
   static bool sFFmpegInitDone;
   static StaticMutex sMonitor;
 };
 
 } // namespace mozilla
 
--- a/dom/media/platforms/ffmpeg/FFmpegH264Decoder.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegH264Decoder.cpp
@@ -27,17 +27,16 @@ namespace mozilla
 FFmpegH264Decoder<LIBAV_VER>::FFmpegH264Decoder(
   FlushableTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
   const VideoInfo& aConfig,
   ImageContainer* aImageContainer)
   : FFmpegDataDecoder(aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
   , mImageContainer(aImageContainer)
   , 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.
   mExtraData = new MediaByteBuffer;
   mExtraData->AppendElements(*aConfig.mExtraData);
 }
 
 nsRefPtr<MediaDataDecoder::InitPromise>
@@ -71,29 +70,21 @@ FFmpegH264Decoder<LIBAV_VER>::GetPts(con
 FFmpegH264Decoder<LIBAV_VER>::DecodeResult
 FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
 {
   MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
 
   uint8_t* inputData = const_cast<uint8_t*>(aSample->Data());
   size_t inputSize = aSample->Size();
 
-  if (inputSize && (mCodecID == AV_CODEC_ID_VP8
+  if (inputSize && mCodecParser && (mCodecID == AV_CODEC_ID_VP8
 #if LIBAVCODEC_VERSION_MAJOR >= 55
       || mCodecID == AV_CODEC_ID_VP9
 #endif
       )) {
-    if (!mCodecParser) {
-      mCodecParser = av_parser_init(mCodecID);
-      if (!mCodecParser) {
-        mCallback->Error();
-        return DecodeResult::DECODE_ERROR;
-      }
-      mCodecParser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
-    }
     bool gotFrame = false;
     while (inputSize) {
       uint8_t* data;
       int size;
       int len = av_parser_parse2(mCodecParser, mCodecContext, &data, &size,
                                  inputData, inputSize,
                                  aSample->mTime, aSample->mTimecode,
                                  aSample->mOffset);
@@ -352,20 +343,16 @@ FFmpegH264Decoder<LIBAV_VER>::ProcessDra
   while (DoDecodeFrame(empty) == DecodeResult::DECODE_FRAME) {
   }
   mCallback->DrainComplete();
 }
 
 FFmpegH264Decoder<LIBAV_VER>::~FFmpegH264Decoder()
 {
   MOZ_COUNT_DTOR(FFmpegH264Decoder);
-  if (mCodecParser) {
-    av_parser_close(mCodecParser);
-    mCodecParser = nullptr;
-  }
 }
 
 AVCodecID
 FFmpegH264Decoder<LIBAV_VER>::GetCodecId(const nsACString& aMimeType)
 {
   if (aMimeType.EqualsLiteral("video/avc") || aMimeType.EqualsLiteral("video/mp4")) {
     return AV_CODEC_ID_H264;
   }
--- a/dom/media/platforms/ffmpeg/FFmpegH264Decoder.h
+++ b/dom/media/platforms/ffmpeg/FFmpegH264Decoder.h
@@ -59,14 +59,13 @@ private:
 
   static int AllocateBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame);
   static void ReleaseBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame);
   int64_t GetPts(const AVPacket& packet);
 
   nsRefPtr<ImageContainer> mImageContainer;
   uint32_t mDisplayWidth;
   uint32_t mDisplayHeight;
-  AVCodecParserContext* mCodecParser;
 };
 
 } // namespace mozilla
 
 #endif // __FFmpegH264Decoder_h__