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

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: Rebased(noop) + addressed comments from PS12 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
« 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 #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. TODO(wolenetz): Change this to [DCHECK + MEDIA_LOG(ERROR...) +
227 if (new_media_segment_ && !buffers.front()->is_key_frame()) { 228 // return false] once the CHECK has baked in a stable release. See
228 MEDIA_LOG(ERROR, media_log_) << "Media segment did not begin with key " 229 // https://crbug.com/580621.
229 "frame. Support for such segments will be " 230 CHECK(!new_coded_frame_group_ || buffers.front()->is_key_frame());
230 "available in a future version. Please see " 231
231 "https://crbug.com/229412."; 232 // Buffers within a coded frame group should be monotonically increasing.
233 if (!IsMonotonicallyIncreasing(buffers)) {
232 return false; 234 return false;
233 } 235 }
234 236
235 // Buffers within a media segment should be monotonically increasing. 237 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()) { 238 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
241 MEDIA_LOG(ERROR, media_log_) 239 MEDIA_LOG(ERROR, media_log_)
242 << "Cannot append a media segment with negative timestamps."; 240 << "Cannot append a coded frame group with negative timestamps.";
243 return false; 241 return false;
244 } 242 }
245 243
246 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(), 244 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(),
247 buffers.front()->is_key_frame())) { 245 buffers.front()->is_key_frame())) {
248 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp(); 246 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp();
249 MEDIA_LOG(ERROR, media_log_) 247 MEDIA_LOG(ERROR, media_log_)
250 << "Invalid same timestamp construct detected at" 248 << "Invalid same timestamp construct detected at"
251 << " time " << dts.InSecondsF(); 249 << " time " << dts.InSecondsF();
252 250
(...skipping 11 matching lines...) Expand all
264 262
265 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, 263 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
266 // create a new range with |buffers|. 264 // create a new range with |buffers|.
267 if (range_for_next_append_ != ranges_.end()) { 265 if (range_for_next_append_ != ranges_.end()) {
268 (*range_for_next_append_)->AppendBuffersToEnd(buffers); 266 (*range_for_next_append_)->AppendBuffersToEnd(buffers);
269 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); 267 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
270 last_appended_buffer_duration_ = buffers.back()->duration(); 268 last_appended_buffer_duration_ = buffers.back()->duration();
271 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); 269 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
272 } else { 270 } else {
273 DecodeTimestamp new_range_start_time = std::min( 271 DecodeTimestamp new_range_start_time = std::min(
274 media_segment_start_time_, buffers.front()->GetDecodeTimestamp()); 272 coded_frame_group_start_time_, buffers.front()->GetDecodeTimestamp());
275 const BufferQueue* buffers_for_new_range = &buffers; 273 const BufferQueue* buffers_for_new_range = &buffers;
276 BufferQueue trimmed_buffers; 274 BufferQueue trimmed_buffers;
277 275
278 // If the new range is not being created because of a new media 276 // 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. 277 // 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 278 // if the GOP in the previous append gets destroyed by a Remove() call.
281 // by a Remove() call. 279 if (!new_coded_frame_group_) {
282 if (!new_media_segment_) {
283 BufferQueue::const_iterator itr = buffers.begin(); 280 BufferQueue::const_iterator itr = buffers.begin();
284 281
285 // Scan past all the non-key-frames. 282 // Scan past all the non-key-frames.
286 while (itr != buffers.end() && !(*itr)->is_key_frame()) { 283 while (itr != buffers.end() && !(*itr)->is_key_frame()) {
287 ++itr; 284 ++itr;
288 } 285 }
289 286
290 // If we didn't find a key frame, then update the last appended 287 // If we didn't find a key frame, then update the last appended
291 // buffer state and return. 288 // buffer state and return.
292 if (itr == buffers.end()) { 289 if (itr == buffers.end()) {
(...skipping 24 matching lines...) Expand all
317 *buffers_for_new_range, new_range_start_time, 314 *buffers_for_new_range, new_range_start_time,
318 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, 315 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
319 base::Unretained(this)))); 316 base::Unretained(this))));
320 last_appended_buffer_timestamp_ = 317 last_appended_buffer_timestamp_ =
321 buffers_for_new_range->back()->GetDecodeTimestamp(); 318 buffers_for_new_range->back()->GetDecodeTimestamp();
322 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration(); 319 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration();
323 last_appended_buffer_is_keyframe_ = 320 last_appended_buffer_is_keyframe_ =
324 buffers_for_new_range->back()->is_key_frame(); 321 buffers_for_new_range->back()->is_key_frame();
325 } 322 }
326 323
327 new_media_segment_ = false; 324 new_coded_frame_group_ = false;
328 325
329 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); 326 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
330 327
331 // Seek to try to fulfill a previous call to Seek(). 328 // Seek to try to fulfill a previous call to Seek().
332 if (seek_pending_) { 329 if (seek_pending_) {
333 DCHECK(!selected_range_); 330 DCHECK(!selected_range_);
334 DCHECK(deleted_buffers.empty()); 331 DCHECK(deleted_buffers.empty());
335 Seek(seek_buffer_timestamp_); 332 Seek(seek_buffer_timestamp_);
336 } 333 }
337 334
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 554
558 prev_timestamp = current_timestamp; 555 prev_timestamp = current_timestamp;
559 prev_is_keyframe = current_is_keyframe; 556 prev_is_keyframe = current_is_keyframe;
560 } 557 }
561 return true; 558 return true;
562 } 559 }
563 560
564 bool SourceBufferStream::IsNextTimestampValid( 561 bool SourceBufferStream::IsNextTimestampValid(
565 DecodeTimestamp next_timestamp, bool next_is_keyframe) const { 562 DecodeTimestamp next_timestamp, bool next_is_keyframe) const {
566 return (last_appended_buffer_timestamp_ != next_timestamp) || 563 return (last_appended_buffer_timestamp_ != next_timestamp) ||
567 new_media_segment_ || 564 new_coded_frame_group_ ||
568 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_, 565 SourceBufferRange::AllowSameTimestamp(
569 next_is_keyframe); 566 last_appended_buffer_is_keyframe_, next_is_keyframe);
570 } 567 }
571 568
572 569
573 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const { 570 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
574 for (RangeList::const_iterator itr = ranges_.begin(); 571 for (RangeList::const_iterator itr = ranges_.begin();
575 itr != ranges_.end(); ++itr) { 572 itr != ranges_.end(); ++itr) {
576 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_) 573 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_)
577 return false; 574 return false;
578 } 575 }
579 return !selected_range_ || selected_range_->HasNextBufferPosition(); 576 return !selected_range_ || selected_range_->HasNextBufferPosition();
(...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1782 return false; 1779 return false;
1783 1780
1784 DCHECK_NE(have_splice_buffers, have_preroll_buffer); 1781 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
1785 splice_buffers_index_ = 0; 1782 splice_buffers_index_ = 0;
1786 pending_buffer_.swap(*out_buffer); 1783 pending_buffer_.swap(*out_buffer);
1787 pending_buffers_complete_ = false; 1784 pending_buffers_complete_ = false;
1788 return true; 1785 return true;
1789 } 1786 }
1790 1787
1791 } // namespace media 1788 } // 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