Bug 1366975 - MediaElement draft
authorbechen <bechen@mozilla.com>
Tue, 13 Jun 2017 18:44:38 +0800
changeset 593228 07614c9d333fc87948918c486cc98e0b3f969957
parent 593227 8ffe2cd238115bff718f86a6c889853665048301
child 593229 5809c6f1ec6347b4830296147c831f4b6a884615
push id63642
push userbechen@mozilla.com
push dateTue, 13 Jun 2017 10:44:55 +0000
bugs1366975
milestone55.0a1
Bug 1366975 - MediaElement MozReview-Commit-ID: HBJFjtCe8Eu
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/media/MediaCache.h
dom/media/MediaCacheStatus.cpp
dom/media/MediaDecoder.cpp
dom/media/MediaResource.cpp
dom/media/MediaResource.h
dom/media/MediaStatistics.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -122,16 +122,17 @@ static mozilla::LazyLogModule gMediaElem
 
 #include "nsIPermissionManager.h"
 #include "nsDocShell.h"
 
 #include "mozilla/EventStateManager.h"
 
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "mozilla/dom/VideoPlaybackQuality.h"
+#include "mozilla/dom/MediaCacheStatus.h"
 #include "HTMLMediaElement.h"
 
 #include "GMPCrashHelper.h"
 
 using namespace mozilla::layers;
 using mozilla::net::nsMediaFragmentURIParser;
 
 namespace mozilla {
@@ -7526,10 +7527,33 @@ HTMLMediaElement::ReportCanPlayTelemetry
           Telemetry::Accumulate(
             Telemetry::HistogramID::VIDEO_CAN_CREATE_H264_DECODER, h264);
           thread->AsyncShutdown();
         }));
     }),
     NS_DISPATCH_NORMAL);
 }
 
+already_AddRefed<MediaCacheStatus>
+HTMLMediaElement::GetMediaCacheStatus()
+{
+  int64_t totalBlocks = 0;
+  int64_t occupiedBlocks = 0;
+
+  if (Preferences::GetBool("media.mediaCacheStatus.enabled", false)) {
+    int32_t cacheSize = Preferences::GetInt("media.cache_size", 500*1024);
+    totalBlocks = static_cast<int64_t>(cacheSize)*1024/MediaCacheStream::BLOCK_SIZE;
+    totalBlocks = std::max<int64_t>(totalBlocks, 1);
+    if (mDecoder) {
+      MediaStatistics stats = mDecoder->GetStatistics();
+      occupiedBlocks = stats.mCachedBlocks;
+    }
+  }
+
+
+  RefPtr<MediaCacheStatus> mediaCacheStatus =
+    new MediaCacheStatus(this, MediaCacheStream::BLOCK_SIZE,
+        totalBlocks,occupiedBlocks);
+  return mediaCacheStatus.forget();
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -100,16 +100,18 @@ public:
   CORSMode GetCORSMode() {
     return mCORSMode;
   }
 
   explicit HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   void ReportCanPlayTelemetry();
 
+  already_AddRefed<MediaCacheStatus> GetMediaCacheStatus();
+
   /**
    * This is used when the browser is constructing a video element to play
    * a channel that we've already started loading. The src attribute and
    * <source> children are ignored.
    * @param aChannel the channel to use
    * @param aListener returns a stream listener that should receive
    * notifications for the stream
    */
--- a/dom/media/MediaCache.h
+++ b/dom/media/MediaCache.h
@@ -277,16 +277,18 @@ public:
   // reset variables such as |mDidNotifyDataEnded|.
   void NotifyChannelRecreated();
 
   // These methods can be called on any thread.
   // Cached blocks associated with this stream will not be evicted
   // while the stream is pinned.
   void Pin();
   void Unpin();
+
+  uint64_t GetBlockCount() {return mBlocks.Length();}
   // See comments above for NotifyDataLength about how the length
   // can vary over time. Returns -1 if no length is known. Returns the
   // reported length if we haven't got any better information. If
   // the stream ended normally we return the length we actually got.
   // If we've successfully read data beyond the originally reported length,
   // we return the end of the data we've read.
   int64_t GetLength();
   // Returns the unique resource ID. Call only on the main thread or while
--- a/dom/media/MediaCacheStatus.cpp
+++ b/dom/media/MediaCacheStatus.cpp
@@ -12,17 +12,17 @@
 #include "nsWrapperCache.h"
 
 namespace mozilla {
 namespace dom {
 
 MediaCacheStatus::MediaCacheStatus(HTMLMediaElement* aElement,
                                    uint32_t aBlockSize,
                                    uint32_t aTotalBlocks,
-                                   uint32_t mOccupiedBlocks)
+                                   uint32_t aOccupiedBlocks)
   : mElement(aElement)
   , mBlockSize(aBlockSize)
   , mTotalBlocks(aTotalBlocks)
   , mOccupiedBlocks(aOccupiedBlocks)
 {
 }
 
 HTMLMediaElement*
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -991,16 +991,17 @@ MediaDecoder::GetStatistics()
   result.mDownloadRate =
     mResource->GetDownloadRate(&result.mDownloadRateReliable);
   result.mDownloadPosition = mResource->GetCachedDataEnd(mDecoderPosition);
   result.mTotalBytes = mResource->GetLength();
   result.mPlaybackRate = mPlaybackBytesPerSecond;
   result.mPlaybackRateReliable = mPlaybackRateReliable;
   result.mDecoderPosition = mDecoderPosition;
   result.mPlaybackPosition = mPlaybackPosition;
+  result.mCachedBlocks = mResource->GetCachedBlockCount();
   return result;
 }
 
 void
 MediaDecoder::ComputePlaybackRate()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mResource);
