Bug 1091008 - Hoist stream pinning into the MediaDecoderReaders and make MediaDecoderStateMachine::GetBuffered just forward to them. r=cpearce
☠☠ backed out by 43a51201545a ☠ ☠
authorBobby Holley <bobbyholley@gmail.com>
Wed, 05 Nov 2014 10:08:58 +0100
changeset 238382 966093bbc26ad7d904ccf89d6775a72e2045b005
parent 238381 9de4746aa59a3236c122fc9fba27bd4fe2f6c544
child 238383 6f270b2d90f471653dcf0e82b1b924feb97e17f2
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1091008
milestone36.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 1091008 - Hoist stream pinning into the MediaDecoderReaders and make MediaDecoderStateMachine::GetBuffered just forward to them. r=cpearce Whether or not we ping a stream depends a lot on what kind of decoder we're dealing with. In particular, it doesn't really make sense for MSE.
dom/media/MediaDecoderReader.cpp
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
dom/media/MediaResource.h
dom/media/fmp4/MP4Reader.cpp
dom/media/gstreamer/GStreamerReader.cpp
dom/media/ogg/OggReader.cpp
dom/media/wave/WaveReader.cpp
dom/media/webm/WebMReader.cpp
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "MediaDecoderReader.h"
 #include "AbstractMediaDecoder.h"
+#include "MediaResource.h"
 #include "VideoUtils.h"
 #include "ImageContainer.h"
 
 #include "mozilla/mozalloc.h"
 #include <stdint.h>
 #include <algorithm>
 
 namespace mozilla {
@@ -126,17 +127,17 @@ MediaDecoderReader::SetStartTime(int64_t
 {
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
   mStartTime = aStartTime;
 }
 
 nsresult
 MediaDecoderReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered)
 {
-  MediaResource* stream = mDecoder->GetResource();
+  AutoPinned<MediaResource> stream(mDecoder->GetResource());
   int64_t durationUs = 0;
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     durationUs = mDecoder->GetMediaDuration();
   }
   GetEstimatedBufferedTimeRanges(stream, durationUs, aBuffered);
   return NS_OK;
 }
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2980,25 +2980,16 @@ void MediaDecoderStateMachine::StartBuff
 #ifdef PR_LOGGING
   MediaDecoder::Statistics stats = mDecoder->GetStatistics();
   DECODER_LOG("Playback rate: %.1lfKB/s%s download rate: %.1lfKB/s%s",
               stats.mPlaybackRate/1024, stats.mPlaybackRateReliable ? "" : " (unreliable)",
               stats.mDownloadRate/1024, stats.mDownloadRateReliable ? "" : " (unreliable)");
 #endif
 }
 
