Bug 1128794 - Refactor EME decoders on top of GMP decoders. r=cpearce a=lmandel
authorMatthew Gregan <kinetik@flim.org>
Mon, 02 Feb 2015 21:49:00 +1300
changeset 250199 87bba928e233
parent 250198 f2e35a9f30a7
child 250200 93c5dec5ad4b
push id4521
push usercpearce@mozilla.com
push date2015-03-04 01:22 +0000
treeherdermozilla-beta@8abdbdecd2d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, lmandel
bugs1128794
milestone37.0
Bug 1128794 - Refactor EME decoders on top of GMP decoders. r=cpearce a=lmandel
dom/media/fmp4/eme/EMEAudioDecoder.cpp
dom/media/fmp4/eme/EMEAudioDecoder.h
dom/media/fmp4/eme/EMEDecoderModule.cpp
dom/media/fmp4/eme/EMEH264Decoder.cpp
dom/media/fmp4/eme/EMEH264Decoder.h
dom/media/fmp4/eme/EMEVideoDecoder.cpp
dom/media/fmp4/eme/EMEVideoDecoder.h
dom/media/fmp4/eme/moz.build
--- a/dom/media/fmp4/eme/EMEAudioDecoder.cpp
+++ b/dom/media/fmp4/eme/EMEAudioDecoder.cpp
@@ -1,343 +1,37 @@
 /* -*- 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 "EMEAudioDecoder.h"
-#include "mp4_demuxer/DecoderData.h"
-#include "mozilla/EMELog.h"
-#include "gmp-audio-host.h"
-#include "gmp-audio-decode.h"
-#include "gmp-audio-samples.h"
-#include "GMPAudioHost.h"
-#include "GMPAudioDecoderProxy.h"
 #include "mozilla/CDMProxy.h"
-#include "nsServiceManagerUtils.h"
-#include "prsystem.h"
 
 namespace mozilla {
 
-EMEAudioDecoder::EMEAudioDecoder(CDMProxy* aProxy,
-                                 const AudioDecoderConfig& aConfig,
-                                 MediaTaskQueue* aTaskQueue,
-                                 MediaDataDecoderCallback* aCallback)
-  : mAudioRate(0)
-  , mAudioBytesPerSample(0)
-  , mAudioChannels(0)
-  , mMustRecaptureAudioPosition(true)
-  , mAudioFrameSum(0)
-  , mAudioFrameOffset(0)
-  , mStreamOffset(0)
-  , mProxy(aProxy)
-  , mGMP(nullptr)
-  , mConfig(aConfig)
-  , mTaskQueue(aTaskQueue)
-  , mCallback(aCallback)
-  , mSamplesWaitingForKey(new SamplesWaitingForKey(this, mTaskQueue, mProxy))
-  , mMonitor("EMEAudioDecoder")
-  , mFlushComplete(false)
-#ifdef DEBUG
-  , mIsShutdown(false)
-#endif
-{
-}
-
-EMEAudioDecoder::~EMEAudioDecoder()
-{
-}
-
-nsresult
-EMEAudioDecoder::Init()
-{
-  // Note: this runs on the decode task queue.
-  MOZ_ASSERT(!mIsShutdown);
-
-  MOZ_ASSERT((mConfig.bits_per_sample / 8) == 2); // Demuxer guarantees this.
-
-  mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
-  MOZ_ASSERT(mMPS);
-
-  nsresult rv = mMPS->GetThread(getter_AddRefs(mGMPThread));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsRefPtr<InitTask> task(new InitTask(this));
-  rv = mGMPThread->Dispatch(task, NS_DISPATCH_SYNC);
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_SUCCESS(task->mResult, task->mResult);
-
-  return NS_OK;
-}
-
-nsresult
-EMEAudioDecoder::Input(MP4Sample* aSample)
-{
-  MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
-  MOZ_ASSERT(!mIsShutdown);
-
-  if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) {
-    return NS_OK;
-  }
-
-  nsRefPtr<nsIRunnable> task(new DeliverSample(this, aSample));
-  nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
-}
-
-nsresult
-EMEAudioDecoder::Flush()
-{
-  MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
-  MOZ_ASSERT(!mIsShutdown);
-
-  {
-    MonitorAutoLock mon(mMonitor);
-    mFlushComplete = false;
-  }
-
-  nsRefPtr<nsIRunnable> task;
-  task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpFlush);
-  nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  {
-    MonitorAutoLock mon(mMonitor);
-    while (!mFlushComplete) {
-      mon.Wait();
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult
-EMEAudioDecoder::Drain()
-{
-  MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
-  MOZ_ASSERT(!mIsShutdown);
-
-  nsRefPtr<nsIRunnable> task;
-  task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpDrain);
-  nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
-  return NS_OK;
-}
-
-nsresult
-EMEAudioDecoder::Shutdown()
+void
+EMEAudioCallbackAdapter::Error(GMPErr aErr)
 {
-  MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
-  MOZ_ASSERT(!mIsShutdown);
-#ifdef DEBUG
-  mIsShutdown = true;
-#endif
-
-  nsRefPtr<nsIRunnable> task;
-  task = NS_NewRunnableMethod(this, &EMEAudioDecoder::GmpShutdown);
-  nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_SYNC);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mSamplesWaitingForKey->BreakCycles();
-  mSamplesWaitingForKey = nullptr;
-
-  return NS_OK;
-}
-
-void
-EMEAudioDecoder::Decoded(const nsTArray<int16_t>& aPCM,
-                         uint64_t aTimeStamp,
-                         uint32_t aChannels,
-                         uint32_t aRate)
-{
-  MOZ_ASSERT(IsOnGMPThread());
-
-  if (aRate == 0 || aChannels == 0) {
-    NS_WARNING("Invalid rate or num channels returned on GMP audio samples");
-    mCallback->Error();
-    return;
-  }
-
-  size_t numFrames = aPCM.Length() / aChannels;
-  MOZ_ASSERT((aPCM.Length() % aChannels) == 0);
-  nsAutoArrayPtr<AudioDataValue> audioData(new AudioDataValue[aPCM.Length()]);
-
-  for (size_t i = 0; i < aPCM.Length(); ++i) {
-    audioData[i] = AudioSampleToFloat(aPCM[i]);
-  }
-
-  if (mMustRecaptureAudioPosition) {
-    mAudioFrameSum = 0;
-    auto timestamp = UsecsToFrames(aTimeStamp, aRate);
-    if (!timestamp.isValid()) {
-      NS_WARNING("Invalid timestamp");
-      mCallback->Error();
-      return;
-    }
-    mAudioFrameOffset = timestamp.value();
-    MOZ_ASSERT(mAudioFrameOffset >= 0);
-    mMustRecaptureAudioPosition = false;
-  }
-
-  auto timestamp = FramesToUsecs(mAudioFrameOffset + mAudioFrameSum, aRate);
-  if (!timestamp.isValid()) {
-    NS_WARNING("Invalid timestamp on audio samples");
-    mCallback->Error();
-    return;
-  }
-  mAudioFrameSum += numFrames;
-
-  auto duration = FramesToUsecs(numFrames, aRate);
-  if (!duration.isValid()) {
-    NS_WARNING("Invalid duration on audio samples");
-    mCallback->Error();
-    return;
-  }
-
-  nsRefPtr<AudioData> audio(new AudioData(mStreamOffset,
-                                          timestamp.value(),
-                                          duration.value(),
-                                          numFrames,
-                                          audioData.forget(),
-                                          aChannels,
-                                          aRate));
-
-  #ifdef LOG_SAMPLE_DECODE
-  LOG("Decoded audio sample! timestamp=%lld duration=%lld currentLength=%u",
-      timestamp, duration, currentLength);
-  #endif
-
-  mCallback->Output(audio);
-}
-
-void
-EMEAudioDecoder::InputDataExhausted()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  mCallback->InputExhausted();
-}
-
-void
-EMEAudioDecoder::DrainComplete()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  mCallback->DrainComplete();
-}
-
-void
-EMEAudioDecoder::ResetComplete()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  mMustRecaptureAudioPosition = true;
-  {
-    MonitorAutoLock mon(mMonitor);
-    mFlushComplete = true;
-    mon.NotifyAll();
-  }
-}
-
-void
-EMEAudioDecoder::Error(GMPErr aErr)
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  EME_LOG("EMEAudioDecoder::Error %d", aErr);
   if (aErr == GMPNoKeyErr) {
     // The GMP failed to decrypt a frame due to not having a key. This can
     // happen if a key expires or a session is closed during playback.
     NS_WARNING("GMP failed to decrypt due to lack of key");
-  } else {
-    mCallback->Error();
-    GmpShutdown();
+    return;
   }
+  AudioCallbackAdapter::Error(aErr);
 }
 
 void
-EMEAudioDecoder::Terminated()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  GmpShutdown();
-}
-
-nsresult
-EMEAudioDecoder::GmpInit()
+EMEAudioDecoder::InitTags(nsTArray<nsCString>& aTags)
 {
-  MOZ_ASSERT(IsOnGMPThread());
-
-  nsTArray<nsCString> tags;
-  tags.AppendElement(NS_LITERAL_CSTRING("aac"));
-  tags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem()));
-  nsresult rv = mMPS->GetGMPAudioDecoder(&tags,
-                                         mProxy->GetNodeId(),
-                                         &mGMP);
-  NS_ENSURE_SUCCESS(rv, rv);
-  MOZ_ASSERT(mGMP);
-
-  mAudioRate = mConfig.samples_per_second;
-  mAudioBytesPerSample = mConfig.bits_per_sample / 8;
-  mAudioChannels = mConfig.channel_count;
-
-  nsTArray<uint8_t> extraData;
-  extraData.AppendElements(mConfig.audio_specific_config->Elements(),
-                           mConfig.audio_specific_config->Length());
-  mGMP->InitDecode(kGMPAudioCodecAAC,
-                   mAudioChannels,
-                   mConfig.bits_per_sample,
-                   mAudioRate,
-                   extraData,
-                   this);
-
-  return NS_OK;
+  GMPAudioDecoder::InitTags(aTags);
+  aTags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem()));
 }
 
-nsresult
-EMEAudioDecoder::GmpInput(MP4Sample* aSample)
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  nsAutoPtr<MP4Sample> sample(aSample);
-  if (!mGMP) {
-    mCallback->Error();
-    return NS_ERROR_FAILURE;
-  }
-
-  gmp::GMPAudioSamplesImpl samples(sample, mAudioChannels, mAudioRate);
-  mGMP->Decode(samples);
-
-  mStreamOffset = sample->byte_offset;
-
-  return NS_OK;
-}
-
-void
-EMEAudioDecoder::GmpFlush()
+nsCString
+EMEAudioDecoder::GetNodeId()
 {
-  MOZ_ASSERT(IsOnGMPThread());
-  if (!mGMP || NS_FAILED(mGMP->Reset())) {
-    // Abort the flush...
-    MonitorAutoLock mon(mMonitor);
-    mFlushComplete = true;
-    mon.NotifyAll();
-  }
-}
-
-void
-EMEAudioDecoder::GmpDrain()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  if (!mGMP || NS_FAILED(mGMP->Drain())) {
-    mCallback->DrainComplete();
-  }
-}
-
-void
-EMEAudioDecoder::GmpShutdown()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  if (!mGMP) {
-    return;
-  }
-  mGMP->Close();
-  mGMP = nullptr;
+  return mProxy->GetNodeId();
 }
 
 } // namespace mozilla
--- a/dom/media/fmp4/eme/EMEAudioDecoder.h
+++ b/dom/media/fmp4/eme/EMEAudioDecoder.h
@@ -1,124 +1,44 @@
 /* -*- 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/. */
 
