Bug 895754 - Update VideoPlaybackQuality to current MSE spec (remove playbackJitter, add totalFrameDelay). r=doublec
authorMatthew Gregan <kinetik@flim.org>
Wed, 24 Jul 2013 11:46:43 +1200
changeset 152013 63020f14491b8e9a357e0f7ba872945532ea5af4
parent 152012 d9dbb5dbb96a60b6c921ef80c955e48a97b2eaa5
child 152014 e3b66a9d34ddb949628d4a35cb63d9cac9ddaa18
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdoublec
bugs895754
milestone25.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 895754 - Update VideoPlaybackQuality to current MSE spec (remove playbackJitter, add totalFrameDelay). r=doublec
content/html/content/src/HTMLVideoElement.cpp
content/media/MediaDecoder.h
content/media/MediaDecoderStateMachine.cpp
content/media/VideoPlaybackQuality.cpp
content/media/VideoPlaybackQuality.h
content/media/test/test_VideoPlaybackQuality.html
dom/webidl/VideoPlaybackQuality.webidl
--- a/content/html/content/src/HTMLVideoElement.cpp
+++ b/content/html/content/src/HTMLVideoElement.cpp
@@ -259,39 +259,39 @@ HTMLVideoElement::NotifyOwnerDocumentAct
 
 already_AddRefed<VideoPlaybackQuality>
 HTMLVideoElement::GetVideoPlaybackQuality()
 {
   DOMHighResTimeStamp creationTime = 0;
   uint64_t totalFrames = 0;
   uint64_t droppedFrames = 0;
   uint64_t corruptedFrames = 0;
-  double playbackJitter = 0.0;
+  double totalFrameDelay = 0.0;
 
   if (sVideoStatsEnabled) {
     nsPIDOMWindow* window = OwnerDoc()->GetInnerWindow();
     if (window) {
       nsPerformance* perf = window->GetPerformance();
       if (perf) {
         creationTime = perf->GetDOMTiming()->TimeStampToDOMHighRes(TimeStamp::Now());
       }
     }
 
     if (mDecoder) {
       MediaDecoder::FrameStatistics& stats = mDecoder->GetFrameStatistics();
       totalFrames = stats.GetParsedFrames();
       droppedFrames = totalFrames - stats.GetPresentedFrames();
       corruptedFrames = totalFrames - stats.GetDecodedFrames();
-      playbackJitter = stats.GetPlaybackJitter();
+      totalFrameDelay = stats.GetTotalFrameDelay();
     }
   }
 
   nsRefPtr<VideoPlaybackQuality> playbackQuality =
     new VideoPlaybackQuality(this, creationTime, totalFrames, droppedFrames,
-                             corruptedFrames, playbackJitter);
+                             corruptedFrames, totalFrameDelay);
   return playbackQuality.forget();
 }
 
 void
 HTMLVideoElement::WakeLockCreate()
 {
   WakeLockUpdate();
 }
