Bug 1093654 - Fix various memory leaks in MediaDecoders. r=jwwang
☠☠ backed out by b141758cfbc3 ☠ ☠
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 06 Nov 2014 19:17:05 +1100
changeset 230598 70a72a19cb4b2940d31d49951ffeef9b35c7c718
parent 230597 1c969fba2f6487a8ea3769091ab68ff6db82689a
child 230599 24195469c77e9ddcd05b77fea5a761adfe8ffa21
push id7326
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:58:42 +0000
treeherdermozilla-aurora@d3a3b2a0f2f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang
bugs1093654
milestone36.0a1
Bug 1093654 - Fix various memory leaks in MediaDecoders. r=jwwang Change various function prototyping to make object ownership more explicit.
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/media/AbstractMediaDecoder.h
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/MediaDecoderOwner.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
dom/media/MediaMetadataManager.h
dom/media/gtest/MockMediaDecoderOwner.h
dom/media/mediasource/SourceBufferDecoder.cpp
dom/media/mediasource/SourceBufferDecoder.h
dom/media/ogg/OggReader.cpp
dom/media/omx/MediaOmxCommonDecoder.cpp
dom/media/omx/MediaOmxCommonDecoder.h
dom/media/webaudio/BufferDecoder.cpp
dom/media/webaudio/BufferDecoder.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2881,21 +2881,21 @@ void HTMLMediaElement::ProcessMediaFragm
 
   if (parser.HasStartTime()) {
     SetCurrentTime(parser.GetStartTime());
     mFragmentStart = parser.GetStartTime();
   }
 }
 
 void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
-                                      const MetadataTags* aTags)
+                                      nsAutoPtr<const MetadataTags> aTags)
 {
   mHasAudio = aInfo->HasAudio();
   mHasVideo = aInfo->HasVideo();
-  mTags = aTags;
+  mTags = aTags.forget();
   mLoadedDataFired = false;
   ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
   DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
   DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
   if (mDecoder && mDecoder->IsTransportSeekable() && mDecoder->IsMediaSeekable()) {
     ProcessMediaFragmentURI();
     mDecoder->SetFragmentEndTime(mFragmentEnd);
   }
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -155,17 +155,17 @@ public:
    * document being active, inactive, visible or hidden.
    */
   virtual void NotifyOwnerDocumentActivityChanged();
 
   // Called by the video decoder object, on the main thread,
   // when it has read the metadata containing video dimensions,
   // etc.
   virtual void MetadataLoaded(const MediaInfo* aInfo,
-                              const MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
+                              nsAutoPtr<const MetadataTags> aTags) MOZ_FINAL MOZ_OVERRIDE;
 
   // Called by the decoder object, on the main thread,
   // when it has read the first frame of the video or audio.
   virtual void FirstFrameLoaded() MOZ_FINAL MOZ_OVERRIDE;
 
   // Called by the video decoder object, on the main thread,
   // when the resource has a network error during loading.
   virtual void NetworkError() MOZ_FINAL MOZ_OVERRIDE;
--- a/dom/media/AbstractMediaDecoder.h
+++ b/dom/media/AbstractMediaDecoder.h
@@ -83,19 +83,19 @@ public:
   virtual mozilla::layers::ImageContainer* GetImageContainer() = 0;
 
   // Return true if the media layer supports seeking.
   virtual bool IsTransportSeekable() = 0;
 
   // Return true if the transport layer supports seeking.
   virtual bool IsMediaSeekable() = 0;
 
-  virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) = 0;
-  virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) = 0;
-  virtual void FirstFrameLoaded(MediaInfo* aInfo) = 0;
+  virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) = 0;
+  virtual void QueueMetadata(int64_t aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) = 0;
+  virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo) = 0;
 
   virtual void RemoveMediaTracks() = 0;
 
   // Set the media end time in microseconds
   virtual void SetMediaEndTime(int64_t aTime) = 0;
 
   // Make the decoder state machine update the playback position. Called by
   // the reader on the decoder thread (Assertions for this checked by
@@ -149,85 +149,80 @@ public:
   };
 
 #ifdef MOZ_EME
   virtual nsresult SetCDMProxy(CDMProxy* aProxy) { return NS_ERROR_NOT_IMPLEMENTED; }
   virtual CDMProxy* GetCDMProxy() { return nullptr; }
 #endif
 };
 
