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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 | 126 |
| 127 void StartWaitingForSeek(); | 127 void StartWaitingForSeek(); |
| 128 void Seek(base::TimeDelta time); | 128 void Seek(base::TimeDelta time); |
| 129 bool IsSeekPending() const; | 129 bool IsSeekPending() const; |
| 130 | 130 |
| 131 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, | 131 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, |
| 132 // which handle ordering and overlap resolution. | 132 // which handle ordering and overlap resolution. |
| 133 // Returns true if buffers were successfully added. | 133 // Returns true if buffers were successfully added. |
| 134 bool Append(const StreamParser::BufferQueue& buffers); | 134 bool Append(const StreamParser::BufferQueue& buffers); |
| 135 | 135 |
| 136 // Returns a list of the buffered time ranges. | |
| 137 SourceBufferStream::TimespanList GetBufferedTime() const; | |
| 138 | |
| 136 // Called when mid-stream config updates occur. | 139 // Called when mid-stream config updates occur. |
| 137 // Returns true if the new config is accepted. | 140 // Returns true if the new config is accepted. |
| 138 // Returns false if the new config should trigger an error. | 141 // Returns false if the new config should trigger an error. |
| 139 bool UpdateAudioConfig(const AudioDecoderConfig& config); | 142 bool UpdateAudioConfig(const AudioDecoderConfig& config); |
| 140 bool UpdateVideoConfig(const VideoDecoderConfig& config); | 143 bool UpdateVideoConfig(const VideoDecoderConfig& config); |
| 141 | 144 |
| 142 void EndOfStream(); | 145 void EndOfStream(); |
| 143 bool CanEndOfStream() const; | 146 bool CanEndOfStream() const; |
| 144 void Shutdown(); | 147 void Shutdown(); |
| 145 | 148 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 } | 242 } |
| 240 CreateReadDoneClosures_Locked(&closures); | 243 CreateReadDoneClosures_Locked(&closures); |
| 241 } | 244 } |
| 242 | 245 |
| 243 for (ClosureQueue::iterator it = closures.begin(); it != closures.end(); ++it) | 246 for (ClosureQueue::iterator it = closures.begin(); it != closures.end(); ++it) |
| 244 it->Run(); | 247 it->Run(); |
| 245 | 248 |
| 246 return true; | 249 return true; |
| 247 } | 250 } |
| 248 | 251 |
| 252 SourceBufferStream::TimespanList ChunkDemuxerStream::GetBufferedTime() const { | |
| 253 base::AutoLock auto_lock(lock_); | |
| 254 return stream_->GetBufferedTime(); | |
| 255 } | |
| 256 | |
| 249 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config) { | 257 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config) { |
| 250 DCHECK(config.IsValidConfig()); | 258 DCHECK(config.IsValidConfig()); |
| 251 DCHECK_EQ(type_, AUDIO); | 259 DCHECK_EQ(type_, AUDIO); |
| 252 | 260 |
| 253 const AudioDecoderConfig& current_config = | 261 const AudioDecoderConfig& current_config = |
| 254 stream_->GetCurrentAudioDecoderConfig(); | 262 stream_->GetCurrentAudioDecoderConfig(); |
| 255 | 263 |
| 256 bool success = (current_config.codec() == config.codec()) && | 264 bool success = (current_config.codec() == config.codec()) && |
| 257 (current_config.bits_per_channel() == config.bits_per_channel()) && | 265 (current_config.bits_per_channel() == config.bits_per_channel()) && |
| 258 (current_config.channel_layout() == config.channel_layout()) && | 266 (current_config.channel_layout() == config.channel_layout()) && |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 573 audio_->Shutdown(); | 581 audio_->Shutdown(); |
| 574 | 582 |
| 575 if (source_id_video_ == id && video_) | 583 if (source_id_video_ == id && video_) |
| 576 video_->Shutdown(); | 584 video_->Shutdown(); |
| 577 } | 585 } |
| 578 | 586 |
| 579 bool ChunkDemuxer::GetBufferedRanges(const std::string& id, | 587 bool ChunkDemuxer::GetBufferedRanges(const std::string& id, |
| 580 Ranges* ranges_out) const { | 588 Ranges* ranges_out) const { |
| 581 DCHECK(!id.empty()); | 589 DCHECK(!id.empty()); |
| 582 DCHECK_GT(stream_parser_map_.count(id), 0u); | 590 DCHECK_GT(stream_parser_map_.count(id), 0u); |
| 591 DCHECK(id == source_id_audio_ || id == source_id_video_); | |
| 583 DCHECK(ranges_out); | 592 DCHECK(ranges_out); |
| 584 | 593 |
| 585 base::AutoLock auto_lock(lock_); | 594 base::AutoLock auto_lock(lock_); |
| 586 | 595 |
| 587 // TODO(annacc): Calculate buffered ranges (http://crbug.com/129852 ). | 596 if (id == source_id_audio_ && id != source_id_video_) { |
| 588 return false; | 597 // Only include ranges that have been buffered in |audio_| |
| 598 return CopyIntoRanges(audio_->GetBufferedTime(), ranges_out); | |
| 599 } | |
| 600 | |
| 601 if (id != source_id_audio_ && id == source_id_video_) { | |
| 602 // Only include ranges that have been buffered in |video_| | |
| 603 return CopyIntoRanges(video_->GetBufferedTime(), ranges_out); | |
| 604 } | |
| 605 | |
| 606 // Include ranges that have been buffered in both |audio_| and |video_|. | |
| 607 SourceBufferStream::TimespanList audio_ranges = audio_->GetBufferedTime(); | |
| 608 SourceBufferStream::TimespanList video_ranges = video_->GetBufferedTime(); | |
| 609 SourceBufferStream::TimespanList::const_iterator video_ranges_itr = | |
| 610 video_ranges.begin(); | |
| 611 SourceBufferStream::TimespanList::const_iterator audio_ranges_itr = | |
| 612 audio_ranges.begin(); | |
| 613 bool success = false; | |
| 614 | |
| 615 while (audio_ranges_itr != audio_ranges.end() && | |
| 616 video_ranges_itr != video_ranges.end()) { | |
| 617 | |
|
acolwell GONE FROM CHROMIUM
2012/06/13 00:33:40
nit: remove blank line
annacc
2012/06/13 03:35:43
Done.
| |
| 618 // If this is the last range and EndOfStream() was called (i.e. all data | |
| 619 // has been appended), choose the max end point of the ranges. | |
| 620 bool last_range_after_ended = | |
| 621 state_ == ENDED && | |
| 622 (audio_ranges_itr + 1) == audio_ranges.end() && | |
| 623 (video_ranges_itr + 1) == video_ranges.end(); | |
| 624 | |
| 625 // Audio range start time is within the video range. | |
| 626 if ((*audio_ranges_itr).first >= (*video_ranges_itr).first && | |
| 627 (*audio_ranges_itr).first <= (*video_ranges_itr).second) { | |
| 628 AddIntersectionRange(*audio_ranges_itr, *video_ranges_itr, | |
| 629 last_range_after_ended, ranges_out); | |
| 630 audio_ranges_itr++; | |
| 631 success = true; | |
| 632 continue; | |
| 633 } | |
| 634 | |
| 635 // Video range start time is within the audio range. | |
| 636 if ((*video_ranges_itr).first >= (*audio_ranges_itr).first && | |
| 637 (*video_ranges_itr).first <= (*audio_ranges_itr).second) { | |
| 638 AddIntersectionRange(*video_ranges_itr, *audio_ranges_itr, | |
| 639 last_range_after_ended, ranges_out); | |
| 640 video_ranges_itr++; | |
| 641 success = true; | |
| 642 continue; | |
| 643 } | |
| 644 | |
| 645 // No overlap was found. Increment the earliest one and keep looking. | |
| 646 if ((*audio_ranges_itr).first < (*video_ranges_itr).first) | |
| 647 audio_ranges_itr++; | |
| 648 else | |
| 649 video_ranges_itr++; | |
| 650 } | |
| 651 | |
| 652 return success; | |
| 653 } | |
| 654 | |
| 655 bool ChunkDemuxer::CopyIntoRanges( | |
| 656 const SourceBufferStream::TimespanList& timespans, | |
| 657 Ranges* ranges_out) const { | |
| 658 bool success = false; | |
| 659 for (SourceBufferStream::TimespanList::const_iterator itr = timespans.begin(); | |
| 660 itr != timespans.end(); ++itr) { | |
| 661 ranges_out->push_back(*itr); | |
| 662 success = true; | |
| 663 } | |
| 664 return success; | |
|
acolwell GONE FROM CHROMIUM
2012/06/13 00:33:40
nit: You can use !timestamps.empty() here instead.
annacc
2012/06/13 03:35:43
Done.
| |
| 665 } | |
| 666 | |
| 667 void ChunkDemuxer::AddIntersectionRange( | |
| 668 SourceBufferStream::Timespan timespan_a, | |
| 669 SourceBufferStream::Timespan timespan_b, | |
| 670 bool last_range_after_ended, | |
| 671 Ranges* ranges_out) const { | |
| 672 base::TimeDelta start = timespan_a.first; | |
| 673 | |
| 674 // If this is the last range after EndOfStream() was called, choose the later | |
| 675 // end point of the ranges, otherwise choose the earlier. | |
| 676 base::TimeDelta end; | |
| 677 if (last_range_after_ended) | |
| 678 end = std::max(timespan_a.second, timespan_b.second); | |
| 679 else | |
| 680 end = std::min(timespan_a.second, timespan_b.second); | |
| 681 | |
| 682 ranges_out->push_back(std::make_pair(start, end)); | |
| 589 } | 683 } |
| 590 | 684 |
| 591 bool ChunkDemuxer::AppendData(const std::string& id, | 685 bool ChunkDemuxer::AppendData(const std::string& id, |
| 592 const uint8* data, | 686 const uint8* data, |
| 593 size_t length) { | 687 size_t length) { |
| 594 DVLOG(1) << "AppendData(" << id << ", " << length << ")"; | 688 DVLOG(1) << "AppendData(" << id << ", " << length << ")"; |
| 595 | 689 |
| 596 DCHECK(!id.empty()); | 690 DCHECK(!id.empty()); |
| 597 DCHECK(data); | 691 DCHECK(data); |
| 598 DCHECK_GT(length, 0u); | 692 DCHECK_GT(length, 0u); |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 885 return true; | 979 return true; |
| 886 } | 980 } |
| 887 | 981 |
| 888 bool ChunkDemuxer::OnKeyNeeded(scoped_array<uint8> init_data, | 982 bool ChunkDemuxer::OnKeyNeeded(scoped_array<uint8> init_data, |
| 889 int init_data_size) { | 983 int init_data_size) { |
| 890 client_->KeyNeeded(init_data.Pass(), init_data_size); | 984 client_->KeyNeeded(init_data.Pass(), init_data_size); |
| 891 return true; | 985 return true; |
| 892 } | 986 } |
| 893 | 987 |
| 894 } // namespace media | 988 } // namespace media |
| OLD | NEW |