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/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "media/base/audio_decoder_config.h" | 10 #include "media/base/audio_decoder_config.h" |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 read_cb.Run(buffer); | 232 read_cb.Run(buffer); |
233 } | 233 } |
234 | 234 |
235 // DemuxerStream methods. | 235 // DemuxerStream methods. |
236 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { | 236 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { |
237 scoped_refptr<Buffer> buffer; | 237 scoped_refptr<Buffer> buffer; |
238 | 238 |
239 { | 239 { |
240 base::AutoLock auto_lock(lock_); | 240 base::AutoLock auto_lock(lock_); |
241 | 241 |
242 switch(state_) { | 242 switch (state_) { |
243 case RETURNING_DATA_FOR_READS: | 243 case RETURNING_DATA_FOR_READS: |
244 // If we don't have any buffers ready or already have | 244 // If we don't have any buffers ready or already have |
245 // pending reads, then defer this read. | 245 // pending reads, then defer this read. |
246 if (buffers_.empty() || !read_cbs_.empty()) { | 246 if (buffers_.empty() || !read_cbs_.empty()) { |
247 DeferRead_Locked(read_cb); | 247 DeferRead_Locked(read_cb); |
248 return; | 248 return; |
249 } | 249 } |
250 | 250 |
251 buffer = buffers_.front(); | 251 buffer = buffers_.front(); |
252 buffers_.pop_front(); | 252 buffers_.pop_front(); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 | 444 |
445 if (state_ == SHUTDOWN) | 445 if (state_ == SHUTDOWN) |
446 return; | 446 return; |
447 | 447 |
448 if (audio_.get()) | 448 if (audio_.get()) |
449 audio_->Flush(); | 449 audio_->Flush(); |
450 | 450 |
451 if (video_.get()) | 451 if (video_.get()) |
452 video_->Flush(); | 452 video_->Flush(); |
453 | 453 |
454 byte_queue_.Reset(); | |
455 stream_parser_->Flush(); | 454 stream_parser_->Flush(); |
456 | 455 |
457 seek_waits_for_data_ = true; | 456 seek_waits_for_data_ = true; |
458 ChangeState_Locked(INITIALIZED); | 457 ChangeState_Locked(INITIALIZED); |
459 } | 458 } |
460 | 459 |
461 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, | 460 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, |
462 const std::string& type) { | 461 const std::string& type) { |
463 // TODO(acolwell): Proper mimetype decoding and support for more than one ID | 462 // TODO(acolwell): Proper mimetype decoding and support for more than one ID |
464 // will be added as part of http://crbug.com/122909 | 463 // will be added as part of http://crbug.com/122909 |
(...skipping 28 matching lines...) Expand all Loading... |
493 DCHECK(data); | 492 DCHECK(data); |
494 DCHECK_GT(length, 0u); | 493 DCHECK_GT(length, 0u); |
495 | 494 |
496 int64 buffered_bytes = 0; | 495 int64 buffered_bytes = 0; |
497 base::TimeDelta buffered_ts = base::TimeDelta::FromSeconds(-1); | 496 base::TimeDelta buffered_ts = base::TimeDelta::FromSeconds(-1); |
498 | 497 |
499 PipelineStatusCB cb; | 498 PipelineStatusCB cb; |
500 { | 499 { |
501 base::AutoLock auto_lock(lock_); | 500 base::AutoLock auto_lock(lock_); |
502 | 501 |
503 byte_queue_.Push(data, length); | |
504 | |
505 const uint8* cur = NULL; | |
506 int cur_size = 0; | |
507 int bytes_parsed = 0; | |
508 int result = -1; | |
509 | |
510 // Capture |seek_waits_for_data_| state before we start parsing. | 502 // Capture |seek_waits_for_data_| state before we start parsing. |
511 // Its state can be changed by OnAudioBuffers() or OnVideoBuffers() | 503 // Its state can be changed by OnAudioBuffers() or OnVideoBuffers() |
512 // calls during the parse. | 504 // calls during the parse. |
513 bool old_seek_waits_for_data = seek_waits_for_data_; | 505 bool old_seek_waits_for_data = seek_waits_for_data_; |
514 | 506 |
515 byte_queue_.Peek(&cur, &cur_size); | 507 switch (state_) { |
| 508 case INITIALIZING: |
| 509 if (!stream_parser_->Parse(data, length)) { |
| 510 DCHECK_EQ(state_, INITIALIZING); |
| 511 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
| 512 return true; |
| 513 } |
| 514 break; |
516 | 515 |
517 do { | 516 case INITIALIZED: { |
518 switch(state_) { | 517 if (!stream_parser_->Parse(data, length)) { |
519 case INITIALIZING: | 518 ReportError_Locked(PIPELINE_ERROR_DECODE); |
520 result = stream_parser_->Parse(cur, cur_size); | 519 return true; |
521 if (result < 0) { | 520 } |
522 DCHECK_EQ(state_, INITIALIZING); | 521 } break; |
523 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | |
524 return true; | |
525 } | |
526 break; | |
527 | 522 |
528 case INITIALIZED: { | 523 case WAITING_FOR_INIT: |
529 result = stream_parser_->Parse(cur, cur_size); | 524 case ENDED: |
530 if (result < 0) { | 525 case PARSE_ERROR: |
531 ReportError_Locked(PIPELINE_ERROR_DECODE); | 526 case SHUTDOWN: |
532 return true; | 527 DVLOG(1) << "AppendData(): called in unexpected state " << state_; |
533 } | 528 return false; |
534 } break; | 529 } |
535 | |
536 case WAITING_FOR_INIT: | |
537 case ENDED: | |
538 case PARSE_ERROR: | |
539 case SHUTDOWN: | |
540 DVLOG(1) << "AppendData(): called in unexpected state " << state_; | |
541 return false; | |
542 } | |
543 | |
544 if (result > 0) { | |
545 cur += result; | |
546 cur_size -= result; | |
547 bytes_parsed += result; | |
548 } | |
549 } while (result > 0 && cur_size > 0); | |
550 | |
551 byte_queue_.Pop(bytes_parsed); | |
552 | 530 |
553 // Check to see if parsing triggered seek_waits_for_data_ to go from true to | 531 // Check to see if parsing triggered seek_waits_for_data_ to go from true to |
554 // false. This indicates we have parsed enough data to complete the seek. | 532 // false. This indicates we have parsed enough data to complete the seek. |
555 if (old_seek_waits_for_data && !seek_waits_for_data_ && | 533 if (old_seek_waits_for_data && !seek_waits_for_data_ && |
556 !seek_cb_.is_null()) { | 534 !seek_cb_.is_null()) { |
557 std::swap(cb, seek_cb_); | 535 std::swap(cb, seek_cb_); |
558 } | 536 } |
559 | 537 |
560 base::TimeDelta tmp; | 538 base::TimeDelta tmp; |
561 if (audio_.get() && audio_->GetLastBufferTimestamp(&tmp) && | 539 if (audio_.get() && audio_->GetLastBufferTimestamp(&tmp) && |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 duration_ = duration; | 677 duration_ = duration; |
700 host_->SetDuration(duration_); | 678 host_->SetDuration(duration_); |
701 host_->SetCurrentReadPosition(0); | 679 host_->SetCurrentReadPosition(0); |
702 | 680 |
703 ChangeState_Locked(INITIALIZED); | 681 ChangeState_Locked(INITIALIZED); |
704 PipelineStatusCB cb; | 682 PipelineStatusCB cb; |
705 std::swap(cb, init_cb_); | 683 std::swap(cb, init_cb_); |
706 cb.Run(PIPELINE_OK); | 684 cb.Run(PIPELINE_OK); |
707 } | 685 } |
708 | 686 |
709 bool ChunkDemuxer::OnNewAudioConfig(const AudioDecoderConfig& config) { | 687 bool ChunkDemuxer::OnNewConfigs(const AudioDecoderConfig& audio_config, |
| 688 const VideoDecoderConfig& video_config) { |
| 689 CHECK(audio_config.IsValidConfig() || video_config.IsValidConfig()); |
710 lock_.AssertAcquired(); | 690 lock_.AssertAcquired(); |
| 691 |
711 // Only allow a single audio config for now. | 692 // Only allow a single audio config for now. |
712 if (audio_.get()) | 693 if (audio_config.IsValidConfig()) { |
713 return false; | 694 if (audio_.get()) |
| 695 return false; |
714 | 696 |
715 audio_ = new ChunkDemuxerStream(config); | 697 audio_ = new ChunkDemuxerStream(audio_config); |
| 698 } |
| 699 |
| 700 // Only allow a single video config for now. |
| 701 if (video_config.IsValidConfig()) { |
| 702 if (video_.get()) |
| 703 return false; |
| 704 |
| 705 video_ = new ChunkDemuxerStream(video_config); |
| 706 } |
| 707 |
716 return true; | 708 return true; |
717 } | 709 } |
718 | 710 |
719 bool ChunkDemuxer::OnNewVideoConfig(const VideoDecoderConfig& config) { | |
720 lock_.AssertAcquired(); | |
721 // Only allow a single video config for now. | |
722 if (video_.get()) | |
723 return false; | |
724 | |
725 video_ = new ChunkDemuxerStream(config); | |
726 return true; | |
727 } | |
728 | |
729 bool ChunkDemuxer::OnAudioBuffers(const BufferQueue& buffers) { | 711 bool ChunkDemuxer::OnAudioBuffers(const BufferQueue& buffers) { |
730 if (!audio_.get()) | 712 if (!audio_.get()) |
731 return false; | 713 return false; |
732 | 714 |
733 if (!audio_->CanAddBuffers(buffers)) | 715 if (!audio_->CanAddBuffers(buffers)) |
734 return false; | 716 return false; |
735 | 717 |
736 audio_->AddBuffers(buffers); | 718 audio_->AddBuffers(buffers); |
737 seek_waits_for_data_ = false; | 719 seek_waits_for_data_ = false; |
738 | 720 |
739 return true; | 721 return true; |
740 } | 722 } |
741 | 723 |
742 bool ChunkDemuxer::OnVideoBuffers(const BufferQueue& buffers) { | 724 bool ChunkDemuxer::OnVideoBuffers(const BufferQueue& buffers) { |
743 if (!video_.get()) | 725 if (!video_.get()) |
744 return false; | 726 return false; |
745 | 727 |
746 if (!video_->CanAddBuffers(buffers)) | 728 if (!video_->CanAddBuffers(buffers)) |
747 return false; | 729 return false; |
748 | 730 |
749 video_->AddBuffers(buffers); | 731 video_->AddBuffers(buffers); |
750 seek_waits_for_data_ = false; | 732 seek_waits_for_data_ = false; |
751 | 733 |
752 return true; | 734 return true; |
753 } | 735 } |
754 | 736 |
755 } // namespace media | 737 } // namespace media |
OLD | NEW |