Bug 1295921 - P8: Extract BlankMediaDataDecoder so it can be shared. r?jwwang draft
authorDan Glastonbury <dglastonbury@mozilla.com>
Wed, 21 Sep 2016 14:27:58 +1000
changeset 495123 6904d4502648fb1e393d2a7dd8bcfb4b35df0be0
parent 495122 ba2a12cd4b5ab776bf00b2927cb0addc702ce697
child 495124 9fa75d6adb8540525283361375ea2984683f4ec0
push id48245
push userbmo:kaku@mozilla.com
push dateWed, 08 Mar 2017 09:46:17 +0000
reviewersjwwang
bugs1295921
milestone53.0a1
Bug 1295921 - P8: Extract BlankMediaDataDecoder so it can be shared. r?jwwang Change name to 'Dummy' to signify it's base for decoders that don't decode. MozReview-Commit-ID: 8RY8eKpWJE3
dom/media/platforms/agnostic/BlankDecoderModule.cpp
dom/media/platforms/agnostic/DummyMediaDataDecoder.cpp
dom/media/platforms/agnostic/DummyMediaDataDecoder.h
dom/media/platforms/moz.build
dom/media/platforms/wrappers/FuzzingWrapper.cpp
dom/media/platforms/wrappers/H264Converter.cpp
--- a/dom/media/platforms/agnostic/BlankDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/BlankDecoderModule.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "DummyMediaDataDecoder.h"
 #include "ImageContainer.h"
 #include "MediaDecoderReader.h"
 #include "MediaInfo.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/mozalloc.h" // for operator new, and new (fallible)
 #include "mozilla/RefPtr.h"
 #include "mozilla/TaskQueue.h"
 #include "mp4_demuxer/AnnexB.h"
