Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: media/filters/source_buffer_stream.cc

Issue 10696182: Add config change handling to SourceBufferStream & ChunkDemuxer (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added copyright headers to manifest files Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/source_buffer_stream.h ('k') | media/filters/source_buffer_stream_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/source_buffer_stream.h" 5 #include "media/filters/source_buffer_stream.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/stl_util.h"
12 13
13 namespace media { 14 namespace media {
14 15
15 // Helper class representing a range of buffered data. All buffers in a 16 // Helper class representing a range of buffered data. All buffers in a
16 // SourceBufferRange are ordered sequentially in presentation order with no 17 // SourceBufferRange are ordered sequentially in presentation order with no
17 // gaps. 18 // gaps.
18 class SourceBufferRange { 19 class SourceBufferRange {
19 public: 20 public:
20 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; 21 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
21 22
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 bool DeleteAll(BufferQueue* deleted_buffers); 87 bool DeleteAll(BufferQueue* deleted_buffers);
87 88
88 // Updates |out_buffer| with the next buffer in presentation order. Seek() 89 // Updates |out_buffer| with the next buffer in presentation order. Seek()
89 // must be called before calls to GetNextBuffer(), and buffers are returned 90 // must be called before calls to GetNextBuffer(), and buffers are returned
90 // in order from the last call to Seek(). Returns true if |out_buffer| is 91 // in order from the last call to Seek(). Returns true if |out_buffer| is
91 // filled with a valid buffer, false if there is not enough data to fulfill 92 // filled with a valid buffer, false if there is not enough data to fulfill
92 // the request. 93 // the request.
93 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer); 94 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer);
94 bool HasNextBuffer() const; 95 bool HasNextBuffer() const;
95 96
97 // Returns the config ID for the buffer that will be returned by
98 // GetNextBuffer().
99 int GetNextConfigId() const;
100
96 // Returns true if the range knows the position of the next buffer it should 101 // Returns true if the range knows the position of the next buffer it should
97 // return, i.e. it has been Seek()ed. This does not necessarily mean that it 102 // return, i.e. it has been Seek()ed. This does not necessarily mean that it
98 // has the next buffer yet. 103 // has the next buffer yet.
99 bool HasNextBufferPosition() const; 104 bool HasNextBufferPosition() const;
100 105
101 // Resets this range to an "unseeked" state. 106 // Resets this range to an "unseeked" state.
102 void ResetNextBufferPosition(); 107 void ResetNextBufferPosition();
103 108
104 // Returns the timestamp of the next buffer that will be returned from 109 // Returns the timestamp of the next buffer that will be returned from
105 // GetNextBuffer(), or kNoTimestamp() if the timestamp is unknown. 110 // GetNextBuffer(), or kNoTimestamp() if the timestamp is unknown.
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 return first->GetDecodeTimestamp() < second->GetDecodeTimestamp(); 227 return first->GetDecodeTimestamp() < second->GetDecodeTimestamp();
223 } 228 }
224 229
225 // An arbitrarily-chosen number to estimate the duration of a buffer if none 230 // An arbitrarily-chosen number to estimate the duration of a buffer if none
226 // is set and there's not enough information to get a better estimate. 231 // is set and there's not enough information to get a better estimate.
227 static int kDefaultBufferDurationInMs = 125; 232 static int kDefaultBufferDurationInMs = 125;
228 233
229 namespace media { 234 namespace media {
230 235
231 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config) 236 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config)
232 : stream_start_time_(kNoTimestamp()), 237 : current_config_index_(0),
238 append_config_index_(0),
239 audio_configs_(1),
240 video_configs_(0),
241 stream_start_time_(kNoTimestamp()),
233 seek_pending_(false), 242 seek_pending_(false),
234 seek_buffer_timestamp_(kNoTimestamp()), 243 seek_buffer_timestamp_(kNoTimestamp()),
235 selected_range_(NULL), 244 selected_range_(NULL),
236 media_segment_start_time_(kNoTimestamp()), 245 media_segment_start_time_(kNoTimestamp()),
237 range_for_next_append_(ranges_.end()), 246 range_for_next_append_(ranges_.end()),
238 new_media_segment_(false), 247 new_media_segment_(false),
239 last_buffer_timestamp_(kNoTimestamp()), 248 last_buffer_timestamp_(kNoTimestamp()),
240 max_interbuffer_distance_(kNoTimestamp()) { 249 max_interbuffer_distance_(kNoTimestamp()) {
241 audio_config_.CopyFrom(audio_config); 250 audio_configs_[0] = new AudioDecoderConfig();
251 audio_configs_[0]->CopyFrom(audio_config);
242 } 252 }
243 253
244 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config) 254 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config)
245 : stream_start_time_(kNoTimestamp()), 255 : current_config_index_(0),
256 append_config_index_(0),
257 audio_configs_(0),
258 video_configs_(1),
259 stream_start_time_(kNoTimestamp()),
246 seek_pending_(false), 260 seek_pending_(false),
247 seek_buffer_timestamp_(kNoTimestamp()), 261 seek_buffer_timestamp_(kNoTimestamp()),
248 selected_range_(NULL), 262 selected_range_(NULL),
249 media_segment_start_time_(kNoTimestamp()), 263 media_segment_start_time_(kNoTimestamp()),
250 range_for_next_append_(ranges_.end()), 264 range_for_next_append_(ranges_.end()),
251 new_media_segment_(false), 265 new_media_segment_(false),
252 last_buffer_timestamp_(kNoTimestamp()), 266 last_buffer_timestamp_(kNoTimestamp()),
253 max_interbuffer_distance_(kNoTimestamp()) { 267 max_interbuffer_distance_(kNoTimestamp()) {
254 video_config_.CopyFrom(video_config); 268 video_configs_[0] = new VideoDecoderConfig();
269 video_configs_[0]->CopyFrom(video_config);
255 } 270 }
256 271
257 SourceBufferStream::~SourceBufferStream() { 272 SourceBufferStream::~SourceBufferStream() {
258 while (!ranges_.empty()) { 273 while (!ranges_.empty()) {
259 delete ranges_.front(); 274 delete ranges_.front();
260 ranges_.pop_front(); 275 ranges_.pop_front();
261 } 276 }
277
278 STLDeleteElements(&audio_configs_);
279 STLDeleteElements(&video_configs_);
262 } 280 }
263 281
264 void SourceBufferStream::OnNewMediaSegment( 282 void SourceBufferStream::OnNewMediaSegment(
265 base::TimeDelta media_segment_start_time) { 283 base::TimeDelta media_segment_start_time) {
266 media_segment_start_time_ = media_segment_start_time; 284 media_segment_start_time_ = media_segment_start_time;
267 285
268 // Find the range that will house the buffers appended through the next 286 // Find the range that will house the buffers appended through the next
269 // Append() call. 287 // Append() call.
270 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time); 288 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time);
271 new_media_segment_ = true; 289 new_media_segment_ = true;
(...skipping 26 matching lines...) Expand all
298 return false; 316 return false;
299 } 317 }
300 318
301 if (stream_start_time_ != kNoTimestamp() && 319 if (stream_start_time_ != kNoTimestamp() &&
302 media_segment_start_time_ < stream_start_time_) { 320 media_segment_start_time_ < stream_start_time_) {
303 DVLOG(1) << "Cannot append a media segment before the start of stream."; 321 DVLOG(1) << "Cannot append a media segment before the start of stream.";
304 return false; 322 return false;
305 } 323 }
306 324
307 UpdateMaxInterbufferDistance(buffers); 325 UpdateMaxInterbufferDistance(buffers);
326 SetConfigIds(buffers);
308 327
309 // Save a snapshot of stream state before range modifications are made. 328 // Save a snapshot of stream state before range modifications are made.
310 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp(); 329 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp();
311 base::TimeDelta end_buffer_timestamp = GetEndBufferTimestamp(); 330 base::TimeDelta end_buffer_timestamp = GetEndBufferTimestamp();
312 331
313 bool deleted_next_buffer = false; 332 bool deleted_next_buffer = false;
314 BufferQueue deleted_buffers; 333 BufferQueue deleted_buffers;
315 334
316 RangeList::iterator range_for_new_buffers = range_for_next_append_; 335 RangeList::iterator range_for_new_buffers = range_for_next_append_;
317 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, 336 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 max_interbuffer_distance_ = interbuffer_distance; 435 max_interbuffer_distance_ = interbuffer_distance;
417 } else { 436 } else {
418 max_interbuffer_distance_ = 437 max_interbuffer_distance_ =
419 std::max(max_interbuffer_distance_, interbuffer_distance); 438 std::max(max_interbuffer_distance_, interbuffer_distance);
420 } 439 }
421 } 440 }
422 prev_timestamp = current_timestamp; 441 prev_timestamp = current_timestamp;
423 } 442 }
424 } 443 }
425 444
445 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
446 for (BufferQueue::const_iterator itr = buffers.begin();
447 itr != buffers.end(); ++itr) {
448 (*itr)->SetConfigId(append_config_index_);
449 }
450 }
451
426 void SourceBufferStream::InsertIntoExistingRange( 452 void SourceBufferStream::InsertIntoExistingRange(
427 const RangeList::iterator& range_for_new_buffers_itr, 453 const RangeList::iterator& range_for_new_buffers_itr,
428 const BufferQueue& new_buffers, 454 const BufferQueue& new_buffers,
429 bool* deleted_next_buffer, BufferQueue* deleted_buffers) { 455 bool* deleted_next_buffer, BufferQueue* deleted_buffers) {
430 DCHECK(deleted_next_buffer); 456 DCHECK(deleted_next_buffer);
431 DCHECK(deleted_buffers); 457 DCHECK(deleted_buffers);
432 458
433 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr; 459 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr;
434 460
435 // If this is a simple case where we can just append to the end of the range, 461 // If this is a simple case where we can just append to the end of the range,
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 672
647 SetSelectedRange(*itr); 673 SetSelectedRange(*itr);
648 selected_range_->Seek(timestamp); 674 selected_range_->Seek(timestamp);
649 seek_pending_ = false; 675 seek_pending_ = false;
650 } 676 }
651 677
652 bool SourceBufferStream::IsSeekPending() const { 678 bool SourceBufferStream::IsSeekPending() const {
653 return seek_pending_; 679 return seek_pending_;
654 } 680 }
655 681
656 bool SourceBufferStream::GetNextBuffer( 682 SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
657 scoped_refptr<StreamParserBuffer>* out_buffer) { 683 scoped_refptr<StreamParserBuffer>* out_buffer) {
658 if (!track_buffer_.empty()) { 684 if (!track_buffer_.empty()) {
685 if (track_buffer_.front()->GetConfigId() != current_config_index_)
686 return kConfigChange;
687
659 *out_buffer = track_buffer_.front(); 688 *out_buffer = track_buffer_.front();
660 track_buffer_.pop_front(); 689 track_buffer_.pop_front();
661 return true; 690 return kSuccess;
662 } 691 }
663 692
664 return selected_range_ && selected_range_->GetNextBuffer(out_buffer); 693 if (!selected_range_ || !selected_range_->HasNextBuffer())
694 return kNeedBuffer;
695
696 if (selected_range_->GetNextConfigId() != current_config_index_)
697 return kConfigChange;
698
699 CHECK(selected_range_->GetNextBuffer(out_buffer));
700 return kSuccess;
665 } 701 }
666 702
667 base::TimeDelta SourceBufferStream::GetNextBufferTimestamp() { 703 base::TimeDelta SourceBufferStream::GetNextBufferTimestamp() {
668 if (!selected_range_) 704 if (!selected_range_)
669 return kNoTimestamp(); 705 return kNoTimestamp();
670 706
671 DCHECK(selected_range_->HasNextBufferPosition()); 707 DCHECK(selected_range_->HasNextBufferPosition());
672 return selected_range_->GetNextTimestamp(); 708 return selected_range_->GetNextTimestamp();
673 } 709 }
674 710
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 itr != ranges_.end(); ++itr) { 758 itr != ranges_.end(); ++itr) {
723 ranges.Add((*itr)->GetStartTimestamp(), (*itr)->GetBufferedEndTimestamp()); 759 ranges.Add((*itr)->GetStartTimestamp(), (*itr)->GetBufferedEndTimestamp());
724 } 760 }
725 return ranges; 761 return ranges;
726 } 762 }
727 763
728 bool SourceBufferStream::IsEndSelected() const { 764 bool SourceBufferStream::IsEndSelected() const {
729 return ranges_.empty() || selected_range_ == ranges_.back(); 765 return ranges_.empty() || selected_range_ == ranges_.back();
730 } 766 }
731 767
768 const AudioDecoderConfig& SourceBufferStream::GetCurrentAudioDecoderConfig() {
769 CompleteConfigChange();
770 return *audio_configs_[current_config_index_];
771 }
772
773 const VideoDecoderConfig& SourceBufferStream::GetCurrentVideoDecoderConfig() {
774 CompleteConfigChange();
775 return *video_configs_[current_config_index_];
776 }
777
732 base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const { 778 base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const {
733 if (max_interbuffer_distance_ == kNoTimestamp()) 779 if (max_interbuffer_distance_ == kNoTimestamp())
734 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs); 780 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs);
735 return max_interbuffer_distance_; 781 return max_interbuffer_distance_;
736 } 782 }
737 783
784 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) {
785 DCHECK(!audio_configs_.empty());
786 DCHECK(video_configs_.empty());
787
788 if (audio_configs_[0]->codec() != config.codec()) {
789 DVLOG(1) << "UpdateAudioConfig() : Codec changes not allowed.";
790 return false;
791 }
792
793 if (audio_configs_[0]->samples_per_second() != config.samples_per_second()) {
794 DVLOG(1) << "UpdateAudioConfig() : Sample rate changes not allowed.";
795 return false;
796 }
797
798 if (audio_configs_[0]->channel_layout() != config.channel_layout()) {
799 DVLOG(1) << "UpdateAudioConfig() : Channel layout changes not allowed.";
800 return false;
801 }
802
803 if (audio_configs_[0]->bits_per_channel() != config.bits_per_channel()) {
804 DVLOG(1) << "UpdateAudioConfig() : Bits per channel changes not allowed.";
805 return false;
806 }
807
808 // Check to see if the new config matches an existing one.
809 for (size_t i = 0; i < audio_configs_.size(); ++i) {
810 if (config.Matches(*audio_configs_[i])) {
811 append_config_index_ = i;
812 return true;
813 }
814 }
815
816 // No matches found so let's add this one to the list.
817 append_config_index_ = audio_configs_.size();
818 audio_configs_.resize(audio_configs_.size() + 1);
819 audio_configs_[append_config_index_] = new AudioDecoderConfig();
820 audio_configs_[append_config_index_]->CopyFrom(config);
821 return true;
822 }
823
824 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) {
825 DCHECK(!video_configs_.empty());
826 DCHECK(audio_configs_.empty());
827
828 if (video_configs_[0]->codec() != config.codec()) {
829 DVLOG(1) << "UpdateVideoConfig() : Codec changes not allowed.";
830 return false;
831 }
832
833 // Check to see if the new config matches an existing one.
834 for (size_t i = 0; i < video_configs_.size(); ++i) {
835 if (config.Matches(*video_configs_[i])) {
836 append_config_index_ = i;
837 return true;
838 }
839 }
840
841 // No matches found so let's add this one to the list.
842 append_config_index_ = video_configs_.size();
843 video_configs_.resize(video_configs_.size() + 1);
844 video_configs_[append_config_index_] = new VideoDecoderConfig();
845 video_configs_[append_config_index_]->CopyFrom(config);
846 return true;
847 }
848
849 void SourceBufferStream::CompleteConfigChange() {
850 if (!track_buffer_.empty()) {
851 current_config_index_ = track_buffer_.front()->GetConfigId();
852 return;
853 }
854
855 if (!selected_range_ || !selected_range_->HasNextBuffer())
856 return;
857
858 current_config_index_ = selected_range_->GetNextConfigId();
859 }
860
738 SourceBufferRange::SourceBufferRange( 861 SourceBufferRange::SourceBufferRange(
739 const BufferQueue& new_buffers, base::TimeDelta media_segment_start_time, 862 const BufferQueue& new_buffers, base::TimeDelta media_segment_start_time,
740 const InterbufferDistanceCB& interbuffer_distance_cb) 863 const InterbufferDistanceCB& interbuffer_distance_cb)
741 : next_buffer_index_(-1), 864 : next_buffer_index_(-1),
742 waiting_for_keyframe_(false), 865 waiting_for_keyframe_(false),
743 next_keyframe_timestamp_(kNoTimestamp()), 866 next_keyframe_timestamp_(kNoTimestamp()),
744 media_segment_start_time_(media_segment_start_time), 867 media_segment_start_time_(media_segment_start_time),
745 interbuffer_distance_cb_(interbuffer_distance_cb) { 868 interbuffer_distance_cb_(interbuffer_distance_cb) {
746 DCHECK(!new_buffers.empty()); 869 DCHECK(!new_buffers.empty());
747 DCHECK(new_buffers.front()->IsKeyframe()); 870 DCHECK(new_buffers.front()->IsKeyframe());
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp()); 1041 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp());
919 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end()); 1042 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end());
920 1043
921 // Remove everything from |starting_point| onward. 1044 // Remove everything from |starting_point| onward.
922 buffers_.erase(starting_point, buffers_.end()); 1045 buffers_.erase(starting_point, buffers_.end());
923 return removed_next_buffer; 1046 return removed_next_buffer;
924 } 1047 }
925 1048
926 bool SourceBufferRange::GetNextBuffer( 1049 bool SourceBufferRange::GetNextBuffer(
927 scoped_refptr<StreamParserBuffer>* out_buffer) { 1050 scoped_refptr<StreamParserBuffer>* out_buffer) {
928 if (waiting_for_keyframe_ || 1051 if (!HasNextBuffer())
929 next_buffer_index_ >= static_cast<int>(buffers_.size())) {
930 return false; 1052 return false;
931 }
932 1053
933 DCHECK_GE(next_buffer_index_, 0);
934 *out_buffer = buffers_.at(next_buffer_index_); 1054 *out_buffer = buffers_.at(next_buffer_index_);
935 next_buffer_index_++; 1055 next_buffer_index_++;
936 return true; 1056 return true;
937 } 1057 }
938 1058
939 bool SourceBufferRange::HasNextBuffer() const { 1059 bool SourceBufferRange::HasNextBuffer() const {
940 return next_buffer_index_ >= 0 && 1060 return next_buffer_index_ >= 0 &&
941 next_buffer_index_ < static_cast<int>(buffers_.size()); 1061 next_buffer_index_ < static_cast<int>(buffers_.size()) &&
1062 !waiting_for_keyframe_;
942 } 1063 }
943 1064
1065 int SourceBufferRange::GetNextConfigId() const {
1066 DCHECK(HasNextBuffer());
1067 return buffers_.at(next_buffer_index_)->GetConfigId();
1068 }
1069
1070
944 base::TimeDelta SourceBufferRange::GetNextTimestamp() const { 1071 base::TimeDelta SourceBufferRange::GetNextTimestamp() const {
945 DCHECK(!buffers_.empty()); 1072 DCHECK(!buffers_.empty());
946 DCHECK(HasNextBufferPosition()); 1073 DCHECK(HasNextBufferPosition());
947 1074
948 if (waiting_for_keyframe_) 1075 if (waiting_for_keyframe_)
949 return next_keyframe_timestamp_; 1076 return next_keyframe_timestamp_;
950 1077
951 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) 1078 if (next_buffer_index_ >= static_cast<int>(buffers_.size()))
952 return kNoTimestamp(); 1079 return kNoTimestamp();
953 1080
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 return 2 * GetApproximateDuration(); 1174 return 2 * GetApproximateDuration();
1048 } 1175 }
1049 1176
1050 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { 1177 base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
1051 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run(); 1178 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
1052 DCHECK(max_interbuffer_distance != kNoTimestamp()); 1179 DCHECK(max_interbuffer_distance != kNoTimestamp());
1053 return max_interbuffer_distance; 1180 return max_interbuffer_distance;
1054 } 1181 }
1055 1182
1056 } // namespace media 1183 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/source_buffer_stream.h ('k') | media/filters/source_buffer_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698