-class MetadataEventRunner : public nsRunnable
+class MetadataContainer
 {
-  private:
-    nsRefPtr<AbstractMediaDecoder> mDecoder;
-  public:
-    MetadataEventRunner(AbstractMediaDecoder* aDecoder, MediaInfo* aInfo, MetadataTags* aTags)
-          : mDecoder(aDecoder),
-            mInfo(aInfo),
-            mTags(aTags)
+protected:
+  MetadataContainer(AbstractMediaDecoder* aDecoder,
+                    nsAutoPtr<MediaInfo> aInfo,
+                    nsAutoPtr<MetadataTags> aTags)
+    : mDecoder(aDecoder),
+      mInfo(aInfo),
+      mTags(aTags)
+  {}
+
+  nsRefPtr<AbstractMediaDecoder> mDecoder;
+  nsAutoPtr<MediaInfo>  mInfo;
+  nsAutoPtr<MetadataTags> mTags;
+};
+
+class MetadataEventRunner : public nsRunnable, private MetadataContainer
+{
+public:
+  MetadataEventRunner(AbstractMediaDecoder* aDecoder,
+                      nsAutoPtr<MediaInfo> aInfo,
+                      nsAutoPtr<MetadataTags> aTags)
+    : MetadataContainer(aDecoder, aInfo, aTags)
   {}
 
   NS_IMETHOD Run() MOZ_OVERRIDE
   {
     mDecoder->MetadataLoaded(mInfo, mTags);
     return NS_OK;
   }
-
-  // The ownership is transferred to MediaDecoder.
-  MediaInfo* mInfo;
-
-  // The ownership is transferred to its owning element.
-  MetadataTags* mTags;
 };
 
-class FirstFrameLoadedEventRunner : public nsRunnable
+class FirstFrameLoadedEventRunner : public nsRunnable, private MetadataContainer
 {
-  private:
-    nsRefPtr<AbstractMediaDecoder> mDecoder;
-  public:
-    FirstFrameLoadedEventRunner(AbstractMediaDecoder* aDecoder, MediaInfo* aInfo)
-          : mDecoder(aDecoder),
-            mInfo(aInfo)
+public:
+  FirstFrameLoadedEventRunner(AbstractMediaDecoder* aDecoder,
+                              nsAutoPtr<MediaInfo> aInfo)
+    : MetadataContainer(aDecoder, aInfo, nsAutoPtr<MetadataTags>(nullptr))
   {}
 
   NS_IMETHOD Run() MOZ_OVERRIDE
   {
     mDecoder->FirstFrameLoaded(mInfo);
     return NS_OK;
   }
-
-  // The ownership is transferred to MediaDecoder.
-  MediaInfo* mInfo;
 };
 
-class MetadataUpdatedEventRunner : public nsRunnable
+class MetadataUpdatedEventRunner : public nsRunnable, private MetadataContainer
 {
-  private:
-    nsRefPtr<AbstractMediaDecoder> mDecoder;
-  public:
-    MetadataUpdatedEventRunner(AbstractMediaDecoder* aDecoder, MediaInfo* aInfo, MetadataTags* aTags)
-          : mDecoder(aDecoder),
-            mInfo(aInfo),
-            mTags(aTags)
+public:
+  MetadataUpdatedEventRunner(AbstractMediaDecoder* aDecoder,
+                             nsAutoPtr<MediaInfo> aInfo,
+                             nsAutoPtr<MetadataTags> aTags)
+    : MetadataContainer(aDecoder, aInfo, aTags)
   {}
 
   NS_IMETHOD Run() MOZ_OVERRIDE
   {
     nsAutoPtr<MediaInfo> info(new MediaInfo());
     *info = *mInfo;
-    mDecoder->MetadataLoaded(info.forget(), mTags);
+    mDecoder->MetadataLoaded(info, mTags);
     mDecoder->FirstFrameLoaded(mInfo);
     return NS_OK;
   }
-
-  // The ownership is transferred to MediaDecoder.
-  MediaInfo* mInfo;
-
-  // The ownership is transferred to its owning element.
-  MetadataTags* mTags;
 };
 
 class RemoveMediaTracksEventRunner : public nsRunnable
 {
 public:
   explicit RemoveMediaTracksEventRunner(AbstractMediaDecoder* aDecoder)
     : mDecoder(aDecoder)
   {}
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -663,35 +663,37 @@ double MediaDecoder::GetCurrentTime()
 
 already_AddRefed<nsIPrincipal> MediaDecoder::GetCurrentPrincipal()
 {
   MOZ_ASSERT(NS_IsMainThread());
   return mResource ? mResource->GetCurrentPrincipal() : nullptr;
 }
 
 void MediaDecoder::QueueMetadata(int64_t aPublishTime,
-                                 MediaInfo* aInfo,
-                                 MetadataTags* aTags)
+                                 nsAutoPtr<MediaInfo> aInfo,
+                                 nsAutoPtr<MetadataTags> aTags)
 {
   NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
   GetReentrantMonitor().AssertCurrentThreadIn();
   mDecoderStateMachine->QueueMetadata(aPublishTime, aInfo, aTags);
 }
 
 bool
 MediaDecoder::IsDataCachedToEndOfResource()
 {
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   return (mResource &&
           mResource->IsDataCachedToEndOfResource(mDecoderPosition));
 }
 
