OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // VideoRendererBase creates its own thread for the sole purpose of timing frame | 5 // VideoRendererBase creates its own thread for the sole purpose of timing frame |
6 // presentation. It handles reading from the decoder and stores the results in | 6 // presentation. It handles reading from the decoder and stores the results in |
7 // a queue of decoded frames, calling OnFrameAvailable() on subclasses to notify | 7 // a queue of decoded frames, calling OnFrameAvailable() on subclasses to notify |
8 // when a frame is ready to display. | 8 // when a frame is ready to display. |
9 // | 9 // |
10 // The media filter methods Initialize(), Stop(), SetPlaybackRate() and Seek() | 10 // The media filter methods Initialize(), Stop(), SetPlaybackRate() and Seek() |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 // | 81 // |
82 // Implementors should avoid doing any sort of heavy work in this method and | 82 // Implementors should avoid doing any sort of heavy work in this method and |
83 // instead post a task to a common/worker thread to handle rendering. Slowing | 83 // instead post a task to a common/worker thread to handle rendering. Slowing |
84 // down the video thread may result in losing synchronization with audio. | 84 // down the video thread may result in losing synchronization with audio. |
85 // | 85 // |
86 // IMPORTANT: This method is called on the video renderer thread, which is | 86 // IMPORTANT: This method is called on the video renderer thread, which is |
87 // different from the thread OnInitialize(), OnStop(), and the rest of the | 87 // different from the thread OnInitialize(), OnStop(), and the rest of the |
88 // class executes on. | 88 // class executes on. |
89 virtual void OnFrameAvailable() = 0; | 89 virtual void OnFrameAvailable() = 0; |
90 | 90 |
91 void ReadInput(scoped_refptr<VideoFrame> frame); | 91 private: |
| 92 // Callback from the video decoder delivering decoded video frames. |
| 93 void FrameReady(scoped_refptr<VideoFrame> frame); |
92 | 94 |
93 private: | 95 // Helper method that schedules an asynchronous read from the decoder as long |
94 // Callback from video decoder to deliver decoded video frames and decrements | 96 // as there isn't a pending read and we have capacity. |
95 // |pending_reads_|. | 97 void AttemptRead_Locked(); |
96 void ConsumeVideoFrame(scoped_refptr<VideoFrame> frame); | |
97 | 98 |
98 // Helper method that schedules an asynchronous read from the decoder and | 99 // Attempts to complete flushing and transition into the flushed state. |
99 // increments |pending_reads_|. | 100 void AttemptFlush_Locked(); |
100 // | |
101 // Safe to call from any thread. | |
102 void ScheduleRead_Locked(); | |
103 | |
104 // Helper function to finished "flush" operation | |
105 void OnFlushDone_Locked(); | |
106 | |
107 // Helper method that flushes all video frame in "ready queue" including | |
108 // current frame into "done queue". | |
109 void FlushBuffers_Locked(); | |
110 | 101 |
111 // Calculates the duration to sleep for based on |current_frame_|'s timestamp, | 102 // Calculates the duration to sleep for based on |current_frame_|'s timestamp, |
112 // the next frame timestamp (may be NULL), and the provided playback rate. | 103 // the next frame timestamp (may be NULL), and the provided playback rate. |
113 // | 104 // |
114 // We don't use |playback_rate_| to avoid locking. | 105 // We don't use |playback_rate_| to avoid locking. |
115 base::TimeDelta CalculateSleepDuration(VideoFrame* next_frame, | 106 base::TimeDelta CalculateSleepDuration(VideoFrame* next_frame, |
116 float playback_rate); | 107 float playback_rate); |
117 | 108 |
118 // Safely handles entering to an error state. | 109 // Safely handles entering to an error state. |
119 void EnterErrorState_Locked(PipelineStatus status); | 110 void EnterErrorState_Locked(PipelineStatus status); |
120 | 111 |
121 // Helper function that flushes the buffers when a Stop() or error occurs. | 112 // Helper function that flushes the buffers when a Stop() or error occurs. |
122 void DoStopOrErrorFlush_Locked(); | 113 void DoStopOrError_Locked(); |
123 | 114 |
124 // Used for accessing data members. | 115 // Used for accessing data members. |
125 base::Lock lock_; | 116 base::Lock lock_; |
126 | 117 |
127 scoped_refptr<VideoDecoder> decoder_; | 118 scoped_refptr<VideoDecoder> decoder_; |
128 | 119 |
129 // Queue of incoming frames as well as the current frame since the last time | 120 // Queue of incoming frames as well as the current frame since the last time |
130 // OnFrameAvailable() was called. | 121 // OnFrameAvailable() was called. |
131 typedef std::deque< scoped_refptr<VideoFrame> > VideoFrameQueue; | 122 typedef std::deque<scoped_refptr<VideoFrame> > VideoFrameQueue; |
132 VideoFrameQueue frames_queue_ready_; | 123 VideoFrameQueue frames_queue_ready_; |
133 VideoFrameQueue frames_queue_done_; | 124 |
| 125 // The current frame available to subclasses for rendering via |
| 126 // GetCurrentFrame(). |current_frame_| can only be altered when |
| 127 // |pending_paint_| is false. |
134 scoped_refptr<VideoFrame> current_frame_; | 128 scoped_refptr<VideoFrame> current_frame_; |
| 129 |
| 130 // The previous |current_frame_| and is returned via GetCurrentFrame() in the |
| 131 // situation where all frames were deallocated (i.e., during a flush). |
| 132 // |
| 133 // TODO(scherkus): remove this after getting rid of Get/PutCurrentFrame() in |
| 134 // favour of passing ownership of the current frame to the renderer via |
| 135 // callback. |
135 scoped_refptr<VideoFrame> last_available_frame_; | 136 scoped_refptr<VideoFrame> last_available_frame_; |
136 | 137 |
137 // Used to signal |thread_| as frames are added to |frames_|. Rule of thumb: | 138 // Used to signal |thread_| as frames are added to |frames_|. Rule of thumb: |
138 // always check |state_| to see if it was set to STOPPED after waking up! | 139 // always check |state_| to see if it was set to STOPPED after waking up! |
139 base::ConditionVariable frame_available_; | 140 base::ConditionVariable frame_available_; |
140 | 141 |
141 // State transition Diagram of this class: | 142 // State transition Diagram of this class: |
142 // [kUninitialized] -------> [kError] | 143 // [kUninitialized] -------> [kError] |
143 // | | 144 // | |
144 // | Initialize() | 145 // | Initialize() |
(...skipping 30 matching lines...) Expand all Loading... |
175 kError, | 176 kError, |
176 }; | 177 }; |
177 State state_; | 178 State state_; |
178 | 179 |
179 // Video thread handle. | 180 // Video thread handle. |
180 base::PlatformThreadHandle thread_; | 181 base::PlatformThreadHandle thread_; |
181 | 182 |
182 // Previous time returned from the pipeline. | 183 // Previous time returned from the pipeline. |
183 base::TimeDelta previous_time_; | 184 base::TimeDelta previous_time_; |
184 | 185 |
185 // Keeps track of our pending buffers. We *must* have no pending reads | 186 // Keep track of various pending operations: |
186 // before executing the flush callback; We decrement it each time we receive | 187 // - |pending_read_| is true when there's an active video decoding request. |
187 // a buffer and increment it each time we send a buffer out. therefore if | 188 // - |pending_paint_| is true when |current_frame_| is currently being |
188 // decoder provides buffer, |pending_reads_| is always non-positive and if | 189 // accessed by the subclass. |
189 // renderer provides buffer, |pending_reads_| is always non-negative. | 190 // - |pending_paint_with_last_available_| is true when |
190 int pending_reads_; | 191 // |last_available_frame_| is currently being accessed by the subclass. |
| 192 // |
| 193 // Flushing cannot complete until both |pending_read_| and |pending_paint_| |
| 194 // are false. |
| 195 bool pending_read_; |
191 bool pending_paint_; | 196 bool pending_paint_; |
192 bool pending_paint_with_last_available_; | 197 bool pending_paint_with_last_available_; |
193 | 198 |
194 float playback_rate_; | 199 float playback_rate_; |
195 | 200 |
196 // Filter callbacks. | 201 // Filter callbacks. |
197 base::Closure flush_callback_; | 202 base::Closure flush_callback_; |
198 FilterStatusCB seek_cb_; | 203 FilterStatusCB seek_cb_; |
199 StatisticsCallback statistics_callback_; | 204 StatisticsCallback statistics_callback_; |
200 | 205 |
201 base::TimeDelta seek_timestamp_; | 206 base::TimeDelta seek_timestamp_; |
202 | 207 |
| 208 VideoDecoder::ReadCB read_cb_; |
| 209 |
203 DISALLOW_COPY_AND_ASSIGN(VideoRendererBase); | 210 DISALLOW_COPY_AND_ASSIGN(VideoRendererBase); |
204 }; | 211 }; |
205 | 212 |
206 } // namespace media | 213 } // namespace media |
207 | 214 |
208 #endif // MEDIA_FILTERS_VIDEO_RENDERER_BASE_H_ | 215 #endif // MEDIA_FILTERS_VIDEO_RENDERER_BASE_H_ |
OLD | NEW |