1 // Copyright (c) 2012 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_BASE_H_ 6 #define MEDIA_FILTERS_VIDEO_RENDERER_BASE_H_ 7 8 #include <deque> 9 10 #include "base/memory/ref_counted.h" 11 #include "base/memory/scoped_vector.h" 12 #include "base/memory/weak_ptr.h" 13 #include "base/synchronization/condition_variable.h" 14 #include "base/synchronization/lock.h" 15 #include "base/threading/platform_thread.h" 16 #include "media/base/decryptor.h" 17 #include "media/base/demuxer_stream.h" 18 #include "media/base/pipeline_status.h" 19 #include "media/base/video_decoder.h" 20 #include "media/base/video_frame.h" 21 #include "media/base/video_renderer.h" 22 #include "media/filters/video_frame_stream.h" 23 24 namespace base { 25 class MessageLoopProxy; 26 } 27 28 namespace media { 29 30 // VideoRendererBase creates its own thread for the sole purpose of timing frame 31 // presentation. It handles reading from the VideoFrameStream and stores the 32 // results in a queue of decoded frames and executing a callback when a frame is 33 // ready for rendering. 34 class MEDIA_EXPORT VideoRendererBase 35 : public VideoRenderer, 36 public base::PlatformThread::Delegate { 37 public: 38 typedef base::Callback<void(const scoped_refptr<VideoFrame>&)> PaintCB; 39 typedef base::Callback<void(bool)> SetOpaqueCB; 40 41 // Maximum duration of the last frame. 42 static base::TimeDelta kMaxLastFrameDuration(); 43 44 // |decoders| contains the VideoDecoders to use when initializing. 45 // 46 // |paint_cb| is executed on the video frame timing thread whenever a new 47 // frame is available for painting. 48 // 49 // |set_opaque_cb| is executed when the renderer is initialized to inform 50 // the player whether the decoded output will be opaque or not. 51 // 52 // Implementors should avoid doing any sort of heavy work in this method and 53 // instead post a task to a common/worker thread to handle rendering. Slowing 54 // down the video thread may result in losing synchronization with audio. 55 // 56 // Setting |drop_frames_| to true causes the renderer to drop expired frames. 57 VideoRendererBase(const scoped_refptr<base::MessageLoopProxy>& message_loop, 58 ScopedVector<VideoDecoder> decoders, 59 const SetDecryptorReadyCB& set_decryptor_ready_cb, 60 const PaintCB& paint_cb, 61 const SetOpaqueCB& set_opaque_cb, 62 bool drop_frames); 63 virtual ~VideoRendererBase(); 64 65 // VideoRenderer implementation. 66 virtual void Initialize(DemuxerStream* stream, 67 const PipelineStatusCB& init_cb, 68 const StatisticsCB& statistics_cb, 69 const TimeCB& max_time_cb, 70 const NaturalSizeChangedCB& size_changed_cb, 71 const base::Closure& ended_cb, 72 const PipelineStatusCB& error_cb, 73 const TimeDeltaCB& get_time_cb, 74 const TimeDeltaCB& get_duration_cb) OVERRIDE; 75 virtual void Play(const base::Closure& callback) OVERRIDE; 76 virtual void Pause(const base::Closure& callback) OVERRIDE; 77 virtual void Flush(const base::Closure& callback) OVERRIDE; 78 virtual void Preroll(base::TimeDelta time, 79 const PipelineStatusCB& cb) OVERRIDE; 80 virtual void Stop(const base::Closure& callback) OVERRIDE; 81 virtual void SetPlaybackRate(float playback_rate) OVERRIDE; 82 83 // PlatformThread::Delegate implementation. 84 virtual void ThreadMain() OVERRIDE; 85 86 private: 87 // Callback for |video_frame_stream_| initialization. 88 void OnVideoFrameStreamInitialized(bool success, bool has_alpha); 89 90 // Callback for |video_frame_stream_| to deliver decoded video frames and 91 // report video decoding status. 92 void FrameReady(VideoFrameStream::Status status, 93 const scoped_refptr<VideoFrame>& frame); 94 95 // Helper method for adding a frame to |ready_frames_|. 96 void AddReadyFrame_Locked(const scoped_refptr<VideoFrame>& frame); 97 98 // Helper method that schedules an asynchronous read from the 99 // |video_frame_stream_| as long as there isn't a pending read and we have 100 // capacity. 101 void AttemptRead(); 102 void AttemptRead_Locked(); 103 104 // Called when VideoFrameStream::Reset() completes. 105 void OnVideoFrameStreamResetDone(); 106 107 // Calculates the duration to sleep for based on |last_timestamp_|, 108 // the next frame timestamp (may be NULL), and the provided playback rate. 109 // 110 // We don't use |playback_rate_| to avoid locking. 111 base::TimeDelta CalculateSleepDuration( 112 const scoped_refptr<VideoFrame>& next_frame, 113 float playback_rate); 114 115 // Helper function that flushes the buffers when a Stop() or error occurs. 116 void DoStopOrError_Locked(); 117 118 // Runs |paint_cb_| with the next frame from |ready_frames_|, updating 119 // |last_natural_size_| and running |size_changed_cb_| if the natural size 120 // changes. 121 // 122 // A read is scheduled to replace the frame. 123 void PaintNextReadyFrame_Locked(); 124 125 // Drops the next frame from |ready_frames_| and runs |statistics_cb_|. 126 // 127 // A read is scheduled to replace the frame. 128 void DropNextReadyFrame_Locked(); 129 130 void TransitionToPrerolled_Locked(); 131 132 scoped_refptr<base::MessageLoopProxy> message_loop_; 133 base::WeakPtrFactory<VideoRendererBase> weak_factory_; 134 base::WeakPtr<VideoRendererBase> weak_this_; 135 136 // Used for accessing data members. 137 base::Lock lock_; 138 139 // Provides video frames to VideoRendererBase. 140 VideoFrameStream video_frame_stream_; 141 142 // Queue of incoming frames yet to be painted. 143 typedef std::deque<scoped_refptr<VideoFrame> > VideoFrameQueue; 144 VideoFrameQueue ready_frames_; 145 146 // Keeps track of whether we received the end of stream buffer. 147 bool received_end_of_stream_; 148 149 // Used to signal |thread_| as frames are added to |frames_|. Rule of thumb: 150 // always check |state_| to see if it was set to STOPPED after waking up! 151 base::ConditionVariable frame_available_; 152 153 // State transition Diagram of this class: 154 // [kUninitialized] -------> [kError] 155 // | 156 // | Initialize() 157 // [kInitializing] 158 // | 159 // V 160 // +------[kFlushed]<---------------OnVideoFrameStreamResetDone() 161 // | | Preroll() or upon ^ 162 // | V got first frame [kFlushing] 163 // | [kPrerolling] ^ 164 // | | | Flush() 165 // | V Got enough frames | 166 // | [kPrerolled]---------------------->[kPaused] 167 // | | Pause() ^ 168 // | V Play() | 169 // | [kPlaying]---------------------------| 170 // | | Pause() ^ 171 // | V Receive EOF frame. | Pause() 172 // | [kEnded]-----------------------------+ 173 // | ^ 174 // | | 175 // +-----> [kStopped] [Any state other than] 176 // [kUninitialized/kError] 177 178 // Simple state tracking variable. 179 enum State { 180 kUninitialized, 181 kInitializing, 182 kPrerolled, 183 kPaused, 184 kFlushing, 185 kFlushed, 186 kPrerolling, 187 kPlaying, 188 kEnded, 189 kStopped, 190 kError, 191 }; 192 State state_; 193 194 // Video thread handle. 195 base::PlatformThreadHandle thread_; 196 197 // Keep track of the outstanding read on the VideoFrameStream. Flushing can 198 // only complete once the read has completed. 199 bool pending_read_; 200 201 bool drop_frames_; 202 203 float playback_rate_; 204 205 // Playback operation callbacks. 206 base::Closure flush_cb_; 207 PipelineStatusCB preroll_cb_; 208 209 // Event callbacks. 210 PipelineStatusCB init_cb_; 211 StatisticsCB statistics_cb_; 212 TimeCB max_time_cb_; 213 NaturalSizeChangedCB size_changed_cb_; 214 base::Closure ended_cb_; 215 PipelineStatusCB error_cb_; 216 TimeDeltaCB get_time_cb_; 217 TimeDeltaCB get_duration_cb_; 218 219 base::TimeDelta preroll_timestamp_; 220 221 // Embedder callback for notifying a new frame is available for painting. 222 PaintCB paint_cb_; 223 224 // Callback to execute to inform the player if the decoded output is opaque. 225 SetOpaqueCB set_opaque_cb_; 226 227 // The last natural size |size_changed_cb_| was called with. 228 // 229 // TODO(scherkus): WebMediaPlayerImpl should track this instead of plumbing 230 // this through Pipeline. The one tricky bit might be guaranteeing we deliver 231 // the size information before we reach HAVE_METADATA. 232 gfx::Size last_natural_size_; 233 234 // The timestamp of the last frame removed from the |ready_frames_| queue, 235 // either for calling |paint_cb_| or for dropping. Set to kNoTimestamp() 236 // during flushing. 237 base::TimeDelta last_timestamp_; 238 239 DISALLOW_COPY_AND_ASSIGN(VideoRendererBase); 240 }; 241 242 } // namespace media 243 244 #endif // MEDIA_FILTERS_VIDEO_RENDERER_BASE_H_ 245