-void MediaDecoder::MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags)
+void MediaDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
+                                  nsAutoPtr<MetadataTags> aTags)
 {
   MOZ_ASSERT(NS_IsMainThread());
+
   if (mShuttingDown) {
     return;
   }
 
   DECODER_LOG("MetadataLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d",
               aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
               aInfo->HasAudio(), aInfo->HasVideo());
 
@@ -707,43 +709,44 @@ void MediaDecoder::MetadataLoaded(MediaI
     // Duration has changed so we should recompute playback rate
     UpdatePlaybackRate();
   }
 
   if (mDuration == -1) {
     SetInfinite(true);
   }
 
-  mInfo = aInfo;
+  mInfo = aInfo.forget();
   ConstructMediaTracks();
 
   if (mOwner) {
     // Make sure the element and the frame (if any) are told about
     // our new size.
     Invalidate();
-    mOwner->MetadataLoaded(aInfo, aTags);
+    mOwner->MetadataLoaded(mInfo, nsAutoPtr<const MetadataTags>(aTags.forget()));
   }
 }
 
-void MediaDecoder::FirstFrameLoaded(MediaInfo* aInfo)
+void MediaDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo)
 {
   MOZ_ASSERT(NS_IsMainThread());
+
   if (mShuttingDown) {
     return;
   }
 
   DECODER_LOG("FirstFrameLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d",
               aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
               aInfo->HasAudio(), aInfo->HasVideo());
 
   if (mPlayState == PLAY_STATE_LOADING && mIsDormant && !mIsExitingDormant) {
     return;
   }
 
-  mInfo = aInfo;
+  mInfo = aInfo.forget();
 
   if (mOwner) {
     Invalidate();
     mOwner->FirstFrameLoaded();
   }
 
   // This can run cache callbacks.
   mResource->EnsureCacheUpToDate();
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -757,18 +757,18 @@ public:
 
   void SetAudioChannel(dom::AudioChannel aChannel) { mAudioChannel = aChannel; }
   dom::AudioChannel GetAudioChannel() { return mAudioChannel; }
 
   // Send a new set of metadata to the state machine, to be dispatched to the
   // main thread to be presented when the |currentTime| of the media is greater
   // or equal to aPublishTime.
   void QueueMetadata(int64_t aPublishTime,
-                     MediaInfo* aInfo,
-                     MetadataTags* aTags);
+                     nsAutoPtr<MediaInfo> aInfo,
+                     nsAutoPtr<MetadataTags> aTags);
 
   int64_t GetSeekTime() { return mRequestedSeekTarget.mTime; }
   void ResetSeekTime() { mRequestedSeekTarget.Reset(); }
 
   /******
    * The following methods must only be called on the main
    * thread.
    ******/
