Backed out 6 changesets (bug 1346120) for autophone Mdm tests failure in test_background_video_drawimage_with_suspended_video.html
authorIris Hsiao <ihsiao@mozilla.com>
Mon, 13 Mar 2017 16:53:14 +0800
changeset 347083 a7f05a91241e2f63f454910ecbb0b5c19c992acc
parent 347082 cc79715e83a51e53ae65a4ab0610da47239d3f51
child 347084 e9c111cf48f56c4fe55a52255522db078e5cdefe
push id31490
push usercbook@mozilla.com
push dateMon, 13 Mar 2017 14:19:54 +0000
treeherdermozilla-central@419c70029023 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1346120
milestone55.0a1
backs outa30c73fc8d69d96084d3b3d58404209e99a56dc1
f16556658fd98cc0a8dac32ee7c30d5042053708
98d212462786378a0f41aae93f15b4cbb5f80d58
ba579adbed2193650d9ddf4e34f4d40bbf6ff3c8
c0758b9bf7b553b4061c6ee184f306e8aabbd1c4
94a483ef784e446c64ce5130c421a4733c62ef3f
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 6 changesets (bug 1346120) for autophone Mdm tests failure in test_background_video_drawimage_with_suspended_video.html Backed out changeset a30c73fc8d69 (bug 1346120) Backed out changeset f16556658fd9 (bug 1346120) Backed out changeset 98d212462786 (bug 1346120) Backed out changeset ba579adbed21 (bug 1346120) Backed out changeset c0758b9bf7b5 (bug 1346120) Backed out changeset 94a483ef784e (bug 1346120)
dom/media/MediaDecoderReader.h
dom/media/MediaDecoderReaderWrapper.cpp
dom/media/MediaFormatReader.cpp
dom/media/MediaFormatReader.h
dom/media/mediasink/VideoSink.cpp
dom/media/platforms/PDMFactory.cpp
dom/media/platforms/PDMFactory.h
dom/media/platforms/PlatformDecoderModule.h
dom/media/platforms/agnostic/BlankDecoderModule.cpp
dom/media/platforms/agnostic/DummyMediaDataDecoder.cpp
dom/media/platforms/agnostic/DummyMediaDataDecoder.h
dom/media/platforms/agnostic/NullDecoderModule.cpp
dom/media/platforms/moz.build
dom/media/test/mochitest.ini
dom/media/test/test_background_video_drawimage_with_suspended_video.html
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -255,20 +255,20 @@ public:
     return mOnTrackWaitingForKey;
   }
 
   MediaEventProducer<TrackInfo::TrackType>& OnTrackWaitingForKeyProducer()
   {
     return mOnTrackWaitingForKey;
   }
 
-  // Switch the video decoder to NullDecoderModule. It might takes effective
+  // Switch the video decoder to BlankDecoderModule. It might takes effective
   // since a few samples later depends on how much demuxed samples are already
   // queued in the original video decoder.
-  virtual void SetVideoNullDecode(bool aIsNullDecode) { }
+  virtual void SetVideoBlankDecode(bool aIsBlankDecode) { }
 
 protected:
   virtual ~MediaDecoderReader();
 
   // Recomputes mBuffered.
   virtual void UpdateBuffered();
 
   RefPtr<MediaDataPromise> DecodeToFirstVideoData();
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -143,14 +143,14 @@ MediaDecoderReaderWrapper::OnMetadataRea
   }
 }
 
 void
 MediaDecoderReaderWrapper::SetVideoBlankDecode(bool aIsBlankDecode)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   nsCOMPtr<nsIRunnable> r =
