Bug 1203374. Part 1 - extract the code of computing canplaythrough so it is reusable. r=jya.
authorJW Wang <jwwang@mozilla.com>
Thu, 10 Sep 2015 16:37:26 +0800
changeset 294371 d849c8c7a9952efed3376c38a45b9cf6388d3b1e
parent 294370 4281bd4ca5d819207f81f6c22c66c3cc458b6811
child 294372 d27278fc308e5059e7f05c1c966d848963b5adfc
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1203374
milestone43.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 1203374. Part 1 - extract the code of computing canplaythrough so it is reusable. r=jya. 1. extract MediaDecoder::Statistics to its own file. 2. sort out include orders of MediaDecoderStateMachine.cpp
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaStatistics.h
dom/media/moz.build
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -32,24 +32,16 @@ using namespace mozilla::dom;
 using namespace mozilla::layers;
 using namespace mozilla::media;
 
 // Default timeout msecs until try to enter dormant state by heuristic.
 static const int DEFAULT_HEURISTIC_DORMANT_TIMEOUT_MSECS = 60000;
 
 namespace mozilla {
 
-// Number of estimated seconds worth of data we need to have buffered
-// ahead of the current playback position before we allow the media decoder
-// to report that it can play through the entire media without the decode
-// catching up with the download. Having this margin make the
-// MediaDecoder::CanPlayThrough() calculation more stable in the case of
-// fluctuating bitrates.
-static const int64_t CAN_PLAY_THROUGH_MARGIN = 1;
-
 // The amount of instability we tollerate in calls to
 // MediaDecoder::UpdateEstimatedMediaDuration(); changes of duration
 // less than this are ignored, as they're assumed to be the result of
 // instability in the duration estimation.
 static const uint64_t ESTIMATED_DURATION_FUZZ_FACTOR_USECS = USECS_PER_S / 2;
 
 // avoid redefined macro in unified build
 #undef DECODER_LOG
@@ -816,20 +808,20 @@ void MediaDecoder::PlaybackEnded()
 
   // This must be called after |mOwner->PlaybackEnded()| call above, in order
   // to fire the required durationchange.
   if (IsInfinite()) {
     SetInfinite(false);
   }
 }
 
