video_renderer_impl.h revision 116680a4aac90f2aa7413d9095a592090648e557
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef MEDIA_FILTERS_VIDEO_RENDERER_IMPL_H_ 6#define MEDIA_FILTERS_VIDEO_RENDERER_IMPL_H_ 7 8#include <deque> 9 10#include "base/memory/ref_counted.h" 11#include "base/memory/scoped_ptr.h" 12#include "base/memory/scoped_vector.h" 13#include "base/memory/weak_ptr.h" 14#include "base/synchronization/condition_variable.h" 15#include "base/synchronization/lock.h" 16#include "base/threading/platform_thread.h" 17#include "media/base/decryptor.h" 18#include "media/base/demuxer_stream.h" 19#include "media/base/pipeline_status.h" 20#include "media/base/video_decoder.h" 21#include "media/base/video_frame.h" 22#include "media/base/video_renderer.h" 23#include "media/filters/decoder_stream.h" 24 25namespace base { 26class SingleThreadTaskRunner; 27} 28 29namespace media { 30 31// VideoRendererImpl creates its own thread for the sole purpose of timing frame 32// presentation. It handles reading from the VideoFrameStream and stores the 33// results in a queue of decoded frames and executing a callback when a frame is 34// ready for rendering. 35class MEDIA_EXPORT VideoRendererImpl 36 : public VideoRenderer, 37 public base::PlatformThread::Delegate { 38 public: 39 typedef base::Callback<void(const scoped_refptr<VideoFrame>&)> PaintCB; 40 41 // |decoders| contains the VideoDecoders to use when initializing. 42 // 43 // |paint_cb| is executed on the video frame timing thread whenever a new 44 // frame is available for painting. 45 // 46 // Implementors should avoid doing any sort of heavy work in this method and 47 // instead post a task to a common/worker thread to handle rendering. Slowing 48 // down the video thread may result in losing synchronization with audio. 49 // 50 // Setting |drop_frames_| to true causes the renderer to drop expired frames. 51 VideoRendererImpl( 52 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 53 ScopedVector<VideoDecoder> decoders, 54 const SetDecryptorReadyCB& set_decryptor_ready_cb, 55 const PaintCB& paint_cb, 56 bool drop_frames); 57 virtual ~VideoRendererImpl(); 58 59 // VideoRenderer implementation. 60 virtual void Initialize(DemuxerStream* stream, 61 bool low_delay, 62 const PipelineStatusCB& init_cb, 63 const StatisticsCB& statistics_cb, 64 const TimeCB& max_time_cb, 65 const BufferingStateCB& buffering_state_cb, 66 const base::Closure& ended_cb, 67 const PipelineStatusCB& error_cb, 68 const TimeDeltaCB& get_time_cb, 69 const TimeDeltaCB& get_duration_cb) OVERRIDE; 70 virtual void Flush(const base::Closure& callback) OVERRIDE; 71 virtual void StartPlayingFrom(base::TimeDelta timestamp) OVERRIDE; 72 virtual void Stop(const base::Closure& callback) OVERRIDE; 73 74 // PlatformThread::Delegate implementation. 75 virtual void ThreadMain() OVERRIDE; 76 77 private: 78 // Callback for |video_frame_stream_| initialization. 79 void OnVideoFrameStreamInitialized(bool success); 80 81 // Callback for |video_frame_stream_| to deliver decoded video frames and 82 // report video decoding status. 83 void FrameReady(VideoFrameStream::Status status, 84 const scoped_refptr<VideoFrame>& frame); 85 86 // Helper method for adding a frame to |ready_frames_|. 87 void AddReadyFrame_Locked(const scoped_refptr<VideoFrame>& frame); 88 89 // Helper method that schedules an asynchronous read from the 90 // |video_frame_stream_| as long as there isn't a pending read and we have 91 // capacity. 92 void AttemptRead(); 93 void AttemptRead_Locked(); 94 95 // Called when VideoFrameStream::Reset() completes. 96 void OnVideoFrameStreamResetDone(); 97 98 // Helper function that flushes the buffers when a Stop() or error occurs. 99 void DoStopOrError_Locked(); 100 101 // Runs |paint_cb_| with the next frame from |ready_frames_|. 102 // 103 // A read is scheduled to replace the frame. 104 void PaintNextReadyFrame_Locked(); 105 106 // Drops the next frame from |ready_frames_| and runs |statistics_cb_|. 107 // 108 // A read is scheduled to replace the frame. 109 void DropNextReadyFrame_Locked(); 110 111 // Returns true if the renderer has enough data for playback purposes. 112 // Note that having enough data may be due to reaching end of stream. 113 bool HaveEnoughData_Locked(); 114 void TransitionToHaveEnough_Locked(); 115 116 // Runs |statistics_cb_| with |frames_decoded_| and |frames_dropped_|, resets 117 // them to 0, and then waits on |frame_available_| for up to the 118 // |wait_duration|. 119 void UpdateStatsAndWait_Locked(base::TimeDelta wait_duration); 120 121 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 122 123 // Used for accessing data members. 124 base::Lock lock_; 125 126 // Provides video frames to VideoRendererImpl. 127 scoped_ptr<VideoFrameStream> video_frame_stream_; 128 129 // Flag indicating low-delay mode. 130 bool low_delay_; 131 132 // Queue of incoming frames yet to be painted. 133 typedef std::deque<scoped_refptr<VideoFrame> > VideoFrameQueue; 134 VideoFrameQueue ready_frames_; 135 136 // Keeps track of whether we received the end of stream buffer and finished 137 // rendering. 138 bool received_end_of_stream_; 139 bool rendered_end_of_stream_; 140 141 // Used to signal |thread_| as frames are added to |frames_|. Rule of thumb: 142 // always check |state_| to see if it was set to STOPPED after waking up! 143 base::ConditionVariable frame_available_; 144 145 // Important detail: being in kPlaying doesn't imply that video is being 146 // rendered. Rather, it means that the renderer is ready to go. The actual 147 // rendering of video is controlled by time advancing via |time_cb_|. 148 // 149 // kUninitialized 150 // | Initialize() 151 // | 152 // V 153 // kInitializing 154 // | Decoders initialized 155 // | 156 // V Decoders reset 157 // kFlushed <------------------ kFlushing 158 // | StartPlayingFrom() ^ 159 // | | 160 // | | Flush() 161 // `---------> kPlaying --------' 162 enum State { 163 kUninitialized, 164 kInitializing, 165 kFlushing, 166 kFlushed, 167 kPlaying, 168 kStopped, 169 }; 170 State state_; 171 172 // Video thread handle. 173 base::PlatformThreadHandle thread_; 174 175 // Keep track of the outstanding read on the VideoFrameStream. Flushing can 176 // only complete once the read has completed. 177 bool pending_read_; 178 179 bool drop_frames_; 180 181 BufferingState buffering_state_; 182 183 // Playback operation callbacks. 184 base::Closure flush_cb_; 185 186 // Event callbacks. 187 PipelineStatusCB init_cb_; 188 StatisticsCB statistics_cb_; 189 TimeCB max_time_cb_; 190 BufferingStateCB buffering_state_cb_; 191 base::Closure ended_cb_; 192 PipelineStatusCB error_cb_; 193 TimeDeltaCB get_time_cb_; 194 TimeDeltaCB get_duration_cb_; 195 196 base::TimeDelta start_timestamp_; 197 198 // Embedder callback for notifying a new frame is available for painting. 199 PaintCB paint_cb_; 200 201 // The timestamp of the last frame removed from the |ready_frames_| queue, 202 // either for calling |paint_cb_| or for dropping. Set to kNoTimestamp() 203 // during flushing. 204 base::TimeDelta last_timestamp_; 205 206 // Keeps track of the number of frames decoded and dropped since the 207 // last call to |statistics_cb_|. These must be accessed under lock. 208 int frames_decoded_; 209 int frames_dropped_; 210 211 // NOTE: Weak pointers must be invalidated before all other member variables. 212 base::WeakPtrFactory<VideoRendererImpl> weak_factory_; 213 214 DISALLOW_COPY_AND_ASSIGN(VideoRendererImpl); 215}; 216 217} // namespace media 218 219#endif // MEDIA_FILTERS_VIDEO_RENDERER_IMPL_H_ 220