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

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

Issue 1091293005: MSE: Relax the 'media segment must begin with keyframe' requirement (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Try to fix bot flakes by strictly ordering the blocks in muxed test 3 Created 4 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
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 #include <sstream> 9 #include <sstream>
10 10
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 return SourceBufferRange::NO_GAPS_ALLOWED; 130 return SourceBufferRange::NO_GAPS_ALLOWED;
131 } 131 }
132 132
133 } // namespace 133 } // namespace
134 134
135 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, 135 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config,
136 const scoped_refptr<MediaLog>& media_log, 136 const scoped_refptr<MediaLog>& media_log,
137 bool splice_frames_enabled) 137 bool splice_frames_enabled)
138 : media_log_(media_log), 138 : media_log_(media_log),
139 seek_buffer_timestamp_(kNoTimestamp()), 139 seek_buffer_timestamp_(kNoTimestamp()),
140 media_segment_start_time_(kNoDecodeTimestamp()), 140 coded_frame_group_start_time_(kNoDecodeTimestamp()),
141 range_for_next_append_(ranges_.end()), 141 range_for_next_append_(ranges_.end()),
142 last_output_buffer_timestamp_(kNoDecodeTimestamp()), 142 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
143 max_interbuffer_distance_(kNoTimestamp()), 143 max_interbuffer_distance_(kNoTimestamp()),
144 memory_limit_(kSourceBufferAudioMemoryLimit), 144 memory_limit_(kSourceBufferAudioMemoryLimit),
145 splice_frames_enabled_(splice_frames_enabled) { 145 splice_frames_enabled_(splice_frames_enabled) {
146 DCHECK(audio_config.IsValidConfig()); 146 DCHECK(audio_config.IsValidConfig());
147 audio_configs_.push_back(audio_config); 147 audio_configs_.push_back(audio_config);
148 } 148 }
149 149
150 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, 150 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
151 const scoped_refptr<MediaLog>& media_log, 151 const scoped_refptr<MediaLog>& media_log,
152 bool splice_frames_enabled) 152 bool splice_frames_enabled)
153 : media_log_(media_log), 153 : media_log_(media_log),
154 seek_buffer_timestamp_(kNoTimestamp()), 154 seek_buffer_timestamp_(kNoTimestamp()),
155 media_segment_start_time_(kNoDecodeTimestamp()), 155 coded_frame_group_start_time_(kNoDecodeTimestamp()),
156 range_for_next_append_(ranges_.end()), 156 range_for_next_append_(ranges_.end()),
157 last_output_buffer_timestamp_(kNoDecodeTimestamp()), 157 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
158 max_interbuffer_distance_(kNoTimestamp()), 158 max_interbuffer_distance_(kNoTimestamp()),
159 memory_limit_(kSourceBufferVideoMemoryLimit), 159 memory_limit_(kSourceBufferVideoMemoryLimit),
160 splice_frames_enabled_(splice_frames_enabled) { 160 splice_frames_enabled_(splice_frames_enabled) {
161 DCHECK(video_config.IsValidConfig()); 161 DCHECK(video_config.IsValidConfig());
162 video_configs_.push_back(video_config); 162 video_configs_.push_back(video_config);
163 } 163 }
164 164
165 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, 165 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
166 const scoped_refptr<MediaLog>& media_log, 166 const scoped_refptr<MediaLog>& media_log,
167 bool splice_frames_enabled) 167 bool splice_frames_enabled)
168 : media_log_(media_log), 168 : media_log_(media_log),
169 text_track_config_(text_config), 169 text_track_config_(text_config),
170 seek_buffer_timestamp_(kNoTimestamp()), 170 seek_buffer_timestamp_(kNoTimestamp()),
171 media_segment_start_time_(kNoDecodeTimestamp()), 171 coded_frame_group_start_time_(kNoDecodeTimestamp()),
172 range_for_next_append_(ranges_.end()), 172 range_for_next_append_(ranges_.end()),
173 last_output_buffer_timestamp_(kNoDecodeTimestamp()), 173 last_output_buffer_timestamp_(kNoDecodeTimestamp()),
174 max_interbuffer_distance_(kNoTimestamp()), 174 max_interbuffer_distance_(kNoTimestamp()),
175 memory_limit_(kSourceBufferAudioMemoryLimit), 175 memory_limit_(kSourceBufferAudioMemoryLimit),
176 splice_frames_enabled_(splice_frames_enabled) {} 176 splice_frames_enabled_(splice_frames_enabled) {}
177 177
178 SourceBufferStream::~SourceBufferStream() { 178 SourceBufferStream::~SourceBufferStream() {
179 while (!ranges_.empty()) { 179 while (!ranges_.empty()) {
180 delete ranges_.front(); 180 delete ranges_.front();
181 ranges_.pop_front(); 181 ranges_.pop_front();
182 } 182 }
183 } 183 }
184 184
185 void SourceBufferStream::OnNewMediaSegment( 185 void SourceBufferStream::OnStartOfCodedFrameGroup(
186 DecodeTimestamp media_segment_start_time) { 186 DecodeTimestamp coded_frame_group_start_time) {
187 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() 187 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << " ("
188 << " (" << media_segment_start_time.InSecondsF() << ")"; 188 << coded_frame_group_start_time.InSecondsF() << ")";
189 DCHECK(!end_of_stream_); 189 DCHECK(!end_of_stream_);
190 media_segment_start_time_ = media_segment_start_time; 190 coded_frame_group_start_time_ = coded_frame_group_start_time;
191 new_media_segment_ = true; 191 new_coded_frame_group_ = true;
192 192
193 RangeList::iterator last_range = range_for_next_append_; 193 RangeList::iterator last_range = range_for_next_append_;
194 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time); 194 range_for_next_append_ = FindExistingRangeFor(coded_frame_group_start_time);
195 195
196 // Only reset |last_appended_buffer_timestamp_| if this new media segment is 196 // Only reset |last_appended_buffer_timestamp_| if this new coded frame group
197 // not adjacent to the previous media segment appended to the stream. 197 // is not adjacent to the previous coded frame group appended to the stream.
198 if (range_for_next_append_ == ranges_.end() || 198 if (range_for_next_append_ == ranges_.end() ||
199 !AreAdjacentInSequence(last_appended_buffer_timestamp_, 199 !AreAdjacentInSequence(last_appended_buffer_timestamp_,
200 media_segment_start_time)) { 200 coded_frame_group_start_time)) {
201 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); 201 last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
202 last_appended_buffer_duration_ = kNoTimestamp(); 202 last_appended_buffer_duration_ = kNoTimestamp();
203 last_appended_buffer_is_keyframe_ = false; 203 last_appended_buffer_is_keyframe_ = false;
204 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range"; 204 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range";
205 } else if (last_range != ranges_.end()) { 205 } else if (last_range != ranges_.end()) {
206 DCHECK(last_range == range_for_next_append_); 206 DCHECK(last_range == range_for_next_append_);
207 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " 207 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range "
208 << "unless intervening remove makes discontinuity"; 208 << "unless intervening remove makes discontinuity";
209 } 209 }
210 } 210 }
211 211
212 bool SourceBufferStream::Append(const BufferQueue& buffers) { 212 bool SourceBufferStream::Append(const BufferQueue& buffers) {
213 TRACE_EVENT2("media", "SourceBufferStream::Append", 213 TRACE_EVENT2("media", "SourceBufferStream::Append",
214 "stream type", GetStreamTypeName(), 214 "stream type", GetStreamTypeName(),
215 "buffers to append", buffers.size()); 215 "buffers to append", buffers.size());
216 216
217 DCHECK(!buffers.empty()); 217 DCHECK(!buffers.empty());
218 DCHECK(media_segment_start_time_ != kNoDecodeTimestamp()); 218 DCHECK(coded_frame_group_start_time_ != kNoDecodeTimestamp());
219 DCHECK(media_segment_start_time_ <= buffers.front()->GetDecodeTimestamp()); 219 DCHECK(coded_frame_group_start_time_ <=
220 buffers.front()->GetDecodeTimestamp());
220 DCHECK(!end_of_stream_); 221 DCHECK(!end_of_stream_);
221 222
222 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() 223 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
223 << ": buffers " << BufferQueueToLogString(buffers); 224 << ": buffers " << BufferQueueToLogString(buffers);
224 225
225 // New media segments must begin with a keyframe. 226 // New coded frame groups emitted by the coded frame processor must begin with
226 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412. 227 // a keyframe.
227 if (new_media_segment_ && !buffers.front()->is_key_frame()) { 228 CHECK(!new_coded_frame_group_ || buffers.front()->is_key_frame());
chcunningham 2016/01/22 01:26:38 Just to confirm/document: this is a CHECK because
wolenetz 2016/01/22 01:50:03 Correct. Normally I'd use a DCHECK for something l
wolenetz 2016/01/22 18:59:31 From offline chat w/chcunningham@, temporary CHECK
chcunningham 2016/01/22 19:26:02 Acknowledged.
228 MEDIA_LOG(ERROR, media_log_) << "Media segment did not begin with key " 229
229 "frame. Support for such segments will be " 230 // Buffers within a coded frame group should be monotonically increasing.
230 "available in a future version. Please see " 231 if (!IsMonotonicallyIncreasing(buffers)) {
231 "https://crbug.com/229412.";
232 return false; 232 return false;
233 } 233 }
234 234
235 // Buffers within a media segment should be monotonically increasing. 235 if (coded_frame_group_start_time_ < DecodeTimestamp() ||
236 if (!IsMonotonicallyIncreasing(buffers))
237 return false;
238
239 if (media_segment_start_time_ < DecodeTimestamp() ||
240 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) { 236 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
241 MEDIA_LOG(ERROR, media_log_) 237 MEDIA_LOG(ERROR, media_log_)
242 << "Cannot append a media segment with negative timestamps."; 238 << "Cannot append a coded frame group with negative timestamps.";
243 return false; 239 return false;
244 } 240 }
245 241
246 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(), 242 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(),
247 buffers.front()->is_key_frame())) { 243 buffers.front()->is_key_frame())) {
248 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp(); 244 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp();
249 MEDIA_LOG(ERROR, media_log_) 245 MEDIA_LOG(ERROR, media_log_)
250 << "Invalid same timestamp construct detected at" 246 << "Invalid same timestamp construct detected at"
251 << " time " << dts.InSecondsF(); 247 << " time " << dts.InSecondsF();
252 248
(...skipping 11 matching lines...) Expand all
264 260
265 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, 261 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
266 // create a new range with |buffers|. 262 // create a new range with |buffers|.
267 if (range_for_next_append_ != ranges_.end()) { 263 if (range_for_next_append_ != ranges_.end()) {
268 (*range_for_next_append_)->AppendBuffersToEnd(buffers); 264 (*range_for_next_append_)->AppendBuffersToEnd(buffers);
269 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); 265 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
270 last_appended_buffer_duration_ = buffers.back()->duration(); 266 last_appended_buffer_duration_ = buffers.back()->duration();
271 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); 267 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
272 } else { 268 } else {
273 DecodeTimestamp new_range_start_time = std::min( 269 DecodeTimestamp new_range_start_time = std::min(
274 media_segment_start_time_, buffers.front()->GetDecodeTimestamp()); 270 coded_frame_group_start_time_, buffers.front()->GetDecodeTimestamp());
275 const BufferQueue* buffers_for_new_range = &buffers; 271 const BufferQueue* buffers_for_new_range = &buffers;
276 BufferQueue trimmed_buffers; 272 BufferQueue trimmed_buffers;
277 273
278 // If the new range is not being created because of a new media 274 // If the new range is not being created because of a new coded frame group,
279 // segment, then we must make sure that we start with a key frame. 275 // then we must make sure that we start with a key frame. This can happen
280 // This can happen if the GOP in the previous append gets destroyed 276 // if the GOP in the previous append gets destroyed by a Remove() call.
281 // by a Remove() call. 277 if (!new_coded_frame_group_) {
282 if (!new_media_segment_) {
283 BufferQueue::const_iterator itr = buffers.begin(); 278 BufferQueue::const_iterator itr = buffers.begin();
284 279
285 // Scan past all the non-key-frames. 280 // Scan past all the non-key-frames.
286 while (itr != buffers.end() && !(*itr)->is_key_frame()) { 281 while (itr != buffers.end() && !(*itr)->is_key_frame()) {
287 ++itr; 282 ++itr;
288 } 283 }
289 284
290 // If we didn't find a key frame, then update the last appended 285 // If we didn't find a key frame, then update the last appended
291 // buffer state and return. 286 // buffer state and return.
292 if (itr == buffers.end()) { 287 if (itr == buffers.end()) {
(...skipping 24 matching lines...) Expand all
317 *buffers_for_new_range, new_range_start_time, 312 *buffers_for_new_range, new_range_start_time,
318 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, 313 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
319 base::Unretained(this)))); 314 base::Unretained(this))));
320 last_appended_buffer_timestamp_ = 315 last_appended_buffer_timestamp_ =
321 buffers_for_new_range->back()->GetDecodeTimestamp(); 316 buffers_for_new_range->back()->GetDecodeTimestamp();
322 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration(); 317 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration();
323 last_appended_buffer_is_keyframe_ = 318 last_appended_buffer_is_keyframe_ =
324 buffers_for_new_range->back()->is_key_frame(); 319 buffers_for_new_range->back()->is_key_frame();
325 } 320 }
326 321
327 new_media_segment_ = false; 322 new_coded_frame_group_ = false;
328 323
329 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); 324 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
330 325
331 // Seek to try to fulfill a previous call to Seek(). 326 // Seek to try to fulfill a previous call to Seek().
332 if (seek_pending_) { 327 if (seek_pending_) {
333 DCHECK(!selected_range_); 328 DCHECK(!selected_range_);
334 DCHECK(deleted_buffers.empty()); 329 DCHECK(deleted_buffers.empty());
335 Seek(seek_buffer_timestamp_); 330 Seek(seek_buffer_timestamp_);
336 } 331 }
337 332
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 552
558 prev_timestamp = current_timestamp; 553 prev_timestamp = current_timestamp;
559 prev_is_keyframe = current_is_keyframe; 554 prev_is_keyframe = current_is_keyframe;
560 } 555 }
561 return true; 556 return true;
562 } 557 }
563 558
564 bool SourceBufferStream::IsNextTimestampValid( 559 bool SourceBufferStream::IsNextTimestampValid(
565 DecodeTimestamp next_timestamp, bool next_is_keyframe) const { 560 DecodeTimestamp next_timestamp, bool next_is_keyframe) const {
566 return (last_appended_buffer_timestamp_ != next_timestamp) || 561 return (last_appended_buffer_timestamp_ != next_timestamp) ||
567 new_media_segment_ || 562 new_coded_frame_group_ ||
568 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_, 563 SourceBufferRange::AllowSameTimestamp(
569 next_is_keyframe); 564 last_appended_buffer_is_keyframe_, next_is_keyframe);
570 } 565 }
571 566
572 567
573 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const { 568 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
574 for (RangeList::const_iterator itr = ranges_.begin(); 569 for (RangeList::const_iterator itr = ranges_.begin();
575 itr != ranges_.end(); ++itr) { 570 itr != ranges_.end(); ++itr) {
576 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_) 571 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_)
577 return false; 572 return false;
578 } 573 }
579 return !selected_range_ || selected_range_->HasNextBufferPosition(); 574 return !selected_range_ || selected_range_->HasNextBufferPosition();
(...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1782 return false; 1777 return false;
1783 1778
1784 DCHECK_NE(have_splice_buffers, have_preroll_buffer); 1779 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
1785 splice_buffers_index_ = 0; 1780 splice_buffers_index_ = 0;
1786 pending_buffer_.swap(*out_buffer); 1781 pending_buffer_.swap(*out_buffer);
1787 pending_buffers_complete_ = false; 1782 pending_buffers_complete_ = false;
1788 return true; 1783 return true;
1789 } 1784 }
1790 1785
1791 } // namespace media 1786 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698