@@ -783,22 +783,22 @@ public:
   virtual void ApplyStateToStateMachine(PlayState aState);
 
   // May be called by the reader to notify this decoder that the metadata from
   // the media file has been read. Call on the decode thread only.
   void OnReadMetadataCompleted() MOZ_OVERRIDE { }
 
   // Called when the metadata from the media file has been loaded by the
   // state machine. Call on the main thread only.
-  virtual void MetadataLoaded(MediaInfo* aInfo,
-                              MetadataTags* aTags);
+  virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
+                              nsAutoPtr<MetadataTags> aTags);
 
   // Called when the first audio and/or video from the media file has been loaded
   // by the state machine. Call on the main thread only.
-  virtual void FirstFrameLoaded(MediaInfo* aInfo);
+  virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo);
 
   // Called from MetadataLoaded(). Creates audio tracks and adds them to its
   // owner's audio track list, and implies to video tracks respectively.
   // Call on the main thread only.
   void ConstructMediaTracks();
 
   // Removes all audio tracks and video tracks that are previously added into
   // the track list. Call on the main thread only.
--- a/dom/media/MediaDecoderOwner.h
+++ b/dom/media/MediaDecoderOwner.h
@@ -46,18 +46,19 @@ public:
   }
 
   // Return true if decoding should be paused
   virtual bool GetPaused() = 0;
 
   // Called by the video decoder object, on the main thread,
   // when it has read the metadata containing video dimensions,
   // etc.
+  // Must take ownership of MetadataTags aTags argument.
   virtual void MetadataLoaded(const MediaInfo* aInfo,
-                              const MetadataTags* aTags) = 0;
+                              nsAutoPtr<const MetadataTags> aTags) = 0;
 
   // Called by the decoder object, on the main thread,
   // when it has read the first frame of the video or audio.
   virtual void FirstFrameLoaded() = 0;
 
   // Called by the video decoder object, on the main thread,
   // when the resource has a network error during loading.
   virtual void NetworkError() = 0;
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2044,17 +2044,17 @@ nsresult MediaDecoderStateMachine::Decod
 }
 
 void
 MediaDecoderStateMachine::EnqueueLoadedMetadataEvent()
 {
   nsAutoPtr<MediaInfo> info(new MediaInfo());
   *info = mInfo;
   nsCOMPtr<nsIRunnable> metadataLoadedEvent =
-    new MetadataEventRunner(mDecoder, info.forget(), mMetadataTags.forget());
+    new MetadataEventRunner(mDecoder, info, mMetadataTags);
   NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL);
 }
 
 void
 MediaDecoderStateMachine::CallDecodeFirstFrame()
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   if (mState != DECODER_STATE_DECODING_FIRSTFRAME) {
@@ -2160,22 +2160,22 @@ MediaDecoderStateMachine::FinishDecodeFi
   nsAutoPtr<MediaInfo> info(new MediaInfo());
   *info = mInfo;
   nsCOMPtr<nsIRunnable> event;
   if (!mGotDurationFromMetaData) {
     // We now have a duration, we can fire the LoadedMetadata and
     // FirstFrame event.
     event =
       new MetadataUpdatedEventRunner(mDecoder,
-                                     info.forget(),
-                                     mMetadataTags.forget());
+                                     info,
+                                     mMetadataTags);
   } else {
     // Inform the element that we've loaded the first frame.
     event =
-      new FirstFrameLoadedEventRunner(mDecoder, info.forget());
+      new FirstFrameLoadedEventRunner(mDecoder, info);
   }
   NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
 
   if (mState == DECODER_STATE_DECODING_FIRSTFRAME) {
     StartDecoding();
   }
 
   // For very short media the first frame decode can decode the entire media.