@@ -20,109 +21,31 @@
 #include "ReorderQueue.h"
 #include "TimeUnits.h"
 #include "VideoUtils.h"
 
 namespace mozilla {
 
 // Decoder that uses a passed in object's Create function to create blank
 // MediaData objects.
-template<class BlankMediaDataCreator>
-class BlankMediaDataDecoder : public MediaDataDecoder {
-public:
 
-  BlankMediaDataDecoder(BlankMediaDataCreator* aCreator,
-                        const CreateDecoderParams& aParams)
-    : mCreator(aCreator)
-    , mCallback(aParams.mCallback)
-    , mMaxRefFrames(aParams.mConfig.GetType() == TrackInfo::kVideoTrack &&
-                    MP4Decoder::IsH264(aParams.mConfig.mMimeType)
-                    ? mp4_demuxer::AnnexB::HasSPS(aParams.VideoConfig().mExtraData)
-                      ? mp4_demuxer::H264::ComputeMaxRefFrames(aParams.VideoConfig().mExtraData)
-                      : 16
-                    : 0)
-    , mType(aParams.mConfig.GetType())
-  {
-  }
-
-  RefPtr<InitPromise> Init() override {
-    return InitPromise::CreateAndResolve(mType, __func__);
-  }
-
-  void Shutdown() override {}
-
-  void Input(MediaRawData* aSample) override
-  {
-    RefPtr<MediaData> data =
-      mCreator->Create(media::TimeUnit::FromMicroseconds(aSample->mTime),
-                       media::TimeUnit::FromMicroseconds(aSample->mDuration),
-                       aSample->mOffset);
-
-    OutputFrame(data);
-  }
-
-  void Flush() override
-  {
-    mReorderQueue.Clear();
-  }
-
-  void Drain() override
-  {
-    while (!mReorderQueue.IsEmpty()) {
-      mCallback->Output(mReorderQueue.Pop().get());
-    }
-
-    mCallback->DrainComplete();
-  }
-
-  const char* GetDescriptionName() const override
-  {
-    return "blank media data decoder";
-  }
-
-private:
-  void OutputFrame(MediaData* aData)
-  {
-    if (!aData) {
-      mCallback->Error(MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__));
-      return;
-    }
-
-    // Frames come out in DTS order but we need to output them in PTS order.
-    mReorderQueue.Push(aData);
-
-    while (mReorderQueue.Length() > mMaxRefFrames) {
-      mCallback->Output(mReorderQueue.Pop().get());
-    }
-    mCallback->InputExhausted();
-  }
-
-private:
-  nsAutoPtr<BlankMediaDataCreator> mCreator;
-  MediaDataDecoderCallback* mCallback;
-  const uint32_t mMaxRefFrames;
-  ReorderQueue mReorderQueue;
-  TrackInfo::TrackType mType;
-};
-
-class BlankVideoDataCreator {
+class BlankVideoDataCreator : public DummyDataCreator {
 public:
   BlankVideoDataCreator(uint32_t aFrameWidth,
                         uint32_t aFrameHeight,
                         layers::ImageContainer* aImageContainer)
     : mFrameWidth(aFrameWidth)
     , mFrameHeight(aFrameHeight)
     , mImageContainer(aImageContainer)
   {
     mInfo.mDisplay = nsIntSize(mFrameWidth, mFrameHeight);
     mPicture = gfx::IntRect(0, 0, mFrameWidth, mFrameHeight);
   }
 
-  already_AddRefed<MediaData>
-  Create(const media::TimeUnit& aDTS, const media::TimeUnit& aDuration, int64_t aOffsetInStream)
+  already_AddRefed<MediaData> Create(MediaRawData* aSample)
   {
     // Create a fake YUV buffer in a 420 format. That is, an 8bpp Y plane,
     // with a U and V plane that are half the size of the Y plane, i.e 8 bit,
     // 2x2 subsampled.
     const int sizeY = mFrameWidth * mFrameHeight;
     const int sizeCbCr = ((mFrameWidth + 1) / 2) * ((mFrameHeight + 1) / 2);
     auto frame = MakeUnique<uint8_t[]>(sizeY + sizeCbCr);
     VideoData::YCbCrBuffer buffer;
@@ -152,48 +75,45 @@ public:
     buffer.mPlanes[2].mSkip = 0;
 
     // Set to color white.
     memset(buffer.mPlanes[0].mData, 255, sizeY);
     memset(buffer.mPlanes[1].mData, 128, sizeCbCr);
 
     return VideoData::CreateAndCopyData(mInfo,
                                         mImageContainer,
-                                        aOffsetInStream,
-                                        aDTS.ToMicroseconds(),
-                                        aDuration.ToMicroseconds(),
+                                        aSample->mOffset,
+                                        aSample->mTime,
+                                        aSample->mDuration,
                                         buffer,
-                                        true,
-                                        aDTS.ToMicroseconds(),
+                                        aSample->mKeyframe,
+                                        aSample->mTime,
                                         mPicture);
   }
 
 private:
   VideoInfo mInfo;
   gfx::IntRect mPicture;
   uint32_t mFrameWidth;
   uint32_t mFrameHeight;
   RefPtr<layers::ImageContainer> mImageContainer;
 };
 
-class BlankAudioDataCreator {
+class BlankAudioDataCreator : public DummyDataCreator {
 public:
   BlankAudioDataCreator(uint32_t aChannelCount, uint32_t aSampleRate)
     : mFrameSum(0), mChannelCount(aChannelCount), mSampleRate(aSampleRate)
   {
   }
 
-  MediaData* Create(const media::TimeUnit& aDTS,
-                    const media::TimeUnit& aDuration,
-                    int64_t aOffsetInStream)
+  already_AddRefed<MediaData> Create(MediaRawData* aSample) override
   {
     // Convert duration to frames. We add 1 to duration to account for
     // rounding errors, so we get a consistent tone.
-    CheckedInt64 frames =
-      UsecsToFrames(aDuration.ToMicroseconds()+1, mSampleRate);
+    CheckedInt64 frames = UsecsToFrames(aSample->mDuration+1, mSampleRate);
     if (!frames.isValid() ||
         !mChannelCount ||
         !mSampleRate ||
         frames.value() > (UINT32_MAX / mChannelCount)) {
       return nullptr;
     }
     AlignedAudioBuffer samples(frames.value() * mChannelCount);
     if (!samples) {
@@ -204,54 +124,59 @@ public:
     static const float noteHz = 440.0f;
     for (int i = 0; i < frames.value(); i++) {
       float f = sin(2 * pi * noteHz * mFrameSum / mSampleRate);
       for (unsigned c = 0; c < mChannelCount; c++) {
         samples[i * mChannelCount + c] = AudioDataValue(f);
       }
       mFrameSum++;
     }
-    return new AudioData(aOffsetInStream,
-                         aDTS.ToMicroseconds(),
-                         aDuration.ToMicroseconds(),
-                         uint32_t(frames.value()),
-                         Move(samples),
-                         mChannelCount,
-                         mSampleRate);
+    RefPtr<AudioData> a(new AudioData(aSample->mOffset,
+                                      aSample->mTime,
+                                      aSample->mDuration,
+                                      uint32_t(frames.value()),
+                                      Move(samples),
+                                      mChannelCount,
+                                      mSampleRate));
+    return a.forget();
   }
 
 private:
   int64_t mFrameSum;
   uint32_t mChannelCount;
   uint32_t mSampleRate;
 };
 
 class BlankDecoderModule : public PlatformDecoderModule {
 public:
 
   // Decode thread.
   already_AddRefed<MediaDataDecoder>
   CreateVideoDecoder(const CreateDecoderParams& aParams) override {
     const VideoInfo& config = aParams.VideoConfig();
-    BlankVideoDataCreator* creator = new BlankVideoDataCreator(
-      config.mDisplay.width, config.mDisplay.height, aParams.mImageContainer);
+    auto creator = UniquePtr<DummyDataCreator>{
+      MakeUnique<BlankVideoDataCreator>(config.mDisplay.width,
+                                        config.mDisplay.height,
+                                        aParams.mImageContainer)
+    };
     RefPtr<MediaDataDecoder> decoder =
-      new BlankMediaDataDecoder<BlankVideoDataCreator>(creator, aParams);
+      new DummyMediaDataDecoder(Move(creator), "blank media data decoder", aParams);
     return decoder.forget();
   }
 
   // Decode thread.
   already_AddRefed<MediaDataDecoder>
   CreateAudioDecoder(const CreateDecoderParams& aParams) override {
     const AudioInfo& config = aParams.AudioConfig();
-    BlankAudioDataCreator* creator = new BlankAudioDataCreator(
-      config.mChannels, config.mRate);
+    auto creator = UniquePtr<DummyDataCreator>{
+      MakeUnique<BlankAudioDataCreator>(config.mChannels, config.mRate)
+    };
 
     RefPtr<MediaDataDecoder> decoder =
-      new BlankMediaDataDecoder<BlankAudioDataCreator>(creator, aParams);
+      new DummyMediaDataDecoder(Move(creator), "blank media data decoder", aParams);
     return decoder.forget();
   }
 
   bool
   SupportsMimeType(const nsACString& aMimeType,
                    DecoderDoctorDiagnostics* aDiagnostics) const override
   {
     return true;
new file mode 100644
--- /dev/null
+++ b/dom/media/platforms/agnostic/DummyMediaDataDecoder.cpp
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DummyMediaDataDecoder.h"
+
+#include "mp4_demuxer/AnnexB.h"
+#include "mp4_demuxer/H264.h"
+#include "MP4Decoder.h"
+
+namespace mozilla {
+
+DummyDataCreator::~DummyDataCreator()
+{ }
+
+DummyMediaDataDecoder::DummyMediaDataDecoder(UniquePtr<DummyDataCreator>&& aCreator,
+                                             const char* aDescription,
+                                             const CreateDecoderParams& aParams)
+  : mCreator(Move(aCreator))
+  , mCallback(aParams.mCallback)
+  , mMaxRefFrames(
+      aParams.mConfig.GetType() == TrackInfo::kVideoTrack &&
+          MP4Decoder::IsH264(aParams.mConfig.mMimeType)
+        ? mp4_demuxer::AnnexB::HasSPS(aParams.VideoConfig().mExtraData)
+            ? mp4_demuxer::H264::ComputeMaxRefFrames(
+                aParams.VideoConfig().mExtraData)
+            : 16
+        : 0)
+  , mType(aParams.mConfig.GetType())
+  , mDescription(aDescription)
+{
+}
+
+RefPtr<DummyMediaDataDecoder::InitPromise>
+DummyMediaDataDecoder::Init()
+{
+  return InitPromise::CreateAndResolve(mType, __func__);
+}
+
+void
+DummyMediaDataDecoder::Shutdown()
+{
+}
+
+void
+DummyMediaDataDecoder::Input(MediaRawData* aSample)
+{
+  RefPtr<MediaData> data = mCreator->Create(aSample);
+  OutputFrame(data);
+}
+
+void
+DummyMediaDataDecoder::Flush()
+{
+  mReorderQueue.Clear();
+}
+
+void
+DummyMediaDataDecoder::Drain()
+{
+  while (!mReorderQueue.IsEmpty()) {
+    mCallback->Output(mReorderQueue.Pop().get());
+  }
+
+  mCallback->DrainComplete();
+}
+
+const char*
+DummyMediaDataDecoder::GetDescriptionName() const
+{
+  return mDescription.get();
+}
+
+void
+DummyMediaDataDecoder::OutputFrame(MediaData* aData)
+{
+  if (!aData) {
+    mCallback->Error(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__));
+    return;
+  }
+
+  // Frames come out in DTS order but we need to output them in PTS order.
+  mReorderQueue.Push(aData);
+
+  while (mReorderQueue.Length() > mMaxRefFrames) {
+    mCallback->Output(mReorderQueue.Pop().get());
+  }
+  mCallback->InputExhausted();
+}
+
+} // namespace Mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/platforms/agnostic/DummyMediaDataDecoder.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#if !defined(DummyMediaDataDecoder_h_)
+#define DummyMediaDataDecoder_h_
+
+#include "PlatformDecoderModule.h"
+#include "ReorderQueue.h"
+
+namespace mozilla {
+
+class MediaData;
+
+class DummyDataCreator {
+public:
+  virtual ~DummyDataCreator();
+  virtual already_AddRefed<MediaData> Create(MediaRawData* aSample) = 0;
+};
+
+// Decoder that uses a passed in object's Create function to create Null
+// MediaData objects.
+class DummyMediaDataDecoder : public MediaDataDecoder {
+public:
+
+  typedef MediaDataDecoder::InitPromise InitPromise;
+
+  DummyMediaDataDecoder(UniquePtr<DummyDataCreator>&& aCreator,
+                        const char* aDescription,
+                        const CreateDecoderParams& aParams);
+
+  RefPtr<InitPromise> Init() override;
+  void Shutdown() override;
+
+  void Input(MediaRawData* aSample) override;
+  void Flush() override;
+  void Drain() override;
+
+  const char* GetDescriptionName() const override;
+
+private:
+  void OutputFrame(MediaData* aData);
+
+private:
+  UniquePtr<DummyDataCreator> mCreator;
+  MediaDataDecoderCallback* mCallback;
+  const uint32_t mMaxRefFrames;
+  ReorderQueue mReorderQueue;
+  TrackInfo::TrackType mType;
+  nsCString mDescription;
+};
+
+} // namespace mozilla
+
+#endif // !defined(DummyMediaDataDecoder_h_)
--- a/dom/media/platforms/moz.build
+++ b/dom/media/platforms/moz.build
@@ -1,30 +1,32 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS += [
     'agnostic/AgnosticDecoderModule.h',
+    'agnostic/DummyMediaDataDecoder.h',
     'agnostic/OpusDecoder.h',
     'agnostic/TheoraDecoder.h',
     'agnostic/VorbisDecoder.h',
     'agnostic/VPXDecoder.h',
     'MediaTelemetryConstants.h',
     'PDMFactory.h',
     'PlatformDecoderModule.h',
     'wrappers/FuzzingWrapper.h',
     'wrappers/H264Converter.h'
 ]
 
 UNIFIED_SOURCES += [
     'agnostic/AgnosticDecoderModule.cpp',
     'agnostic/BlankDecoderModule.cpp',
+    'agnostic/DummyMediaDataDecoder.cpp',
     'agnostic/OpusDecoder.cpp',
     'agnostic/TheoraDecoder.cpp',
     'agnostic/VorbisDecoder.cpp',
     'agnostic/VPXDecoder.cpp',
     'agnostic/WAVDecoder.cpp',
     'PDMFactory.cpp',
     'wrappers/FuzzingWrapper.cpp',
     'wrappers/H264Converter.cpp'
--- a/dom/media/platforms/wrappers/FuzzingWrapper.cpp
+++ b/dom/media/platforms/wrappers/FuzzingWrapper.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "FuzzingWrapper.h"
+#include "mozilla/SharedThreadPool.h"
 
 mozilla::LogModule* GetFuzzingWrapperLog() {
   static mozilla::LazyLogModule log("MediaFuzzingWrapper");
   return log;
 }
 #define DFW_LOGD(arg, ...) MOZ_LOG(GetFuzzingWrapperLog(), mozilla::LogLevel::Debug, ("DecoderFuzzingWrapper(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 #define DFW_LOGV(arg, ...) MOZ_LOG(GetFuzzingWrapperLog(), mozilla::LogLevel::Verbose, ("DecoderFuzzingWrapper(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 #define CFW_LOGD(arg, ...) MOZ_LOG(GetFuzzingWrapperLog(), mozilla::LogLevel::Debug, ("DecoderCallbackFuzzingWrapper(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
--- a/dom/media/platforms/wrappers/H264Converter.cpp
+++ b/dom/media/platforms/wrappers/H264Converter.cpp
@@ -2,16 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/TaskQueue.h"
 
 #include "H264Converter.h"
+#include "DecoderDoctorDiagnostics.h"
 #include "ImageContainer.h"
 #include "MediaInfo.h"
 #include "MediaPrefs.h"
 #include "mp4_demuxer/AnnexB.h"
 #include "mp4_demuxer/H264.h"
 
 namespace mozilla
 {