Chromium Code Reviews| 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 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 441 | 441 |
| 442 if (state_ == SHUTDOWN) | 442 if (state_ == SHUTDOWN) |
| 443 return; | 443 return; |
| 444 | 444 |
| 445 if (audio_.get()) | 445 if (audio_.get()) |
| 446 audio_->Flush(); | 446 audio_->Flush(); |
| 447 | 447 |
| 448 if (video_.get()) | 448 if (video_.get()) |
| 449 video_->Flush(); | 449 video_->Flush(); |
| 450 | 450 |
| 451 byte_queue_.Reset(); | |
| 452 stream_parser_->Flush(); | 451 stream_parser_->Flush(); |
| 453 | 452 |
| 454 seek_waits_for_data_ = true; | 453 seek_waits_for_data_ = true; |
| 455 ChangeState_Locked(INITIALIZED); | 454 ChangeState_Locked(INITIALIZED); |
| 456 } | 455 } |
| 457 | 456 |
| 458 bool ChunkDemuxer::AppendData(const uint8* data, size_t length) { | 457 bool ChunkDemuxer::AppendData(const uint8* data, size_t length) { |
| 459 DVLOG(1) << "AppendData(" << length << ")"; | 458 DVLOG(1) << "AppendData(" << length << ")"; |
| 460 | 459 |
| 461 if (!data || length == 0u) | 460 if (!data || length == 0u) |
| 462 return false; | 461 return false; |
| 463 | 462 |
| 464 int64 buffered_bytes = 0; | 463 int64 buffered_bytes = 0; |
| 465 base::TimeDelta buffered_ts = base::TimeDelta::FromSeconds(-1); | 464 base::TimeDelta buffered_ts = base::TimeDelta::FromSeconds(-1); |
| 466 | 465 |
| 467 PipelineStatusCB cb; | 466 PipelineStatusCB cb; |
| 468 { | 467 { |
| 469 base::AutoLock auto_lock(lock_); | 468 base::AutoLock auto_lock(lock_); |
| 470 | 469 |
| 471 byte_queue_.Push(data, length); | |
| 472 | |
| 473 const uint8* cur = NULL; | |
| 474 int cur_size = 0; | |
| 475 int bytes_parsed = 0; | |
| 476 int result = -1; | |
| 477 | |
| 478 // Capture |seek_waits_for_data_| state before we start parsing. | 470 // Capture |seek_waits_for_data_| state before we start parsing. |
| 479 // Its state can be changed by OnAudioBuffers() or OnVideoBuffers() | 471 // Its state can be changed by OnAudioBuffers() or OnVideoBuffers() |
| 480 // calls during the parse. | 472 // calls during the parse. |
| 481 bool old_seek_waits_for_data = seek_waits_for_data_; | 473 bool old_seek_waits_for_data = seek_waits_for_data_; |
| 482 | 474 |
| 483 byte_queue_.Peek(&cur, &cur_size); | 475 switch(state_) { |
| 476 case INITIALIZING: | |
| 477 if (!stream_parser_->Parse(data, length)) { | |
| 478 DCHECK_EQ(state_, INITIALIZING); | |
| 479 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | |
| 480 return true; | |
| 481 } | |
| 482 break; | |
| 484 | 483 |
| 485 do { | 484 case INITIALIZED: { |
| 486 switch(state_) { | 485 if (!stream_parser_->Parse(data, length)) { |
| 487 case INITIALIZING: | 486 ReportError_Locked(PIPELINE_ERROR_DECODE); |
| 488 result = stream_parser_->Parse(cur, cur_size); | 487 return true; |
| 489 if (result < 0) { | 488 } |
| 490 DCHECK_EQ(state_, INITIALIZING); | 489 } break; |
| 491 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | |
| 492 return true; | |
| 493 } | |
| 494 break; | |
| 495 | 490 |
| 496 case INITIALIZED: { | 491 case WAITING_FOR_INIT: |
| 497 result = stream_parser_->Parse(cur, cur_size); | 492 case ENDED: |
| 498 if (result < 0) { | 493 case PARSE_ERROR: |
| 499 ReportError_Locked(PIPELINE_ERROR_DECODE); | 494 case SHUTDOWN: |
| 500 return true; | 495 DVLOG(1) << "AppendData(): called in unexpected state " << state_; |
| 501 } | 496 return false; |
| 502 } break; | 497 } |
| 503 | |
| 504 case WAITING_FOR_INIT: | |
| 505 case ENDED: | |
| 506 case PARSE_ERROR: | |
| 507 case SHUTDOWN: | |
| 508 DVLOG(1) << "AppendData(): called in unexpected state " << state_; | |
| 509 return false; | |
| 510 } | |
| 511 | |
| 512 if (result > 0) { | |
| 513 cur += result; | |
| 514 cur_size -= result; | |
| 515 bytes_parsed += result; | |
| 516 } | |
| 517 } while (result > 0 && cur_size > 0); | |
| 518 | |
| 519 byte_queue_.Pop(bytes_parsed); | |
| 520 | 498 |
| 521 // Check to see if parsing triggered seek_waits_for_data_ to go from true to | 499 // Check to see if parsing triggered seek_waits_for_data_ to go from true to |
| 522 // false. This indicates we have parsed enough data to complete the seek. | 500 // false. This indicates we have parsed enough data to complete the seek. |
| 523 if (old_seek_waits_for_data && !seek_waits_for_data_ && | 501 if (old_seek_waits_for_data && !seek_waits_for_data_ && |
| 524 !seek_cb_.is_null()) { | 502 !seek_cb_.is_null()) { |
| 525 std::swap(cb, seek_cb_); | 503 std::swap(cb, seek_cb_); |
| 526 } | 504 } |
| 527 | 505 |
| 528 base::TimeDelta tmp; | 506 base::TimeDelta tmp; |
| 529 if (audio_.get() && audio_->GetLastBufferTimestamp(&tmp) && | 507 if (audio_.get() && audio_->GetLastBufferTimestamp(&tmp) && |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 667 duration_ = duration; | 645 duration_ = duration; |
| 668 host_->SetDuration(duration_); | 646 host_->SetDuration(duration_); |
| 669 host_->SetCurrentReadPosition(0); | 647 host_->SetCurrentReadPosition(0); |
| 670 | 648 |
| 671 ChangeState_Locked(INITIALIZED); | 649 ChangeState_Locked(INITIALIZED); |
| 672 PipelineStatusCB cb; | 650 PipelineStatusCB cb; |
| 673 std::swap(cb, init_cb_); | 651 std::swap(cb, init_cb_); |
| 674 cb.Run(PIPELINE_OK); | 652 cb.Run(PIPELINE_OK); |
| 675 } | 653 } |
| 676 | 654 |
| 677 bool ChunkDemuxer::OnNewAudioConfig(const AudioDecoderConfig& config) { | 655 bool ChunkDemuxer::OnNewConfigs(const AudioDecoderConfig& audio_config, |
| 656 const VideoDecoderConfig& video_config) { | |
| 657 DCHECK(audio_config.IsValidConfig() || video_config.IsValidConfig()); | |
| 678 lock_.AssertAcquired(); | 658 lock_.AssertAcquired(); |
| 679 // Only allow a single audio config for now. | 659 |
| 680 if (audio_.get()) | 660 if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) |
|
scherkus (not reviewing)
2012/04/24 01:40:04
Considering we handle the DCHECK (and that the pre
acolwell GONE FROM CHROMIUM
2012/04/24 16:25:55
Done. Picked option 2
| |
| 681 return false; | 661 return false; |
| 682 | 662 |
| 683 audio_ = new ChunkDemuxerStream(config); | 663 // Only allow a single audio config for now. |
|
scherkus (not reviewing)
2012/04/24 01:40:04
nit: you can either dupe this comment below for vi
acolwell GONE FROM CHROMIUM
2012/04/24 16:25:55
Done.
| |
| 664 if (audio_config.IsValidConfig()) { | |
| 665 if (audio_.get()) | |
| 666 return false; | |
| 667 | |
| 668 audio_ = new ChunkDemuxerStream(audio_config); | |
| 669 } | |
| 670 | |
| 671 if (video_config.IsValidConfig()) { | |
| 672 if (video_.get()) | |
| 673 return false; | |
| 674 | |
| 675 video_ = new ChunkDemuxerStream(video_config); | |
| 676 } | |
| 677 | |
| 684 return true; | 678 return true; |
| 685 } | 679 } |
| 686 | 680 |
| 687 bool ChunkDemuxer::OnNewVideoConfig(const VideoDecoderConfig& config) { | |
| 688 lock_.AssertAcquired(); | |
| 689 // Only allow a single video config for now. | |
| 690 if (video_.get()) | |
| 691 return false; | |
| 692 | |
| 693 video_ = new ChunkDemuxerStream(config); | |
| 694 return true; | |
| 695 } | |
| 696 | |
| 697 bool ChunkDemuxer::OnAudioBuffers(const BufferQueue& buffers) { | 681 bool ChunkDemuxer::OnAudioBuffers(const BufferQueue& buffers) { |
| 698 if (!audio_.get()) | 682 if (!audio_.get()) |
| 699 return false; | 683 return false; |
| 700 | 684 |
| 701 if (!audio_->CanAddBuffers(buffers)) | 685 if (!audio_->CanAddBuffers(buffers)) |
| 702 return false; | 686 return false; |
| 703 | 687 |
| 704 audio_->AddBuffers(buffers); | 688 audio_->AddBuffers(buffers); |
| 705 seek_waits_for_data_ = false; | 689 seek_waits_for_data_ = false; |
| 706 | 690 |
| 707 return true; | 691 return true; |
| 708 } | 692 } |
| 709 | 693 |
| 710 bool ChunkDemuxer::OnVideoBuffers(const BufferQueue& buffers) { | 694 bool ChunkDemuxer::OnVideoBuffers(const BufferQueue& buffers) { |
| 711 if (!video_.get()) | 695 if (!video_.get()) |
| 712 return false; | 696 return false; |
| 713 | 697 |
| 714 if (!video_->CanAddBuffers(buffers)) | 698 if (!video_->CanAddBuffers(buffers)) |
| 715 return false; | 699 return false; |
| 716 | 700 |
| 717 video_->AddBuffers(buffers); | 701 video_->AddBuffers(buffers); |
| 718 seek_waits_for_data_ = false; | 702 seek_waits_for_data_ = false; |
| 719 | 703 |
| 720 return true; | 704 return true; |
| 721 } | 705 } |
| 722 | 706 |
| 723 } // namespace media | 707 } // namespace media |
| OLD | NEW |