@@ -3244,25 +3244,25 @@ MediaDecoderStateMachine::SetMinimizePre
 
 bool MediaDecoderStateMachine::IsShutdown()
 {
   AssertCurrentThreadInMonitor();
   return GetState() == DECODER_STATE_SHUTDOWN;
 }
 
 void MediaDecoderStateMachine::QueueMetadata(int64_t aPublishTime,
-                                             MediaInfo* aInfo,
-                                             MetadataTags* aTags)
+                                             nsAutoPtr<MediaInfo> aInfo,
+                                             nsAutoPtr<MetadataTags> aTags)
 {
   NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
   AssertCurrentThreadInMonitor();
   TimedMetadata* metadata = new TimedMetadata;
   metadata->mPublishTime = aPublishTime;
-  metadata->mInfo = aInfo;
-  metadata->mTags = aTags;
+  metadata->mInfo = aInfo.forget();
+  metadata->mTags = aTags.forget();
   mMetadataManager.QueueMetadata(metadata);
 }
 
 void MediaDecoderStateMachine::OnAudioEndTimeUpdate(int64_t aAudioEndTime)
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   MOZ_ASSERT(aAudioEndTime >= mAudioEndTime);
   mAudioEndTime = aAudioEndTime;
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -331,17 +331,19 @@ public:
   void FinishStreamData();
   bool HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs);
   bool HaveEnoughDecodedVideo();
 
   // Returns true if the state machine has shutdown or is in the process of
   // shutting down. The decoder monitor must be held while calling this.
   bool IsShutdown();
 
-  void QueueMetadata(int64_t aPublishTime, MediaInfo* aInfo, MetadataTags* aTags);
+  void QueueMetadata(int64_t aPublishTime,
+                     nsAutoPtr<MediaInfo> aInfo,
+                     nsAutoPtr<MetadataTags> aTags);
 
   // Returns true if we're currently playing. The decoder monitor must
   // be held.
   bool IsPlaying() const;
 
   // Dispatch DoNotifyWaitingForResourcesStatusChanged task to mDecodeTaskQueue.
   // Called when the reader may have acquired the hardware resources required
   // to begin decoding. The decoder monitor must be held while calling this.
--- a/dom/media/MediaMetadataManager.h
+++ b/dom/media/MediaMetadataManager.h
@@ -48,18 +48,18 @@ namespace mozilla {
         while (metadata && aCurrentTime >= static_cast<double>(metadata->mPublishTime) / USECS_PER_S) {
           // Remove all media tracks from the list first.
           nsCOMPtr<nsIRunnable> removeTracksEvent =
             new RemoveMediaTracksEventRunner(aDecoder);
           NS_DispatchToMainThread(removeTracksEvent);
 
           nsCOMPtr<nsIRunnable> metadataUpdatedEvent =
             new MetadataUpdatedEventRunner(aDecoder,
-                                           metadata->mInfo.forget(),
-                                           metadata->mTags.forget());
+                                           metadata->mInfo,
+                                           metadata->mTags);
           NS_DispatchToMainThread(metadataUpdatedEvent);
           delete mMetadataQueue.popFirst();
           metadata = mMetadataQueue.getFirst();
         }
       }
     protected:
       LinkedList<TimedMetadata> mMetadataQueue;
   };
--- a/dom/media/gtest/MockMediaDecoderOwner.h
+++ b/dom/media/gtest/MockMediaDecoderOwner.h
@@ -19,18 +19,18 @@ public:
     return NS_OK;
   }
   virtual nsresult DispatchAsyncEvent(const nsAString& aName) MOZ_OVERRIDE
   {
     return NS_OK;
   }
   virtual void FireTimeUpdate(bool aPeriodic) MOZ_OVERRIDE {}
   virtual bool GetPaused() MOZ_OVERRIDE { return false; }
-  virtual void MetadataLoaded(const MediaInfo* aInfo, const MetadataTags* aTags)
-    MOZ_OVERRIDE
+  virtual void MetadataLoaded(const MediaInfo* aInfo,
+                              nsAutoPtr<const MetadataTags> aTags) MOZ_OVERRIDE
   {
   }
   virtual void NetworkError() MOZ_OVERRIDE {}
   virtual void DecodeError() MOZ_OVERRIDE {}
   virtual void LoadAborted() MOZ_OVERRIDE {}
   virtual void PlaybackEnded() MOZ_OVERRIDE {}
   virtual void SeekStarted() MOZ_OVERRIDE {}
   virtual void SeekCompleted() MOZ_OVERRIDE {}
--- a/dom/media/mediasource/SourceBufferDecoder.cpp
+++ b/dom/media/mediasource/SourceBufferDecoder.cpp
@@ -85,29 +85,32 @@ SourceBufferDecoder::IsTransportSeekable
 bool
 SourceBufferDecoder::IsMediaSeekable()
 {
   MSE_DEBUG("SourceBufferDecoder(%p)::IsMediaSeekable UNIMPLEMENTED", this);
   return false;
 }
 
 void
