Bug 924678: Explicitly clear OmxDecoder::mDecoder, r=doublec
authorThomas Zimmermann <tdz@users.sourceforge.net>
Mon, 14 Oct 2013 10:38:17 +0200
changeset 164452 ddddcbe66ceba6ec4be09ae7adcbb1873b8cc7a4
parent 164451 d4f441a96a9c4e49cf33051f4f41200dc5c169b3
child 164453 841522f90b3da5d2fbf2aa2129282a8726b1d663
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdoublec
bugs924678
milestone27.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 924678: Explicitly clear OmxDecoder::mDecoder, r=doublec The MediaDecoderStateMachine frees the Decoder during its own shutdown. If the the MediaDecoderStateMachine for an MP3 file gets cleaned up before the MP3 frame parser is finished, the OmxDecoder operates with an invalid Decoder. With this patch, the MediaDecoderStateMachine informs the OmxDecoder to clear the decoder field. The MP3 parser logic detects this case and returns.
content/media/MediaDecoderReader.h
content/media/MediaDecoderStateMachine.h
content/media/omx/MediaOmxReader.cpp
content/media/omx/MediaOmxReader.h
content/media/omx/OmxDecoder.cpp
content/media/omx/OmxDecoder.h
--- a/content/media/MediaDecoderReader.h
+++ b/content/media/MediaDecoderReader.h
@@ -442,16 +442,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
   virtual void ReleaseMediaResources() {};
+  // Release the decoder during shutdown
+  virtual void ReleaseDecoder() {};
 
   // Resets all state related to decoding, emptying all buffers etc.
   virtual nsresult ResetDecode();
 
   // Decodes an unspecified amount of audio data, enqueuing the audio data
   // in mAudioQueue. Returns true when there's more audio to decode,
   // false if the audio is finished, end of file has been reached,
   // or an un-recoverable read error has occured.
--- a/content/media/MediaDecoderStateMachine.h
+++ b/content/media/MediaDecoderStateMachine.h
@@ -315,17 +315,23 @@ public:
 
   // Timer function to implement ScheduleStateMachine(aUsecs).
   void TimeoutExpired();
 
   // Set the media fragment end time. aEndTime is in microseconds.
   void SetFragmentEndTime(int64_t aEndTime);
 
   // Drop reference to decoder.  Only called during shutdown dance.
-  void ReleaseDecoder() { mDecoder = nullptr; }
+  void ReleaseDecoder() {
+    MOZ_ASSERT(mReader);
+    if (mReader) {
+      mReader->ReleaseDecoder();
+    }
+    mDecoder = nullptr;
+  }
 
    // Called when a "MozAudioAvailable" event listener is added to the media
    // element. Called on the main thread.
    void NotifyAudioAvailableListener();
 
   // Copy queued audio/video data in the reader to any output MediaStreams that
   // need it.
   void SendStreamData();
--- a/content/media/omx/MediaOmxReader.cpp
+++ b/content/media/omx/MediaOmxReader.cpp
@@ -64,16 +64,23 @@ bool MediaOmxReader::IsDormantNeeded()
 void MediaOmxReader::ReleaseMediaResources()
 {
   ResetDecode();
   if (mOmxDecoder.get()) {
     mOmxDecoder->ReleaseMediaResources();
   }
 }
 
+void MediaOmxReader::ReleaseDecoder()
+{
+  if (mOmxDecoder.get()) {
+    mOmxDecoder->ReleaseDecoder();
+  }
+}
+
 nsresult MediaOmxReader::ReadMetadata(MediaInfo* aInfo,
                                       MetadataTags** aTags)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   *aTags = nullptr;
 
   if (!mOmxDecoder.get()) {
--- a/content/media/omx/MediaOmxReader.h
+++ b/content/media/omx/MediaOmxReader.h
@@ -57,16 +57,18 @@ public:
     return mHasVideo;
   }
 
   virtual bool IsWaitingMediaResources();
 
   virtual bool IsDormantNeeded();
   virtual void ReleaseMediaResources();
 
+  virtual void ReleaseDecoder() MOZ_OVERRIDE;
+
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
   virtual nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered, int64_t aStartTime);
 
   virtual void OnDecodeThreadStart() MOZ_OVERRIDE;
 
   virtual void OnDecodeThreadFinish() MOZ_OVERRIDE;
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -623,19 +623,24 @@ bool OmxDecoder::SetAudioFormat() {
   }
 
   LOG(PR_LOG_DEBUG, "channelCount: %d sampleRate: %d",
       mAudioChannels, mAudioSampleRate);
 
   return true;
 }
 
+void OmxDecoder::ReleaseDecoder()
+{
+  mDecoder = nullptr;
+}
+
 void OmxDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
 {
-  if (!mAudioTrack.get() || !mIsMp3 || !mMP3FrameParser.IsMP3()) {
+  if (!mAudioTrack.get() || !mIsMp3 || !mMP3FrameParser.IsMP3() || !mDecoder) {
     return;
   }
 
   mMP3FrameParser.Parse(aBuffer, aLength, aOffset);
 
   int64_t durationUs = mMP3FrameParser.GetDuration();
 
   if (durationUs != mDurationUs) {
--- a/content/media/omx/OmxDecoder.h
+++ b/content/media/omx/OmxDecoder.h
@@ -176,16 +176,18 @@ public:
   bool TryLoad();
   bool IsDormantNeeded();
   bool IsWaitingMediaResources();
   bool AllocateMediaResources();
   void ReleaseMediaResources();
   bool SetVideoFormat();
   bool SetAudioFormat();
 
+  void ReleaseDecoder();
+
   void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
 
   void GetDuration(int64_t *durationUs) {
     *durationUs = mDurationUs;
   }
 
   void GetVideoParameters(int32_t *width, int32_t *height) {
     *width = mVideoWidth;