-#ifndef EMEAACDecoder_h_
-#define EMEAACDecoder_h_
+#ifndef EMEAudioDecoder_h_
+#define EMEAudioDecoder_h_
 
+#include "GMPAudioDecoder.h"
 #include "PlatformDecoderModule.h"
-#include "mp4_demuxer/DecoderData.h"
-#include "mozIGeckoMediaPluginService.h"
-#include "nsServiceManagerUtils.h"
-#include "GMPAudioHost.h"
-#include "GMPAudioDecoderProxy.h"
-#include "SamplesWaitingForKey.h"
 
 namespace mozilla {
 
-class EMEAudioDecoder : public MediaDataDecoder
-                      , public GMPAudioDecoderCallbackProxy
-{
-  typedef mp4_demuxer::MP4Sample MP4Sample;
-  typedef mp4_demuxer::AudioDecoderConfig AudioDecoderConfig;
+class EMEAudioCallbackAdapter : public AudioCallbackAdapter {
+public:
+  explicit EMEAudioCallbackAdapter(MediaDataDecoderCallbackProxy* aCallback)
+   : AudioCallbackAdapter(aCallback)
+  {}
+
+  virtual void Error(GMPErr aErr) MOZ_OVERRIDE;
+};
+
+class EMEAudioDecoder : public GMPAudioDecoder {
 public:
   EMEAudioDecoder(CDMProxy* aProxy,
-                  const AudioDecoderConfig& aConfig,
+                  const mp4_demuxer::AudioDecoderConfig& aConfig,
                   MediaTaskQueue* aTaskQueue,
-                  MediaDataDecoderCallback* aCallback);
-
-  ~EMEAudioDecoder();
-
-  // MediaDataDecoder implementation.
-  virtual nsresult Init() MOZ_OVERRIDE;
-  virtual nsresult Input(MP4Sample* aSample) MOZ_OVERRIDE;
-  virtual nsresult Flush() MOZ_OVERRIDE;
-  virtual nsresult Drain() MOZ_OVERRIDE;
-  virtual nsresult Shutdown() MOZ_OVERRIDE;
-
-  // GMPAudioDecoderCallbackProxy implementation.
-  virtual void Decoded(const nsTArray<int16_t>& aPCM,
-                       uint64_t aTimeStamp,
-                       uint32_t aChannels,
-                       uint32_t aRate) MOZ_OVERRIDE;
-  virtual void InputDataExhausted() MOZ_OVERRIDE;
-  virtual void DrainComplete() MOZ_OVERRIDE;
-  virtual void ResetComplete() MOZ_OVERRIDE;
-  virtual void Error(GMPErr aErr) MOZ_OVERRIDE;
-  virtual void Terminated() MOZ_OVERRIDE;
+                  MediaDataDecoderCallbackProxy* aCallback)
+   : GMPAudioDecoder(aConfig, aTaskQueue, aCallback, new EMEAudioCallbackAdapter(aCallback))
+   , mProxy(aProxy)
+  {
+  }
 
 private:
-
-  class DeliverSample : public nsRunnable {
-  public:
-    DeliverSample(EMEAudioDecoder* aDecoder,
-                  mp4_demuxer::MP4Sample* aSample)
-      : mDecoder(aDecoder)
-      , mSample(aSample)
-    {}
-
-    NS_IMETHOD Run() {
-      mDecoder->GmpInput(mSample.forget());
-      return NS_OK;
-    }
-  private:
-    nsRefPtr<EMEAudioDecoder> mDecoder;
-    nsAutoPtr<mp4_demuxer::MP4Sample> mSample;
-  };
-
-  class InitTask : public nsRunnable {
-  public:
-    explicit InitTask(EMEAudioDecoder* aDecoder)
-      : mDecoder(aDecoder)
-    {}
-    NS_IMETHOD Run() {
-      mResult = mDecoder->GmpInit();
-      return NS_OK;
-    }
-    nsresult mResult;
-    EMEAudioDecoder* mDecoder;
-  };
+  virtual void InitTags(nsTArray<nsCString>& aTags) MOZ_OVERRIDE;
+  virtual nsCString GetNodeId() MOZ_OVERRIDE;
 
-  nsresult GmpInit();
-  nsresult GmpInput(MP4Sample* aSample);
-  void GmpFlush();
-  void GmpDrain();
-  void GmpShutdown();
-
-#ifdef DEBUG
-  bool IsOnGMPThread() {
-    return NS_GetCurrentThread() == mGMPThread;
-  }
-#endif
-
-  uint32_t mAudioRate;
-  uint32_t mAudioBytesPerSample;
-  uint32_t mAudioChannels;
-  bool mMustRecaptureAudioPosition;
-  int64_t mAudioFrameSum;
-  int64_t mAudioFrameOffset;
-  int64_t mStreamOffset;
-
-  nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
-  nsCOMPtr<nsIThread> mGMPThread;
   nsRefPtr<CDMProxy> mProxy;
-  GMPAudioDecoderProxy* mGMP;
-
-  const mp4_demuxer::AudioDecoderConfig& mConfig;
-  nsRefPtr<MediaTaskQueue> mTaskQueue;
-  MediaDataDecoderCallback* mCallback;
-
-  nsRefPtr<SamplesWaitingForKey> mSamplesWaitingForKey;
-
-  Monitor mMonitor;
-  bool mFlushComplete;
-
-#ifdef DEBUG
-  bool mIsShutdown;
-#endif
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/fmp4/eme/EMEDecoderModule.cpp
+++ b/dom/media/fmp4/eme/EMEDecoderModule.cpp
@@ -1,33 +1,22 @@
 /* -*- 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 "EMEDecoderModule.h"
+#include "EMEAudioDecoder.h"
+#include "EMEVideoDecoder.h"
+#include "MediaDataDecoderProxy.h"
 #include "mozIGeckoMediaPluginService.h"
-#include "nsServiceManagerUtils.h"
-#include "nsThreadUtils.h"
-#include "ImageContainer.h"
-#include "prsystem.h"
-#include "mp4_demuxer/DecoderData.h"
-#include "gfx2DGlue.h"
-#include "nsContentUtils.h"
 #include "mozilla/CDMProxy.h"
-#include "mozilla/EMELog.h"
-#include "MediaTaskQueue.h"
-#include "SharedThreadPool.h"
-#include "mozilla/EMELog.h"
-#include "EMEH264Decoder.h"
-#include "EMEAudioDecoder.h"
 #include "mozilla/unused.h"
-#include "SamplesWaitingForKey.h"
-#include <string>
+#include "nsServiceManagerUtils.h"
 
 namespace mozilla {
 
 class EMEDecryptor : public MediaDataDecoder {
   typedef mp4_demuxer::MP4Sample MP4Sample;
 
 public:
 
@@ -163,16 +152,52 @@ private:
   nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
   nsRefPtr<CDMProxy> mProxy;
   nsRefPtr<SamplesWaitingForKey> mSamplesWaitingForKey;
 #ifdef DEBUG
   bool mIsShutdown;
 #endif
 };
 
+class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy {
+public:
+  EMEMediaDataDecoderProxy(nsIThread* aProxyThread, MediaDataDecoderCallback* aCallback, CDMProxy* aProxy, FlushableMediaTaskQueue* aTaskQueue)
+   : MediaDataDecoderProxy(aProxyThread, aCallback)
+   , mSamplesWaitingForKey(new SamplesWaitingForKey(this, aTaskQueue, aProxy))
+  {
+  }
+
+  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+  virtual nsresult Shutdown() MOZ_OVERRIDE;
+
+private:
+  nsRefPtr<SamplesWaitingForKey> mSamplesWaitingForKey;
+};
+
+nsresult
+EMEMediaDataDecoderProxy::Input(mp4_demuxer::MP4Sample* aSample)
+{
+  if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) {
+    return NS_OK;
+  }
+
+  return MediaDataDecoderProxy::Input(aSample);
+}
+
+nsresult
+EMEMediaDataDecoderProxy::Shutdown()
+{
+  nsresult rv = MediaDataDecoderProxy::Shutdown();
+
+  mSamplesWaitingForKey->BreakCycles();
+  mSamplesWaitingForKey = nullptr;
+
+  return rv;
+}
+
 EMEDecoderModule::EMEDecoderModule(CDMProxy* aProxy,
                                    PlatformDecoderModule* aPDM,
                                    bool aCDMDecodesAudio,
                                    bool aCDMDecodesVideo)
   : mProxy(aProxy)
   , mPDM(aPDM)
   , mCDMDecodesAudio(aCDMDecodesAudio)
   , mCDMDecodesVideo(aCDMDecodesVideo)
@@ -187,31 +212,50 @@ nsresult
 EMEDecoderModule::Shutdown()
 {
   if (mPDM) {
     return mPDM->Shutdown();
   }
   return NS_OK;
 }
 
+static already_AddRefed<MediaDataDecoderProxy>
+CreateDecoderWrapper(MediaDataDecoderCallback* aCallback, CDMProxy* aProxy, FlushableMediaTaskQueue* aTaskQueue)
+{
+  nsCOMPtr<mozIGeckoMediaPluginService> gmpService = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
+  if (!gmpService) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIThread> thread;
+  nsresult rv = gmpService->GetThread(getter_AddRefs(thread));
+  if (NS_FAILED(rv)) {
+    return nullptr;
+  }
+
+  nsRefPtr<MediaDataDecoderProxy> decoder(new EMEMediaDataDecoderProxy(thread, aCallback, aProxy, aTaskQueue));
+  return decoder.forget();
+}
+
 already_AddRefed<MediaDataDecoder>
 EMEDecoderModule::CreateVideoDecoder(const VideoDecoderConfig& aConfig,
                                      layers::LayersBackend aLayersBackend,
                                      layers::ImageContainer* aImageContainer,
                                      FlushableMediaTaskQueue* aVideoTaskQueue,
                                      MediaDataDecoderCallback* aCallback)
 {
   if (mCDMDecodesVideo && aConfig.crypto.valid) {
-    nsRefPtr<MediaDataDecoder> decoder(new EMEH264Decoder(mProxy,
-                                                          aConfig,
-                                                          aLayersBackend,
-                                                          aImageContainer,
-                                                          aVideoTaskQueue,
-                                                          aCallback));
-    return decoder.forget();
+    nsRefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aCallback, mProxy, aVideoTaskQueue);
+    wrapper->SetProxyTarget(new EMEVideoDecoder(mProxy,
+                                                aConfig,
+                                                aLayersBackend,
+                                                aImageContainer,
+                                                aVideoTaskQueue,
+                                                wrapper->Callback()));
+    return wrapper.forget();
   }
 
   nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateVideoDecoder(aConfig,
                                                               aLayersBackend,
                                                               aImageContainer,
                                                               aVideoTaskQueue,
                                                               aCallback));
   if (!decoder) {
@@ -229,21 +273,22 @@ EMEDecoderModule::CreateVideoDecoder(con
 }
 
 already_AddRefed<MediaDataDecoder>
 EMEDecoderModule::CreateAudioDecoder(const AudioDecoderConfig& aConfig,
                                      FlushableMediaTaskQueue* aAudioTaskQueue,
                                      MediaDataDecoderCallback* aCallback)
 {
   if (mCDMDecodesAudio && aConfig.crypto.valid) {
-    nsRefPtr<MediaDataDecoder> decoder(new EMEAudioDecoder(mProxy,
-                                                           aConfig,
-                                                           aAudioTaskQueue,
-                                                           aCallback));
-    return decoder.forget();
+    nsRefPtr<MediaDataDecoderProxy> wrapper = CreateDecoderWrapper(aCallback, mProxy, aAudioTaskQueue);
+    wrapper->SetProxyTarget(new EMEAudioDecoder(mProxy,
+                                                aConfig,
+                                                aAudioTaskQueue,
+                                                wrapper->Callback()));
+    return wrapper.forget();
   }
 
   nsRefPtr<MediaDataDecoder> decoder(mPDM->CreateAudioDecoder(aConfig,
                                                               aAudioTaskQueue,
                                                               aCallback));
   if (!decoder) {
     return nullptr;
   }
rename from dom/media/fmp4/eme/EMEH264Decoder.cpp
rename to dom/media/fmp4/eme/EMEVideoDecoder.cpp
--- a/dom/media/fmp4/eme/EMEH264Decoder.cpp
+++ b/dom/media/fmp4/eme/EMEVideoDecoder.cpp
@@ -1,377 +1,48 @@
 /* -*- 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 "EMEH264Decoder.h"
-#include "gmp-video-host.h"
-#include "gmp-video-decode.h"
-#include "gmp-video-frame-i420.h"
-#include "gmp-video-frame-encoded.h"
+#include "EMEVideoDecoder.h"
 #include "GMPVideoEncodedFrameImpl.h"
-#include "mp4_demuxer/AnnexB.h"
 #include "mozilla/CDMProxy.h"
-#include "nsServiceManagerUtils.h"
-#include "prsystem.h"
-#include "gfx2DGlue.h"
-#include "mozilla/EMELog.h"
-#include "mozilla/Move.h"
 
 namespace mozilla {
 
-EMEH264Decoder::EMEH264Decoder(CDMProxy* aProxy,
-                               const mp4_demuxer::VideoDecoderConfig& aConfig,
-                               layers::LayersBackend aLayersBackend,
-                               layers::ImageContainer* aImageContainer,
-                               MediaTaskQueue* aTaskQueue,
-                               MediaDataDecoderCallback* aCallback)
-  : mProxy(aProxy)
-  , mGMP(nullptr)
-  , mHost(nullptr)
-  , mConfig(aConfig)
-  , mImageContainer(aImageContainer)
-  , mTaskQueue(aTaskQueue)
-  , mCallback(aCallback)
-  , mLastStreamOffset(0)
-  , mSamplesWaitingForKey(new SamplesWaitingForKey(this, mTaskQueue, mProxy))
-  , mMonitor("EMEH264Decoder")
-  , mFlushComplete(false)
-#ifdef DEBUG
-  , mIsShutdown(false)
-#endif
-{
-}
-
-EMEH264Decoder::~EMEH264Decoder() {
-}
-
-nsresult
-EMEH264Decoder::Init()
-{
-  // Note: this runs on the decode task queue.
-  MOZ_ASSERT(!mIsShutdown);
-
-  mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
-  MOZ_ASSERT(mMPS);
-
-  nsresult rv = mMPS->GetThread(getter_AddRefs(mGMPThread));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsRefPtr<InitTask> task(new InitTask(this));
-  rv = mGMPThread->Dispatch(task, NS_DISPATCH_SYNC);
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_SUCCESS(task->mResult, task->mResult);
-
-  return NS_OK;
-}
-
-nsresult
-EMEH264Decoder::Input(MP4Sample* aSample)
-{
-  MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
-  MOZ_ASSERT(!mIsShutdown);
-
-  if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) {
-    return NS_OK;
-  }
-
-  nsRefPtr<nsIRunnable> task(new DeliverSample(this, aSample));
-  nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
-}
-
-nsresult
-EMEH264Decoder::Flush()
-{
-  MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
-  MOZ_ASSERT(!mIsShutdown);
-
-  {
-    MonitorAutoLock mon(mMonitor);
-    mFlushComplete = false;
-  }
-
-  nsRefPtr<nsIRunnable> task;
-  task = NS_NewRunnableMethod(this, &EMEH264Decoder::GmpFlush);
-  nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  {
-    MonitorAutoLock mon(mMonitor);
-    while (!mFlushComplete) {
-      mon.Wait();
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult
-EMEH264Decoder::Drain()
-{
-  MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
-  MOZ_ASSERT(!mIsShutdown);
-
-  nsRefPtr<nsIRunnable> task;
-  task = NS_NewRunnableMethod(this, &EMEH264Decoder::GmpDrain);
-  nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
-  return NS_OK;
-}
-
-nsresult
-EMEH264Decoder::Shutdown()
+void
+EMEVideoCallbackAdapter::Error(GMPErr aErr)
 {
-  MOZ_ASSERT(!IsOnGMPThread()); // Runs on the decode task queue.
-  MOZ_ASSERT(!mIsShutdown);
-#ifdef DEBUG
-  mIsShutdown = true;
-#endif
-
-  nsRefPtr<nsIRunnable> task;
-  task = NS_NewRunnableMethod(this, &EMEH264Decoder::GmpShutdown);
-  nsresult rv = mGMPThread->Dispatch(task, NS_DISPATCH_SYNC);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mSamplesWaitingForKey->BreakCycles();
-  mSamplesWaitingForKey = nullptr;
-
-  return NS_OK;
-}
-
-void
-EMEH264Decoder::Decoded(GMPVideoi420Frame* aDecodedFrame)
-{
-  MOZ_ASSERT(IsOnGMPThread());
-
-  VideoData::YCbCrBuffer b;
-
-  auto height = aDecodedFrame->Height();
-  auto width = aDecodedFrame->Width();
-
-  // Y (Y') plane
-  b.mPlanes[0].mData = aDecodedFrame->Buffer(kGMPYPlane);
-  b.mPlanes[0].mStride = aDecodedFrame->Stride(kGMPYPlane);
-  b.mPlanes[0].mHeight = height;
-  b.mPlanes[0].mWidth = width;
-  b.mPlanes[0].mOffset = 0;
-  b.mPlanes[0].mSkip = 0;
-
-  // U plane (Cb)
-  b.mPlanes[1].mData = aDecodedFrame->Buffer(kGMPUPlane);
-  b.mPlanes[1].mStride = aDecodedFrame->Stride(kGMPUPlane);
-  b.mPlanes[1].mHeight = height / 2;
-  b.mPlanes[1].mWidth = width / 2;
-  b.mPlanes[1].mOffset = 0;
-  b.mPlanes[1].mSkip = 0;
-
-  // V plane (Cr)
-  b.mPlanes[2].mData = aDecodedFrame->Buffer(kGMPVPlane);
-  b.mPlanes[2].mStride = aDecodedFrame->Stride(kGMPVPlane);
-  b.mPlanes[2].mHeight = height / 2;
-  b.mPlanes[2].mWidth = width / 2;
-  b.mPlanes[2].mOffset = 0;
-  b.mPlanes[2].mSkip = 0;
-
-  gfx::IntRect pictureRegion(0, 0, width, height);
-  nsRefPtr<VideoData> v = VideoData::Create(mVideoInfo,
-                                            mImageContainer,
-                                            mLastStreamOffset,
-                                            aDecodedFrame->Timestamp(),
-                                            aDecodedFrame->Duration(),
-                                            b,
-                                            false,
-                                            -1,
-                                            pictureRegion);
-  aDecodedFrame->Destroy();
-  mCallback->Output(v);
-}
-
-void
-EMEH264Decoder::ReceivedDecodedReferenceFrame(const uint64_t aPictureId)
-{
-  // Ignore.
-}
-
-void
-EMEH264Decoder::ReceivedDecodedFrame(const uint64_t aPictureId)
-{
-  // Ignore.
-}
-
-void
-EMEH264Decoder::InputDataExhausted()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  mCallback->InputExhausted();
-}
-
-void
-EMEH264Decoder::DrainComplete()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  mCallback->DrainComplete();
-}
-
-void
-EMEH264Decoder::ResetComplete()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  {
-    MonitorAutoLock mon(mMonitor);
-    mFlushComplete = true;
-    mon.NotifyAll();
-  }
-}
-
-void
-EMEH264Decoder::Error(GMPErr aErr)
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  EME_LOG("EMEH264Decoder::Error %d", aErr);
   if (aErr == GMPNoKeyErr) {
     // The GMP failed to decrypt a frame due to not having a key. This can
     // happen if a key expires or a session is closed during playback.
     NS_WARNING("GMP failed to decrypt due to lack of key");
-  } else {
-    mCallback->Error();
-    GmpShutdown();
+    return;
   }
+  VideoCallbackAdapter::Error(aErr);
 }
 
 void
-EMEH264Decoder::Terminated()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-
-  NS_WARNING("H.264 GMP decoder terminated.");
-  GmpShutdown();
-}
-
-nsresult
-EMEH264Decoder::GmpInit()
+EMEVideoDecoder::InitTags(nsTArray<nsCString>& aTags)
 {
-  MOZ_ASSERT(IsOnGMPThread());
-
-  nsTArray<nsCString> tags;
-  tags.AppendElement(NS_LITERAL_CSTRING("h264"));
-  tags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem()));
-  nsresult rv = mMPS->GetGMPVideoDecoder(&tags,
-                                         mProxy->GetNodeId(),
-                                         &mHost,
-                                         &mGMP);
-  NS_ENSURE_SUCCESS(rv, rv);
-  MOZ_ASSERT(mHost && mGMP);
-
-  GMPVideoCodec codec;
-  memset(&codec, 0, sizeof(codec));
-
-  codec.mGMPApiVersion = kGMPVersion33;
-
-  codec.mCodecType = kGMPVideoCodecH264;
-  codec.mWidth = mConfig.display_width;
-  codec.mHeight = mConfig.display_height;
-
-  nsTArray<uint8_t> codecSpecific;
-  codecSpecific.AppendElement(0); // mPacketizationMode.
-  codecSpecific.AppendElements(mConfig.extra_data->Elements(),
-                               mConfig.extra_data->Length());
-
-  rv = mGMP->InitDecode(codec,
-                        codecSpecific,
-                        this,
-                        PR_GetNumberOfProcessors());
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mVideoInfo.mDisplay = nsIntSize(mConfig.display_width, mConfig.display_height);
-  mVideoInfo.mHasVideo = true;
-
-  return NS_OK;
+  GMPVideoDecoder::InitTags(aTags);
+  aTags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem()));
 }
 
-nsresult
-EMEH264Decoder::GmpInput(MP4Sample* aSample)
+nsCString
+EMEVideoDecoder::GetNodeId()
 {
-  MOZ_ASSERT(IsOnGMPThread());
-
-  nsAutoPtr<MP4Sample> sample(aSample);
-  if (!mGMP) {
-    mCallback->Error();
-    return NS_ERROR_FAILURE;
-  }
-
-  mLastStreamOffset = sample->byte_offset;
-
-  GMPVideoFrame* ftmp = nullptr;
-  GMPErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
-  if (GMP_FAILED(err)) {
-    mCallback->Error();
-    return NS_ERROR_FAILURE;
-  }
-
-  GMPUniquePtr<gmp::GMPVideoEncodedFrameImpl> frame(static_cast<gmp::GMPVideoEncodedFrameImpl*>(ftmp));
-  err = frame->CreateEmptyFrame(sample->size);
-  if (GMP_FAILED(err)) {
-    mCallback->Error();
-    return NS_ERROR_FAILURE;
-  }
-
-  memcpy(frame->Buffer(), sample->data, frame->Size());
-
-  frame->SetEncodedWidth(mConfig.display_width);
-  frame->SetEncodedHeight(mConfig.display_height);
-  frame->SetTimeStamp(sample->composition_timestamp);
-  frame->SetCompleteFrame(true);
-  frame->SetDuration(sample->duration);
-  if (sample->crypto.valid) {
-    frame->InitCrypto(sample->crypto);
-  }
-  frame->SetFrameType(sample->is_sync_point ? kGMPKeyFrame : kGMPDeltaFrame);
-  frame->SetBufferType(GMP_BufferLength32);
-
-  nsTArray<uint8_t> info; // No codec specific per-frame info to pass.
-  nsresult rv = mGMP->Decode(GMPUniquePtr<GMPVideoEncodedFrame>(frame.release()), false, info, 0);
-  if (NS_FAILED(rv)) {
-    mCallback->Error();
-    return rv;
-  }
-
-  return NS_OK;
+  return mProxy->GetNodeId();
 }
 
-void
-EMEH264Decoder::GmpFlush()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  if (!mGMP || NS_FAILED(mGMP->Reset())) {
-    // Abort the flush...
-    MonitorAutoLock mon(mMonitor);
-    mFlushComplete = true;
-    mon.NotifyAll();
-  }
-}
-
-void
-EMEH264Decoder::GmpDrain()
+GMPUniquePtr<GMPVideoEncodedFrame>
+EMEVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
 {
-  MOZ_ASSERT(IsOnGMPThread());
-  if (!mGMP || NS_FAILED(mGMP->Drain())) {
-    mCallback->DrainComplete();
+  GMPUniquePtr<GMPVideoEncodedFrame> frame = GMPVideoDecoder::CreateFrame(aSample);
+  if (frame && aSample->crypto.valid) {
+    static_cast<gmp::GMPVideoEncodedFrameImpl*>(frame.get())->InitCrypto(aSample->crypto);
   }
-}
-
-void
-EMEH264Decoder::GmpShutdown()
-{
-  MOZ_ASSERT(IsOnGMPThread());
-  if (!mGMP) {
-    return;
-  }
-  mGMP->Close();
-  mGMP = nullptr;
+  return frame;
 }
 
 } // namespace mozilla
rename from dom/media/fmp4/eme/EMEH264Decoder.h
rename to dom/media/fmp4/eme/EMEVideoDecoder.h
--- a/dom/media/fmp4/eme/EMEH264Decoder.h
+++ b/dom/media/fmp4/eme/EMEVideoDecoder.h
@@ -1,121 +1,54 @@
 /* -*- 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/. */
 
-#ifndef EMEH264Decoder_h_
-#define EMEH264Decoder_h_
+#ifndef EMEVideoDecoder_h_
+#define EMEVideoDecoder_h_
 
+#include "GMPVideoDecoder.h"
 #include "PlatformDecoderModule.h"
-#include "mp4_demuxer/DecoderData.h"
-#include "ImageContainer.h"
-#include "GMPVideoDecoderProxy.h"
-#include "mozIGeckoMediaPluginService.h"
-#include "SamplesWaitingForKey.h"
 
 namespace mozilla {
 
 class CDMProxy;
 class MediaTaskQueue;
 
-class EMEH264Decoder : public MediaDataDecoder
-                     , public GMPVideoDecoderCallbackProxy
-{
-  typedef mp4_demuxer::MP4Sample MP4Sample;
+class EMEVideoCallbackAdapter : public VideoCallbackAdapter {
 public:
-  EMEH264Decoder(CDMProxy* aProxy,
-                 const mp4_demuxer::VideoDecoderConfig& aConfig,
-                 layers::LayersBackend aLayersBackend,
-                 layers::ImageContainer* aImageContainer,
-                 MediaTaskQueue* aTaskQueue,
-                 MediaDataDecoderCallback* aCallback);
-  ~EMEH264Decoder();
+  EMEVideoCallbackAdapter(MediaDataDecoderCallbackProxy* aCallback,
+                          VideoInfo aVideoInfo,
+                          layers::ImageContainer* aImageContainer)
+   : VideoCallbackAdapter(aCallback, aVideoInfo, aImageContainer)
+  {}
+
+  virtual void Error(GMPErr aErr) MOZ_OVERRIDE;
+};
 
-  // MediaDataDecoder
-  virtual nsresult Init() MOZ_OVERRIDE;
-  virtual nsresult Input(MP4Sample* aSample) MOZ_OVERRIDE;
-  virtual nsresult Flush() MOZ_OVERRIDE;
-  virtual nsresult Drain() MOZ_OVERRIDE;
-  virtual nsresult Shutdown() MOZ_OVERRIDE;
-
-  // GMPVideoDecoderProxyCallback
-  virtual void Decoded(GMPVideoi420Frame* aDecodedFrame) MOZ_OVERRIDE;
-  virtual void ReceivedDecodedReferenceFrame(const uint64_t aPictureId) MOZ_OVERRIDE;
-  virtual void ReceivedDecodedFrame(const uint64_t aPictureId) MOZ_OVERRIDE;
-  virtual void InputDataExhausted() MOZ_OVERRIDE;
-  virtual void DrainComplete() MOZ_OVERRIDE;
-  virtual void ResetComplete() MOZ_OVERRIDE;
-  virtual void Error(GMPErr aErr) MOZ_OVERRIDE;
-  virtual void Terminated() MOZ_OVERRIDE;
+class EMEVideoDecoder : public GMPVideoDecoder {
+public:
+  EMEVideoDecoder(CDMProxy* aProxy,
+                  const mp4_demuxer::VideoDecoderConfig& aConfig,
+                  layers::LayersBackend aLayersBackend,
+                  layers::ImageContainer* aImageContainer,
+                  MediaTaskQueue* aTaskQueue,
+                  MediaDataDecoderCallbackProxy* aCallback)
+   : GMPVideoDecoder(aConfig, aLayersBackend, aImageContainer, aTaskQueue, aCallback,
+                     new EMEVideoCallbackAdapter(aCallback, VideoInfo(aConfig.display_width,
+                                                                      aConfig.display_height), aImageContainer))
+   , mProxy(aProxy)
+  {
+  }
 
 private:
-
-  nsresult GmpInit();
-  nsresult GmpInput(MP4Sample* aSample);
-  void GmpFlush();
-  void GmpDrain();
-  void GmpShutdown();
-
-#ifdef DEBUG
-  bool IsOnGMPThread() {
-    return NS_GetCurrentThread() == mGMPThread;
-  }
-#endif
-
-  class DeliverSample : public nsRunnable {
-  public:
-    DeliverSample(EMEH264Decoder* aDecoder,
-                  mp4_demuxer::MP4Sample* aSample)
-      : mDecoder(aDecoder)
-      , mSample(aSample)
-    {}
-
-    NS_IMETHOD Run() {
-      mDecoder->GmpInput(mSample.forget());
-      return NS_OK;
-    }
-  private:
-    nsRefPtr<EMEH264Decoder> mDecoder;
-    nsAutoPtr<mp4_demuxer::MP4Sample> mSample;
-  };
+  virtual void InitTags(nsTArray<nsCString>& aTags) MOZ_OVERRIDE;
+  virtual nsCString GetNodeId() MOZ_OVERRIDE;
+  virtual GMPUniquePtr<GMPVideoEncodedFrame> CreateFrame(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
 
-  class InitTask : public nsRunnable {
-  public:
-    explicit InitTask(EMEH264Decoder* aDecoder)
-      : mDecoder(aDecoder)
-    {}
-    NS_IMETHOD Run() {
-      mResult = mDecoder->GmpInit();
-      return NS_OK;
-    }
-    nsresult mResult;
-    EMEH264Decoder* mDecoder;
-  };
-
-  nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
-  nsCOMPtr<nsIThread> mGMPThread;
   nsRefPtr<CDMProxy> mProxy;
-  GMPVideoDecoderProxy* mGMP;
-  GMPVideoHost* mHost;
-
-  VideoInfo mVideoInfo;
-  const mp4_demuxer::VideoDecoderConfig& mConfig;
-  nsRefPtr<layers::ImageContainer> mImageContainer;
-  nsRefPtr<MediaTaskQueue> mTaskQueue;
-  MediaDataDecoderCallback* mCallback;
-  int64_t mLastStreamOffset;
-
-  nsRefPtr<SamplesWaitingForKey> mSamplesWaitingForKey;
-
-  Monitor mMonitor;
-  bool mFlushComplete;
-
-#ifdef DEBUG
-  bool mIsShutdown;
-#endif
 };
 
 }
 
-#endif // EMEH264Decoder_h_
+#endif // EMEVideoDecoder_h_
--- a/dom/media/fmp4/eme/moz.build
+++ b/dom/media/fmp4/eme/moz.build
@@ -2,24 +2,24 @@
 # 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 += [
     'EMEAudioDecoder.h',
     'EMEDecoderModule.h',
-    'EMEH264Decoder.h',
+    'EMEVideoDecoder.h',
     'SamplesWaitingForKey.h',
 ]
 
 UNIFIED_SOURCES += [
     'EMEAudioDecoder.cpp',
     'EMEDecoderModule.cpp',
-    'EMEH264Decoder.cpp',
+    'EMEVideoDecoder.cpp',
     'SamplesWaitingForKey.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 FAIL_ON_WARNINGS = True