-SourceBufferDecoder::MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags)
+SourceBufferDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
+                                    nsAutoPtr<MetadataTags> aTags)
 {
   MSE_DEBUG("SourceBufferDecoder(%p)::MetadataLoaded UNIMPLEMENTED", this);
 }
 
 void
-SourceBufferDecoder::FirstFrameLoaded(MediaInfo* aInfo)
+SourceBufferDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo)
 {
   MSE_DEBUG("SourceBufferDecoder(%p)::FirstFrameLoaded UNIMPLEMENTED", this);
 }
 
 void
-SourceBufferDecoder::QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags)
+SourceBufferDecoder::QueueMetadata(int64_t aTime,
+                                   nsAutoPtr<MediaInfo> aInfo,
+                                   nsAutoPtr<MetadataTags> aTags)
 {
   MSE_DEBUG("SourceBufferDecoder(%p)::QueueMetadata UNIMPLEMENTED", this);
 }
 
 void
 SourceBufferDecoder::RemoveMediaTracks()
 {
   MSE_DEBUG("SourceBufferDecoder(%p)::RemoveMediaTracks UNIMPLEMENTED", this);
--- a/dom/media/mediasource/SourceBufferDecoder.h
+++ b/dom/media/mediasource/SourceBufferDecoder.h
@@ -42,24 +42,24 @@ public:
   virtual bool OnDecodeThread() const MOZ_FINAL MOZ_OVERRIDE;
   virtual bool OnStateMachineThread() const MOZ_FINAL MOZ_OVERRIDE;
   virtual int64_t GetMediaDuration() MOZ_FINAL MOZ_OVERRIDE;
   virtual layers::ImageContainer* GetImageContainer() MOZ_FINAL MOZ_OVERRIDE;
   virtual MediaDecoderOwner* GetOwner() MOZ_FINAL MOZ_OVERRIDE;
   virtual SourceBufferResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE;
   virtual ReentrantMonitor& GetReentrantMonitor() MOZ_FINAL MOZ_OVERRIDE;
   virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
-  virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
-  virtual void FirstFrameLoaded(MediaInfo* aInfo) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo) MOZ_FINAL MOZ_OVERRIDE;
   virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
   virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
   virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_FINAL MOZ_OVERRIDE;
   virtual void NotifyWaitingForResourcesStatusChanged() MOZ_FINAL MOZ_OVERRIDE;
   virtual void OnReadMetadataCompleted() MOZ_FINAL MOZ_OVERRIDE;