-    NewRunnableMethod<bool>(mReader, &MediaDecoderReader::SetVideoNullDecode,
+    NewRunnableMethod<bool>(mReader, &MediaDecoderReader::SetVideoBlankDecode,
                             aIsBlankDecode);
   mReader->OwnerThread()->Dispatch(r.forget());
 }
 
 } // namespace mozilla
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -660,17 +660,17 @@ MediaFormatReader::DecoderFactory::DoCre
   switch (aData.mTrack) {
     case TrackInfo::kAudioTrack: {
       aData.mDecoder = mOwner->mPlatform->CreateDecoder({
         ownerData.mInfo
         ? *ownerData.mInfo->GetAsAudioInfo()
         : *ownerData.mOriginalInfo->GetAsAudioInfo(),
         ownerData.mTaskQueue,
         mOwner->mCrashHelper,
-        ownerData.mIsNullDecode,
+        ownerData.mIsBlankDecode,
         &result,
         TrackInfo::kAudioTrack,
         &mOwner->OnTrackWaitingForKeyProducer()
       });
       break;
     }
 
     case TrackType::kVideoTrack: {
@@ -679,17 +679,17 @@ MediaFormatReader::DecoderFactory::DoCre
       aData.mDecoder = mOwner->mPlatform->CreateDecoder({
         ownerData.mInfo
         ? *ownerData.mInfo->GetAsVideoInfo()
         : *ownerData.mOriginalInfo->GetAsVideoInfo(),
         ownerData.mTaskQueue,
         mOwner->mKnowsCompositor,
         mOwner->GetImageContainer(),
         mOwner->mCrashHelper,
-        ownerData.mIsNullDecode,
+        ownerData.mIsBlankDecode,
         &result,
         TrackType::kVideoTrack,
         &mOwner->OnTrackWaitingForKeyProducer()
       });
       break;
     }
 
     default:
@@ -3042,36 +3042,36 @@ MediaFormatReader::GetMozDebugReaderData
       mVideo.mWaitingForData,
       mVideo.mWaitingForKey,
       mVideo.mLastStreamSourceID);
   }
   aString += result;
 }
 
 void
-MediaFormatReader::SetVideoNullDecode(bool aIsNullDecode)
+MediaFormatReader::SetVideoBlankDecode(bool aIsBlankDecode)
 {
   MOZ_ASSERT(OnTaskQueue());
-  return SetNullDecode(TrackType::kVideoTrack, aIsNullDecode);
+  return SetBlankDecode(TrackType::kVideoTrack, aIsBlankDecode);
 }
 
 void
