Bug 1036849 - Share a single MediaSourceReader; r=edwin; a=philor
☠☠ backed out by 5b992c20ee16 ☠ ☠
authorAnthony Jones <ajones@mozilla.com>
Tue, 02 Sep 2014 13:42:39 +1200
changeset 224554 b9e3a9f5d04a122c0f0ae3d7f43a75452d1e4782
parent 224553 232ad77a5d5abb90be4aabc0a397178fdf315f6e
child 224555 d59d58d42f40d32f597e9974dae81d123eb36224
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersedwin, philor
bugs1036849
milestone34.0a1
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
Bug 1036849 - Share a single MediaSourceReader; r=edwin; a=philor
content/media/MediaDecoderReader.h
content/media/fmp4/MP4Reader.cpp
content/media/fmp4/MP4Reader.h
content/media/fmp4/PlatformDecoderModule.h
content/media/fmp4/SharedDecoderManager.cpp
content/media/fmp4/SharedDecoderManager.h
content/media/fmp4/gonk/GonkVideoDecoderManager.cpp
content/media/fmp4/moz.build
content/media/mediasource/MediaSourceReader.cpp
content/media/mediasource/MediaSourceReader.h
media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
--- a/content/media/MediaDecoderReader.h
+++ b/content/media/MediaDecoderReader.h
@@ -15,16 +15,17 @@
 namespace mozilla {
 
 namespace dom {
 class TimeRanges;
 }
 
 class RequestSampleCallback;
 class MediaDecoderReader;
+class SharedDecoderManager;
 
 // Encapsulates the decoding and reading of media data. Reading can either
 // synchronous and done on the calling "decode" thread, or asynchronous and
 // performed on a background thread, with the result being returned by
 // callback. Never hold the decoder monitor when calling into this class.
 // Unless otherwise specified, methods and fields of this class can only
 // be accessed on the decode task queue.
 class MediaDecoderReader {
@@ -38,17 +39,18 @@ public:
   virtual nsresult Init(MediaDecoderReader* aCloneDonor) = 0;
 
   // True if this reader is waiting media resource allocation
   virtual bool IsWaitingMediaResources() { return false; }
   // True when this reader need to become dormant state
   virtual bool IsDormantNeeded() { return false; }
   // Release media resources they should be released in dormant state
   // The reader can be made usable again by calling ReadMetadata().
-  virtual void ReleaseMediaResources() {};
+  virtual void ReleaseMediaResources() {}
+  virtual void SetSharedDecoderManager(SharedDecoderManager* aManager) {}
   // Breaks reference-counted cycles. Called during shutdown.
   // WARNING: If you override this, you must call the base implementation
   // in your override.
   virtual void BreakCycles();
 
   // Destroys the decoding state. The reader cannot be made usable again.
   // This is different from ReleaseMediaResources() as it is irreversable,
   // whereas ReleaseMediaResources() is.
--- a/content/media/fmp4/MP4Reader.cpp
+++ b/content/media/fmp4/MP4Reader.cpp
@@ -9,16 +9,17 @@
 #include "nsSize.h"
 #include "VideoUtils.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "ImageContainer.h"
 #include "Layers.h"
 #include "SharedThreadPool.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/TimeRanges.h"
+#include "SharedDecoderManager.h"
 
 #ifdef MOZ_EME
 #include "mozilla/CDMProxy.h"
 #endif
 
 using mozilla::layers::Image;
 using mozilla::layers::LayerManager;
 using mozilla::layers::LayersBackend;
@@ -398,22 +399,31 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo
     // sampling rate from demuxer.
     Decode(kAudio);
   }
 
   if (HasVideo()) {
     const VideoDecoderConfig& video = mDemuxer->VideoConfig();
     mInfo.mVideo.mDisplay =
       nsIntSize(video.display_width, video.display_height);
-    mVideo.mCallback = new  DecoderCallback(this, kVideo);
-    mVideo.mDecoder = mPlatform->CreateH264Decoder(video,
-                                                   mLayersBackendType,
-                                                   mDecoder->GetImageContainer(),
-                                                   mVideo.mTaskQueue,
-                                                   mVideo.mCallback);
+    mVideo.mCallback = new DecoderCallback(this, kVideo);
+    if (mSharedDecoderManager) {
+      mVideo.mDecoder =
+        mSharedDecoderManager->CreateH264Decoder(video,
+                                                 mLayersBackendType,
+                                                 mDecoder->GetImageContainer(),
+                                                 mVideo.mTaskQueue,
+                                                 mVideo.mCallback);
+    } else {
+      mVideo.mDecoder = mPlatform->CreateH264Decoder(video,
+                                                     mLayersBackendType,
+                                                     mDecoder->GetImageContainer(),
+                                                     mVideo.mTaskQueue,
+                                                     mVideo.mCallback);
+    }
     NS_ENSURE_TRUE(mVideo.mDecoder != nullptr, NS_ERROR_FAILURE);
     nsresult rv = mVideo.mDecoder->Init();
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Get the duration, and report it to the decoder if we have it.
   Microseconds duration = mDemuxer->Duration();
   if (duration != -1) {
@@ -451,22 +461,16 @@ MP4Reader::HasVideo()
 
 MP4Reader::DecoderData&
 MP4Reader::GetDecoderData(TrackType aTrack)
 {
   MOZ_ASSERT(aTrack == kAudio || aTrack == kVideo);
   return (aTrack == kAudio) ? mAudio : mVideo;
 }
 
-MediaDataDecoder*
-MP4Reader::Decoder(TrackType aTrack)
-{
-  return GetDecoderData(aTrack).mDecoder;
-}
-
 MP4Sample*
 MP4Reader::PopSample(TrackType aTrack)
 {
   switch (aTrack) {
     case kAudio:
       return mDemuxer->DemuxAudioSample();
 
     case kVideo:
@@ -864,9 +868,26 @@ void MP4Reader::NotifyResourcesStatusCha
 {
 #ifdef MOZ_GONK_MEDIACODEC
   if (mDecoder) {
     mDecoder->NotifyWaitingForResourcesStatusChanged();
   }
 #endif
 }
 
+void
+MP4Reader::SetIdle()
+{
+  if (mSharedDecoderManager && mVideo.mDecoder) {
+    mSharedDecoderManager->SetIdle(mVideo.mDecoder);
+    NotifyResourcesStatusChanged();
+  }
+}
+
+void
+MP4Reader::SetSharedDecoderManager(SharedDecoderManager* aManager)
+{
+#ifdef MOZ_GONK_MEDIACODEC
+  mSharedDecoderManager = aManager;
+#endif
+}
+
 } // namespace mozilla
--- a/content/media/fmp4/MP4Reader.h
+++ b/content/media/fmp4/MP4Reader.h
@@ -56,19 +56,22 @@ public:
                                  int64_t aOffset) MOZ_OVERRIDE;
 
   virtual int64_t GetEvictionOffset(double aTime) MOZ_OVERRIDE;
 
   virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
                                int64_t aStartTime) MOZ_OVERRIDE;
 
   // For Media Resource Management
+  virtual void SetIdle() MOZ_OVERRIDE;
   virtual bool IsWaitingMediaResources() MOZ_OVERRIDE;
   virtual bool IsDormantNeeded() MOZ_OVERRIDE;
   virtual void ReleaseMediaResources() MOZ_OVERRIDE;
+  virtual void SetSharedDecoderManager(SharedDecoderManager* aManager)
+    MOZ_OVERRIDE;
 
   virtual nsresult ResetDecode() MOZ_OVERRIDE;
 
   virtual void Shutdown() MOZ_OVERRIDE;
 
 private:
 
   void ExtractCryptoInitData(nsTArray<uint8_t>& aInitData);
@@ -173,27 +176,27 @@ private:
 
   // The last number of decoded output frames that we've reported to
   // MediaDecoder::NotifyDecoded(). We diff the number of output video
   // frames every time that DecodeVideoData() is called, and report the
   // delta there.
   uint64_t mLastReportedNumDecodedFrames;
 
   DecoderData& GetDecoderData(mp4_demuxer::TrackType aTrack);
-  MediaDataDecoder* Decoder(mp4_demuxer::TrackType aTrack);
 
   layers::LayersBackend mLayersBackendType;
 
   nsTArray<nsTArray<uint8_t>> mInitDataEncountered;
 
   // True if we've read the streams' metadata.
   bool mDemuxerInitialized;
 
   // Synchronized by decoder monitor.
   bool mIsEncrypted;
 
   bool mIndexReady;
   Monitor mIndexMonitor;
+  nsRefPtr<SharedDecoderManager> mSharedDecoderManager;
 };
 
 } // namespace mozilla
 
 #endif