-  virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void QueueMetadata(int64_t aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) MOZ_FINAL MOZ_OVERRIDE;
   virtual void RemoveMediaTracks() MOZ_FINAL MOZ_OVERRIDE;
   virtual void SetMediaDuration(int64_t aDuration) MOZ_FINAL MOZ_OVERRIDE;
   virtual void SetMediaEndTime(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
   virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_FINAL MOZ_OVERRIDE;
   virtual void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_FINAL MOZ_OVERRIDE;
   virtual void UpdatePlaybackPosition(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
   virtual bool HasInitializationData() MOZ_FINAL MOZ_OVERRIDE;
 
--- a/dom/media/ogg/OggReader.cpp
+++ b/dom/media/ogg/OggReader.cpp
@@ -748,17 +748,17 @@ void OggReader::SetChained(bool aIsChain
 
 bool OggReader::ReadOggChain()
 {
   bool chained = false;
 #ifdef MOZ_OPUS
   OpusState* newOpusState = nullptr;
 #endif /* MOZ_OPUS */
   VorbisState* newVorbisState = nullptr;
-  MetadataTags* tags = nullptr;
+  nsAutoPtr<MetadataTags> tags;
 
   if (HasVideo() || HasSkeleton() || !HasAudio()) {
     return false;
   }
 
   ogg_page page;
   if (!ReadOggPage(&page) || !ogg_page_bos(&page)) {
     return false;
@@ -841,17 +841,17 @@ bool OggReader::ReadOggChain()
     SetChained(true);
     {
       mInfo.mAudio.mHasAudio = HasAudio();
       mInfo.mVideo.mHasVideo = HasVideo();
       nsAutoPtr<MediaInfo> info(new MediaInfo());
       *info = mInfo;
       ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
       mDecoder->QueueMetadata((mDecodedAudioFrames * USECS_PER_S) / mInfo.mAudio.mRate,
-                              info.forget(), tags);
+                              info, tags);
     }
     return true;
   }
 
   return false;
 }
 
 nsresult OggReader::DecodeTheora(ogg_packet* aPacket, int64_t aTimeThreshold)
--- a/dom/media/omx/MediaOmxCommonDecoder.cpp
+++ b/dom/media/omx/MediaOmxCommonDecoder.cpp
@@ -52,17 +52,17 @@ MediaOmxCommonDecoder::SetPlatformCanOff
 bool
 MediaOmxCommonDecoder::CheckDecoderCanOffloadAudio()
 {
   return (mCanOffloadAudio && !mFallbackToStateMachine && !mOutputStreams.Length() &&
       mInitialPlaybackRate == 1.0);
 }
 
 void
-MediaOmxCommonDecoder::FirstFrameLoaded(MediaInfo* aInfo)
+MediaOmxCommonDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MediaDecoder::FirstFrameLoaded(aInfo);
 
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   if (!CheckDecoderCanOffloadAudio()) {
     DECODER_LOG(PR_LOG_DEBUG, ("In %s Offload Audio check failed",
         __PRETTY_FUNCTION__));
--- a/dom/media/omx/MediaOmxCommonDecoder.h
+++ b/dom/media/omx/MediaOmxCommonDecoder.h
@@ -18,17 +18,17 @@ namespace mozilla {
 class AudioOffloadPlayerBase;
 class MediaOmxCommonReader;
 
 class MediaOmxCommonDecoder : public MediaDecoder
 {
 public:
   MediaOmxCommonDecoder();
 
-  virtual void FirstFrameLoaded(MediaInfo* aInfo);
+  virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo);
   virtual void ChangeState(PlayState aState);
   virtual void ApplyStateToStateMachine(PlayState aState);
   virtual void SetVolume(double aVolume);
   virtual void PlaybackPositionChanged();
   virtual void UpdateReadyStateForData();
   virtual void SetElementVisibility(bool aIsVisible);
   virtual void SetPlatformCanOffloadAudio(bool aCanOffloadAudio);
   virtual bool CheckDecoderCanOffloadAudio();
--- a/dom/media/webaudio/BufferDecoder.cpp
+++ b/dom/media/webaudio/BufferDecoder.cpp
@@ -135,29 +135,29 @@ BufferDecoder::IsTransportSeekable()
 
 bool
 BufferDecoder::IsMediaSeekable()
 {
   return false;
 }
 
 void
-BufferDecoder::MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags)
+BufferDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags)
 {
   // ignore
 }
 
 void
-BufferDecoder::FirstFrameLoaded(MediaInfo* aInfo)
+BufferDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo)
 {
   // ignore
 }
 
 void
-BufferDecoder::QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags)
+BufferDecoder::QueueMetadata(int64_t aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags)
 {
   // ignore
 }
 
 void
 BufferDecoder::RemoveMediaTracks()
 {
   // ignore
--- a/dom/media/webaudio/BufferDecoder.h
+++ b/dom/media/webaudio/BufferDecoder.h
@@ -53,19 +53,19 @@ public:
 
   virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
   virtual layers::ImageContainer* GetImageContainer() MOZ_FINAL MOZ_OVERRIDE;
 
   virtual bool IsTransportSeekable() MOZ_FINAL MOZ_OVERRIDE;
 
   virtual bool IsMediaSeekable() MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
-  virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
-  virtual void FirstFrameLoaded(MediaInfo* aInfo) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void QueueMetadata(int64_t aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo) MOZ_FINAL MOZ_OVERRIDE;
 
   virtual void RemoveMediaTracks() MOZ_FINAL MOZ_OVERRIDE;
 
   virtual void SetMediaEndTime(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
 
   virtual void UpdatePlaybackPosition(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
 
   virtual void OnReadMetadataCompleted() MOZ_FINAL MOZ_OVERRIDE;