--- a/content/media/MediaDecoder.h
+++ b/content/media/MediaDecoder.h
@@ -813,17 +813,17 @@ public:
 
   // Frame decoding/painting related performance counters.
   // Threadsafe.
   class FrameStatistics {
   public:
 
     FrameStatistics() :
         mReentrantMonitor("MediaDecoder::FrameStats"),
-        mPlaybackJitter(0.0),
+        mTotalFrameDelay(0.0),
         mParsedFrames(0),
         mDecodedFrames(0),
         mPresentedFrames(0) {}
 
     // Returns number of frames which have been parsed from the media.
     // Can be called on any thread.
     uint32_t GetParsedFrames() {
       ReentrantMonitorAutoEnter mon(mReentrantMonitor);
@@ -840,19 +840,19 @@ public:
     // 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() {
       ReentrantMonitorAutoEnter mon(mReentrantMonitor);
       return mPresentedFrames;
     }
 
-    double GetPlaybackJitter() {
+    double GetTotalFrameDelay() {
       ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-      return mPlaybackJitter;
+      return mTotalFrameDelay;
     }
 
     // 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) {
       if (aParsed == 0 && aDecoded == 0)
         return;
       ReentrantMonitorAutoEnter mon(mReentrantMonitor);
@@ -862,42 +862,42 @@ public:
 
     // Increments the presented frame counters.
     // Can be called on any thread.
     void NotifyPresentedFrame() {
       ReentrantMonitorAutoEnter mon(mReentrantMonitor);
       ++mPresentedFrames;
     }
 
-    // Tracks the sum of display errors.
+    // Tracks the sum of display delay.
     // Can be called on any thread.
-    void NotifyPlaybackJitter(double aDisplayError) {
+    void NotifyFrameDelay(double aFrameDelay) {
       ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-      mPlaybackJitter += aDisplayError;
+      mTotalFrameDelay += aFrameDelay;
     }
 
   private:
 
     // ReentrantMonitor to protect access of playback statistics.
     ReentrantMonitor mReentrantMonitor;
 
-    // Sum of display duration error.
-    // Access protected by mStatsReentrantMonitor.
-    double mPlaybackJitter;
+    // Sum of displayed frame delays.
+    // Access protected by mReentrantMonitor.
+    double mTotalFrameDelay;
 
     // Number of frames parsed and demuxed from media.
-    // Access protected by mStatsReentrantMonitor.
+    // Access protected by mReentrantMonitor.
     uint32_t mParsedFrames;
 
     // Number of parsed frames which were actually decoded.
-    // Access protected by mStatsReentrantMonitor.
+    // Access protected by mReentrantMonitor.
     uint32_t mDecodedFrames;
 
     // Number of decoded frames which were actually sent down the rendering
-    // pipeline to be painted ("presented"). Access protected by mStatsReentrantMonitor.
+    // pipeline to be painted ("presented"). Access protected by mReentrantMonitor.
     uint32_t mPresentedFrames;
   };
 
   // Return the frame decode/paint related statistics.
   FrameStatistics& GetFrameStatistics() { return mFrameStats; }
 
   // Increments the parsed and decoded frame counters by the passed in counts.
   // Can be called on any thread.
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -2535,20 +2535,20 @@ void MediaDecoderStateMachine::AdvanceFr
     // playback must've been stopped on the decode thread (by a seek, for
     // example).  In that case, the current frame is probably out of date.
     if (!IsPlaying()) {
       ScheduleStateMachine();
       return;
     }
     MediaDecoder::FrameStatistics& frameStats = mDecoder->GetFrameStatistics();
     frameStats.NotifyPresentedFrame();
+    double frameDelay = double(clock_time - currentFrame->mTime) / USECS_PER_S;
+    NS_ASSERTION(frameDelay >= 0.0, "Frame should never be displayed early.");
+    frameStats.NotifyFrameDelay(frameDelay);
     remainingTime = currentFrame->mEndTime - clock_time;
-    int64_t frameDuration = currentFrame->mEndTime - currentFrame->mTime;
-    double displayError = fabs(double(frameDuration - remainingTime) / USECS_PER_S);
-    frameStats.NotifyPlaybackJitter(displayError);
     currentFrame = nullptr;
   }
 
   // Cap the current time to the larger of the audio and video end time.
   // This ensures that if we're running off the system clock, we don't
   // advance the clock to after the media end time.
   if (mVideoFrameEndTime != -1 || mAudioEndTime != -1) {
     // These will be non -1 if we've displayed a video frame, or played an audio frame.
--- a/content/media/VideoPlaybackQuality.cpp
+++ b/content/media/VideoPlaybackQuality.cpp
@@ -16,23 +16,23 @@
 namespace mozilla {
 namespace dom {
 
 VideoPlaybackQuality::VideoPlaybackQuality(HTMLMediaElement* aElement,
                                            DOMHighResTimeStamp aCreationTime,
                                            uint64_t aTotalFrames,
                                            uint64_t aDroppedFrames,
                                            uint64_t aCorruptedFrames,
-                                           double aPlaybackJitter)
+                                           double aTotalFrameDelay)
   : mElement(aElement)
   , mCreationTime(aCreationTime)
   , mTotalFrames(aTotalFrames)
   , mDroppedFrames(aDroppedFrames)
   , mCorruptedFrames(aCorruptedFrames)
-  , mPlaybackJitter(aPlaybackJitter)
+  , mTotalFrameDelay(aTotalFrameDelay)
 {
   SetIsDOMBinding();
 }
 
 HTMLMediaElement*
 VideoPlaybackQuality::GetParentObject() const
 {
   return mElement;
--- a/content/media/VideoPlaybackQuality.h
+++ b/content/media/VideoPlaybackQuality.h
@@ -18,17 +18,17 @@ namespace dom {
 class VideoPlaybackQuality MOZ_FINAL : public nsWrapperCache
 {
 public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VideoPlaybackQuality)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VideoPlaybackQuality)
 
   VideoPlaybackQuality(HTMLMediaElement* aElement, DOMHighResTimeStamp aCreationTime,
                        uint64_t aTotalFrames, uint64_t aDroppedFrames,
-                       uint64_t aCorruptedFrames, double aPlaybackJitter);
+                       uint64_t aCorruptedFrames, double aTotalFrameDelay);
 
   HTMLMediaElement* GetParentObject() const;
 
   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   DOMHighResTimeStamp CreationTime() const
   {
     return mCreationTime;
@@ -44,25 +44,25 @@ public:
     return mDroppedFrames;
   }
 
   uint64_t CorruptedVideoFrames()
   {
     return mCorruptedFrames;
   }
 
-  double PlaybackJitter()
+  double TotalFrameDelay()
   {
-    return mPlaybackJitter;
+    return mTotalFrameDelay;
   }
 
 private:
   nsRefPtr<HTMLMediaElement> mElement;
   DOMHighResTimeStamp mCreationTime;
   uint64_t mTotalFrames;
   uint64_t mDroppedFrames;
   uint64_t mCorruptedFrames;
-  double mPlaybackJitter;
+  double mTotalFrameDelay;
 };
 
 } // namespace dom
 } // namespace mozilla
 #endif /* mozilla_dom_VideoPlaybackQuality_h_ */
