Bug 881512 - Fix bogus indexing of audio/video readers by ditching audio/video reader arrays and using the parent decoder directly. r=cajbir
authorMatthew Gregan <kinetik@flim.org>
Tue, 22 Apr 2014 23:59:00 +1200
changeset 199962 81403176036ee6f9c5c2afa494fe176a72e085d6
parent 199961 6c69283f7713d07cde20864ae5e140951e3c3dd8
child 199963 15fe0db2ff8d995651c3c13f23938843d4901152
push id486
push userasasaki@mozilla.com
push dateMon, 14 Jul 2014 18:39:42 +0000
treeherdermozilla-release@d33428174ff1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscajbir
bugs881512
milestone31.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 881512 - Fix bogus indexing of audio/video readers by ditching audio/video reader arrays and using the parent decoder directly. r=cajbir
content/media/mediasource/MediaSourceDecoder.cpp
--- a/content/media/mediasource/MediaSourceDecoder.cpp
+++ b/content/media/mediasource/MediaSourceDecoder.cpp
@@ -37,18 +37,18 @@ class TimeRanges;
 
 } // namespace dom
 
 class MediaSourceReader : public MediaDecoderReader
 {
 public:
   MediaSourceReader(MediaSourceDecoder* aDecoder)
     : MediaDecoderReader(aDecoder)
-    , mActiveVideoReader(-1)
-    , mActiveAudioReader(-1)
+    , mActiveVideoDecoder(-1)
+    , mActiveAudioDecoder(-1)
   {
   }
 
   nsresult Init(MediaDecoderReader* aCloneDonor) MOZ_OVERRIDE
   {
     // Although we technically don't implement anything here, we return NS_OK
     // so that when the state machine initializes and calls this function
     // we don't return an error code back to the media element.
@@ -57,64 +57,64 @@ public:
 
   bool IsWaitingMediaResources() MOZ_OVERRIDE
   {
     return mDecoders.IsEmpty() && mPendingDecoders.IsEmpty();
   }
 
   bool DecodeAudioData() MOZ_OVERRIDE
   {
-    if (mActiveAudioReader == -1) {
+    if (!GetAudioReader()) {
       MSE_DEBUG("%p DecodeAudioFrame called with no audio reader", this);
       MOZ_ASSERT(mPendingDecoders.IsEmpty());
       return false;
     }
-    bool rv = mAudioReaders[mActiveAudioReader]->DecodeAudioData();
+    bool rv = GetAudioReader()->DecodeAudioData();
 
     nsAutoTArray<AudioData*, 10> audio;
-    mAudioReaders[mActiveAudioReader]->AudioQueue().GetElementsAfter(-1, &audio);
+    GetAudioReader()->AudioQueue().GetElementsAfter(-1, &audio);
     for (uint32_t i = 0; i < audio.Length(); ++i) {
       AudioQueue().Push(audio[i]);
     }
-    mAudioReaders[mActiveAudioReader]->AudioQueue().Empty();
+    GetAudioReader()->AudioQueue().Empty();
 
     return rv;
   }
 
   bool DecodeVideoFrame(bool& aKeyFrameSkip, int64_t aTimeThreshold) MOZ_OVERRIDE
   {
-    if (mActiveVideoReader == -1) {
+    if (!GetVideoReader()) {
       MSE_DEBUG("%p DecodeVideoFrame called with no video reader", this);
       MOZ_ASSERT(mPendingDecoders.IsEmpty());
       return false;
     }
-    bool rv = mVideoReaders[mActiveVideoReader]->DecodeVideoFrame(aKeyFrameSkip, aTimeThreshold);
+    bool rv = GetVideoReader()->DecodeVideoFrame(aKeyFrameSkip, aTimeThreshold);
 
     nsAutoTArray<VideoData*, 10> video;
-    mVideoReaders[mActiveVideoReader]->VideoQueue().GetElementsAfter(-1, &video);
+    GetVideoReader()->VideoQueue().GetElementsAfter(-1, &video);
     for (uint32_t i = 0; i < video.Length(); ++i) {
       VideoQueue().Push(video[i]);
     }
-    mVideoReaders[mActiveVideoReader]->VideoQueue().Empty();
+    GetVideoReader()->VideoQueue().Empty();
 
     if (rv) {
       return true;
     }
 
     MSE_DEBUG("%p MSR::DecodeVF %d (%p) returned false (readers=%u)",
-              this, mActiveVideoReader, mVideoReaders[mActiveVideoReader], mVideoReaders.Length());
+              this, mActiveVideoDecoder, mDecoders[mActiveVideoDecoder].get(), mDecoders.Length());
     if (SwitchVideoReaders(aTimeThreshold)) {
-      rv = mVideoReaders[mActiveVideoReader]->DecodeVideoFrame(aKeyFrameSkip, aTimeThreshold);
+      rv = GetVideoReader()->DecodeVideoFrame(aKeyFrameSkip, aTimeThreshold);
 
       nsAutoTArray<VideoData*, 10> video;
-      mVideoReaders[mActiveVideoReader]->VideoQueue().GetElementsAfter(-1, &video);
+      GetVideoReader()->VideoQueue().GetElementsAfter(-1, &video);
       for (uint32_t i = 0; i < video.Length(); ++i) {
         VideoQueue().Push(video[i]);
       }
-      mVideoReaders[mActiveVideoReader]->VideoQueue().Empty();
+      GetVideoReader()->VideoQueue().Empty();
     }
     return rv;
   }
 
   bool HasVideo() MOZ_OVERRIDE
   {
     return mInfo.HasVideo();
   }
@@ -129,69 +129,80 @@ public:
   nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
                 int64_t aCurrentTime) MOZ_OVERRIDE
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime) MOZ_OVERRIDE
   {
-    for (uint32_t i = 0; i < mVideoReaders.Length(); ++i) {
+    for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
       nsRefPtr<dom::TimeRanges> r = new dom::TimeRanges();
-      mVideoReaders[i]->GetBuffered(r, aStartTime);
-      aBuffered->Add(r->GetStartTime(), r->GetEndTime());
-    }
-    for (uint32_t i = 0; i < mAudioReaders.Length(); ++i) {
-      nsRefPtr<dom::TimeRanges> r = new dom::TimeRanges();
-      mAudioReaders[i]->GetBuffered(r, aStartTime);
+      mDecoders[i]->GetBuffered(r);
       aBuffered->Add(r->GetStartTime(), r->GetEndTime());
     }
     aBuffered->Normalize();
     return NS_OK;
   }
 
   already_AddRefed<SubBufferDecoder> CreateSubDecoder(const nsACString& aType,
                                                       MediaSourceDecoder* aParentDecoder);
 
   void CallDecoderInitialization();
 
 private:
   bool SwitchVideoReaders(int64_t aTimeThreshold) {
-    MOZ_ASSERT(mActiveVideoReader != -1);
+    MOZ_ASSERT(mActiveVideoDecoder != -1);
     // XXX: We switch when the first reader is depleted, but it might be
     // better to switch as soon as the next reader is ready to decode and
     // has data for the current media time.
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
 
+    GetVideoReader()->SetIdle();
+
     WaitForPendingDecoders();
 
-    if (mVideoReaders.Length() > uint32_t(mActiveVideoReader + 1)) {
-      mActiveVideoReader += 1;
-      MSE_DEBUG("%p MSR::DecodeVF switching to %d", this, mActiveVideoReader);
+    for (uint32_t i = mActiveVideoDecoder + 1; i < mDecoders.Length(); ++i) {
+      if (!mDecoders[i]->GetReader()->GetMediaInfo().HasVideo()) {
+        continue;
+      }
+      mActiveVideoDecoder = i;
+      MSE_DEBUG("%p MSR::DecodeVF switching to %d", this, mActiveVideoDecoder);
 
-      MOZ_ASSERT(mVideoReaders[mActiveVideoReader]->GetMediaInfo().HasVideo());
-      mVideoReaders[mActiveVideoReader]->SetActive();
-      mVideoReaders[mActiveVideoReader]->DecodeToTarget(aTimeThreshold);
+      GetVideoReader()->SetActive();
+      GetVideoReader()->DecodeToTarget(aTimeThreshold);
 
       return true;
     }
     return false;
   }
 
+  MediaDecoderReader* GetAudioReader() {
+    if (mActiveAudioDecoder == -1) {
+      return nullptr;
+    }
+    return mDecoders[mActiveAudioDecoder]->GetReader();
+  }
+
+  MediaDecoderReader* GetVideoReader() {
+    if (mActiveVideoDecoder == -1) {
+      return nullptr;
+    }
+    return mDecoders[mActiveVideoDecoder]->GetReader();
+  }
+
   bool EnsureWorkQueueInitialized();
   nsresult EnqueueDecoderInitialization();
   void WaitForPendingDecoders();
 
   nsTArray<nsRefPtr<SubBufferDecoder>> mPendingDecoders;
   nsTArray<nsRefPtr<SubBufferDecoder>> mDecoders;
 
-  nsTArray<MediaDecoderReader*> mVideoReaders;
-  nsTArray<MediaDecoderReader*> mAudioReaders;
-  int32_t mActiveVideoReader;
-  int32_t mActiveAudioReader;
+  int32_t mActiveVideoDecoder;
+  int32_t mActiveAudioDecoder;
 
   nsCOMPtr<nsIThread> mWorkQueue;
 };
 
 class MediaSourceStateMachine : public MediaDecoderStateMachine
 {
 public:
   MediaSourceStateMachine(MediaDecoder* aDecoder,
@@ -337,24 +348,18 @@ MediaSourceReader::CallDecoderInitializa
     reader->SetIdle();
     if (NS_FAILED(rv)) {
       // XXX: Need to signal error back to owning SourceBuffer.
       MSE_DEBUG("%p: Reader %p failed to initialize, rv=%x", this, reader, rv);
       continue;
     }
 
     bool active = false;
-    if (mi.HasVideo()) {
-      MSE_DEBUG("%p: Reader %p has video track", this, reader);
-      mVideoReaders.AppendElement(reader);
-      active = true;
-    }
-    if (mi.HasAudio()) {
-      MSE_DEBUG("%p: Reader %p has audio track", this, reader);
-      mAudioReaders.AppendElement(reader);
+    if (mi.HasVideo() || mi.HasAudio()) {
+      MSE_DEBUG("%p: Reader %p has video=%d audio=%d", this, reader, mi.HasVideo(), mi.HasAudio());
       active = true;
     }
 
     if (active) {
       mDecoders.AppendElement(decoder);
     } else {
       MSE_DEBUG("%p: Reader %p not activated", this, reader);
     }
@@ -416,25 +421,25 @@ MediaSourceReader::ReadMetadata(MediaInf
   for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
     MediaDecoderReader* reader = mDecoders[i]->GetReader();
 
     reader->SetActive(); // XXX check where this should be called
 
     MediaInfo mi = reader->GetMediaInfo();
 
     if (mi.HasVideo() && !mInfo.HasVideo()) {
-      MOZ_ASSERT(mActiveVideoReader == -1);
-      mActiveVideoReader = i;
+      MOZ_ASSERT(mActiveVideoDecoder == -1);
+      mActiveVideoDecoder = i;
       mInfo.mVideo = mi.mVideo;
       maxDuration = std::max(maxDuration, mDecoders[i]->GetMediaDuration());
       MSE_DEBUG("%p: MSR::ReadMetadata video decoder=%u maxDuration=%lld", this, i, maxDuration);
     }
     if (mi.HasAudio() && !mInfo.HasAudio()) {
-      MOZ_ASSERT(mActiveAudioReader == -1);
-      mActiveAudioReader = i;
+      MOZ_ASSERT(mActiveAudioDecoder == -1);
+      mActiveAudioDecoder = i;
       mInfo.mAudio = mi.mAudio;
       maxDuration = std::max(maxDuration, mDecoders[i]->GetMediaDuration());
       MSE_DEBUG("%p: MSR::ReadMetadata audio decoder=%u maxDuration=%lld", this, i, maxDuration);
     }
   }
   *aInfo = mInfo;
 
   if (maxDuration != -1) {