-nsresult MediaDecoderStateMachine::GetBuffered(dom::TimeRanges* aBuffered) {
-  MediaResource* resource = mDecoder->GetResource();
-  NS_ENSURE_TRUE(resource, NS_ERROR_FAILURE);
-  resource->Pin();
-  nsresult res = mReader->GetBuffered(aBuffered);
-  resource->Unpin();
-  return res;
-}
-
 void MediaDecoderStateMachine::SetPlayStartTime(const TimeStamp& aTimeStamp)
 {
   AssertCurrentThreadInMonitor();
   mPlayStartTime = aTimeStamp;
   if (!mAudioSink) {
     return;
   }
   if (!mPlayStartTime.IsNull()) {
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -249,17 +249,19 @@ public:
 
   // Must be called with the decode monitor held.
   bool IsSeeking() const {
     AssertCurrentThreadInMonitor();
 
     return mState == DECODER_STATE_SEEKING;
   }
 
-  nsresult GetBuffered(dom::TimeRanges* aBuffered);
+  nsresult GetBuffered(dom::TimeRanges* aBuffered) {
+    return mReader->GetBuffered(aBuffered);
+  }
 
   void SetPlaybackRate(double aPlaybackRate);
   void SetPreservesPitch(bool aPreservesPitch);
 
   size_t SizeOfVideoQueue() {
     if (mReader) {
       return mReader->SizeOfVideoQueueInBytes();
     }
--- a/dom/media/MediaResource.h
+++ b/dom/media/MediaResource.h
@@ -713,11 +713,38 @@ protected:
   // Start and end offset of the bytes to be requested.
   MediaByteRange mByteRange;
 
   // True if the stream can seek into unbuffered ranged, i.e. if the
   // connection supports byte range requests.
   bool mIsTransportSeekable;
 };
 
+/**
+ * RAII class that handles pinning and unpinning for MediaResource and derived.
+ * This should be used when making calculations that involve potentially-cached
+ * MediaResource data, so that the state of the world can't change out from under
+ * us.
+ */
+template<class T>
+class MOZ_STACK_CLASS AutoPinned {
+ public:
+  explicit AutoPinned(T* aResource MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : mResource(aResource) {
+    MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+    MOZ_ASSERT(mResource);
+    mResource->Pin();
+  }
+
+  ~AutoPinned() {
+    mResource->Unpin();
+  }
+
+  operator T*() const { return mResource; }
+  T* operator->() const { return mResource; }
+
+private:
+  T* mResource;
+  MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
 } // namespace mozilla
 
 #endif
--- a/dom/media/fmp4/MP4Reader.cpp
+++ b/dom/media/fmp4/MP4Reader.cpp
@@ -795,23 +795,21 @@ MP4Reader::NotifyDataArrived(const char*
 void
 MP4Reader::UpdateIndex()
 {
   MonitorAutoLock mon(mIndexMonitor);
   if (!mIndexReady) {
     return;
   }
 
-  MediaResource* resource = mDecoder->GetResource();
-  resource->Pin();
+  AutoPinned<MediaResource> resource(mDecoder->GetResource());
   nsTArray<MediaByteRange> ranges;
   if (NS_SUCCEEDED(resource->GetCachedRanges(ranges))) {
     mDemuxer->UpdateIndex(ranges);
   }
-  resource->Unpin();
 }
 
 int64_t
 MP4Reader::GetEvictionOffset(double aTime)
 {
   MonitorAutoLock mon(mIndexMonitor);
   if (!mIndexReady) {
     return 0;
@@ -824,21 +822,19 @@ nsresult
 MP4Reader::GetBuffered(dom::TimeRanges* aBuffered)
 {
   MonitorAutoLock mon(mIndexMonitor);
   if (!mIndexReady) {
     return NS_OK;
   }
   MOZ_ASSERT(mStartTime != -1, "Need to finish metadata decode first");
 
-  MediaResource* resource = mDecoder->GetResource();
+  AutoPinned<MediaResource> resource(mDecoder->GetResource());
   nsTArray<MediaByteRange> ranges;
-  resource->Pin();
   nsresult rv = resource->GetCachedRanges(ranges);
-  resource->Unpin();
 
   if (NS_SUCCEEDED(rv)) {
     nsTArray<Interval<Microseconds>> timeRanges;
     mDemuxer->ConvertByteRangesToTime(ranges, &timeRanges);
     for (size_t i = 0; i < timeRanges.Length(); i++) {
       aBuffered->Add((timeRanges[i].start - mStartTime) / 1000000.0,
                      (timeRanges[i].end - mStartTime) / 1000000.0);
     }
--- a/dom/media/gstreamer/GStreamerReader.cpp
+++ b/dom/media/gstreamer/GStreamerReader.cpp
@@ -819,17 +819,17 @@ nsresult GStreamerReader::GetBuffered(do
 {
   if (!mInfo.HasValidMedia()) {
     return NS_OK;
   }
 
 #if GST_VERSION_MAJOR == 0
   GstFormat format = GST_FORMAT_TIME;
 #endif
-  MediaResource* resource = mDecoder->GetResource();
+  AutoPinned<MediaResource> resource(mDecoder->GetResource());
   nsTArray<MediaByteRange> ranges;
   resource->GetCachedRanges(ranges);
 
   if (resource->IsDataCachedToEndOfResource(0)) {
     /* fast path for local or completely cached files */
     gint64 duration = 0;
 
     {
--- a/dom/media/ogg/OggReader.cpp
+++ b/dom/media/ogg/OggReader.cpp
@@ -1895,17 +1895,17 @@ nsresult OggReader::GetBuffered(dom::Tim
   // HasAudio and HasVideo are not used here as they take a lock and cause
   // a deadlock. Accessing mInfo doesn't require a lock - it doesn't change
   // after metadata is read.
   if (!mInfo.HasValidMedia()) {
     // No need to search through the file if there are no audio or video tracks
     return NS_OK;
   }
 
-  MediaResource* resource = mDecoder->GetResource();
+  AutoPinned<MediaResource> resource(mDecoder->GetResource());
   nsTArray<MediaByteRange> ranges;
   nsresult res = resource->GetCachedRanges(ranges);
   NS_ENSURE_SUCCESS(res, res);
 
   // Traverse across the buffered byte ranges, determining the time ranges
   // they contain. MediaResource::GetNextCachedData(offset) returns -1 when
   // offset is after the end of the media resource, or there's no more cached
   // data after the offset. This loop will run until we've checked every
--- a/dom/media/wave/WaveReader.cpp
+++ b/dom/media/wave/WaveReader.cpp
@@ -278,29 +278,30 @@ static double RoundToUsecs(double aSecon
   return floor(aSeconds * USECS_PER_S) / USECS_PER_S;
 }
 
 nsresult WaveReader::GetBuffered(dom::TimeRanges* aBuffered)
 {
   if (!mInfo.HasAudio()) {
     return NS_OK;
   }
-  int64_t startOffset = mDecoder->GetResource()->GetNextCachedData(mWavePCMOffset);
+  AutoPinned<MediaResource> resource(mDecoder->GetResource());
+  int64_t startOffset = resource->GetNextCachedData(mWavePCMOffset);
   while (startOffset >= 0) {
-    int64_t endOffset = mDecoder->GetResource()->GetCachedDataEnd(startOffset);
+    int64_t endOffset = resource->GetCachedDataEnd(startOffset);
     // Bytes [startOffset..endOffset] are cached.
     NS_ASSERTION(startOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
     NS_ASSERTION(endOffset >= mWavePCMOffset, "Integer underflow in GetBuffered");
 
     // We need to round the buffered ranges' times to microseconds so that they
     // have the same precision as the currentTime and duration attribute on
     // the media element.
     aBuffered->Add(RoundToUsecs(BytesToTime(startOffset - mWavePCMOffset)),
                    RoundToUsecs(BytesToTime(endOffset - mWavePCMOffset)));
-    startOffset = mDecoder->GetResource()->GetNextCachedData(endOffset);
+    startOffset = resource->GetNextCachedData(endOffset);
   }
   return NS_OK;
 }
 
 bool
 WaveReader::ReadAll(char* aBuf, int64_t aSize, int64_t* aBytesRead)
 {
   uint32_t got = 0;
--- a/dom/media/webm/WebMReader.cpp
+++ b/dom/media/webm/WebMReader.cpp
@@ -1087,17 +1087,17 @@ nsresult WebMReader::Seek(int64_t aTarge
 
 nsresult WebMReader::GetBuffered(dom::TimeRanges* aBuffered)
 {
   MOZ_ASSERT(mStartTime != -1, "Need to finish metadata decode first");
   if (aBuffered->Length() != 0) {
     return NS_ERROR_FAILURE;
   }
 
-  MediaResource* resource = mDecoder->GetResource();
+  AutoPinned<MediaResource> resource(mDecoder->GetResource());
 
   // Special case completely cached files.  This also handles local files.
   if (mContext && resource->IsDataCachedToEndOfResource(0)) {
     uint64_t duration = 0;
     if (nestegg_duration(mContext, &duration) == 0) {
       aBuffered->Add(0, duration / NS_PER_S);
       return NS_OK;
     }