| 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 |