OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef MEDIA_FILTERS_VIDEO_RENDERER_BASE_H_ | 5 #ifndef MEDIA_FILTERS_VIDEO_RENDERER_BASE_H_ |
6 #define MEDIA_FILTERS_VIDEO_RENDERER_BASE_H_ | 6 #define MEDIA_FILTERS_VIDEO_RENDERER_BASE_H_ |
7 | 7 |
8 #include <deque> | 8 #include <deque> |
9 | 9 |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
(...skipping 18 matching lines...) Expand all Loading... | |
29 | 29 |
30 // VideoRendererBase creates its own thread for the sole purpose of timing frame | 30 // VideoRendererBase creates its own thread for the sole purpose of timing frame |
31 // presentation. It handles reading from the decoder and stores the results in | 31 // presentation. It handles reading from the decoder and stores the results in |
32 // a queue of decoded frames and executing a callback when a frame is ready for | 32 // a queue of decoded frames and executing a callback when a frame is ready for |
33 // rendering. | 33 // rendering. |
34 class MEDIA_EXPORT VideoRendererBase | 34 class MEDIA_EXPORT VideoRendererBase |
35 : public VideoRenderer, | 35 : public VideoRenderer, |
36 public base::PlatformThread::Delegate { | 36 public base::PlatformThread::Delegate { |
37 public: | 37 public: |
38 typedef base::Callback<void(bool)> SetOpaqueCB; | 38 typedef base::Callback<void(bool)> SetOpaqueCB; |
39 typedef base::Callback<void(const scoped_refptr<VideoFrame>&)> PaintCB; | |
39 | 40 |
40 // Maximum duration of the last frame. | 41 // Maximum duration of the last frame. |
41 static base::TimeDelta kMaxLastFrameDuration(); | 42 static base::TimeDelta kMaxLastFrameDuration(); |
42 | 43 |
43 // |paint_cb| is executed on the video frame timing thread whenever a new | 44 // |paint_cb| is executed on the video frame timing thread whenever a new |
44 // frame is available for painting via GetCurrentFrame(). | 45 // frame is available for painting. |
45 // | 46 // |
46 // |set_opaque_cb| is executed when the renderer is initialized to inform | 47 // |set_opaque_cb| is executed when the renderer is initialized to inform |
47 // the player whether the decoder's output will be opaque or not. | 48 // the player whether the decoder's output will be opaque or not. |
48 // | 49 // |
49 // Implementors should avoid doing any sort of heavy work in this method and | 50 // Implementors should avoid doing any sort of heavy work in this method and |
50 // instead post a task to a common/worker thread to handle rendering. Slowing | 51 // instead post a task to a common/worker thread to handle rendering. Slowing |
51 // down the video thread may result in losing synchronization with audio. | 52 // down the video thread may result in losing synchronization with audio. |
52 // | 53 // |
53 // Setting |drop_frames_| to true causes the renderer to drop expired frames. | 54 // Setting |drop_frames_| to true causes the renderer to drop expired frames. |
54 // | 55 // |
55 // TODO(scherkus): pass the VideoFrame* to this callback and remove | 56 // TODO(scherkus): pass the VideoFrame* to this callback and remove |
56 // Get/PutCurrentFrame() http://crbug.com/108435 | 57 // Get/PutCurrentFrame() http://crbug.com/108435 |
57 VideoRendererBase(const scoped_refptr<base::MessageLoopProxy>& message_loop, | 58 VideoRendererBase(const scoped_refptr<base::MessageLoopProxy>& message_loop, |
58 const SetDecryptorReadyCB& set_decryptor_ready_cb, | 59 const SetDecryptorReadyCB& set_decryptor_ready_cb, |
59 const base::Closure& paint_cb, | 60 const PaintCB& paint_cb, |
60 const SetOpaqueCB& set_opaque_cb, | 61 const SetOpaqueCB& set_opaque_cb, |
61 bool drop_frames); | 62 bool drop_frames); |
62 | 63 |
63 // VideoRenderer implementation. | 64 // VideoRenderer implementation. |
64 virtual void Initialize(const scoped_refptr<DemuxerStream>& stream, | 65 virtual void Initialize(const scoped_refptr<DemuxerStream>& stream, |
65 const VideoDecoderList& decoders, | 66 const VideoDecoderList& decoders, |
66 const PipelineStatusCB& init_cb, | 67 const PipelineStatusCB& init_cb, |
67 const StatisticsCB& statistics_cb, | 68 const StatisticsCB& statistics_cb, |
68 const TimeCB& max_time_cb, | 69 const TimeCB& max_time_cb, |
69 const NaturalSizeChangedCB& size_changed_cb, | 70 const NaturalSizeChangedCB& size_changed_cb, |
70 const base::Closure& ended_cb, | 71 const base::Closure& ended_cb, |
71 const PipelineStatusCB& error_cb, | 72 const PipelineStatusCB& error_cb, |
72 const TimeDeltaCB& get_time_cb, | 73 const TimeDeltaCB& get_time_cb, |
73 const TimeDeltaCB& get_duration_cb) OVERRIDE; | 74 const TimeDeltaCB& get_duration_cb) OVERRIDE; |
74 virtual void Play(const base::Closure& callback) OVERRIDE; | 75 virtual void Play(const base::Closure& callback) OVERRIDE; |
75 virtual void Pause(const base::Closure& callback) OVERRIDE; | 76 virtual void Pause(const base::Closure& callback) OVERRIDE; |
76 virtual void Flush(const base::Closure& callback) OVERRIDE; | 77 virtual void Flush(const base::Closure& callback) OVERRIDE; |
77 virtual void Preroll(base::TimeDelta time, | 78 virtual void Preroll(base::TimeDelta time, |
78 const PipelineStatusCB& cb) OVERRIDE; | 79 const PipelineStatusCB& cb) OVERRIDE; |
79 virtual void Stop(const base::Closure& callback) OVERRIDE; | 80 virtual void Stop(const base::Closure& callback) OVERRIDE; |
80 virtual void SetPlaybackRate(float playback_rate) OVERRIDE; | 81 virtual void SetPlaybackRate(float playback_rate) OVERRIDE; |
81 | 82 |
82 // PlatformThread::Delegate implementation. | 83 // PlatformThread::Delegate implementation. |
83 virtual void ThreadMain() OVERRIDE; | 84 virtual void ThreadMain() OVERRIDE; |
84 | 85 |
85 // Clients of this class (painter/compositor) should use GetCurrentFrame() | |
86 // obtain ownership of VideoFrame, it should always relinquish the ownership | |
87 // by use PutCurrentFrame(). Current frame is not guaranteed to be non-NULL. | |
88 // It expects clients to use color-fill the background if current frame | |
89 // is NULL. This could happen before pipeline is pre-rolled or during | |
90 // pause/flush/preroll. | |
91 void GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out); | |
92 void PutCurrentFrame(scoped_refptr<VideoFrame> frame); | |
93 | |
94 protected: | 86 protected: |
95 virtual ~VideoRendererBase(); | 87 virtual ~VideoRendererBase(); |
96 | 88 |
97 private: | 89 private: |
98 // Called when |decoder_selector_| selected the |selected_decoder|. | 90 // Called when |decoder_selector_| selected the |selected_decoder|. |
99 // |decrypting_demuxer_stream| was also populated if a DecryptingDemuxerStream | 91 // |decrypting_demuxer_stream| was also populated if a DecryptingDemuxerStream |
100 // created to help decrypt the encrypted stream. | 92 // created to help decrypt the encrypted stream. |
101 // Note: |decoder_selector| is passed here to keep the VideoDecoderSelector | 93 // Note: |decoder_selector| is passed here to keep the VideoDecoderSelector |
102 // alive until OnDecoderSelected() finishes. | 94 // alive until OnDecoderSelected() finishes. |
103 void OnDecoderSelected( | 95 void OnDecoderSelected( |
(...skipping 13 matching lines...) Expand all Loading... | |
117 // as there isn't a pending read and we have capacity. | 109 // as there isn't a pending read and we have capacity. |
118 void AttemptRead(); | 110 void AttemptRead(); |
119 void AttemptRead_Locked(); | 111 void AttemptRead_Locked(); |
120 | 112 |
121 // Called when VideoDecoder::Reset() completes. | 113 // Called when VideoDecoder::Reset() completes. |
122 void OnDecoderResetDone(); | 114 void OnDecoderResetDone(); |
123 | 115 |
124 // Attempts to complete flushing and transition into the flushed state. | 116 // Attempts to complete flushing and transition into the flushed state. |
125 void AttemptFlush_Locked(); | 117 void AttemptFlush_Locked(); |
126 | 118 |
127 // Calculates the duration to sleep for based on |current_frame_|'s timestamp, | 119 // Calculates the duration to sleep for based on |last_timestamp_|, |
128 // the next frame timestamp (may be NULL), and the provided playback rate. | 120 // the next frame timestamp (may be NULL), and the provided playback rate. |
129 // | 121 // |
130 // We don't use |playback_rate_| to avoid locking. | 122 // We don't use |playback_rate_| to avoid locking. |
131 base::TimeDelta CalculateSleepDuration( | 123 base::TimeDelta CalculateSleepDuration( |
132 const scoped_refptr<VideoFrame>& next_frame, | 124 const scoped_refptr<VideoFrame>& next_frame, |
133 float playback_rate); | 125 float playback_rate); |
134 | 126 |
135 // Helper function that flushes the buffers when a Stop() or error occurs. | 127 // Helper function that flushes the buffers when a Stop() or error occurs. |
136 void DoStopOrError_Locked(); | 128 void DoStopOrError_Locked(); |
137 | 129 |
138 // Return the number of frames currently held by this class. | 130 // Return the number of frames currently held by this class. |
139 int NumFrames_Locked() const; | 131 int NumFrames_Locked() const; |
140 | 132 |
141 // Updates |current_frame_| to the next frame on |ready_frames_| and calls | 133 // Runs |paint_cb_| with the next frame from |ready_frames_|, updating |
142 // |size_changed_cb_| if the natural size changes. | 134 // |last_natural_size_| and running |size_changed_cb_| if the natural size |
143 void SetCurrentFrameToNextReadyFrame(); | 135 // changes. |
136 void PaintWithNextReadyFrame(); | |
144 | 137 |
145 void ResetDecoder(); | 138 void ResetDecoder(); |
146 void StopDecoder(const base::Closure& callback); | 139 void StopDecoder(const base::Closure& callback); |
147 | 140 |
148 // Pops the front of |decoders|, assigns it to |decoder_| and then | 141 // Pops the front of |decoders|, assigns it to |decoder_| and then |
149 // calls initialize on the new decoder. | 142 // calls initialize on the new decoder. |
150 void InitializeNextDecoder(const scoped_refptr<DemuxerStream>& demuxer_stream, | 143 void InitializeNextDecoder(const scoped_refptr<DemuxerStream>& demuxer_stream, |
151 scoped_ptr<VideoDecoderList> decoders); | 144 scoped_ptr<VideoDecoderList> decoders); |
152 | 145 |
153 // Called when |decoder_| initialization completes. | 146 // Called when |decoder_| initialization completes. |
154 // |demuxer_stream| & |decoders| are used if initialization failed and | 147 // |demuxer_stream| & |decoders| are used if initialization failed and |
155 // InitializeNextDecoder() needs to be called again. | 148 // InitializeNextDecoder() needs to be called again. |
156 void OnDecoderInitDone(const scoped_refptr<DemuxerStream>& demuxer_stream, | 149 void OnDecoderInitDone(const scoped_refptr<DemuxerStream>& demuxer_stream, |
157 scoped_ptr<VideoDecoderList> decoders, | 150 scoped_ptr<VideoDecoderList> decoders, |
158 PipelineStatus status); | 151 PipelineStatus status); |
159 | 152 |
160 scoped_refptr<base::MessageLoopProxy> message_loop_; | 153 scoped_refptr<base::MessageLoopProxy> message_loop_; |
161 | 154 |
162 // Used for accessing data members. | 155 // Used for accessing data members. |
163 base::Lock lock_; | 156 base::Lock lock_; |
164 | 157 |
165 SetDecryptorReadyCB set_decryptor_ready_cb_; | 158 SetDecryptorReadyCB set_decryptor_ready_cb_; |
166 | 159 |
167 // These two will be set by VideoDecoderSelector::SelectVideoDecoder(). | 160 // These two will be set by VideoDecoderSelector::SelectVideoDecoder(). |
168 scoped_refptr<VideoDecoder> decoder_; | 161 scoped_refptr<VideoDecoder> decoder_; |
169 scoped_refptr<DecryptingDemuxerStream> decrypting_demuxer_stream_; | 162 scoped_refptr<DecryptingDemuxerStream> decrypting_demuxer_stream_; |
170 | 163 |
171 // Queue of incoming frames as well as the current frame since the last time | 164 // Queue of incoming frames yet to be painted. |
172 // OnFrameAvailable() was called. | |
173 typedef std::deque<scoped_refptr<VideoFrame> > VideoFrameQueue; | 165 typedef std::deque<scoped_refptr<VideoFrame> > VideoFrameQueue; |
174 VideoFrameQueue ready_frames_; | 166 VideoFrameQueue ready_frames_; |
175 | 167 |
176 // The current frame available to subclasses for rendering via | |
177 // GetCurrentFrame(). |current_frame_| can only be altered when | |
178 // |pending_paint_| is false. | |
179 scoped_refptr<VideoFrame> current_frame_; | |
180 | |
181 // The previous |current_frame_| and is returned via GetCurrentFrame() in the | |
182 // situation where all frames were deallocated (i.e., during a flush). | |
183 // | |
184 // TODO(scherkus): remove this after getting rid of Get/PutCurrentFrame() in | |
185 // favour of passing ownership of the current frame to the renderer via | |
186 // callback. | |
187 scoped_refptr<VideoFrame> last_available_frame_; | |
188 | |
189 // Used to signal |thread_| as frames are added to |frames_|. Rule of thumb: | 168 // Used to signal |thread_| as frames are added to |frames_|. Rule of thumb: |
190 // always check |state_| to see if it was set to STOPPED after waking up! | 169 // always check |state_| to see if it was set to STOPPED after waking up! |
191 base::ConditionVariable frame_available_; | 170 base::ConditionVariable frame_available_; |
192 | 171 |
193 // State transition Diagram of this class: | 172 // State transition Diagram of this class: |
194 // [kUninitialized] -------> [kError] | 173 // [kUninitialized] -------> [kError] |
195 // | | 174 // | |
196 // | Initialize() | 175 // | Initialize() |
197 // V All frames returned | 176 // V All frames returned |
198 // +------[kFlushed]<-----[kFlushing]<--- OnDecoderResetDone() | 177 // +------[kFlushed]<-----[kFlushing]<--- OnDecoderResetDone() |
(...skipping 26 matching lines...) Expand all Loading... | |
225 kPlaying, | 204 kPlaying, |
226 kEnded, | 205 kEnded, |
227 kStopped, | 206 kStopped, |
228 kError, | 207 kError, |
229 }; | 208 }; |
230 State state_; | 209 State state_; |
231 | 210 |
232 // Video thread handle. | 211 // Video thread handle. |
233 base::PlatformThreadHandle thread_; | 212 base::PlatformThreadHandle thread_; |
234 | 213 |
235 // Keep track of various pending operations: | 214 // Keep track of outstanding reads on the video decoder. Flushing can only |
236 // - |pending_read_| is true when there's an active video decoding request. | 215 // complete once reads have completed. |
237 // - |pending_paint_| is true when |current_frame_| is currently being | |
238 // accessed by the subclass. | |
239 // - |pending_paint_with_last_available_| is true when | |
240 // |last_available_frame_| is currently being accessed by the subclass. | |
241 // | |
242 // Flushing cannot complete until both |pending_read_| and |pending_paint_| | |
243 // are false. | |
244 bool pending_read_; | 216 bool pending_read_; |
245 bool pending_paint_; | |
246 bool pending_paint_with_last_available_; | |
247 | 217 |
248 bool drop_frames_; | 218 bool drop_frames_; |
249 | 219 |
250 float playback_rate_; | 220 float playback_rate_; |
251 | 221 |
252 // Playback operation callbacks. | 222 // Playback operation callbacks. |
253 base::Closure flush_cb_; | 223 base::Closure flush_cb_; |
254 PipelineStatusCB preroll_cb_; | 224 PipelineStatusCB preroll_cb_; |
255 | 225 |
256 // Event callbacks. | 226 // Event callbacks. |
257 PipelineStatusCB init_cb_; | 227 PipelineStatusCB init_cb_; |
258 StatisticsCB statistics_cb_; | 228 StatisticsCB statistics_cb_; |
259 TimeCB max_time_cb_; | 229 TimeCB max_time_cb_; |
260 NaturalSizeChangedCB size_changed_cb_; | 230 NaturalSizeChangedCB size_changed_cb_; |
261 base::Closure ended_cb_; | 231 base::Closure ended_cb_; |
262 PipelineStatusCB error_cb_; | 232 PipelineStatusCB error_cb_; |
263 TimeDeltaCB get_time_cb_; | 233 TimeDeltaCB get_time_cb_; |
264 TimeDeltaCB get_duration_cb_; | 234 TimeDeltaCB get_duration_cb_; |
265 | 235 |
266 base::TimeDelta preroll_timestamp_; | 236 base::TimeDelta preroll_timestamp_; |
267 | 237 |
268 // Delayed frame used during kPrerolling to determine whether | 238 // Delayed frame used during kPrerolling to determine whether |
269 // |preroll_timestamp_| is between this frame and the next one. | 239 // |preroll_timestamp_| is between this frame and the next one. |
270 scoped_refptr<VideoFrame> prerolling_delayed_frame_; | 240 scoped_refptr<VideoFrame> prerolling_delayed_frame_; |
271 | 241 |
272 // Embedder callback for notifying a new frame is available for painting. | 242 // Embedder callback for notifying a new frame is available for painting. |
273 base::Closure paint_cb_; | 243 PaintCB paint_cb_; |
274 | 244 |
275 // Callback to execute to inform the player if the video decoder's output is | 245 // Callback to execute to inform the player if the video decoder's output is |
276 // opaque. | 246 // opaque. |
277 SetOpaqueCB set_opaque_cb_; | 247 SetOpaqueCB set_opaque_cb_; |
278 | 248 |
279 // The last natural size |size_changed_cb_| was called with. | 249 // The last natural size |size_changed_cb_| was called with. |
250 // | |
251 // TODO(scherkus): WebMediaPlayerImpl should track this instead of plumbing | |
252 // this through Pipeline. | |
scherkus (not reviewing)
2013/01/31 17:54:05
actually ... this might not be true
I wonder if t
acolwell GONE FROM CHROMIUM
2013/02/01 00:24:34
I think it depends on whether we want to bubble fr
scherkus (not reviewing)
2013/02/01 22:45:25
Yeah I had the same thought -- updated TODO w/ pot
| |
280 gfx::Size last_natural_size_; | 253 gfx::Size last_natural_size_; |
281 | 254 |
255 // The last timestamp of the frame |paint_cb_| was called with. Set to | |
acolwell GONE FROM CHROMIUM
2013/02/01 00:24:34
nit:s/The last timestamp of the frame/The timestam
scherkus (not reviewing)
2013/02/01 22:45:25
Done.
| |
256 // kNoTimestamp() during flushing. | |
257 base::TimeDelta last_timestamp_; | |
258 | |
282 DISALLOW_COPY_AND_ASSIGN(VideoRendererBase); | 259 DISALLOW_COPY_AND_ASSIGN(VideoRendererBase); |
283 }; | 260 }; |
284 | 261 |
285 } // namespace media | 262 } // namespace media |
286 | 263 |
287 #endif // MEDIA_FILTERS_VIDEO_RENDERER_BASE_H_ | 264 #endif // MEDIA_FILTERS_VIDEO_RENDERER_BASE_H_ |
OLD | NEW |