Bug 1272565 - draw a blank image when no frames in the video track.
authorJW Wang <jwwang@mozilla.com>
Tue, 17 May 2016 10:33:32 +0800
changeset 298535 4d6593879275d59e9ac962870d586bff133c8ce6
parent 298534 5eb32f60c6c47085208a5337088412750116441b
child 298536 9f29bac7747d2747f93081ef3c9f3a3bb3945fb6
push id77222
push userjwwang@mozilla.com
push dateTue, 24 May 2016 02:33:13 +0000
treeherdermozilla-inbound@4d6593879275 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1272565
milestone49.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 1272565 - draw a blank image when no frames in the video track. MozReview-Commit-ID: 1Kijn00XAnQ
dom/media/MediaDecoderStateMachine.cpp
dom/media/mediasink/MediaSink.h
dom/media/mediasink/VideoSink.cpp
dom/media/mediasink/VideoSink.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2040,17 +2040,17 @@ MediaDecoderStateMachine::IsDecodingFirs
 
 void
 MediaDecoderStateMachine::FinishDecodeFirstFrame()
 {
   MOZ_ASSERT(OnTaskQueue());
   DECODER_LOG("FinishDecodeFirstFrame");
 
   if (!IsRealTime() && !mSentFirstFrameLoadedEvent) {
-    mMediaSink->Redraw();
+    mMediaSink->Redraw(mInfo.mVideo);
   }
 
   // If we don't know the duration by this point, we assume infinity, per spec.
   if (mDuration.Ref().isNothing()) {
     mDuration = Some(TimeUnit::FromInfinity());
   }
 
   DECODER_LOG("Media duration %lld, "
@@ -2152,17 +2152,17 @@ MediaDecoderStateMachine::SeekCompleted(
   // Reset quick buffering status. This ensures that if we began the
   // seek while quick-buffering, we won't bypass quick buffering mode
   // if we need to buffer after the seek.
   mQuickBuffering = false;
 
   ScheduleStateMachine();
 
   if (video) {
-    mMediaSink->Redraw();
+    mMediaSink->Redraw(mInfo.mVideo);
     mOnPlaybackEvent.Notify(MediaEventType::Invalidate);
   }
 }
 
 RefPtr<ShutdownPromise>
 MediaDecoderStateMachine::BeginShutdown()
 {
   return InvokeAsync(OwnerThread(), this, __func__,
--- a/dom/media/mediasink/MediaSink.h
+++ b/dom/media/mediasink/MediaSink.h
@@ -91,17 +91,17 @@ public:
   virtual void SetPreservesPitch(bool aPreservesPitch) {}
 
   // Pause/resume the playback. Only work after playback starts.
   virtual void SetPlaying(bool aPlaying) = 0;
 
   // Single frame rendering operation may need to be done before playback
   // started (1st frame) or right after seek completed or playback stopped.
   // Do nothing if this sink has no video track. Can be called in any state.
-  virtual void Redraw() {};
+  virtual void Redraw(const VideoInfo& aInfo) {};
 
   // Begin a playback session with the provided start time and media info.
   // Must be called when playback is stopped.
   virtual void Start(int64_t aStartTime, const MediaInfo& aInfo) = 0;
 
   // Finish a playback session.
   // Must be called after playback starts.
   virtual void Stop() = 0;
--- a/dom/media/mediasink/VideoSink.cpp
+++ b/dom/media/mediasink/VideoSink.cpp
@@ -259,20 +259,36 @@ VideoSink::OnVideoQueueFinished()
   if (!mUpdateScheduler.IsScheduled() &&
       mAudioSink->IsPlaying() &&
       !mEndPromiseHolder.IsEmpty()) {
     UpdateRenderedVideoFrames();
   }
 }
 
 void
-VideoSink::Redraw()
+VideoSink::Redraw(const VideoInfo& aInfo)
 {
   AssertOwnerThread();
-  RenderVideoFrames(1);
+
+  // No video track, nothing to draw.
+  if (!aInfo.IsValid() || !mContainer) {
+    return;
+  }
+
+  if (VideoQueue().GetSize() > 0) {
+    RenderVideoFrames(1);
+    return;
+  }
+
+  // When we reach here, it means there are no frames in this video track.
+  // Draw a blank frame to ensure there is something in the image container
+  // to fire 'loadeddata'.
+  RefPtr<Image> blank =
+    mContainer->GetImageContainer()->CreatePlanarYCbCrImage();
+  mContainer->SetCurrentFrame(aInfo.mDisplay, blank, TimeStamp::Now());
 }
 
 void
 VideoSink::TryUpdateRenderedVideoFrames()
 {
   AssertOwnerThread();
   if (!mUpdateScheduler.IsScheduled() && VideoQueue().GetSize() >= 1 &&
       mAudioSink->IsPlaying()) {
--- a/dom/media/mediasink/VideoSink.h
+++ b/dom/media/mediasink/VideoSink.h
@@ -51,17 +51,17 @@ public:
   void SetPlaybackRate(double aPlaybackRate) override;
 
   void SetVolume(double aVolume) override;
 
   void SetPreservesPitch(bool aPreservesPitch) override;
 
   void SetPlaying(bool aPlaying) override;
 
-  void Redraw() override;
+  void Redraw(const VideoInfo& aInfo) override;
 
   void Start(int64_t aStartTime, const MediaInfo& aInfo) override;
 
   void Stop() override;
 
   bool IsStarted() const override;
 
   bool IsPlaying() const override;