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

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: Rebase. 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
« 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"
(...skipping 11 matching lines...) Expand all
22 // same timestamp situation that is allowed. False is returned otherwise. 22 // same timestamp situation that is allowed. False is returned otherwise.
23 static bool AllowSameTimestamp( 23 static bool AllowSameTimestamp(
24 bool prev_is_keyframe, bool current_is_keyframe, 24 bool prev_is_keyframe, bool current_is_keyframe,
25 SourceBufferStream::Type type) { 25 SourceBufferStream::Type type) {
26 if (type == SourceBufferStream::kVideo) 26 if (type == SourceBufferStream::kVideo)
27 return !prev_is_keyframe && !current_is_keyframe; 27 return !prev_is_keyframe && !current_is_keyframe;
28 28
29 return prev_is_keyframe || !current_is_keyframe; 29 return prev_is_keyframe || !current_is_keyframe;
30 } 30 }
31 31
32 // Returns the config ID of |buffer| if |buffer| has no fade out preroll or
33 // |index| is out of range. Otherwise returns the config ID for the fade out
34 // preroll buffer at position |index|.
35 static int GetConfigId(StreamParserBuffer* buffer, size_t index) {
36 return index < buffer->GetFadeOutPreroll().size()
37 ? buffer->GetFadeOutPreroll()[index]->GetConfigId()
38 : buffer->GetConfigId();
39 }
40
32 // Helper class representing a range of buffered data. All buffers in a 41 // Helper class representing a range of buffered data. All buffers in a
33 // SourceBufferRange are ordered sequentially in presentation order with no 42 // SourceBufferRange are ordered sequentially in presentation order with no
34 // gaps. 43 // gaps.
35 class SourceBufferRange { 44 class SourceBufferRange {
36 public: 45 public:
37 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; 46 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
38 47
39 // Returns the maximum distance in time between any buffer seen in this 48 // Returns the maximum distance in time between any buffer seen in this
40 // stream. Used to estimate the duration of a buffer if its duration is not 49 // stream. Used to estimate the duration of a buffer if its duration is not
41 // known. 50 // known.
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 seek_buffer_timestamp_(kNoTimestamp()), 348 seek_buffer_timestamp_(kNoTimestamp()),
340 selected_range_(NULL), 349 selected_range_(NULL),
341 media_segment_start_time_(kNoTimestamp()), 350 media_segment_start_time_(kNoTimestamp()),
342 range_for_next_append_(ranges_.end()), 351 range_for_next_append_(ranges_.end()),
343 new_media_segment_(false), 352 new_media_segment_(false),
344 last_appended_buffer_timestamp_(kNoTimestamp()), 353 last_appended_buffer_timestamp_(kNoTimestamp()),
345 last_appended_buffer_is_keyframe_(false), 354 last_appended_buffer_is_keyframe_(false),
346 last_output_buffer_timestamp_(kNoTimestamp()), 355 last_output_buffer_timestamp_(kNoTimestamp()),
347 max_interbuffer_distance_(kNoTimestamp()), 356 max_interbuffer_distance_(kNoTimestamp()),
348 memory_limit_(kDefaultAudioMemoryLimit), 357 memory_limit_(kDefaultAudioMemoryLimit),
349 config_change_pending_(false) { 358 config_change_pending_(false),
359 fade_out_preroll_index_(0) {
350 DCHECK(audio_config.IsValidConfig()); 360 DCHECK(audio_config.IsValidConfig());
351 audio_configs_.push_back(audio_config); 361 audio_configs_.push_back(audio_config);
352 } 362 }
353 363
354 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, 364 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
355 const LogCB& log_cb) 365 const LogCB& log_cb)
356 : log_cb_(log_cb), 366 : log_cb_(log_cb),
357 current_config_index_(0), 367 current_config_index_(0),
358 append_config_index_(0), 368 append_config_index_(0),
359 seek_pending_(false), 369 seek_pending_(false),
360 end_of_stream_(false), 370 end_of_stream_(false),
361 seek_buffer_timestamp_(kNoTimestamp()), 371 seek_buffer_timestamp_(kNoTimestamp()),
362 selected_range_(NULL), 372 selected_range_(NULL),
363 media_segment_start_time_(kNoTimestamp()), 373 media_segment_start_time_(kNoTimestamp()),
364 range_for_next_append_(ranges_.end()), 374 range_for_next_append_(ranges_.end()),
365 new_media_segment_(false), 375 new_media_segment_(false),
366 last_appended_buffer_timestamp_(kNoTimestamp()), 376 last_appended_buffer_timestamp_(kNoTimestamp()),
367 last_appended_buffer_is_keyframe_(false), 377 last_appended_buffer_is_keyframe_(false),
368 last_output_buffer_timestamp_(kNoTimestamp()), 378 last_output_buffer_timestamp_(kNoTimestamp()),
369 max_interbuffer_distance_(kNoTimestamp()), 379 max_interbuffer_distance_(kNoTimestamp()),
370 memory_limit_(kDefaultVideoMemoryLimit), 380 memory_limit_(kDefaultVideoMemoryLimit),
371 config_change_pending_(false) { 381 config_change_pending_(false),
382 fade_out_preroll_index_(0) {
372 DCHECK(video_config.IsValidConfig()); 383 DCHECK(video_config.IsValidConfig());
373 video_configs_.push_back(video_config); 384 video_configs_.push_back(video_config);
374 } 385 }
375 386
376 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, 387 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
377 const LogCB& log_cb) 388 const LogCB& log_cb)
378 : log_cb_(log_cb), 389 : log_cb_(log_cb),
379 current_config_index_(0), 390 current_config_index_(0),
380 append_config_index_(0), 391 append_config_index_(0),
381 text_track_config_(text_config), 392 text_track_config_(text_config),
382 seek_pending_(false), 393 seek_pending_(false),
383 end_of_stream_(false), 394 end_of_stream_(false),
384 seek_buffer_timestamp_(kNoTimestamp()), 395 seek_buffer_timestamp_(kNoTimestamp()),
385 selected_range_(NULL), 396 selected_range_(NULL),
386 media_segment_start_time_(kNoTimestamp()), 397 media_segment_start_time_(kNoTimestamp()),
387 range_for_next_append_(ranges_.end()), 398 range_for_next_append_(ranges_.end()),
388 new_media_segment_(false), 399 new_media_segment_(false),
389 last_appended_buffer_timestamp_(kNoTimestamp()), 400 last_appended_buffer_timestamp_(kNoTimestamp()),
390 last_appended_buffer_is_keyframe_(false), 401 last_appended_buffer_is_keyframe_(false),
391 last_output_buffer_timestamp_(kNoTimestamp()), 402 last_output_buffer_timestamp_(kNoTimestamp()),
392 max_interbuffer_distance_(kNoTimestamp()), 403 max_interbuffer_distance_(kNoTimestamp()),
393 memory_limit_(kDefaultAudioMemoryLimit), 404 memory_limit_(kDefaultAudioMemoryLimit),
394 config_change_pending_(false) { 405 config_change_pending_(false),
406 fade_out_preroll_index_(0) {
395 } 407 }
396 408
397 SourceBufferStream::~SourceBufferStream() { 409 SourceBufferStream::~SourceBufferStream() {
398 while (!ranges_.empty()) { 410 while (!ranges_.empty()) {
399 delete ranges_.front(); 411 delete ranges_.front();
400 ranges_.pop_front(); 412 ranges_.pop_front();
401 } 413 }
402 } 414 }
403 415
404 void SourceBufferStream::OnNewMediaSegment( 416 void SourceBufferStream::OnNewMediaSegment(
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 DCHECK(IsRangeListSorted(ranges_)); 675 DCHECK(IsRangeListSorted(ranges_));
664 DCHECK(OnlySelectedRangeIsSeeked()); 676 DCHECK(OnlySelectedRangeIsSeeked());
665 DVLOG(1) << __FUNCTION__ << " : done"; 677 DVLOG(1) << __FUNCTION__ << " : done";
666 } 678 }
667 679
668 void SourceBufferStream::ResetSeekState() { 680 void SourceBufferStream::ResetSeekState() {
669 SetSelectedRange(NULL); 681 SetSelectedRange(NULL);
670 track_buffer_.clear(); 682 track_buffer_.clear();
671 config_change_pending_ = false; 683 config_change_pending_ = false;
672 last_output_buffer_timestamp_ = kNoTimestamp(); 684 last_output_buffer_timestamp_ = kNoTimestamp();
685 fade_out_preroll_index_ = 0;
686 fade_in_buffer_ = NULL;
673 } 687 }
674 688
675 bool SourceBufferStream::ShouldSeekToStartOfBuffered( 689 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
676 base::TimeDelta seek_timestamp) const { 690 base::TimeDelta seek_timestamp) const {
677 if (ranges_.empty()) 691 if (ranges_.empty())
678 return false; 692 return false;
679 base::TimeDelta beginning_of_buffered = 693 base::TimeDelta beginning_of_buffered =
680 ranges_.front()->GetStartTimestamp(); 694 ranges_.front()->GetStartTimestamp();
681 return (seek_timestamp <= beginning_of_buffered && 695 return (seek_timestamp <= beginning_of_buffered &&
682 beginning_of_buffered < kSeekToStartFudgeRoom()); 696 beginning_of_buffered < kSeekToStartFudgeRoom());
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 // If we're about to delete the selected range, also reset the seek state. 1104 // If we're about to delete the selected range, also reset the seek state.
1091 DCHECK((*itr)->GetStartTimestamp() >= duration); 1105 DCHECK((*itr)->GetStartTimestamp() >= duration);
1092 if (*itr == selected_range_) 1106 if (*itr == selected_range_)
1093 ResetSeekState(); 1107 ResetSeekState();
1094 DeleteAndRemoveRange(&itr); 1108 DeleteAndRemoveRange(&itr);
1095 } 1109 }
1096 } 1110 }
1097 1111
1098 SourceBufferStream::Status SourceBufferStream::GetNextBuffer( 1112 SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
1099 scoped_refptr<StreamParserBuffer>* out_buffer) { 1113 scoped_refptr<StreamParserBuffer>* out_buffer) {
1114 if (!fade_in_buffer_) {
1115 const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer);
1116
1117 // Just return if GetNextBufferInternal() failed or there's no fade out
1118 // preroll, there's nothing else to do.
1119 if (status != SourceBufferStream::kSuccess ||
1120 (*out_buffer)->GetFadeOutPreroll().empty()) {
1121 return status;
1122 }
1123
1124 // Setup fade in buffer and fall through into splice frame buffer handling.
1125 fade_out_preroll_index_ = 0;
1126 fade_in_buffer_.swap(*out_buffer);
1127 }
1128
1129 DCHECK(fade_in_buffer_);
1130 const std::vector<scoped_refptr<StreamParserBuffer> >& fade_out_preroll =
1131 fade_in_buffer_->GetFadeOutPreroll();
1132
1133 // Are there any fade out buffers left to hand out?
1134 if (fade_out_preroll_index_ < fade_out_preroll.size()) {
1135 // Account for config changes which occur between fade out buffers.
1136 if (current_config_index_ !=
1137 fade_out_preroll[fade_out_preroll_index_]->GetConfigId()) {
1138 config_change_pending_ = true;
1139 DVLOG(1) << "Config change (fade out preroll config ID does not match).";
1140 return SourceBufferStream::kConfigChange;
1141 }
1142
1143 *out_buffer = fade_out_preroll[fade_out_preroll_index_++];
1144 return SourceBufferStream::kSuccess;
1145 }
1146
1147 // Did we hand out the last fade out buffer on the last call?
1148 if (fade_out_preroll_index_ == fade_out_preroll.size()) {
1149 fade_out_preroll_index_++;
1150 config_change_pending_ = true;
1151 DVLOG(1) << "Config change (forced for fade in of splice frame).";
1152 return SourceBufferStream::kConfigChange;
1153 }
1154
1155 // All fade out buffers have been handed out and a config change completed, so
1156 // hand out the final buffer for fade in. Because a config change is always
1157 // issued prior to handing out this buffer, any changes in config id have been
1158 // inherently handled.
1159 DCHECK_GT(fade_out_preroll_index_, fade_out_preroll.size());
1160 out_buffer->swap(fade_in_buffer_);
1161 fade_in_buffer_ = NULL;
1162 fade_out_preroll_index_ = 0;
1163 return SourceBufferStream::kSuccess;
1164 }
1165
1166 SourceBufferStream::Status SourceBufferStream::GetNextBufferInternal(
1167 scoped_refptr<StreamParserBuffer>* out_buffer) {
1100 CHECK(!config_change_pending_); 1168 CHECK(!config_change_pending_);
1101 1169
1102 if (!track_buffer_.empty()) { 1170 if (!track_buffer_.empty()) {
1103 DCHECK(!selected_range_); 1171 DCHECK(!selected_range_);
1104 if (track_buffer_.front()->GetConfigId() != current_config_index_) { 1172 scoped_refptr<StreamParserBuffer>& next_buffer = track_buffer_.front();
1173
1174 // If the next buffer is an audio splice frame, the next effective config id
1175 // comes from the first fade out preroll buffer.
1176 if (GetConfigId(next_buffer, 0) != current_config_index_) {
1105 config_change_pending_ = true; 1177 config_change_pending_ = true;
1106 DVLOG(1) << "Config change (track buffer config ID does not match)."; 1178 DVLOG(1) << "Config change (track buffer config ID does not match).";
1107 return kConfigChange; 1179 return kConfigChange;
1108 } 1180 }
1109 1181
1110 *out_buffer = track_buffer_.front(); 1182 *out_buffer = next_buffer;
1111 track_buffer_.pop_front(); 1183 track_buffer_.pop_front();
1112 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp(); 1184 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1113 1185
1114 // If the track buffer becomes empty, then try to set the selected range 1186 // If the track buffer becomes empty, then try to set the selected range
1115 // based on the timestamp of this buffer being returned. 1187 // based on the timestamp of this buffer being returned.
1116 if (track_buffer_.empty()) 1188 if (track_buffer_.empty())
1117 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_); 1189 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_);
1118 1190
1119 return kSuccess; 1191 return kSuccess;
1120 } 1192 }
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
1336 append_config_index_ = video_configs_.size(); 1408 append_config_index_ = video_configs_.size();
1337 DVLOG(2) << "New video config - index: " << append_config_index_; 1409 DVLOG(2) << "New video config - index: " << append_config_index_;
1338 video_configs_.resize(video_configs_.size() + 1); 1410 video_configs_.resize(video_configs_.size() + 1);
1339 video_configs_[append_config_index_] = config; 1411 video_configs_[append_config_index_] = config;
1340 return true; 1412 return true;
1341 } 1413 }
1342 1414
1343 void SourceBufferStream::CompleteConfigChange() { 1415 void SourceBufferStream::CompleteConfigChange() {
1344 config_change_pending_ = false; 1416 config_change_pending_ = false;
1345 1417
1346 if (!track_buffer_.empty()) { 1418 if (fade_in_buffer_) {
1347 current_config_index_ = track_buffer_.front()->GetConfigId(); 1419 current_config_index_ =
1420 GetConfigId(fade_in_buffer_, fade_out_preroll_index_);
1348 return; 1421 return;
1349 } 1422 }
1350 1423
1424 if (!track_buffer_.empty()) {
1425 current_config_index_ = GetConfigId(track_buffer_.front(), 0);
1426 return;
1427 }
1428
1351 if (selected_range_ && selected_range_->HasNextBuffer()) 1429 if (selected_range_ && selected_range_->HasNextBuffer())
1352 current_config_index_ = selected_range_->GetNextConfigId(); 1430 current_config_index_ = selected_range_->GetNextConfigId();
1353 } 1431 }
1354 1432
1355 void SourceBufferStream::SetSelectedRangeIfNeeded( 1433 void SourceBufferStream::SetSelectedRangeIfNeeded(
1356 const base::TimeDelta timestamp) { 1434 const base::TimeDelta timestamp) {
1357 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")"; 1435 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")";
1358 1436
1359 if (selected_range_) { 1437 if (selected_range_) {
1360 DCHECK(track_buffer_.empty()); 1438 DCHECK(track_buffer_.empty());
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
1857 // Remove everything from |starting_point| onward. 1935 // Remove everything from |starting_point| onward.
1858 FreeBufferRange(starting_point, buffers_.end()); 1936 FreeBufferRange(starting_point, buffers_.end());
1859 return buffers_.empty(); 1937 return buffers_.empty();
1860 } 1938 }
1861 1939
1862 bool SourceBufferRange::GetNextBuffer( 1940 bool SourceBufferRange::GetNextBuffer(
1863 scoped_refptr<StreamParserBuffer>* out_buffer) { 1941 scoped_refptr<StreamParserBuffer>* out_buffer) {
1864 if (!HasNextBuffer()) 1942 if (!HasNextBuffer())
1865 return false; 1943 return false;
1866 1944
1867 *out_buffer = buffers_.at(next_buffer_index_); 1945 *out_buffer = buffers_[next_buffer_index_];
1868 next_buffer_index_++; 1946 next_buffer_index_++;
1869 return true; 1947 return true;
1870 } 1948 }
1871 1949
1872 bool SourceBufferRange::HasNextBuffer() const { 1950 bool SourceBufferRange::HasNextBuffer() const {
1873 return next_buffer_index_ >= 0 && 1951 return next_buffer_index_ >= 0 &&
1874 next_buffer_index_ < static_cast<int>(buffers_.size()); 1952 next_buffer_index_ < static_cast<int>(buffers_.size());
1875 } 1953 }
1876 1954
1877 int SourceBufferRange::GetNextConfigId() const { 1955 int SourceBufferRange::GetNextConfigId() const {
1878 DCHECK(HasNextBuffer()); 1956 DCHECK(HasNextBuffer());
1879 return buffers_.at(next_buffer_index_)->GetConfigId(); 1957 // If the next buffer is an audio splice frame, the next effective config id
1958 // comes from the first fade out preroll buffer.
1959 return GetConfigId(buffers_[next_buffer_index_], 0);
1880 } 1960 }
1881 1961
1882 base::TimeDelta SourceBufferRange::GetNextTimestamp() const { 1962 base::TimeDelta SourceBufferRange::GetNextTimestamp() const {
1883 DCHECK(!buffers_.empty()); 1963 DCHECK(!buffers_.empty());
1884 DCHECK(HasNextBufferPosition()); 1964 DCHECK(HasNextBufferPosition());
1885 1965
1886 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) { 1966 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
1887 return kNoTimestamp(); 1967 return kNoTimestamp();
1888 } 1968 }
1889 1969
1890 return buffers_.at(next_buffer_index_)->GetDecodeTimestamp(); 1970 return buffers_[next_buffer_index_]->GetDecodeTimestamp();
1891 } 1971 }
1892 1972
1893 bool SourceBufferRange::HasNextBufferPosition() const { 1973 bool SourceBufferRange::HasNextBufferPosition() const {
1894 return next_buffer_index_ >= 0; 1974 return next_buffer_index_ >= 0;
1895 } 1975 }
1896 1976
1897 void SourceBufferRange::ResetNextBufferPosition() { 1977 void SourceBufferRange::ResetNextBufferPosition() {
1898 next_buffer_index_ = -1; 1978 next_buffer_index_ = -1;
1899 } 1979 }
1900 1980
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
2007 return ComputeFudgeRoom(GetApproximateDuration()); 2087 return ComputeFudgeRoom(GetApproximateDuration());
2008 } 2088 }
2009 2089
2010 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { 2090 base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
2011 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run(); 2091 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
2012 DCHECK(max_interbuffer_distance != kNoTimestamp()); 2092 DCHECK(max_interbuffer_distance != kNoTimestamp());
2013 return max_interbuffer_distance; 2093 return max_interbuffer_distance;
2014 } 2094 }
2015 2095
2016 } // namespace media 2096 } // 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