Bug 1289668 - Use 64 bits to store FrameStatistics values - r=kamidphish
authorGerald Squelart <gsquelart@mozilla.com>
Mon, 18 Jul 2016 10:51:30 +1000
changeset 332130 98c9b3317cbfc02821d096a7e44303da625e59be
parent 332129 86cec74f5da677e7960ad18545242f4bec8a4368
child 332131 12a97f1e4297f74a5a82e54dacefc05c3d58bed1
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskamidphish
bugs1289668
milestone50.0a1
Bug 1289668 - Use 64 bits to store FrameStatistics values - r=kamidphish Decoders uses 64-bit values to count frames, so we should use the same type in FrameStatistics. Because VideoPlaybackQuality can only use 32 bits (as defined in W3C specs), we need to ensure that imported FrameStatistics numbers can fit in 32 bits, while keeping their ratios the same. MozReview-Commit-ID: 3pUTGK0ekGv
dom/html/HTMLVideoElement.cpp
dom/media/FrameStatistics.h
--- a/dom/html/HTMLVideoElement.cpp
+++ b/dom/html/HTMLVideoElement.cpp
@@ -26,16 +26,19 @@
 #include "MediaError.h"
 #include "MediaDecoder.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/WakeLock.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/Performance.h"
 #include "mozilla/dom/VideoPlaybackQuality.h"
 
+#include <algorithm>
+#include <limits>
+
 NS_IMPL_NS_NEW_HTML_ELEMENT(Video)
 
 namespace mozilla {
 namespace dom {
 
 static bool sVideoStatsEnabled;
 
 NS_IMPL_ELEMENT_CLONE(HTMLVideoElement)
@@ -239,20 +242,32 @@ HTMLVideoElement::GetVideoPlaybackQualit
       if (perf) {
         creationTime = perf->Now();
       }
     }
 
     if (mDecoder) {
       FrameStatisticsData stats =
         mDecoder->GetFrameStatistics().GetFrameStatisticsData();
-      static_assert(sizeof(totalFrames) >= sizeof(stats.mParsedFrames),
-                    "possible truncation from FrameStatistics to VideoPlaybackQuality");
-      totalFrames = stats.mParsedFrames;
-      droppedFrames = stats.mDroppedFrames;
+      if (sizeof(totalFrames) >= sizeof(stats.mParsedFrames)) {
+        totalFrames = stats.mParsedFrames;
+        droppedFrames = stats.mDroppedFrames;
+      } else {
+        auto maxStat = std::max(stats.mParsedFrames, stats.mDroppedFrames);
+        const auto maxNumber = std::numeric_limits<uint32_t>::max();
+        if (maxStat <= maxNumber) {
+          totalFrames = static_cast<uint32_t>(stats.mParsedFrames);
+          droppedFrames = static_cast<uint32_t>(stats.mDroppedFrames);
+        } else {
+          // Too big number(s) -> Resize everything to fit in 32 bits.
+          double ratio = double(maxNumber) / double(maxStat);
+          totalFrames = double(stats.mParsedFrames) * ratio;
+          droppedFrames = double(stats.mDroppedFrames) * ratio;
+        }
+      }
       corruptedFrames = 0;
     }
   }
 
   RefPtr<VideoPlaybackQuality> playbackQuality =
     new VideoPlaybackQuality(this, creationTime, totalFrames, droppedFrames,
                              corruptedFrames);
   return playbackQuality.forget();
--- a/dom/media/FrameStatistics.h
+++ b/dom/media/FrameStatistics.h
@@ -8,29 +8,29 @@
 #define FrameStatistics_h_
 
 namespace mozilla {
 
 struct FrameStatisticsData
 {
   // Number of frames parsed and demuxed from media.
   // Access protected by mReentrantMonitor.
-  uint32_t mParsedFrames = 0;
+  uint64_t mParsedFrames = 0;
 
   // Number of parsed frames which were actually decoded.
   // Access protected by mReentrantMonitor.
-  uint32_t mDecodedFrames = 0;
+  uint64_t mDecodedFrames = 0;
 
   // Number of decoded frames which were actually sent down the rendering
   // pipeline to be painted ("presented"). Access protected by mReentrantMonitor.
-  uint32_t mPresentedFrames = 0;
+  uint64_t mPresentedFrames = 0;
 
   // Number of frames that have been skipped because they have missed their
   // composition deadline.
-  uint32_t mDroppedFrames = 0;
+  uint64_t mDroppedFrames = 0;
 };
 
 // Frame decoding/painting related performance counters.
 // Threadsafe.
 class FrameStatistics
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FrameStatistics);
@@ -44,51 +44,51 @@ public:
   FrameStatisticsData GetFrameStatisticsData() const
   {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     return mFrameStatisticsData;
   }
 
   // Returns number of frames which have been parsed from the media.
   // Can be called on any thread.
-  uint32_t GetParsedFrames() const
+  uint64_t GetParsedFrames() const
   {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     return mFrameStatisticsData.mParsedFrames;
   }
 
   // Returns the number of parsed frames which have been decoded.
   // Can be called on any thread.
-  uint32_t GetDecodedFrames() const
+  uint64_t GetDecodedFrames() const
   {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     return mFrameStatisticsData.mDecodedFrames;
   }
 
   // Returns the number of decoded frames which have been sent to the rendering
   // pipeline for painting ("presented").
   // Can be called on any thread.
-  uint32_t GetPresentedFrames() const
+  uint64_t GetPresentedFrames() const
   {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     return mFrameStatisticsData.mPresentedFrames;
   }
 
   // Returns the number of frames that have been skipped because they have
   // missed their composition deadline.
-  uint32_t GetDroppedFrames() const
+  uint64_t GetDroppedFrames() const
   {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     return mFrameStatisticsData.mDroppedFrames;
   }
 
   // Increments the parsed and decoded frame counters by the passed in counts.
   // Can be called on any thread.
-  void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded,
-                           uint32_t aDropped)
+  void NotifyDecodedFrames(uint64_t aParsed, uint64_t aDecoded,
+                           uint64_t aDropped)
   {
     if (aParsed == 0 && aDecoded == 0 && aDropped == 0) {
       return;
     }
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     mFrameStatisticsData.mParsedFrames += aParsed;
     mFrameStatisticsData.mDecodedFrames += aDecoded;
     mFrameStatisticsData.mDroppedFrames += aDropped;