--- a/dom/media/MediaResource.cpp
+++ b/dom/media/MediaResource.cpp
@@ -1015,16 +1015,22 @@ ChannelMediaResource::IsDataCachedToEndO
 }
 
 void
 ChannelMediaResource::EnsureCacheUpToDate()
 {
   mCacheStream.EnsureCacheUpdate();
 }
 
+int64_t
+ChannelMediaResource::GetCachedBlockCount()
+{
+  return mCacheStream.GetBlockCount();
+}
+
 bool
 ChannelMediaResource::IsSuspendedByCache()
 {
   return mCacheStream.AreAllStreamsForResourceSuspended();
 }
 
 bool
 ChannelMediaResource::IsSuspended()
--- a/dom/media/MediaResource.h
+++ b/dom/media/MediaResource.h
@@ -256,16 +256,17 @@ public:
   // Moves any existing channel loads into or out of background. Background
   // loads don't block the load event. This also determines whether or not any
   // new loads initiated (for example to seek) will be in the background.
   virtual void SetLoadInBackground(bool aLoadInBackground) {}
   // Ensures that the value returned by IsSuspendedByCache below is up to date
   // (i.e. the cache has examined this stream at least once).
   virtual void EnsureCacheUpToDate() {}
 
+  virtual int64_t GetCachedBlockCount() { return 0;};
   // These can be called on any thread.
   // Cached blocks associated with this stream will not be evicted
   // while the stream is pinned.
   virtual void Pin() = 0;
   virtual void Unpin() = 0;
   // Get the estimated download rate in bytes per second (assuming no
   // pausing of the channel is requested by Gecko).
   // *aIsReliable is set to true if we think the estimate is useful.
@@ -573,16 +574,17 @@ public:
   already_AddRefed<nsIPrincipal> GetCurrentPrincipal() override;
   // Return true if the stream has been closed.
   bool     IsClosed() const { return mCacheStream.IsClosed(); }
   bool     CanClone() override;
   already_AddRefed<MediaResource> CloneData(MediaResourceCallback* aDecoder) override;
   nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount) override;
   void     EnsureCacheUpToDate() override;
 
+  int64_t GetCachedBlockCount() override;
   // Other thread
   void     SetReadMode(MediaCacheStream::ReadMode aMode) override;
   void     SetPlaybackRate(uint32_t aBytesPerSecond) override;
   nsresult ReadAt(int64_t offset, char* aBuffer,
                   uint32_t aCount, uint32_t* aBytes) override;
   // Data stored in IO&lock-encumbered MediaCacheStream, caching recommended.
   bool ShouldCacheReads() override { return true; }
   already_AddRefed<MediaByteBuffer> MediaReadAt(int64_t aOffset, uint32_t aCount) override;
--- a/dom/media/MediaStatistics.h
+++ b/dom/media/MediaStatistics.h
@@ -29,16 +29,18 @@ struct MediaStatistics {
   // 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;
 
+  int64_t mCachedBlocks;
+
   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.