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 #include "media/filters/chunk_demuxer.h" | 5 #include "media/filters/chunk_demuxer.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 | 204 |
205 // Adds the callback to |read_cbs_| so it can be called later when we | 205 // Adds the callback to |read_cbs_| so it can be called later when we |
206 // have data. | 206 // have data. |
207 void DeferRead_Locked(const ReadCB& read_cb); | 207 void DeferRead_Locked(const ReadCB& read_cb); |
208 | 208 |
209 // Creates closures that bind ReadCBs in |read_cbs_| to data in | 209 // Creates closures that bind ReadCBs in |read_cbs_| to data in |
210 // |buffers_| and pops the callbacks & buffers from the respecive queues. | 210 // |buffers_| and pops the callbacks & buffers from the respecive queues. |
211 void CreateReadDoneClosures_Locked(ClosureQueue* closures); | 211 void CreateReadDoneClosures_Locked(ClosureQueue* closures); |
212 | 212 |
213 // Gets the value to pass to the next Read() callback. Returns true if | 213 // Gets the value to pass to the next Read() callback. Returns true if |
214 // |buffer| should be passed to the callback. False indicates that |buffer| | 214 // |status| and |buffer| should be passed to the callback. False indicates |
215 // was not set and more data is needed. | 215 // that |status| and |buffer| were not set and more data is needed. |
216 bool GetNextBuffer_Locked(scoped_refptr<StreamParserBuffer>* buffer); | 216 bool GetNextBuffer_Locked(DemuxerStream::Status* status, |
| 217 scoped_refptr<StreamParserBuffer>* buffer); |
217 | 218 |
218 // Specifies the type of the stream (must be AUDIO or VIDEO for now). | 219 // Specifies the type of the stream (must be AUDIO or VIDEO for now). |
219 Type type_; | 220 Type type_; |
220 | 221 |
221 scoped_ptr<SourceBufferStream> stream_; | 222 scoped_ptr<SourceBufferStream> stream_; |
222 | 223 |
223 mutable base::Lock lock_; | 224 mutable base::Lock lock_; |
224 State state_; | 225 State state_; |
225 ReadCBQueue read_cbs_; | 226 ReadCBQueue read_cbs_; |
226 bool end_of_stream_; | 227 bool end_of_stream_; |
(...skipping 19 matching lines...) Expand all Loading... |
246 DVLOG(1) << "StartWaitingForSeek()"; | 247 DVLOG(1) << "StartWaitingForSeek()"; |
247 ReadCBQueue read_cbs; | 248 ReadCBQueue read_cbs; |
248 { | 249 { |
249 base::AutoLock auto_lock(lock_); | 250 base::AutoLock auto_lock(lock_); |
250 ChangeState_Locked(WAITING_FOR_SEEK); | 251 ChangeState_Locked(WAITING_FOR_SEEK); |
251 end_of_stream_ = false; | 252 end_of_stream_ = false; |
252 std::swap(read_cbs_, read_cbs); | 253 std::swap(read_cbs_, read_cbs); |
253 } | 254 } |
254 | 255 |
255 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) | 256 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) |
256 it->Run(NULL); | 257 it->Run(kAborted, NULL); |
257 } | 258 } |
258 | 259 |
259 void ChunkDemuxerStream::Seek(TimeDelta time) { | 260 void ChunkDemuxerStream::Seek(TimeDelta time) { |
260 base::AutoLock auto_lock(lock_); | 261 base::AutoLock auto_lock(lock_); |
261 | 262 |
262 DCHECK(read_cbs_.empty()); | 263 DCHECK(read_cbs_.empty()); |
263 | 264 |
264 stream_->Seek(time); | 265 stream_->Seek(time); |
265 | 266 |
266 if (state_ == WAITING_FOR_SEEK) | 267 if (state_ == WAITING_FOR_SEEK) |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 ReadCBQueue read_cbs; | 379 ReadCBQueue read_cbs; |
379 { | 380 { |
380 base::AutoLock auto_lock(lock_); | 381 base::AutoLock auto_lock(lock_); |
381 ChangeState_Locked(SHUTDOWN); | 382 ChangeState_Locked(SHUTDOWN); |
382 std::swap(read_cbs_, read_cbs); | 383 std::swap(read_cbs_, read_cbs); |
383 } | 384 } |
384 | 385 |
385 // Pass end of stream buffers to all callbacks to signal that no more data | 386 // Pass end of stream buffers to all callbacks to signal that no more data |
386 // will be sent. | 387 // will be sent. |
387 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) | 388 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) |
388 it->Run(StreamParserBuffer::CreateEOSBuffer()); | 389 it->Run(DemuxerStream::kOk, StreamParserBuffer::CreateEOSBuffer()); |
389 } | 390 } |
390 | 391 |
391 // Helper function that makes sure |read_cb| runs on |message_loop|. | 392 // Helper function that makes sure |read_cb| runs on |message_loop|. |
392 static void RunOnMessageLoop(const DemuxerStream::ReadCB& read_cb, | 393 static void RunOnMessageLoop(const DemuxerStream::ReadCB& read_cb, |
393 MessageLoop* message_loop, | 394 MessageLoop* message_loop, |
| 395 DemuxerStream::Status status, |
394 const scoped_refptr<DecoderBuffer>& buffer) { | 396 const scoped_refptr<DecoderBuffer>& buffer) { |
395 if (MessageLoop::current() != message_loop) { | 397 if (MessageLoop::current() != message_loop) { |
396 message_loop->PostTask(FROM_HERE, base::Bind( | 398 message_loop->PostTask(FROM_HERE, base::Bind( |
397 &RunOnMessageLoop, read_cb, message_loop, buffer)); | 399 &RunOnMessageLoop, read_cb, message_loop, status, buffer)); |
398 return; | 400 return; |
399 } | 401 } |
400 | 402 |
401 read_cb.Run(buffer); | 403 read_cb.Run(status, buffer); |
402 } | 404 } |
403 | 405 |
404 // DemuxerStream methods. | 406 // DemuxerStream methods. |
405 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { | 407 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { |
| 408 DemuxerStream::Status status = kOk; |
406 scoped_refptr<StreamParserBuffer> buffer; | 409 scoped_refptr<StreamParserBuffer> buffer; |
407 { | 410 { |
408 base::AutoLock auto_lock(lock_); | 411 base::AutoLock auto_lock(lock_); |
409 if (!read_cbs_.empty() || !GetNextBuffer_Locked(&buffer)) { | 412 if (!read_cbs_.empty() || !GetNextBuffer_Locked(&status, &buffer)) { |
410 DeferRead_Locked(read_cb); | 413 DeferRead_Locked(read_cb); |
411 return; | 414 return; |
412 } | 415 } |
413 } | 416 } |
414 | 417 |
415 read_cb.Run(buffer); | 418 read_cb.Run(status, buffer); |
416 } | 419 } |
417 | 420 |
418 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } | 421 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } |
419 | 422 |
420 void ChunkDemuxerStream::EnableBitstreamConverter() {} | 423 void ChunkDemuxerStream::EnableBitstreamConverter() {} |
421 | 424 |
422 const AudioDecoderConfig& ChunkDemuxerStream::audio_decoder_config() { | 425 const AudioDecoderConfig& ChunkDemuxerStream::audio_decoder_config() { |
423 CHECK_EQ(type_, AUDIO); | 426 CHECK_EQ(type_, AUDIO); |
424 base::AutoLock auto_lock(lock_); | 427 base::AutoLock auto_lock(lock_); |
425 return stream_->GetCurrentAudioDecoderConfig(); | 428 return stream_->GetCurrentAudioDecoderConfig(); |
(...skipping 19 matching lines...) Expand all Loading... |
445 read_cbs_.push_back(base::Bind(&RunOnMessageLoop, read_cb, | 448 read_cbs_.push_back(base::Bind(&RunOnMessageLoop, read_cb, |
446 MessageLoop::current())); | 449 MessageLoop::current())); |
447 } | 450 } |
448 | 451 |
449 void ChunkDemuxerStream::CreateReadDoneClosures_Locked(ClosureQueue* closures) { | 452 void ChunkDemuxerStream::CreateReadDoneClosures_Locked(ClosureQueue* closures) { |
450 lock_.AssertAcquired(); | 453 lock_.AssertAcquired(); |
451 | 454 |
452 if (state_ != RETURNING_DATA_FOR_READS) | 455 if (state_ != RETURNING_DATA_FOR_READS) |
453 return; | 456 return; |
454 | 457 |
| 458 DemuxerStream::Status status; |
455 scoped_refptr<StreamParserBuffer> buffer; | 459 scoped_refptr<StreamParserBuffer> buffer; |
456 while (!read_cbs_.empty()) { | 460 while (!read_cbs_.empty()) { |
457 if (!GetNextBuffer_Locked(&buffer)) | 461 if (!GetNextBuffer_Locked(&status, &buffer)) |
458 return; | 462 return; |
459 closures->push_back(base::Bind(read_cbs_.front(), buffer)); | 463 closures->push_back(base::Bind(read_cbs_.front(), |
| 464 status, buffer)); |
460 read_cbs_.pop_front(); | 465 read_cbs_.pop_front(); |
461 } | 466 } |
462 } | 467 } |
463 | 468 |
464 bool ChunkDemuxerStream::GetNextBuffer_Locked( | 469 bool ChunkDemuxerStream::GetNextBuffer_Locked( |
| 470 DemuxerStream::Status* status, |
465 scoped_refptr<StreamParserBuffer>* buffer) { | 471 scoped_refptr<StreamParserBuffer>* buffer) { |
466 lock_.AssertAcquired(); | 472 lock_.AssertAcquired(); |
467 | 473 |
468 switch (state_) { | 474 switch (state_) { |
469 case RETURNING_DATA_FOR_READS: | 475 case RETURNING_DATA_FOR_READS: |
470 if (stream_->GetNextBuffer(buffer)) | 476 if (stream_->GetNextBuffer(buffer)) { |
| 477 *status = DemuxerStream::kOk; |
471 return true; | 478 return true; |
| 479 } |
472 | 480 |
473 if (end_of_stream_) { | 481 if (end_of_stream_) { |
| 482 *status = DemuxerStream::kOk; |
474 *buffer = StreamParserBuffer::CreateEOSBuffer(); | 483 *buffer = StreamParserBuffer::CreateEOSBuffer(); |
475 return true; | 484 return true; |
476 } | 485 } |
477 return false; | 486 return false; |
478 case WAITING_FOR_SEEK: | 487 case WAITING_FOR_SEEK: |
479 // Null buffers should be returned in this state since we are waiting | 488 // Null buffers should be returned in this state since we are waiting |
480 // for a seek. Any buffers in the SourceBuffer should NOT be returned | 489 // for a seek. Any buffers in the SourceBuffer should NOT be returned |
481 // because they are associated with the seek. | 490 // because they are associated with the seek. |
482 DCHECK(read_cbs_.empty()); | 491 DCHECK(read_cbs_.empty()); |
| 492 *status = DemuxerStream::kAborted; |
483 *buffer = NULL; | 493 *buffer = NULL; |
484 return true; | 494 return true; |
485 case SHUTDOWN: | 495 case SHUTDOWN: |
486 DCHECK(read_cbs_.empty()); | 496 DCHECK(read_cbs_.empty()); |
| 497 *status = DemuxerStream::kOk; |
487 *buffer = StreamParserBuffer::CreateEOSBuffer(); | 498 *buffer = StreamParserBuffer::CreateEOSBuffer(); |
488 return true; | 499 return true; |
489 } | 500 } |
490 | 501 |
491 NOTREACHED(); | 502 NOTREACHED(); |
492 return false; | 503 return false; |
493 } | 504 } |
494 | 505 |
495 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) | 506 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) |
496 : state_(WAITING_FOR_INIT), | 507 : state_(WAITING_FOR_INIT), |
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1038 video_->SetStartTime(start_time_); | 1049 video_->SetStartTime(start_time_); |
1039 video_->Seek(start_time_); | 1050 video_->Seek(start_time_); |
1040 } | 1051 } |
1041 | 1052 |
1042 // The demuxer is now initialized after the |start_timestamp_| was set. | 1053 // The demuxer is now initialized after the |start_timestamp_| was set. |
1043 ChangeState_Locked(INITIALIZED); | 1054 ChangeState_Locked(INITIALIZED); |
1044 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 1055 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
1045 } | 1056 } |
1046 | 1057 |
1047 } // namespace media | 1058 } // namespace media |
OLD | NEW |