Bug 1272565 - draw a blank image when no frames in the video track. draft 1272565_blank_frame
authorJW Wang <jwwang@mozilla.com>
Tue, 17 May 2016 10:33:32 +0800
branch1272565_blank_frame
changeset 369084 bc2fcc908cc807a1953e04c99063a5de6bec13ea
parent 368365 c4449eab07d39e20ea315603f1b1863eeed7dcfe
child 724564 e83d0147ddc890cb603dd4826c509c52aa53f0b5
push id18731
push userjwwang@mozilla.com
push dateFri, 20 May 2016 07:57:16 +0000
bugs1272565
milestone49.0a1
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
@@ -2031,17 +2031,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, "
@@ -2143,17 +2143,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;