--- a/content/media/test/test_VideoPlaybackQuality.html
+++ b/content/media/test/test_VideoPlaybackQuality.html
@@ -16,42 +16,42 @@ function test() {
   ok(video.getVideoPlaybackQuality, "getVideoPlaybackQuality should be exposed with pref set");
 
   var vpq = video.getVideoPlaybackQuality();
   ok(vpq, "getVideoPlaybackQuality should return an object");
   ok(vpq.creationTime <= performance.now(), "creationTime should be in the past");
   is(vpq.totalVideoFrames, 0, "totalVideoFrames should be 0");
   is(vpq.droppedVideoFrames, 0, "droppedVideoFrames should be 0");
   is(vpq.corruptedVideoFrames, 0, "corruptedVideoFrames should be 0");
-  is(vpq.playbackJitter, 0, "playbackJitter should be 0");
+  is(vpq.totalFrameDelay, 0, "totalFrameDelay should be 0");
 
   var vpq2 = video.getVideoPlaybackQuality();
   ok(vpq !== vpq2, "getVideoPlaybackQuality should return a new object");
   ok(vpq.creationTime <= vpq2.creationTime, "VideoPlaybackQuality objects should have increasing creationTime");
 
   var audio = document.createElement("audio");
   ok(!audio.getVideoPlaybackQuality, "getVideoPlaybackQuality should not be available on Audio elements");
 
   video.src = "seek.webm";
   video.play();
   video.addEventListener("ended", function () {
     vpq = video.getVideoPlaybackQuality();
     ok(vpq.creationTime <= performance.now(), "creationTime should be in the past");
     ok(vpq.totalVideoFrames > 0, "totalVideoFrames should be > 0");
     ok(vpq.droppedVideoFrames >= 0, "droppedVideoFrames should be >= 0");
     ok(vpq.corruptedVideoFrames >= 0, "corruptedVideoFrames should be >= 0");
-    ok(vpq.playbackJitter >= 0, "playbackJitter should be >= 0");
+    ok(vpq.totalFrameDelay >= 0, "totalFrameDelay should be >= 0");
 
     SpecialPowers.pushPrefEnv({"set": [["media.video_stats.enabled", false]]}, function () {
       vpq = video.getVideoPlaybackQuality();
       is(vpq.creationTime, 0, "creationTime should be 0");
       is(vpq.totalVideoFrames, 0, "totalVideoFrames should be 0");
       is(vpq.droppedVideoFrames, 0, "droppedVideoFrames should be 0");
       is(vpq.corruptedVideoFrames, 0, "corruptedVideoFrames should be 0");
-      is(vpq.playbackJitter, 0, "playbackJitter should be 0");
+      is(vpq.totalFrameDelay, 0, "totalFrameDelay should be 0");
 
       SimpleTest.finish();
     });
   });
 }
 
 addLoadEvent(function() {
   SpecialPowers.pushPrefEnv({"set": [["media.mediasource.enabled", true]]}, test);
--- a/dom/webidl/VideoPlaybackQuality.webidl
+++ b/dom/webidl/VideoPlaybackQuality.webidl
@@ -11,11 +11,11 @@
  */
 
 [Pref="media.mediasource.enabled"]
 interface VideoPlaybackQuality {
   readonly attribute DOMHighResTimeStamp creationTime;
   readonly attribute unsigned long totalVideoFrames;
   readonly attribute unsigned long droppedVideoFrames;
   readonly attribute unsigned long corruptedVideoFrames;
-  readonly attribute double playbackJitter;
+  readonly attribute double totalFrameDelay;
 };