Bug 1346120 part 1 - Extract BlankMediaDataDecoder so it can be shared; r?jwwang draft
authorKaku Kuo <kaku@mozilla.com>
Thu, 09 Mar 2017 15:33:53 +0800
changeset 497394 4ea126c513aadef2dee78f820550ca002e8d77b6
parent 497393 c5c4911b892f0125f1a5621ae327b044b960d83d
child 497395 5d1fe150a5bc1f63602c20ec5becabd4eca1176c
push id48887
push userbmo:kaku@mozilla.com
push dateMon, 13 Mar 2017 08:42:35 +0000
reviewersjwwang
bugs1346120
milestone55.0a1
Bug 1346120 part 1 - Extract BlankMediaDataDecoder so it can be shared; r?jwwang Change name to 'Dummy' to signify it's base for decoders that don't decode. And we will implement a new NullDecoderModule in the next patch which will utilize the DummyMediaDataDecoder. MozReview-Commit-ID: LPsczoztgx3
dom/media/platforms/agnostic/BlankDecoderModule.cpp
dom/media/platforms/agnostic/DummyMediaDataDecoder.cpp
dom/media/platforms/agnostic/DummyMediaDataDecoder.h
dom/media/platforms/moz.build
--- a/dom/media/platforms/agnostic/BlankDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/BlankDecoderModule.cpp
@@ -1,137 +1,42 @@
 /* -*- 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 "mozilla/CheckedInt.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/RefPtr.h"
+#include "nsRect.h"
+#include "nsSize.h"
+#include "DummyMediaDataDecoder.h"
 #include "ImageContainer.h"
-#include "MP4Decoder.h"
-#include "MediaDecoderReader.h"
+#include "MediaData.h"
 #include "MediaInfo.h"
 #include "PlatformDecoderModule.h"
-#include "ReorderQueue.h"
-#include "TimeUnits.h"
 #include "VideoUtils.h"
-#include "mozilla/CheckedInt.h"
-#include "mozilla/RefPtr.h"
-#include "mozilla/TaskQueue.h"
-#include "mozilla/mozalloc.h" // for operator new, and new (fallible)
-#include "mp4_demuxer/AnnexB.h"
-#include "mp4_demuxer/H264.h"
-#include "nsAutoPtr.h"
-#include "nsRect.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)
-    , mIsH264(MP4Decoder::IsH264(aParams.mConfig.mMimeType))
-    , mMaxRefFrames(
-        mIsH264
-        ? 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__);
-  }
-
-  RefPtr<ShutdownPromise> Shutdown() override
-  {
-    return ShutdownPromise::CreateAndResolve(true, __func__);
-  }
-
-  RefPtr<DecodePromise> Decode(MediaRawData* aSample) override
-  {
-    RefPtr<MediaData> data =
-      mCreator->Create(media::TimeUnit::FromMicroseconds(aSample->mTime),
-                       media::TimeUnit::FromMicroseconds(aSample->mDuration),
-                       aSample->mOffset);
-
-    if (!data) {
-      return DecodePromise::CreateAndReject(NS_ERROR_OUT_OF_MEMORY, __func__);
-    }
-
-    // Frames come out in DTS order but we need to output them in PTS order.
-    mReorderQueue.Push(data);
-
-    if (mReorderQueue.Length() > mMaxRefFrames) {
-      return DecodePromise::CreateAndResolve(
-        DecodedData{ mReorderQueue.Pop().get() }, __func__);
-    }
-    return DecodePromise::CreateAndResolve(DecodedData(), __func__);
-  }
-
-  RefPtr<DecodePromise> Drain() override
-  {
-    DecodedData samples;
-    while (!mReorderQueue.IsEmpty()) {
-      samples.AppendElement(mReorderQueue.Pop().get());
-    }
-    return DecodePromise::CreateAndResolve(samples, __func__);
-  }
-
-  RefPtr<FlushPromise> Flush() override
-  {
-    mReorderQueue.Clear();
-    return FlushPromise::CreateAndResolve(true, __func__);
-  }
-
-  const char* GetDescriptionName() const override
-  {
-    return "blank media data decoder";
-  }
-
-  ConversionRequired NeedsConversion() const override
-  {
-    return mIsH264
-           ? ConversionRequired::kNeedAVCC
-           : ConversionRequired::kNeedNone;
-  }
-
-private:
-  nsAutoPtr<BlankMediaDataCreator> mCreator;
-  const bool mIsH264;
-  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) override
   {
     // 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;
@@ -161,49 +66,46 @@ 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) {
@@ -214,23 +116,24 @@ 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> data(new AudioData(aSample->mOffset,
+                                         aSample->mTime,
+                                         aSample->mDuration,
+                                         uint32_t(frames.value()),
+                                         Move(samples),
+                                         mChannelCount,
+                                         mSampleRate));
+    return data.forget();
   }
 
 private:
   int64_t mFrameSum;
   uint32_t mChannelCount;
   uint32_t mSampleRate;
 };
 
@@ -238,33 +141,32 @@ class BlankDecoderModule : public Platfo
 {
 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);
+    UniquePtr<DummyDataCreator> creator =
+      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);
-
+    UniquePtr<DummyDataCreator> creator =
+      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"
+
+namespace mozilla {
+
+DummyDataCreator::~DummyDataCreator() {}
+
+DummyMediaDataDecoder::DummyMediaDataDecoder(UniquePtr<DummyDataCreator>&& aCreator,
+                                             const char* aDescription,
+                                             const CreateDecoderParams& aParams)
+  : mCreator(Move(aCreator))
+  , mIsH264(MP4Decoder::IsH264(aParams.mConfig.mMimeType))
+  , mMaxRefFrames(
+      mIsH264
+      ? mp4_demuxer::AnnexB::HasSPS(aParams.VideoConfig().mExtraData)
+        ? mp4_demuxer::H264::ComputeMaxRefFrames(aParams.VideoConfig().mExtraData)
+        : 16
+      : 0)
+  , mType(aParams.mConfig.GetType())
+  , mDescription(aDescription)
+{
+}
+
+RefPtr<MediaDataDecoder::InitPromise>
+DummyMediaDataDecoder::Init()
+{
+  return InitPromise::CreateAndResolve(mType, __func__);
+}
+
+RefPtr<ShutdownPromise>
+DummyMediaDataDecoder::Shutdown()
+{
+  return ShutdownPromise::CreateAndResolve(true, __func__);
+}
+
+RefPtr<MediaDataDecoder::DecodePromise>
+DummyMediaDataDecoder::Decode(MediaRawData* aSample)
+{
+  RefPtr<MediaData> data = mCreator->Create(aSample);
+
+  if (!data) {
+    return DecodePromise::CreateAndReject(NS_ERROR_OUT_OF_MEMORY, __func__);
+  }
+
+  // Frames come out in DTS order but we need to output them in PTS order.
+  mReorderQueue.Push(data);
+
+  if (mReorderQueue.Length() > mMaxRefFrames) {
+    return DecodePromise::CreateAndResolve(
+      DecodedData{ mReorderQueue.Pop().get() }, __func__);
+  }
+  return DecodePromise::CreateAndResolve(DecodedData(), __func__);
+}
+
+RefPtr<MediaDataDecoder::DecodePromise>
+DummyMediaDataDecoder::Drain()
+{
+  DecodedData samples;
+  while (!mReorderQueue.IsEmpty()) {
+    samples.AppendElement(mReorderQueue.Pop().get());
+  }
+  return DecodePromise::CreateAndResolve(samples, __func__);
+}
+
+RefPtr<MediaDataDecoder::FlushPromise>
+DummyMediaDataDecoder::Flush()
+{
+  mReorderQueue.Clear();
+  return FlushPromise::CreateAndResolve(true, __func__);
+}
+
+const char*
+DummyMediaDataDecoder::GetDescriptionName() const
+{
+  return "blank media data decoder";
+}
+
+MediaDataDecoder::ConversionRequired
+DummyMediaDataDecoder::NeedsConversion() const
+{
+  return mIsH264
+         ? ConversionRequired::kNeedAVCC
+         : ConversionRequired::kNeedNone;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/platforms/agnostic/DummyMediaDataDecoder.h
@@ -0,0 +1,60 @@
+/* -*- 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 "MediaInfo.h"
+#include "mozilla/UniquePtr.h"
+#include "PlatformDecoderModule.h"
+#include "ReorderQueue.h"
+
+namespace mozilla {
+
+class MediaRawData;
+
+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:
+  DummyMediaDataDecoder(UniquePtr<DummyDataCreator>&& aCreator,
+                        const char* aDescription,
+                        const CreateDecoderParams& aParams);
+
+  RefPtr<InitPromise> Init() override;
+
+  RefPtr<ShutdownPromise> Shutdown() override;
+
+  RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
+
+  RefPtr<DecodePromise> Drain() override;
+
+  RefPtr<FlushPromise> Flush() override;
+
+  const char* GetDescriptionName() const override;
+
+  ConversionRequired NeedsConversion() const override;
+
+private:
+  UniquePtr<DummyDataCreator> mCreator;
+  const bool mIsH264;
+  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,32 +1,34 @@
 # -*- 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',
     'DurationMap.h',
     'MediaTelemetryConstants.h',
     'PDMFactory.h',
     'PlatformDecoderModule.h',
     'wrappers/H264Converter.h',
     'wrappers/MediaDataDecoderProxy.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/H264Converter.cpp',
     'wrappers/MediaDataDecoderProxy.cpp'