-MediaDecoder::Statistics
+MediaStatistics
 MediaDecoder::GetStatistics()
 {
-  Statistics result;
+  MediaStatistics result;
 
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   if (mResource) {
     result.mDownloadRate =
       mResource->GetDownloadRate(&result.mDownloadRateReliable);
     result.mDownloadPosition =
       mResource->GetCachedDataEnd(mDecoderPosition);
     result.mTotalBytes = mResource->GetLength();
@@ -1367,50 +1359,21 @@ void MediaDecoder::UnpinForSeek()
   MediaResource* resource = GetResource();
   if (!resource || !mPinnedForSeek) {
     return;
   }
   mPinnedForSeek = false;
   resource->Unpin();
 }
 
-bool MediaDecoder::CanPlayThrough()
+bool
+MediaDecoder::CanPlayThrough()
 {
-  Statistics stats = GetStatistics();
   NS_ENSURE_TRUE(mDecoderStateMachine, false);
-
-  if (mDecoderStateMachine->IsRealTime() ||
-      (stats.mTotalBytes < 0 && stats.mDownloadRateReliable) ||
-      (stats.mTotalBytes >= 0 && stats.mTotalBytes == stats.mDownloadPosition)) {
-    return true;
-  }
-  if (!stats.mDownloadRateReliable || !stats.mPlaybackRateReliable) {
-    return false;
-  }
-  int64_t bytesToDownload = stats.mTotalBytes - stats.mDownloadPosition;
-  int64_t bytesToPlayback = stats.mTotalBytes - stats.mPlaybackPosition;
-  double timeToDownload = bytesToDownload / stats.mDownloadRate;
-  double timeToPlay = bytesToPlayback / stats.mPlaybackRate;
-
-  if (timeToDownload > timeToPlay) {
-    // Estimated time to download is greater than the estimated time to play.
-    // We probably can't play through without having to stop to buffer.
-    return false;
-  }
-
-  // Estimated time to download is less than the estimated time to play.
-  // We can probably play through without having to buffer, but ensure that
-  // we've got a reasonable amount of data buffered after the current
-  // playback position, so that if the bitrate of the media fluctuates, or if
-  // our download rate or decode rate estimation is otherwise inaccurate,
-  // we don't suddenly discover that we need to buffer. This is particularly
-  // required near the start of the media, when not much data is downloaded.
-  int64_t readAheadMargin =
-    static_cast<int64_t>(stats.mPlaybackRate * CAN_PLAY_THROUGH_MARGIN);
-  return stats.mDownloadPosition > stats.mPlaybackPosition + readAheadMargin;
+  return mDecoderStateMachine->IsRealTime() || GetStatistics().CanPlayThrough();
 }
 
 #ifdef MOZ_EME
 nsresult
 MediaDecoder::SetCDMProxy(CDMProxy* aProxy)
 {
   MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -202,16 +202,17 @@ destroying the MediaDecoder object.
 #include "nsISupports.h"
 #include "nsITimer.h"
 
 #include "AbstractMediaDecoder.h"
 #include "MediaDecoderOwner.h"
 #include "MediaEventSource.h"
 #include "MediaMetadataManager.h"
 #include "MediaResource.h"
+#include "MediaStatistics.h"
 #include "MediaStreamGraph.h"
 #include "TimeUnits.h"
 
 class nsIStreamListener;
 class nsIPrincipal;
 
 namespace mozilla {
 
@@ -711,47 +712,21 @@ public:
 #ifdef MOZ_WMF
   static bool IsWMFEnabled();
 #endif
 
 #ifdef MOZ_APPLEMEDIA
   static bool IsAppleMP3Enabled();
 #endif
 
-  struct Statistics {
-    // Estimate of the current playback rate (bytes/second).
-    double mPlaybackRate;
-    // Estimate of the current download rate (bytes/second). This
-    // ignores time that the channel was paused by Gecko.
-    double mDownloadRate;
-    // Total length of media stream in bytes; -1 if not known
-    int64_t mTotalBytes;
-    // Current position of the download, in bytes. This is the offset of
-    // the first uncached byte after the decoder position.
-    int64_t mDownloadPosition;
-    // Current position of decoding, in bytes (how much of the stream
-    // has been consumed)
-    int64_t mDecoderPosition;
-    // Current position of playback, in bytes
-    int64_t mPlaybackPosition;
-    // If false, then mDownloadRate cannot be considered a reliable
-    // estimate (probably because the download has only been running
-    // a short time).
-    bool mDownloadRateReliable;
-    // If false, then mPlaybackRate cannot be considered a reliable
-    // estimate (probably because playback has only been running
-    // a short time).
-    bool mPlaybackRateReliable;
-  };
-
   // Return statistics. This is used for progress events and other things.
   // This can be called from any thread. It's only a snapshot of the
   // current state, since other threads might be changing the state
   // at any time.
-  virtual Statistics GetStatistics();
+  MediaStatistics GetStatistics();
 
   // Frame decoding/painting related performance counters.
   // Threadsafe.
   class FrameStatistics {
   public:
 
     FrameStatistics() :
         mReentrantMonitor("MediaDecoder::FrameStats"),
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -4,50 +4,53 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifdef XP_WIN
 // Include Windows headers required for enabling high precision timers.
 #include "windows.h"
 #include "mmsystem.h"
 #endif
 
-#include "mozilla/DebugOnly.h"
+#include <algorithm>
 #include <stdint.h>
 
-#include "MediaDecoderStateMachine.h"
-#include "MediaTimer.h"
+#include "gfx2DGlue.h"
+
 #include "mediasink/DecodedAudioDataSink.h"
 #include "mediasink/AudioSinkWrapper.h"
 #include "mediasink/DecodedStream.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Logging.h"
+#include "mozilla/mozalloc.h"
+#include "mozilla/MathAlgorithms.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/SharedThreadPool.h"
+#include "mozilla/TaskQueue.h"
+
+#include "nsComponentManagerUtils.h"
+#include "nsContentUtils.h"
+#include "nsIEventTarget.h"
+#include "nsITimer.h"
+#include "nsPrintfCString.h"
 #include "nsTArray.h"
+#include "nsDeque.h"
+#include "prenv.h"
+
+#include "AudioSegment.h"
+#include "DOMMediaStream.h"
+#include "ImageContainer.h"
 #include "MediaDecoder.h"
 #include "MediaDecoderReader.h"
-#include "mozilla/MathAlgorithms.h"
-#include "mozilla/mozalloc.h"
-#include "VideoUtils.h"
-#include "TimeUnits.h"
-#include "nsDeque.h"
-#include "AudioSegment.h"
-#include "VideoSegment.h"
-#include "ImageContainer.h"
-#include "nsComponentManagerUtils.h"
-#include "nsITimer.h"
-#include "nsContentUtils.h"
+#include "MediaDecoderStateMachine.h"
 #include "MediaShutdownManager.h"
-#include "mozilla/SharedThreadPool.h"
-#include "mozilla/TaskQueue.h"
-#include "nsIEventTarget.h"
-#include "prenv.h"
-#include "mozilla/Preferences.h"
-#include "gfx2DGlue.h"
-#include "nsPrintfCString.h"
-#include "DOMMediaStream.h"
-#include "mozilla/Logging.h"
-
-#include <algorithm>
+#include "MediaStatistics.h"
+#include "MediaTimer.h"
+#include "TimeUnits.h"
+#include "VideoSegment.h"
+#include "VideoUtils.h"
 
 namespace mozilla {
 
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 using namespace mozilla::media;
 
 #define NS_DispatchToMainThread(...) CompileError_UseAbstractThreadDispatchInstead
@@ -2817,17 +2820,17 @@ void MediaDecoderStateMachine::StartBuff
   mQuickBuffering =
     !JustExitedQuickBuffering() &&
     decodeDuration < UsecsToDuration(QUICK_BUFFER_THRESHOLD_USECS);
   mBufferingStart = TimeStamp::Now();
 
   SetState(DECODER_STATE_BUFFERING);
   DECODER_LOG("Changed state from DECODING to BUFFERING, decoded for %.3lfs",
               decodeDuration.ToSeconds());
-  MediaDecoder::Statistics stats = mDecoder->GetStatistics();
+  MediaStatistics 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)");
 }
 
 void MediaDecoderStateMachine::ScheduleStateMachineWithLockAndWakeDecoder()
 {
   MOZ_ASSERT(OnTaskQueue());
new file mode 100644
--- /dev/null
+++ b/dom/media/MediaStatistics.h
@@ -0,0 +1,82 @@
+/* -*- 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/. */
+
+#ifndef MediaStatistics_h_
+#define MediaStatistics_h_
+
+namespace mozilla {
+
+struct MediaStatistics {
+  // Estimate of the current playback rate (bytes/second).
+  double mPlaybackRate;
+  // Estimate of the current download rate (bytes/second). This
+  // ignores time that the channel was paused by Gecko.
+  double mDownloadRate;
+  // Total length of media stream in bytes; -1 if not known
+  int64_t mTotalBytes;
+  // Current position of the download, in bytes. This is the offset of
+  // the first uncached byte after the decoder position.
+  int64_t mDownloadPosition;
+  // Current position of decoding, in bytes (how much of the stream
+  // has been consumed)
+  int64_t mDecoderPosition;
+  // Current position of playback, in bytes
+  int64_t mPlaybackPosition;
+  // If false, then mDownloadRate cannot be considered a reliable
+  // estimate (probably because the download has only been running
+  // a short time).
+  bool mDownloadRateReliable;
+  // If false, then mPlaybackRate cannot be considered a reliable
+  // estimate (probably because playback has only been running
+  // a short time).
+  bool mPlaybackRateReliable;
+
+  bool CanPlayThrough()
+  {
+    // Number of estimated seconds worth of data we need to have buffered
+    // ahead of the current playback position before we allow the media decoder
+    // to report that it can play through the entire media without the decode
+    // catching up with the download. Having this margin make the
+    // CanPlayThrough() calculation more stable in the case of
+    // fluctuating bitrates.
+    static const int64_t CAN_PLAY_THROUGH_MARGIN = 1;
+
+    if ((mTotalBytes < 0 && mDownloadRateReliable) ||
+        (mTotalBytes >= 0 && mTotalBytes == mDownloadPosition)) {
+      return true;
+    }
+
+    if (!mDownloadRateReliable || !mPlaybackRateReliable) {
+      return false;
+    }
+
+    int64_t bytesToDownload = mTotalBytes - mDownloadPosition;
+    int64_t bytesToPlayback = mTotalBytes - mPlaybackPosition;
+    double timeToDownload = bytesToDownload / mDownloadRate;
+    double timeToPlay = bytesToPlayback / mPlaybackRate;
+
+    if (timeToDownload > timeToPlay) {
+      // Estimated time to download is greater than the estimated time to play.
+      // We probably can't play through without having to stop to buffer.
+      return false;
+    }
+
+    // Estimated time to download is less than the estimated time to play.
+    // We can probably play through without having to buffer, but ensure that
+    // we've got a reasonable amount of data buffered after the current
+    // playback position, so that if the bitrate of the media fluctuates, or if
+    // our download rate or decode rate estimation is otherwise inaccurate,
+    // we don't suddenly discover that we need to buffer. This is particularly
+    // required near the start of the media, when not much data is downloaded.
+    int64_t readAheadMargin =
+      static_cast<int64_t>(mPlaybackRate * CAN_PLAY_THROUGH_MARGIN);
+    return mDownloadPosition > mPlaybackPosition + readAheadMargin;
+  }
+};
+
+} // namespace mozilla
+
+#endif // MediaStatistics_h_
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -124,16 +124,17 @@ EXPORTS += [
     'MediaEventSource.h',
     'MediaFormatReader.h',
     'MediaInfo.h',
     'MediaMetadataManager.h',
     'MediaQueue.h',
     'MediaRecorder.h',
     'MediaResource.h',
     'MediaSegment.h',
+    'MediaStatistics.h',
     'MediaStreamGraph.h',
     'MediaTimer.h',
     'MediaTrack.h',
     'MediaTrackList.h',
     'MP3Decoder.h',
     'MP3Demuxer.h',
     'MP3FrameParser.h',
     'nsIDocumentActivity.h',