OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // A base class that provides the plumbing for a decoder filters. | 5 // A base class that provides the plumbing for a decoder filters. |
6 | 6 |
7 #ifndef MEDIA_FILTERS_DECODER_BASE_H_ | 7 #ifndef MEDIA_FILTERS_DECODER_BASE_H_ |
8 #define MEDIA_FILTERS_DECODER_BASE_H_ | 8 #define MEDIA_FILTERS_DECODER_BASE_H_ |
9 | 9 |
10 #include <deque> | 10 #include <deque> |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 DCHECK_EQ(MessageLoop::current(), this->message_loop()); | 201 DCHECK_EQ(MessageLoop::current(), this->message_loop()); |
202 | 202 |
203 // TODO(scherkus): should reply with a null operation (empty buffer). | 203 // TODO(scherkus): should reply with a null operation (empty buffer). |
204 if (IsStopped()) { | 204 if (IsStopped()) { |
205 delete read_callback; | 205 delete read_callback; |
206 return; | 206 return; |
207 } | 207 } |
208 | 208 |
209 // Enqueue the callback and attempt to fulfill it immediately. | 209 // Enqueue the callback and attempt to fulfill it immediately. |
210 read_queue_.push_back(read_callback); | 210 read_queue_.push_back(read_callback); |
211 FulfillPendingRead(); | 211 if (FulfillPendingRead()) |
| 212 return; |
212 | 213 |
213 // Issue reads as necessary. | 214 // Since we can't fulfill a read request now then submit a read |
214 while (pending_reads_ < read_queue_.size()) { | 215 // request to the demuxer stream. |
215 demuxer_stream_->Read(NewCallback(this, &DecoderBase::OnReadComplete)); | 216 demuxer_stream_->Read(NewCallback(this, &DecoderBase::OnReadComplete)); |
216 ++pending_reads_; | 217 ++pending_reads_; |
217 } | |
218 } | 218 } |
219 | 219 |
220 void ReadCompleteTask(scoped_refptr<Buffer> buffer) { | 220 void ReadCompleteTask(scoped_refptr<Buffer> buffer) { |
221 DCHECK_EQ(MessageLoop::current(), this->message_loop()); | 221 DCHECK_EQ(MessageLoop::current(), this->message_loop()); |
222 DCHECK_GT(pending_reads_, 0u); | 222 DCHECK_GT(pending_reads_, 0u); |
223 --pending_reads_; | 223 --pending_reads_; |
224 if (IsStopped()) { | 224 if (IsStopped()) { |
225 return; | 225 return; |
226 } | 226 } |
227 | 227 |
228 // TODO(scherkus): remove this when we're less paranoid about our seeking | 228 // TODO(scherkus): remove this when we're less paranoid about our seeking |
229 // invariants. | 229 // invariants. |
230 if (buffer->IsDiscontinuous()) { | 230 if (buffer->IsDiscontinuous()) { |
231 DCHECK(expecting_discontinuous_); | 231 DCHECK(expecting_discontinuous_); |
232 expecting_discontinuous_ = false; | 232 expecting_discontinuous_ = false; |
233 } | 233 } |
234 | 234 |
235 // Decode the frame right away. | 235 // Decode the frame right away. |
236 DoDecode(buffer, NewRunnableMethod(this, &DecoderBase::OnDecodeComplete)); | 236 DoDecode(buffer, NewRunnableMethod(this, &DecoderBase::OnDecodeComplete)); |
237 } | 237 } |
238 | 238 |
239 void OnDecodeComplete() { | 239 void OnDecodeComplete() { |
240 // Attempt to fulfill a pending read callback and schedule additional reads | 240 // Attempt to fulfill a pending read callback and schedule additional reads |
241 // if necessary. | 241 // if necessary. |
242 FulfillPendingRead(); | 242 bool fulfilled = FulfillPendingRead(); |
243 | 243 |
244 // Issue reads as necessary. | 244 // Issue reads as necessary. |
245 // | 245 // |
246 // Note that it's possible for us to decode but not produce a frame, in | 246 // Note that it's possible for us to decode but not produce a frame, in |
247 // which case |pending_reads_| will remain less than |read_queue_| so we | 247 // which case |pending_reads_| will remain less than |read_queue_| so we |
248 // need to schedule an additional read. | 248 // need to schedule an additional read. |
249 // TODO(hclam): Enable this line again to make sure we don't break the | 249 DCHECK_LE(pending_reads_, read_queue_.size()); |
250 // flow control. (BUG=32947) | 250 if (!fulfilled) { |
251 // DCHECK_LE(pending_reads_, read_queue_.size()); | 251 DCHECK_LT(pending_reads_, read_queue_.size()); |
252 while (pending_reads_ < read_queue_.size()) { | |
253 demuxer_stream_->Read(NewCallback(this, &DecoderBase::OnReadComplete)); | 252 demuxer_stream_->Read(NewCallback(this, &DecoderBase::OnReadComplete)); |
254 ++pending_reads_; | 253 ++pending_reads_; |
255 } | 254 } |
256 } | 255 } |
257 | 256 |
258 // Attempts to fulfill a single pending read by dequeuing a buffer and read | 257 // Attempts to fulfill a single pending read by dequeuing a buffer and read |
259 // callback pair and executing the callback. | 258 // callback pair and executing the callback. |
260 void FulfillPendingRead() { | 259 // |
| 260 // Return true if one read request is fulfilled. |
| 261 bool FulfillPendingRead() { |
261 DCHECK_EQ(MessageLoop::current(), this->message_loop()); | 262 DCHECK_EQ(MessageLoop::current(), this->message_loop()); |
262 if (read_queue_.empty() || result_queue_.empty()) { | 263 if (read_queue_.empty() || result_queue_.empty()) { |
263 return; | 264 return false; |
264 } | 265 } |
265 | 266 |
266 // Dequeue a frame and read callback pair. | 267 // Dequeue a frame and read callback pair. |
267 scoped_refptr<Output> output = result_queue_.front(); | 268 scoped_refptr<Output> output = result_queue_.front(); |
268 scoped_ptr<ReadCallback> read_callback(read_queue_.front()); | 269 scoped_ptr<ReadCallback> read_callback(read_queue_.front()); |
269 result_queue_.pop_front(); | 270 result_queue_.pop_front(); |
270 read_queue_.pop_front(); | 271 read_queue_.pop_front(); |
271 | 272 |
272 // Execute the callback! | 273 // Execute the callback! |
273 read_callback->Run(output); | 274 read_callback->Run(output); |
| 275 return true; |
274 } | 276 } |
275 | 277 |
276 // Tracks the number of asynchronous reads issued to |demuxer_stream_|. | 278 // Tracks the number of asynchronous reads issued to |demuxer_stream_|. |
277 // Using size_t since it is always compared against deque::size(). | 279 // Using size_t since it is always compared against deque::size(). |
278 size_t pending_reads_; | 280 size_t pending_reads_; |
279 | 281 |
280 // A flag used for debugging that we expect our next read to be discontinuous. | 282 // A flag used for debugging that we expect our next read to be discontinuous. |
281 bool expecting_discontinuous_; | 283 bool expecting_discontinuous_; |
282 | 284 |
283 // Pointer to the demuxer stream that will feed us compressed buffers. | 285 // Pointer to the demuxer stream that will feed us compressed buffers. |
(...skipping 24 matching lines...) Expand all Loading... |
308 kStopped, | 310 kStopped, |
309 }; | 311 }; |
310 State state_; | 312 State state_; |
311 | 313 |
312 DISALLOW_COPY_AND_ASSIGN(DecoderBase); | 314 DISALLOW_COPY_AND_ASSIGN(DecoderBase); |
313 }; | 315 }; |
314 | 316 |
315 } // namespace media | 317 } // namespace media |
316 | 318 |
317 #endif // MEDIA_FILTERS_DECODER_BASE_H_ | 319 #endif // MEDIA_FILTERS_DECODER_BASE_H_ |
OLD | NEW |