--- a/content/media/fmp4/PlatformDecoderModule.h
+++ b/content/media/fmp4/PlatformDecoderModule.h
@@ -223,15 +223,15 @@ public:
 
   // For Codec Resource Management
   virtual bool IsWaitingMediaResources() {
     return false;
   };
   virtual bool IsDormantNeeded() {
     return false;
   };
-  virtual void ReleaseMediaResources() {};
-  virtual void ReleaseDecoder() {};
+  virtual void ReleaseMediaResources() {}
+  virtual void ReleaseDecoder() {}
 };
 
 } // namespace mozilla
 
 #endif
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/SharedDecoderManager.cpp
@@ -0,0 +1,211 @@
+/* -*- 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 "SharedDecoderManager.h"
+#include "mp4_demuxer/DecoderData.h"
+
+namespace mozilla {
+
+class SharedDecoderCallback : public MediaDataDecoderCallback
+{
+public:
+  SharedDecoderCallback(SharedDecoderManager* aManager) : mManager(aManager) {}
+
+  virtual void Output(MediaData* aData) MOZ_OVERRIDE
+  {
+    if (mManager->mActiveCallback) {
+      mManager->mActiveCallback->Output(aData);
+    }
+  }
+  virtual void Error() MOZ_OVERRIDE
+  {
+    if (mManager->mActiveCallback) {
+      mManager->mActiveCallback->Error();
+    }
+  }
+  virtual void InputExhausted() MOZ_OVERRIDE
+  {
+    if (mManager->mActiveCallback) {
+      mManager->mActiveCallback->InputExhausted();
+    }
+  }
+  virtual void DrainComplete() MOZ_OVERRIDE
+  {
+    if (mManager->mActiveCallback) {
+      mManager->DrainComplete();
+    }
+  }
+  virtual void NotifyResourcesStatusChanged() MOZ_OVERRIDE
+  {
+    if (mManager->mActiveCallback) {
+      mManager->mActiveCallback->NotifyResourcesStatusChanged();
+    }
+  }
+  virtual void ReleaseMediaResources() MOZ_OVERRIDE
+  {
+    if (mManager->mActiveCallback) {
+      mManager->mActiveCallback->ReleaseMediaResources();
+    }
+  }
+
+  nsRefPtr<SharedDecoderManager> mManager;
+};
+
+SharedDecoderManager::SharedDecoderManager()
+  : mActiveProxy(nullptr)
+  , mActiveCallback(nullptr)
+  , mWaitForInternalDrain(false)
+  , mMonitor("SharedDecoderProxy")
+{
+  mCallback = new SharedDecoderCallback(this);
+}
+
+SharedDecoderManager::~SharedDecoderManager() {}
+
+already_AddRefed<MediaDataDecoder>
+SharedDecoderManager::CreateH264Decoder(
+  const mp4_demuxer::VideoDecoderConfig& aConfig,
+  layers::LayersBackend aLayersBackend, layers::ImageContainer* aImageContainer,
+  MediaTaskQueue* aVideoTaskQueue, MediaDataDecoderCallback* aCallback)
+{
+  if (!mDecoder) {
+    mConfig = aConfig;
+    nsAutoPtr<PlatformDecoderModule> platform(PlatformDecoderModule::Create());
+    mDecoder = platform->CreateH264Decoder(
+      mConfig, aLayersBackend, aImageContainer, aVideoTaskQueue, mCallback);
+    if (!mDecoder) {
+      return nullptr;
+    }
+    nsresult rv = mDecoder->Init();
+    NS_ENSURE_SUCCESS(rv, nullptr);
+  }
+
+  nsRefPtr<SharedDecoderProxy> proxy(
+    new SharedDecoderProxy(this, aCallback, aConfig));
+  return proxy.forget();
+}
+
+void
+SharedDecoderManager::Select(SharedDecoderProxy* aProxy)
+{
+  if (mActiveProxy == aProxy) {
+    return;
+  }
+  SetIdle(mActiveProxy);
+
+  mActiveProxy = aProxy;
+  mActiveCallback = aProxy->mCallback;
+  mConfig = aProxy->mConfig;
+}
+
+void
+SharedDecoderManager::SetIdle(MediaDataDecoder* aProxy)
+{
+  if (aProxy && mActiveProxy == aProxy) {
+    mWaitForInternalDrain = true;
+    mActiveProxy->Drain();
+    MonitorAutoLock mon(mMonitor);
+    while (mWaitForInternalDrain) {
+      mon.Wait();
+    }
+    mActiveProxy->Flush();
+    mActiveProxy = nullptr;
+  }
+}
+
+void
+SharedDecoderManager::DrainComplete()
+{
+  if (mWaitForInternalDrain) {
+    MonitorAutoLock mon(mMonitor);
+    mWaitForInternalDrain = false;
+    mon.NotifyAll();
+  } else {
+    mActiveCallback->DrainComplete();
+  }
+}
+
+SharedDecoderProxy::SharedDecoderProxy(
+  SharedDecoderManager* aManager, MediaDataDecoderCallback* aCallback,
+  const mp4_demuxer::VideoDecoderConfig& aConfig)
+  : mManager(aManager), mCallback(aCallback), mConfig(aConfig)
+{
+}
+
+SharedDecoderProxy::~SharedDecoderProxy() { Shutdown(); }
+
+nsresult
+SharedDecoderProxy::Init()
+{
+  return NS_OK;
+}
+
+nsresult
+SharedDecoderProxy::Input(mp4_demuxer::MP4Sample* aSample)
+{
+  if (mManager->mActiveProxy != this) {
+    mManager->Select(this);
+  }
+  return mManager->mDecoder->Input(aSample);
+  return NS_OK;
+}
+
+nsresult
+SharedDecoderProxy::Flush()
+{
+  if (mManager->mActiveProxy == this) {
+    return mManager->mDecoder->Flush();
+  }
+  return NS_OK;
+}
+
+nsresult
+SharedDecoderProxy::Drain()
+{
+  if (mManager->mActiveProxy == this) {
+    return mManager->mDecoder->Drain();
+  }
+  return NS_OK;
+}
+
+nsresult
+SharedDecoderProxy::Shutdown()
+{
+  mManager->SetIdle(this);
+  return NS_OK;
+}
+
+bool
+SharedDecoderProxy::IsWaitingMediaResources()
+{
+  if (mManager->mActiveProxy == this) {
+    return mManager->mDecoder->IsWaitingMediaResources();
+  }
+  return mManager->mActiveProxy != nullptr;
+}
+
+bool
+SharedDecoderProxy::IsDormantNeeded()
+{
+  return mManager->mDecoder->IsDormantNeeded();
+}
+
+void
+SharedDecoderProxy::ReleaseMediaResources()
+{
+  if (mManager->mActiveProxy == this) {
+    mManager->mDecoder->ReleaseMediaResources();
+  }
+}
+
+void
+SharedDecoderProxy::ReleaseDecoder()
+{
+  if (mManager->mActiveProxy == this) {
+    mManager->mDecoder->ReleaseMediaResources();
+  }
+}
+}
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/SharedDecoderManager.h
@@ -0,0 +1,80 @@
+/* -*- 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 SHARED_DECODER_MANAGER_H_
+#define SHARED_DECODER_MANAGER_H_
+
+#include "PlatformDecoderModule.h"
+#include "mozilla/Monitor.h"
+
+namespace mozilla
+{
+
+class MediaDataDecoder;
+class SharedDecoderProxy;
+class SharedDecoderCallback;
+
+class SharedDecoderManager
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedDecoderManager)
+
+  SharedDecoderManager();
+
+  already_AddRefed<MediaDataDecoder> CreateH264Decoder(
+    const mp4_demuxer::VideoDecoderConfig& aConfig,
+    layers::LayersBackend aLayersBackend,
+    layers::ImageContainer* aImageContainer, MediaTaskQueue* aVideoTaskQueue,
+    MediaDataDecoderCallback* aCallback);
+
+  void SetReader(MediaDecoderReader* aReader);
+  void Select(SharedDecoderProxy* aProxy);
+  void SetIdle(MediaDataDecoder* aProxy);
+
+  friend class SharedDecoderProxy;
+  friend class SharedDecoderCallback;
+
+private:
+  virtual ~SharedDecoderManager();
+  void DrainComplete();
+
+  mp4_demuxer::VideoDecoderConfig mConfig;
+  nsRefPtr<MediaDataDecoder> mDecoder;
+  SharedDecoderProxy* mActiveProxy;
+  MediaDataDecoderCallback* mActiveCallback;
+  nsAutoPtr<MediaDataDecoderCallback> mCallback;
+  bool mWaitForInternalDrain;
+  Monitor mMonitor;
+};
+
+class SharedDecoderProxy : public MediaDataDecoder
+{
+public:
+  SharedDecoderProxy(SharedDecoderManager* aManager,
+                     MediaDataDecoderCallback* aCallback,
+                     const mp4_demuxer::VideoDecoderConfig& aConfig);
+  virtual ~SharedDecoderProxy();
+
+  virtual nsresult Init() MOZ_OVERRIDE;
+  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+  virtual nsresult Flush() MOZ_OVERRIDE;
+  virtual nsresult Drain() MOZ_OVERRIDE;
+  virtual nsresult Shutdown() MOZ_OVERRIDE;
+  virtual bool IsWaitingMediaResources() MOZ_OVERRIDE;
+  virtual bool IsDormantNeeded() MOZ_OVERRIDE;
+  virtual void ReleaseMediaResources() MOZ_OVERRIDE;
+  virtual void ReleaseDecoder() MOZ_OVERRIDE;
+
+  friend class SharedDecoderManager;
+
+private:
+  nsRefPtr<SharedDecoderManager> mManager;
+  MediaDataDecoderCallback* mCallback;
+  const mp4_demuxer::VideoDecoderConfig& mConfig;
+};
+}
+
+#endif
--- a/content/media/fmp4/gonk/GonkVideoDecoderManager.cpp
+++ b/content/media/fmp4/gonk/GonkVideoDecoderManager.cpp
@@ -54,17 +54,17 @@ GonkVideoDecoderManager::GonkVideoDecode
   , mColorConverterBufferSize(0)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
   MOZ_ASSERT(mImageContainer);
   MOZ_COUNT_CTOR(GonkVideoDecoderManager);
   mVideoWidth  = aConfig.display_width;
   mVideoHeight = aConfig.display_height;
   mDisplayWidth = aConfig.display_width;
-  mDisplayHeight = aConfig.display_width;
+  mDisplayHeight = aConfig.display_height;
   mInfo.mVideo.mHasVideo = true;
   nsIntSize displaySize(mDisplayWidth, mDisplayHeight);
   mInfo.mVideo.mDisplay = displaySize;
 
   nsIntRect pictureRect(0, 0, mVideoWidth, mVideoHeight);
   nsIntSize frameSize(mVideoWidth, mVideoHeight);
   mPicture = pictureRect;
   mInitialFrame = frameSize;
--- a/content/media/fmp4/moz.build
+++ b/content/media/fmp4/moz.build
@@ -3,21 +3,23 @@
 # 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 += [
     'MP4Decoder.h',
     'MP4Reader.h',
     'PlatformDecoderModule.h',
+    'SharedDecoderManager.h',
 ]
 
 UNIFIED_SOURCES += [
     'BlankDecoderModule.cpp',
     'PlatformDecoderModule.cpp',
+    'SharedDecoderManager.cpp',
 ]
 
 SOURCES += [
     'MP4Decoder.cpp',
     'MP4Reader.cpp',
 ]
 
 if CONFIG['MOZ_WMF']:
--- a/content/media/mediasource/MediaSourceReader.cpp
+++ b/content/media/mediasource/MediaSourceReader.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/dom/TimeRanges.h"
 #include "DecoderTraits.h"
 #include "MediaDataDecodedListener.h"
 #include "MediaDecoderOwner.h"
 #include "MediaSource.h"
 #include "MediaSourceDecoder.h"
 #include "MediaSourceUtils.h"
 #include "SourceBufferDecoder.h"
+#include "SharedDecoderManager.h"
 
 #ifdef MOZ_FMP4
 #include "MP4Decoder.h"
 #include "MP4Reader.h"
 #endif
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetMediaSourceLog();
@@ -36,16 +37,17 @@ extern PRLogModuleInfo* GetMediaSourceAP
 namespace mozilla {
 
 MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder)
   : MediaDecoderReader(aDecoder)
   , mTimeThreshold(-1)
   , mDropAudioBeforeThreshold(false)
   , mDropVideoBeforeThreshold(false)
   , mEnded(false)
+  , mSharedDecoderManager(new SharedDecoderManager())
 {
 }
 
 bool
 MediaSourceReader::IsWaitingMediaResources()
 {
   return mDecoders.IsEmpty() && mPendingDecoders.IsEmpty();
 }
@@ -349,16 +351,17 @@ MediaSourceReader::CreateSubDecoder(cons
   if (!reader) {
     return nullptr;
   }
   // Set a callback on the subreader that forwards calls to this reader.
   // This reader will then forward them onto the state machine via this
   // reader's callback.
   RefPtr<MediaDataDecodedListener<MediaSourceReader>> callback =
     new MediaDataDecodedListener<MediaSourceReader>(this, GetTaskQueue());
+  reader->SetSharedDecoderManager(mSharedDecoderManager);
   reader->SetCallback(callback);
   reader->SetTaskQueue(GetTaskQueue());
   reader->Init(nullptr);
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   MSE_DEBUG("MediaSourceReader(%p)::CreateSubDecoder subdecoder %p subreader %p",
             this, decoder.get(), reader.get());
   decoder->SetReader(reader);
   mPendingDecoders.AppendElement(decoder);
--- a/content/media/mediasource/MediaSourceReader.h
+++ b/content/media/mediasource/MediaSourceReader.h
@@ -111,13 +111,14 @@ private:
 
   nsTArray<nsRefPtr<SourceBufferDecoder>> mPendingDecoders;
   nsTArray<nsRefPtr<SourceBufferDecoder>> mDecoders;
 
   nsRefPtr<MediaDecoderReader> mAudioReader;
   nsRefPtr<MediaDecoderReader> mVideoReader;
 
   bool mEnded;
+  nsRefPtr<SharedDecoderManager> mSharedDecoderManager;
 };
 
 } // namespace mozilla
 
 #endif /* MOZILLA_MEDIASOURCEREADER_H_ */
--- a/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
@@ -108,16 +108,23 @@ public:
 private:
   friend class MP4Demuxer;
 };
 
 class VideoDecoderConfig : public TrackConfig
 {
 public:
   VideoDecoderConfig() : display_width(0), display_height(0) {}
+  void operator=(const VideoDecoderConfig& aConfig)
+  {
+    display_width = aConfig.display_width;
+    display_height = aConfig.display_height;
+    extra_data.appendAll(aConfig.extra_data);
+    annex_b.appendAll(aConfig.annex_b);
+  }
 
   int32_t display_width;
   int32_t display_height;
 
   mozilla::Vector<uint8_t> extra_data; // Unparsed AVCDecoderConfig payload.
   mozilla::Vector<uint8_t> annex_b;    // Parsed version for sample prepend.
 
   void Update(stagefright::sp<stagefright::MetaData>& aMetaData,