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

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

Issue 125543002: Add plumbing and support for crossfading StreamParserBuffers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: There and back again. Created 6 years, 11 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
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"
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 seek_buffer_timestamp_(kNoTimestamp()), 334 seek_buffer_timestamp_(kNoTimestamp()),
335 selected_range_(NULL), 335 selected_range_(NULL),
336 media_segment_start_time_(kNoTimestamp()), 336 media_segment_start_time_(kNoTimestamp()),
337 range_for_next_append_(ranges_.end()), 337 range_for_next_append_(ranges_.end()),
338 new_media_segment_(false), 338 new_media_segment_(false),
339 last_appended_buffer_timestamp_(kNoTimestamp()), 339 last_appended_buffer_timestamp_(kNoTimestamp()),
340 last_appended_buffer_is_keyframe_(false), 340 last_appended_buffer_is_keyframe_(false),
341 last_output_buffer_timestamp_(kNoTimestamp()), 341 last_output_buffer_timestamp_(kNoTimestamp()),
342 max_interbuffer_distance_(kNoTimestamp()), 342 max_interbuffer_distance_(kNoTimestamp()),
343 memory_limit_(kDefaultAudioMemoryLimit), 343 memory_limit_(kDefaultAudioMemoryLimit),
344 config_change_pending_(false) { 344 config_change_pending_(false),
345 fade_out_preroll_index_(0) {
345 DCHECK(audio_config.IsValidConfig()); 346 DCHECK(audio_config.IsValidConfig());
346 audio_configs_.push_back(audio_config); 347 audio_configs_.push_back(audio_config);
347 } 348 }
348 349
349 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, 350 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
350 const LogCB& log_cb) 351 const LogCB& log_cb)
351 : log_cb_(log_cb), 352 : log_cb_(log_cb),
352 current_config_index_(0), 353 current_config_index_(0),
353 append_config_index_(0), 354 append_config_index_(0),
354 seek_pending_(false), 355 seek_pending_(false),
355 end_of_stream_(false), 356 end_of_stream_(false),
356 seek_buffer_timestamp_(kNoTimestamp()), 357 seek_buffer_timestamp_(kNoTimestamp()),
357 selected_range_(NULL), 358 selected_range_(NULL),
358 media_segment_start_time_(kNoTimestamp()), 359 media_segment_start_time_(kNoTimestamp()),
359 range_for_next_append_(ranges_.end()), 360 range_for_next_append_(ranges_.end()),
360 new_media_segment_(false), 361 new_media_segment_(false),
361 last_appended_buffer_timestamp_(kNoTimestamp()), 362 last_appended_buffer_timestamp_(kNoTimestamp()),
362 last_appended_buffer_is_keyframe_(false), 363 last_appended_buffer_is_keyframe_(false),
363 last_output_buffer_timestamp_(kNoTimestamp()), 364 last_output_buffer_timestamp_(kNoTimestamp()),
364 max_interbuffer_distance_(kNoTimestamp()), 365 max_interbuffer_distance_(kNoTimestamp()),
365 memory_limit_(kDefaultVideoMemoryLimit), 366 memory_limit_(kDefaultVideoMemoryLimit),
366 config_change_pending_(false) { 367 config_change_pending_(false),
368 fade_out_preroll_index_(0) {
367 DCHECK(video_config.IsValidConfig()); 369 DCHECK(video_config.IsValidConfig());
368 video_configs_.push_back(video_config); 370 video_configs_.push_back(video_config);
369 } 371 }
370 372
371 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, 373 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
372 const LogCB& log_cb) 374 const LogCB& log_cb)
373 : log_cb_(log_cb), 375 : log_cb_(log_cb),
374 current_config_index_(0), 376 current_config_index_(0),
375 append_config_index_(0), 377 append_config_index_(0),
376 text_track_config_(text_config), 378 text_track_config_(text_config),
377 seek_pending_(false), 379 seek_pending_(false),
378 end_of_stream_(false), 380 end_of_stream_(false),
379 seek_buffer_timestamp_(kNoTimestamp()), 381 seek_buffer_timestamp_(kNoTimestamp()),
380 selected_range_(NULL), 382 selected_range_(NULL),
381 media_segment_start_time_(kNoTimestamp()), 383 media_segment_start_time_(kNoTimestamp()),
382 range_for_next_append_(ranges_.end()), 384 range_for_next_append_(ranges_.end()),
383 new_media_segment_(false), 385 new_media_segment_(false),
384 last_appended_buffer_timestamp_(kNoTimestamp()), 386 last_appended_buffer_timestamp_(kNoTimestamp()),
385 last_appended_buffer_is_keyframe_(false), 387 last_appended_buffer_is_keyframe_(false),
386 last_output_buffer_timestamp_(kNoTimestamp()), 388 last_output_buffer_timestamp_(kNoTimestamp()),
387 max_interbuffer_distance_(kNoTimestamp()), 389 max_interbuffer_distance_(kNoTimestamp()),
388 memory_limit_(kDefaultAudioMemoryLimit), 390 memory_limit_(kDefaultAudioMemoryLimit),
389 config_change_pending_(false) { 391 config_change_pending_(false),
392 fade_out_preroll_index_(0) {
390 } 393 }
391 394
392 SourceBufferStream::~SourceBufferStream() { 395 SourceBufferStream::~SourceBufferStream() {
393 while (!ranges_.empty()) { 396 while (!ranges_.empty()) {
394 delete ranges_.front(); 397 delete ranges_.front();
395 ranges_.pop_front(); 398 ranges_.pop_front();
396 } 399 }
397 } 400 }
398 401
399 void SourceBufferStream::OnNewMediaSegment( 402 void SourceBufferStream::OnNewMediaSegment(
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 DCHECK(IsRangeListSorted(ranges_)); 666 DCHECK(IsRangeListSorted(ranges_));
664 DCHECK(OnlySelectedRangeIsSeeked()); 667 DCHECK(OnlySelectedRangeIsSeeked());
665 DVLOG(1) << __FUNCTION__ << " : done"; 668 DVLOG(1) << __FUNCTION__ << " : done";
666 } 669 }
667 670
668 void SourceBufferStream::ResetSeekState() { 671 void SourceBufferStream::ResetSeekState() {
669 SetSelectedRange(NULL); 672 SetSelectedRange(NULL);
670 track_buffer_.clear(); 673 track_buffer_.clear();
671 config_change_pending_ = false; 674 config_change_pending_ = false;
672 last_output_buffer_timestamp_ = kNoTimestamp(); 675 last_output_buffer_timestamp_ = kNoTimestamp();
676 fade_out_preroll_index_ = 0;
677 fade_in_buffer_ = NULL;
673 } 678 }
674 679
675 bool SourceBufferStream::ShouldSeekToStartOfBuffered( 680 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
676 base::TimeDelta seek_timestamp) const { 681 base::TimeDelta seek_timestamp) const {
677 if (ranges_.empty()) 682 if (ranges_.empty())
678 return false; 683 return false;
679 base::TimeDelta beginning_of_buffered = 684 base::TimeDelta beginning_of_buffered =
680 ranges_.front()->GetStartTimestamp(); 685 ranges_.front()->GetStartTimestamp();
681 return (seek_timestamp <= beginning_of_buffered && 686 return (seek_timestamp <= beginning_of_buffered &&
682 beginning_of_buffered < kSeekToStartFudgeRoom()); 687 beginning_of_buffered < kSeekToStartFudgeRoom());
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 // If we're about to delete the selected range, also reset the seek state. 1090 // If we're about to delete the selected range, also reset the seek state.
1086 DCHECK((*itr)->GetStartTimestamp() >= duration); 1091 DCHECK((*itr)->GetStartTimestamp() >= duration);
1087 if (*itr == selected_range_) 1092 if (*itr == selected_range_)
1088 ResetSeekState(); 1093 ResetSeekState();
1089 DeleteAndRemoveRange(&itr); 1094 DeleteAndRemoveRange(&itr);
1090 } 1095 }
1091 } 1096 }
1092 1097
1093 SourceBufferStream::Status SourceBufferStream::GetNextBuffer( 1098 SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
1094 scoped_refptr<StreamParserBuffer>* out_buffer) { 1099 scoped_refptr<StreamParserBuffer>* out_buffer) {
1100 if (!fade_in_buffer_) {
1101 const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer);
1102
1103 // Just return if GetNextBufferInternal() failed or there's no fade out
1104 // preroll, there's nothing else to do.
1105 if (status != SourceBufferStream::kSuccess ||
1106 (*out_buffer)->GetFadeOutPreroll().empty()) {
1107 return status;
1108 }
1109
1110 // Setup fade in buffer and fall through into splice frame buffer handling.
1111 fade_out_preroll_index_ = 0;
1112 fade_in_buffer_ = *out_buffer;
1113 }
1114
1115 DCHECK(fade_in_buffer_);
1116 const std::vector<scoped_refptr<StreamParserBuffer> >& fade_out_preroll =
1117 fade_in_buffer_->GetFadeOutPreroll();
1118
1119 // Are there any fade out buffers left to hand out?
1120 if (fade_out_preroll_index_ < fade_out_preroll.size()) {
1121 // Account for config changes which occur between fade out buffers.
1122 if (current_config_index_ !=
1123 fade_out_preroll.at(fade_out_preroll_index_)->GetConfigId()) {
1124 config_change_pending_ = true;
1125 DVLOG(1) << "Config change (fade out preroll config ID does not match).";
1126 return SourceBufferStream::kConfigChange;
1127 }
1128
1129 *out_buffer = fade_out_preroll.at(fade_out_preroll_index_++);
1130 return SourceBufferStream::kSuccess;
1131 }
1132
1133 // Did we hand out the last fade out buffer on the last call?
1134 if (fade_out_preroll_index_ == fade_out_preroll.size()) {
1135 fade_out_preroll_index_++;
1136 config_change_pending_ = true;
1137 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1138 return SourceBufferStream::kConfigChange;
1139 }
1140
1141 // All fade out buffers have been handed out and a config change completed, so
1142 // hand out the final buffer for fade in. Because a config change has already
1143 // been issued, we don't need to account for
acolwell GONE FROM CHROMIUM 2014/01/10 22:53:31 nit: Finish the sentence. :)
DaleCurtis 2014/01/10 23:03:49 Haha, awesome, I accidentally a sentence.
1144 DCHECK_GT(fade_out_preroll_index_, fade_out_preroll.size());
1145 *out_buffer = fade_in_buffer_;
1146 fade_in_buffer_ = NULL;
1147 fade_out_preroll_index_ = 0;
1148 return SourceBufferStream::kSuccess;
1149 }
1150
1151 SourceBufferStream::Status SourceBufferStream::GetNextBufferInternal(
1152 scoped_refptr<StreamParserBuffer>* out_buffer) {
1095 CHECK(!config_change_pending_); 1153 CHECK(!config_change_pending_);
1096 1154
1097 if (!track_buffer_.empty()) { 1155 if (!track_buffer_.empty()) {
1098 DCHECK(!selected_range_); 1156 DCHECK(!selected_range_);
1099 if (track_buffer_.front()->GetConfigId() != current_config_index_) { 1157 scoped_refptr<StreamParserBuffer>& next_buffer = track_buffer_.front();
1158
1159 // If the next buffer is an audio splice frame, the next effective config id
1160 // comes from the first fade out preroll buffer.
1161 const int next_config_id = next_buffer->GetFadeOutPreroll().empty() ?
1162 next_buffer->GetConfigId() :
1163 next_buffer->GetFadeOutPreroll().at(0)->GetConfigId();
acolwell GONE FROM CHROMIUM 2014/01/10 22:53:31 nit: Any reason you can't use the [0] instead of .
DaleCurtis 2014/01/10 23:03:49 I switched to .at() since that seemed to be the st
1164
1165 if (next_config_id != current_config_index_) {
1100 config_change_pending_ = true; 1166 config_change_pending_ = true;
1101 DVLOG(1) << "Config change (track buffer config ID does not match)."; 1167 DVLOG(1) << "Config change (track buffer config ID does not match).";
1102 return kConfigChange; 1168 return kConfigChange;
1103 } 1169 }
1104 1170
1105 *out_buffer = track_buffer_.front(); 1171 *out_buffer = next_buffer;
1106 track_buffer_.pop_front(); 1172 track_buffer_.pop_front();
1107 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp(); 1173 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1108 1174
1109 // If the track buffer becomes empty, then try to set the selected range 1175 // If the track buffer becomes empty, then try to set the selected range
1110 // based on the timestamp of this buffer being returned. 1176 // based on the timestamp of this buffer being returned.
1111 if (track_buffer_.empty()) 1177 if (track_buffer_.empty())
1112 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_); 1178 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_);
1113 1179
1114 return kSuccess; 1180 return kSuccess;
1115 } 1181 }
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 append_config_index_ = video_configs_.size(); 1397 append_config_index_ = video_configs_.size();
1332 DVLOG(2) << "New video config - index: " << append_config_index_; 1398 DVLOG(2) << "New video config - index: " << append_config_index_;
1333 video_configs_.resize(video_configs_.size() + 1); 1399 video_configs_.resize(video_configs_.size() + 1);
1334 video_configs_[append_config_index_] = config; 1400 video_configs_[append_config_index_] = config;
1335 return true; 1401 return true;
1336 } 1402 }
1337 1403
1338 void SourceBufferStream::CompleteConfigChange() { 1404 void SourceBufferStream::CompleteConfigChange() {
1339 config_change_pending_ = false; 1405 config_change_pending_ = false;
1340 1406
1407 if (fade_in_buffer_) {
1408 const std::vector<scoped_refptr<StreamParserBuffer> >& fade_out_preroll =
1409 fade_in_buffer_->GetFadeOutPreroll();
1410 current_config_index_ = fade_out_preroll_index_ < fade_out_preroll.size() ?
1411 fade_out_preroll.at(fade_out_preroll_index_)->GetConfigId() :
1412 fade_in_buffer_->GetConfigId();
1413 return;
1414 }
1415
1341 if (!track_buffer_.empty()) { 1416 if (!track_buffer_.empty()) {
1342 current_config_index_ = track_buffer_.front()->GetConfigId(); 1417 current_config_index_ = track_buffer_.front()->GetConfigId();
1343 return; 1418 return;
1344 } 1419 }
1345 1420
1346 if (selected_range_ && selected_range_->HasNextBuffer()) 1421 if (selected_range_ && selected_range_->HasNextBuffer())
1347 current_config_index_ = selected_range_->GetNextConfigId(); 1422 current_config_index_ = selected_range_->GetNextConfigId();
1348 } 1423 }
1349 1424
1350 void SourceBufferStream::SetSelectedRangeIfNeeded( 1425 void SourceBufferStream::SetSelectedRangeIfNeeded(
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
1851 return true; 1926 return true;
1852 } 1927 }
1853 1928
1854 bool SourceBufferRange::HasNextBuffer() const { 1929 bool SourceBufferRange::HasNextBuffer() const {
1855 return next_buffer_index_ >= 0 && 1930 return next_buffer_index_ >= 0 &&
1856 next_buffer_index_ < static_cast<int>(buffers_.size()); 1931 next_buffer_index_ < static_cast<int>(buffers_.size());
1857 } 1932 }
1858 1933
1859 int SourceBufferRange::GetNextConfigId() const { 1934 int SourceBufferRange::GetNextConfigId() const {
1860 DCHECK(HasNextBuffer()); 1935 DCHECK(HasNextBuffer());
1861 return buffers_.at(next_buffer_index_)->GetConfigId(); 1936 const scoped_refptr<StreamParserBuffer>& next_buffer =
1937 buffers_.at(next_buffer_index_);
1938 // If the next buffer is an audio splice frame, the next effective config id
1939 // comes from the first fade out preroll buffer.
1940 return next_buffer->GetFadeOutPreroll().empty() ?
1941 next_buffer->GetConfigId() :
1942 next_buffer->GetFadeOutPreroll().at(0)->GetConfigId();
1862 } 1943 }
1863 1944
1864 base::TimeDelta SourceBufferRange::GetNextTimestamp() const { 1945 base::TimeDelta SourceBufferRange::GetNextTimestamp() const {
1865 DCHECK(!buffers_.empty()); 1946 DCHECK(!buffers_.empty());
1866 DCHECK(HasNextBufferPosition()); 1947 DCHECK(HasNextBufferPosition());
1867 1948
1868 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) { 1949 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
1869 return kNoTimestamp(); 1950 return kNoTimestamp();
1870 } 1951 }
1871 1952
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1984 return ComputeFudgeRoom(GetApproximateDuration()); 2065 return ComputeFudgeRoom(GetApproximateDuration());
1985 } 2066 }
1986 2067
1987 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { 2068 base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
1988 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run(); 2069 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
1989 DCHECK(max_interbuffer_distance != kNoTimestamp()); 2070 DCHECK(max_interbuffer_distance != kNoTimestamp());
1990 return max_interbuffer_distance; 2071 return max_interbuffer_distance;
1991 } 2072 }
1992 2073
1993 } // namespace media 2074 } // namespace media
OLDNEW
« media/filters/source_buffer_stream.h ('K') | « media/filters/source_buffer_stream.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698