Bug 1295630 - Provide a way for A/V sync to be ruined, so talos can test compositor throughput by painting expired frames. r?mattwoodrow draft
authorChris Pearce <cpearce@mozilla.com>
Fri, 19 Aug 2016 21:34:42 +1200
changeset 403199 d8550ef157a0422440c809c6609213e103d66976
parent 402944 cf06fbc831754e54c6abb71d3136597488a530e0
child 528852 06506b974b99033d61c471419c8401cf23126f12
push id26855
push usercpearce@mozilla.com
push dateFri, 19 Aug 2016 09:49:21 +0000
reviewersmattwoodrow
bugs1295630, 1258870
milestone51.0a1
Bug 1295630 - Provide a way for A/V sync to be ruined, so talos can test compositor throughput by painting expired frames. r?mattwoodrow In bug 1258870 I changed the media code so that we dropped all late video frames. Without this, our A/V sync was broken when the decode was struggling to keep up, and we weren't reporting dropped frames when the decode couldn't keep up, and so players couldn't adapt to a bitrate which the decode could keep up on. However, dropping all late frames broke talos tests which relied on the old behaviour of us rendering video frames that were late. So this patch adds a pref to cause the frame dropping code to not drop the last frame in the queue, so there will always be something for the compositor to composit. This means talos will once again be able to test how fast it can composit frames that aren't supposed to be drawn. The pref is media.ruin-av-sync.enabled. It defaults to false. MozReview-Commit-ID: J3VvpzoDRmI
dom/media/MediaPrefs.h
dom/media/mediasink/VideoSink.cpp
dom/media/mediasink/VideoSink.h
--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -87,16 +87,19 @@ private:
   // This is where DECL_MEDIA_PREF for each of the preferences should go.
 
   // AudioSink
   DECL_MEDIA_PREF("accessibility.monoaudio.enable",           MonoAudio, bool, false);
   DECL_MEDIA_PREF("media.resampling.enabled",                 AudioSinkResampling, bool, false);
   DECL_MEDIA_PREF("media.resampling.rate",                    AudioSinkResampleRate, uint32_t, 48000);
   DECL_MEDIA_PREF("media.forcestereo.enabled",                AudioSinkForceStereo, bool, true);
 
+  // VideoSink
+  DECL_MEDIA_PREF("media.ruin-av-sync.enabled",               RuinAvSync, bool, false);
+
   // PlatformDecoderModule
   DECL_MEDIA_PREF("media.apple.forcevda",                     AppleForceVDA, bool, false);
   DECL_MEDIA_PREF("media.gmp.insecure.allow",                 GMPAllowInsecure, bool, false);
   DECL_MEDIA_PREF("media.gmp.async-shutdown-timeout",         GMPAsyncShutdownTimeout, uint32_t, GMP_DEFAULT_ASYNC_SHUTDOWN_TIMEOUT);
   DECL_MEDIA_PREF("media.eme.enabled",                        EMEEnabled, bool, false);
   DECL_MEDIA_PREF("media.use-blank-decoder",                  PDMUseBlankDecoder, bool, false);
 #ifdef MOZ_GONK_MEDIACODEC
   DECL_MEDIA_PREF("media.gonk.enabled",                       PDMGonkDecoderEnabled, bool, true);
--- a/dom/media/mediasink/VideoSink.cpp
+++ b/dom/media/mediasink/VideoSink.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 "MediaQueue.h"
 #include "VideoSink.h"
+#include "MediaPrefs.h"
 
 namespace mozilla {
 
 extern LazyLogModule gMediaDecoderLog;
 #define VSINK_LOG(msg, ...) \
   MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, \
     ("VideoSink=%p " msg, this, ##__VA_ARGS__))
 #define VSINK_LOG_V(msg, ...) \
@@ -32,16 +33,17 @@ VideoSink::VideoSink(AbstractThread* aTh
   , mVideoQueue(aVideoQueue)
   , mContainer(aContainer)
   , mProducerID(ImageContainer::AllocateProducerID())
   , mFrameStats(aFrameStats)
   , mVideoFrameEndTime(-1)
   , mHasVideo(false)
   , mUpdateScheduler(aThread)
   , mVideoQueueSendToCompositorSize(aVQueueSentToCompositerSize)
+  , mMinVideoQueueSize(MediaPrefs::RuinAvSync() ? 1 : 0)
 {
   MOZ_ASSERT(mAudioSink, "AudioSink should exist.");
 }
 
 VideoSink::~VideoSink()
 {
 }
 
@@ -389,17 +391,17 @@ VideoSink::UpdateRenderedVideoFrames()
 
   // Get the current playback position.
   TimeStamp nowTime;
   const int64_t clockTime = mAudioSink->GetPosition(&nowTime);
   NS_ASSERTION(clockTime >= 0, "Should have positive clock time.");
 
   // Skip frames up to the playback position.
   int64_t lastDisplayedFrameEndTime = 0;
-  while (VideoQueue().GetSize() > 0 &&
+  while (VideoQueue().GetSize() > mMinVideoQueueSize &&
          clockTime > VideoQueue().PeekFront()->GetEndTime()) {
     RefPtr<MediaData> frame = VideoQueue().PopFront();
     if (frame->As<VideoData>()->mSentToCompositor) {
       lastDisplayedFrameEndTime = frame->GetEndTime();
       mFrameStats.NotifyPresentedFrame();
     } else {
       mFrameStats.NotifyDecodedFrames({ 0, 0, 1 });
       VSINK_LOG_V("discarding video frame mTime=%lld clock_time=%lld",
--- a/dom/media/mediasink/VideoSink.h
+++ b/dom/media/mediasink/VideoSink.h
@@ -134,14 +134,23 @@ private:
   bool mHasVideo;
 
   // Used to trigger another update of rendered frames in next round.
   DelayedScheduler mUpdateScheduler;
 
   // Max frame number sent to compositor at a time.
   // Based on the pref value obtained in MDSM.
   const uint32_t mVideoQueueSendToCompositorSize;
+
+  // Talos tests for the compositor require at least one frame in the
+  // video queue so that the compositor has something to composit during
+  // the talos test when the decode is stressed. We have a minimum size
+  // on the video queue in order to facilitate this talos test.
+  // Note: Normal playback should not have a queue size of more than 0,
+  // otherwise A/V sync will be ruined! *Only* make this non-zero for
+  // testing purposes.
+  const uint32_t mMinVideoQueueSize;
 };
 
 } // namespace media
 } // namespace mozilla
 
 #endif