-MediaFormatReader::SetNullDecode(TrackType aTrack, bool aIsNullDecode)
+MediaFormatReader::SetBlankDecode(TrackType aTrack, bool aIsBlankDecode)
 {
   MOZ_ASSERT(OnTaskQueue());
 
   auto& decoder = GetDecoderData(aTrack);
-  if (decoder.mIsNullDecode == aIsNullDecode) {
+  if (decoder.mIsBlankDecode == aIsBlankDecode) {
     return;
   }
 
-  LOG("%s, decoder.mIsNullDecode = %d => aIsNullDecode = %d",
-      TrackTypeToStr(aTrack), decoder.mIsNullDecode, aIsNullDecode);
-
-  decoder.mIsNullDecode = aIsNullDecode;
+  LOG("%s, decoder.mIsBlankDecode = %d => aIsBlankDecode = %d",
+      TrackTypeToStr(aTrack), decoder.mIsBlankDecode, aIsBlankDecode);
+
+  decoder.mIsBlankDecode = aIsBlankDecode;
   ShutdownDecoder(aTrack);
 }
 
 void
 MediaFormatReader::OnFirstDemuxCompleted(
   TrackInfo::TrackType aType, RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples)
 {
   MOZ_ASSERT(OnTaskQueue());
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -73,17 +73,17 @@ public:
   }
 
   void SetCDMProxy(CDMProxy* aProxy) override;
 
   // Returns a string describing the state of the decoder data.
   // Used for debugging purposes.
   void GetMozDebugReaderData(nsACString& aString);
 
-  void SetVideoNullDecode(bool aIsNullDecode) override;
+  void SetVideoBlankDecode(bool aIsBlankDecode) override;
 
 private:
   nsresult InitInternal() override;
 
   bool HasVideo() const { return mVideo.mTrackDemuxer; }
   bool HasAudio() const { return mAudio.mTrackDemuxer; }
 
   bool IsWaitingOnCDMResource();
@@ -199,17 +199,17 @@ private:
       , mMaxConsecutiveError(aNumOfMaxError)
       , mNumSamplesInput(0)
       , mNumSamplesOutput(0)
       , mNumSamplesOutputTotal(0)
       , mNumSamplesSkippedTotal(0)
       , mSizeOfQueue(0)
       , mIsHardwareAccelerated(false)
       , mLastStreamSourceID(UINT32_MAX)
-      , mIsNullDecode(false)
+      , mIsBlankDecode(false)
     {
     }
 
     MediaFormatReader* mOwner;
     // Disambiguate Audio vs Video.
     MediaData::Type mType;
     RefPtr<MediaTrackDemuxer> mTrackDemuxer;
     // TaskQueue on which decoder can choose to decode.
@@ -381,18 +381,18 @@ private:
     uint32_t mLastStreamSourceID;
     Maybe<uint32_t> mNextStreamSourceID;
     media::TimeIntervals mTimeRanges;
     Maybe<media::TimeUnit> mLastTimeRangesEnd;
     // TrackInfo as first discovered during ReadMetadata.
     UniquePtr<TrackInfo> mOriginalInfo;
     RefPtr<TrackInfoSharedPtr> mInfo;
     Maybe<media::TimeUnit> mFirstDemuxedSampleTime;
-    // Use NullDecoderModule or not.
-    bool mIsNullDecode;
+    // Use BlankDecoderModule or not.
+    bool mIsBlankDecode;
 
   };
 
   class DecoderDataWithPromise : public DecoderData
   {
   public:
     DecoderDataWithPromise(MediaFormatReader* aOwner,
                            MediaData::Type aType,
@@ -526,17 +526,17 @@ private:
 
   RefPtr<VideoFrameContainer> mVideoFrameContainer;
   layers::ImageContainer* GetImageContainer();
 
   RefPtr<CDMProxy> mCDMProxy;
 
   RefPtr<GMPCrashHelper> mCrashHelper;
 
-  void SetNullDecode(TrackType aTrack, bool aIsNullDecode);
+  void SetBlankDecode(TrackType aTrack, bool aIsBlankDecode);
 
   class DecoderFactory;
   UniquePtr<DecoderFactory> mDecoderFactory;
 
   class ShutdownPromisePool;
   UniquePtr<ShutdownPromisePool> mShutdownPromisePool;
 
   MediaEventListener mCompositorUpdatedListener;
--- a/dom/media/mediasink/VideoSink.cpp
+++ b/dom/media/mediasink/VideoSink.cpp
@@ -395,20 +395,17 @@ VideoSink::RenderVideoFrames(int32_t aMa
     img->mTimeStamp = t;
     img->mImage = frame->mImage;
     img->mFrameID = frame->mFrameID;
     img->mProducerID = mProducerID;
 
     VSINK_LOG_V("playing video frame %" PRId64 " (id=%x) (vq-queued=%" PRIuSIZE ")",
                 frame->mTime, frame->mFrameID, VideoQueue().GetSize());
   }
-
-  if (images.Length() > 0) {
-    mContainer->SetCurrentFrames(frames[0]->As<VideoData>()->mDisplay, images);
-  }
+  mContainer->SetCurrentFrames(frames[0]->As<VideoData>()->mDisplay, images);
 }
 
 void
 VideoSink::UpdateRenderedVideoFrames()
 {
   AssertOwnerThread();
   MOZ_ASSERT(mAudioSink->IsPlaying(), "should be called while playing.");
 
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -48,17 +48,16 @@
 #include "mp4_demuxer/H264.h"
 
 #include <functional>
 
 namespace mozilla {
 
 extern already_AddRefed<PlatformDecoderModule> CreateAgnosticDecoderModule();
 extern already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule();
-extern already_AddRefed<PlatformDecoderModule> CreateNullDecoderModule();
 
 class PDMFactoryImpl final
 {
 public:
   PDMFactoryImpl()
   {
 #ifdef XP_WIN
     WMFDecoderModule::Init();
@@ -159,17 +158,17 @@ public:
 private:
   nsTArray<std::function<CheckResult()>> mCheckerList;
 }; // SupportChecker
 
 PDMFactory::PDMFactory()
 {
   EnsureInit();
   CreatePDMs();
-  CreateNullPDM();
+  CreateBlankPDM();
 }
 
 PDMFactory::~PDMFactory()
 {
 }
 
 void
 PDMFactory::EnsureInit() const
@@ -199,19 +198,19 @@ PDMFactory::EnsureInit() const
       }
     });
   SyncRunnable::DispatchToThread(mainThread, runnable);
 }
 
 already_AddRefed<MediaDataDecoder>
 PDMFactory::CreateDecoder(const CreateDecoderParams& aParams)
 {
-  if (aParams.mUseNullDecoder) {
-    MOZ_ASSERT(mNullPDM);
-    return CreateDecoderWithPDM(mNullPDM, aParams);
+  if (aParams.mUseBlankDecoder) {
+    MOZ_ASSERT(mBlankPDM);
+    return CreateDecoderWithPDM(mBlankPDM, aParams);
   }
 
   const TrackInfo& config = aParams.mConfig;
   bool isEncrypted = mEMEPDM && config.mCrypto.mValid;
 
   if (isEncrypted) {
     return CreateDecoderWithPDM(mEMEPDM, aParams);
   }
@@ -286,17 +285,17 @@ PDMFactory::CreateDecoderWithPDM(Platfor
 
   if (!config.IsVideo()) {
     *result = MediaResult(
       NS_ERROR_DOM_MEDIA_FATAL_ERR,
       RESULT_DETAIL("Decoder configuration error, expected audio or video."));
     return nullptr;
   }
 
-  if (MP4Decoder::IsH264(config.mMimeType) && !aParams.mUseNullDecoder) {
+  if (MP4Decoder::IsH264(config.mMimeType) && !aParams.mUseBlankDecoder) {
     RefPtr<H264Converter> h = new H264Converter(aPDM, aParams);
     const nsresult rv = h->GetLastError();
     if (NS_SUCCEEDED(rv) || rv == NS_ERROR_NOT_INITIALIZED) {
       // The H264Converter either successfully created the wrapped decoder,
       // or there wasn't enough AVCC data to do so. Otherwise, there was some
       // problem, for example WMF DLLs were missing.
       m = h.forget();
     }
@@ -398,20 +397,20 @@ PDMFactory::CreatePDMs()
     m = new GMPDecoderModule();
     mGMPPDMFailedToStartup = !StartupPDM(m);
   } else {
     mGMPPDMFailedToStartup = false;
   }
 }
 
 void
-PDMFactory::CreateNullPDM()
+PDMFactory::CreateBlankPDM()
 {
-  mNullPDM = CreateNullDecoderModule();
-  MOZ_ASSERT(mNullPDM && NS_SUCCEEDED(mNullPDM->Startup()));
+  mBlankPDM = CreateBlankDecoderModule();
+  MOZ_ASSERT(mBlankPDM && NS_SUCCEEDED(mBlankPDM->Startup()));
 }
 
 bool
 PDMFactory::StartupPDM(PlatformDecoderModule* aPDM)
 {
   if (aPDM && NS_SUCCEEDED(aPDM->Startup())) {
     mCurrentPDMs.AppendElement(aPDM);
     return true;
--- a/dom/media/platforms/PDMFactory.h
+++ b/dom/media/platforms/PDMFactory.h
@@ -48,31 +48,31 @@ public:
   static constexpr int kYUV400 = 0;
   static constexpr int kYUV420 = 1;
   static constexpr int kYUV422 = 2;
   static constexpr int kYUV444 = 3;
 
 private:
   virtual ~PDMFactory();
   void CreatePDMs();
-  void CreateNullPDM();
+  void CreateBlankPDM();
   // Startup the provided PDM and add it to our list if successful.
   bool StartupPDM(PlatformDecoderModule* aPDM);
   // Returns the first PDM in our list supporting the mimetype.
   already_AddRefed<PlatformDecoderModule>
   GetDecoder(const TrackInfo& aTrackInfo,
              DecoderDoctorDiagnostics* aDiagnostics) const;
 
   already_AddRefed<MediaDataDecoder>
   CreateDecoderWithPDM(PlatformDecoderModule* aPDM,
                        const CreateDecoderParams& aParams);
 
   nsTArray<RefPtr<PlatformDecoderModule>> mCurrentPDMs;
   RefPtr<PlatformDecoderModule> mEMEPDM;
-  RefPtr<PlatformDecoderModule> mNullPDM;
+  RefPtr<PlatformDecoderModule> mBlankPDM;
 
   bool mWMFFailedToLoad = false;
   bool mFFmpegFailedToLoad = false;
   bool mGMPPDMFailedToStartup = false;
 
   void EnsureInit() const;
   template<class T> friend class StaticAutoPtr;
   static StaticAutoPtr<PDMFactoryImpl> sInstance;
--- a/dom/media/platforms/PlatformDecoderModule.h
+++ b/dom/media/platforms/PlatformDecoderModule.h
@@ -80,34 +80,34 @@ struct MOZ_STACK_CLASS CreateDecoderPara
 
   const TrackInfo& mConfig;
   TaskQueue* mTaskQueue = nullptr;
   DecoderDoctorDiagnostics* mDiagnostics = nullptr;
   layers::ImageContainer* mImageContainer = nullptr;
   MediaResult* mError = nullptr;
   RefPtr<layers::KnowsCompositor> mKnowsCompositor;
   RefPtr<GMPCrashHelper> mCrashHelper;
-  bool mUseNullDecoder = false;
+  bool mUseBlankDecoder = false;
   TrackInfo::TrackType mType = TrackInfo::kUndefinedTrack;
   MediaEventProducer<TrackInfo::TrackType>* mOnWaitingForKeyEvent = nullptr;
   OptionSet mOptions = OptionSet(Option::Default);
 
 private:
   void Set(TaskQueue* aTaskQueue) { mTaskQueue = aTaskQueue; }
   void Set(DecoderDoctorDiagnostics* aDiagnostics)
   {
     mDiagnostics = aDiagnostics;
   }
   void Set(layers::ImageContainer* aImageContainer)
   {
     mImageContainer = aImageContainer;
   }
   void Set(MediaResult* aError) { mError = aError; }
   void Set(GMPCrashHelper* aCrashHelper) { mCrashHelper = aCrashHelper; }
-  void Set(bool aUseNullDecoder) { mUseNullDecoder = aUseNullDecoder; }
+  void Set(bool aUseBlankDecoder) { mUseBlankDecoder = aUseBlankDecoder; }
   void Set(OptionSet aOptions) { mOptions = aOptions; }
   void Set(layers::KnowsCompositor* aKnowsCompositor)
   {
     mKnowsCompositor = aKnowsCompositor;
   }
   void Set(TrackInfo::TrackType aType)
   {
     mType = aType;
--- a/dom/media/platforms/agnostic/BlankDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/BlankDecoderModule.cpp
@@ -1,107 +1,209 @@
 /* -*- 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 "MediaData.h"
+#include "MP4Decoder.h"
+#include "MediaDecoderReader.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 {
 
-class BlankVideoDataCreator : public DummyDataCreator {
+// 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
+{
 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(MediaRawData* aSample) override
+  already_AddRefed<MediaData> Create(const media::TimeUnit& aDTS,
+                                     const media::TimeUnit& aDuration,
+                                     int64_t aOffsetInStream)
   {
     // 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. Have the data pointer of each frame point to the
-    // first plane, they'll always be zero'd memory anyway.
-    auto frame = MakeUnique<uint8_t[]>(mFrameWidth * mFrameHeight);
-    memset(frame.get(), 0, mFrameWidth * mFrameHeight);
+    // 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;
 
     // Y plane.
     buffer.mPlanes[0].mData = frame.get();
     buffer.mPlanes[0].mStride = mFrameWidth;
     buffer.mPlanes[0].mHeight = mFrameHeight;
     buffer.mPlanes[0].mWidth = mFrameWidth;
     buffer.mPlanes[0].mOffset = 0;
     buffer.mPlanes[0].mSkip = 0;
 
     // Cb plane.
-    buffer.mPlanes[1].mData = frame.get();
+    buffer.mPlanes[1].mData = frame.get() + sizeY;
     buffer.mPlanes[1].mStride = (mFrameWidth + 1) / 2;
     buffer.mPlanes[1].mHeight = (mFrameHeight + 1) / 2;
     buffer.mPlanes[1].mWidth = (mFrameWidth + 1) / 2;
     buffer.mPlanes[1].mOffset = 0;
     buffer.mPlanes[1].mSkip = 0;
 
     // Cr plane.
-    buffer.mPlanes[2].mData = frame.get();
+    buffer.mPlanes[2].mData = frame.get() + sizeY;
     buffer.mPlanes[2].mStride = (mFrameWidth + 1) / 2;
     buffer.mPlanes[2].mHeight = (mFrameHeight + 1) / 2;
     buffer.mPlanes[2].mWidth = (mFrameWidth + 1) / 2;
     buffer.mPlanes[2].mOffset = 0;
     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,
-                                        aSample->mOffset,
-                                        aSample->mTime,
-                                        aSample->mDuration,
+                                        aOffsetInStream,
+                                        aDTS.ToMicroseconds(),
+                                        aDuration.ToMicroseconds(),
                                         buffer,
-                                        aSample->mKeyframe,
-                                        aSample->mTime,
+                                        true,
+                                        aDTS.ToMicroseconds(),
                                         mPicture);
   }
 
 private:
   VideoInfo mInfo;
   gfx::IntRect mPicture;
   uint32_t mFrameWidth;
   uint32_t mFrameHeight;
   RefPtr<layers::ImageContainer> mImageContainer;
 };
 
-class BlankAudioDataCreator : public DummyDataCreator
+class BlankAudioDataCreator
 {
 public:
   BlankAudioDataCreator(uint32_t aChannelCount, uint32_t aSampleRate)
     : mFrameSum(0), mChannelCount(aChannelCount), mSampleRate(aSampleRate)
   {
   }
 
-  already_AddRefed<MediaData> Create(MediaRawData* aSample) override
+  MediaData* Create(const media::TimeUnit& aDTS,
+                    const media::TimeUnit& aDuration,
+                    int64_t aOffsetInStream)
   {
     // Convert duration to frames. We add 1 to duration to account for
     // rounding errors, so we get a consistent tone.
-    CheckedInt64 frames = UsecsToFrames(aSample->mDuration+1, mSampleRate);
+    CheckedInt64 frames =
+      UsecsToFrames(aDuration.ToMicroseconds()+1, mSampleRate);
     if (!frames.isValid()
         || !mChannelCount
         || !mSampleRate
         || frames.value() > (UINT32_MAX / mChannelCount)) {
       return nullptr;
     }
     AlignedAudioBuffer samples(frames.value() * mChannelCount);
     if (!samples) {
@@ -112,24 +214,23 @@ 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++;
     }
-    RefPtr<AudioData> data(new AudioData(aSample->mOffset,
-                                         aSample->mTime,
-                                         aSample->mDuration,
-                                         uint32_t(frames.value()),
-                                         Move(samples),
-                                         mChannelCount,
-                                         mSampleRate));
-    return data.forget();
+    return new AudioData(aOffsetInStream,
+                         aDTS.ToMicroseconds(),
+                         aDuration.ToMicroseconds(),
+                         uint32_t(frames.value()),
+                         Move(samples),
+                         mChannelCount,
+                         mSampleRate);
   }
 
 private:
   int64_t mFrameSum;
   uint32_t mChannelCount;
   uint32_t mSampleRate;
 };
 
@@ -137,32 +238,33 @@ class BlankDecoderModule : public Platfo
 {
 public:
 
   // Decode thread.
   already_AddRefed<MediaDataDecoder>
   CreateVideoDecoder(const CreateDecoderParams& aParams) override
   {
     const VideoInfo& config = aParams.VideoConfig();
-    UniquePtr<DummyDataCreator> creator =
-      MakeUnique<BlankVideoDataCreator>(config.mDisplay.width, config.mDisplay.height, aParams.mImageContainer);
+    BlankVideoDataCreator* creator = new BlankVideoDataCreator(
+      config.mDisplay.width, config.mDisplay.height, aParams.mImageContainer);
     RefPtr<MediaDataDecoder> decoder =
-      new DummyMediaDataDecoder(Move(creator), "blank media data decoder", aParams);
+      new BlankMediaDataDecoder<BlankVideoDataCreator>(creator, aParams);
     return decoder.forget();
   }
 
   // Decode thread.
   already_AddRefed<MediaDataDecoder>
   CreateAudioDecoder(const CreateDecoderParams& aParams) override
   {
     const AudioInfo& config = aParams.AudioConfig();
-    UniquePtr<DummyDataCreator> creator =
-      MakeUnique<BlankAudioDataCreator>(config.mChannels, config.mRate);
+    BlankAudioDataCreator* creator = new BlankAudioDataCreator(
+      config.mChannels, config.mRate);
+
     RefPtr<MediaDataDecoder> decoder =
-      new DummyMediaDataDecoder(Move(creator), "blank media data decoder", aParams);
+      new BlankMediaDataDecoder<BlankAudioDataCreator>(creator, aParams);
     return decoder.forget();
   }
 
   bool SupportsMimeType(const nsACString& aMimeType,
                         DecoderDoctorDiagnostics* aDiagnostics) const override
   {
     return true;
   }
deleted file mode 100644
--- a/dom/media/platforms/agnostic/DummyMediaDataDecoder.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- 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
deleted file mode 100644
--- a/dom/media/platforms/agnostic/DummyMediaDataDecoder.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- 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_)
deleted file mode 100644
--- a/dom/media/platforms/agnostic/NullDecoderModule.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- 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"
-
-namespace mozilla {
-
-class NullVideoDataCreator : public DummyDataCreator {
-public:
-  NullVideoDataCreator() {}
-
-  already_AddRefed<MediaData> Create(MediaRawData* aSample) override
-  {
-    // Create a dummy VideoData with no image. This gives us something to
-    // send to media streams if necessary.
-    RefPtr<VideoData> v(new VideoData(aSample->mOffset,
-                                      aSample->mTime,
-                                      aSample->mDuration,
-                                      aSample->mKeyframe,
-                                      aSample->mTimecode,
-                                      gfx::IntSize(),
-                                      0));
-    return v.forget();
-  }
-};
-
-class NullDecoderModule : public PlatformDecoderModule {
-public:
-
-  // Decode thread.
-  already_AddRefed<MediaDataDecoder>
-  CreateVideoDecoder(const CreateDecoderParams& aParams) override {
-    UniquePtr<DummyDataCreator> creator = MakeUnique<NullVideoDataCreator>();
-    RefPtr<MediaDataDecoder> decoder =
-      new DummyMediaDataDecoder(Move(creator), "null media data decoder", aParams);
-    return decoder.forget();
-  }
-
-  // Decode thread.
-  already_AddRefed<MediaDataDecoder>
-  CreateAudioDecoder(const CreateDecoderParams& aParams) override {
-    MOZ_ASSERT(false, "Audio decoders are unsupported.");
-    return nullptr;
-  }
-
-  bool
-  SupportsMimeType(const nsACString& aMimeType,
-                   DecoderDoctorDiagnostics* aDiagnostics) const override
-  {
-    return true;
-  }
-};
-
-already_AddRefed<PlatformDecoderModule> CreateNullDecoderModule()
-{
-  RefPtr<PlatformDecoderModule> pdm = new NullDecoderModule();
-  return pdm.forget();
-}
-
-} // namespace mozilla
--- a/dom/media/platforms/moz.build
+++ b/dom/media/platforms/moz.build
@@ -1,35 +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',
     '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/NullDecoderModule.cpp',
     'agnostic/OpusDecoder.cpp',
     'agnostic/TheoraDecoder.cpp',
     'agnostic/VorbisDecoder.cpp',
     'agnostic/VPXDecoder.cpp',
     'agnostic/WAVDecoder.cpp',
     'PDMFactory.cpp',
     'wrappers/H264Converter.cpp',
     'wrappers/MediaDataDecoderProxy.cpp'
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -1135,13 +1135,10 @@ tags = suspend
 skip-if = toolkit == 'android' # bug 1295884, android(bug 1304480, bug 1232305)
 tags = suspend
 [test_background_video_no_suspend_short_vid.html]
 skip-if = toolkit == 'android' # android(bug 1304480)
 tags = suspend
 [test_background_video_no_suspend_disabled.html]
 skip-if = toolkit == 'android' # android(bug 1304480)
 tags = suspend
-[test_background_video_drawimage_with_suspended_video.html]
-tags = suspend
-
 [test_temporary_file_blob_video_plays.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
deleted file mode 100644
--- a/dom/media/test/test_background_video_drawimage_with_suspended_video.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>Test Background Video Displays Video Frame via drawImage When Suspended</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<script src="manifest.js"></script>
-<script src="background_video.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
-<style>
-video, canvas {
-  border: 1px solid black;
-}
-</style>
-<script type="text/javascript">
-"use strict";
-
-var manager = new MediaTestManager;
-
-function drawVideoToCanvas(v) {
-  console.log('drawVideoToCanvas');
-  let w = v.width,
-      h = v.height,
-      c = document.createElement('canvas');
-  c.width = 4;
-  c.height = 4;
-  c.style.width = 64;
-  c.style.height = 64;
-  document.body.appendChild(c);
-
-  let gfx = c.getContext('2d');
-  if (!gfx) {
-    throw Error("Unable to obtain context '2d' from canvas");
-  }
-
-  gfx.drawImage(v, 0, 0, 4, 4);
-  let imageData = gfx.getImageData(0, 0, 4, 4);
-  let pixels = imageData.data;
-
-  // Check that pixels aren't all the same colour.
-  // Implements by checking against rgb of the first pixel.
-  let rr = pixels[0],
-      gg = pixels[1],
-      bb = pixels[2],
-      allSame = true;
-
-  for (let i = 0; i < 4*4; i++) {
-    let r = pixels[4*i+0];
-    let g = pixels[4*i+1];
-    let b = pixels[4*i+2];
-    if (r != rr || g != gg || b != bb) {
-      allSame = false;
-      break;
-    }
-  }
-
-  ok(!allSame, "Pixels aren't all the same color");
-}
-
-startTest({
-  desc: 'Test Background Video Displays Video Frame via drawImage When Suspended',
-  prefs: [
-    [ "media.test.video-suspend", true ],
-    [ "media.suspend-bkgnd-video.enabled", true ],
-    [ "media.suspend-bkgnd-video.delay-ms", 500 ]
-  ],
-  tests: gDecodeSuspendTests,
-  runTest: (test, token) => {
-    let v = appendVideoToDoc(test.name, token);
-    manager.started(token);
-
-    waitUntilPlaying(v)
-      .then(() => testVideoSuspendsWhenHidden(v))
-      .then(() => {
-        drawVideoToCanvas(v);
-        manager.finished(token);
-      });
-  }
-});
-</script>
\ No newline at end of file