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

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

Issue 1637213002: Revert of MSE: Relax the 'media segment must begin with keyframe' requirement (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 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 coded_frame_group_start_time_(kNoDecodeTimestamp()), 140 media_segment_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 coded_frame_group_start_time_(kNoDecodeTimestamp()), 155 media_segment_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 coded_frame_group_start_time_(kNoDecodeTimestamp()), 171 media_segment_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::OnStartOfCodedFrameGroup( 185 void SourceBufferStream::OnNewMediaSegment(
186 DecodeTimestamp coded_frame_group_start_time) { 186 DecodeTimestamp media_segment_start_time) {
187 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << " (" 187 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
188 << coded_frame_group_start_time.InSecondsF() << ")"; 188 << " (" << media_segment_start_time.InSecondsF() << ")";
189 DCHECK(!end_of_stream_); 189 DCHECK(!end_of_stream_);
190 coded_frame_group_start_time_ = coded_frame_group_start_time; 190 media_segment_start_time_ = media_segment_start_time;
191 new_coded_frame_group_ = true; 191 new_media_segment_ = 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(coded_frame_group_start_time); 194 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time);
195 195
196 // Only reset |last_appended_buffer_timestamp_| if this new coded frame group 196 // Only reset |last_appended_buffer_timestamp_| if this new media segment is
197 // is not adjacent to the previous coded frame group appended to the stream. 197 // not adjacent to the previous media segment 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 coded_frame_group_start_time)) { 200 media_segment_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(coded_frame_group_start_time_ != kNoDecodeTimestamp()); 218 DCHECK(media_segment_start_time_ != kNoDecodeTimestamp());
219 DCHECK(coded_frame_group_start_time_ <= 219 DCHECK(media_segment_start_time_ <= buffers.front()->GetDecodeTimestamp());
220 buffers.front()->GetDecodeTimestamp());
221 DCHECK(!end_of_stream_); 220 DCHECK(!end_of_stream_);
222 221
223 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() 222 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName()
224 << ": buffers " << BufferQueueToLogString(buffers); 223 << ": buffers " << BufferQueueToLogString(buffers);
225 224
226 // New coded frame groups emitted by the coded frame processor must begin with 225 // New media segments must begin with a keyframe.
227 // a keyframe. TODO(wolenetz): Change this to [DCHECK + MEDIA_LOG(ERROR...) + 226 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412.
228 // return false] once the CHECK has baked in a stable release. See 227 if (new_media_segment_ && !buffers.front()->is_key_frame()) {
229 // https://crbug.com/580621. 228 MEDIA_LOG(ERROR, media_log_) << "Media segment did not begin with key "
230 CHECK(!new_coded_frame_group_ || buffers.front()->is_key_frame()); 229 "frame. Support for such segments will be "
231 230 "available in a future version. Please see "
232 // Buffers within a coded frame group should be monotonically increasing. 231 "https://crbug.com/229412.";
233 if (!IsMonotonicallyIncreasing(buffers)) {
234 return false; 232 return false;
235 } 233 }
236 234
237 if (coded_frame_group_start_time_ < DecodeTimestamp() || 235 // Buffers within a media segment should be monotonically increasing.
236 if (!IsMonotonicallyIncreasing(buffers))
237 return false;
238
239 if (media_segment_start_time_ < DecodeTimestamp() ||
238 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) { 240 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) {
239 MEDIA_LOG(ERROR, media_log_) 241 MEDIA_LOG(ERROR, media_log_)
240 << "Cannot append a coded frame group with negative timestamps."; 242 << "Cannot append a media segment with negative timestamps.";
241 return false; 243 return false;
242 } 244 }
243 245
244 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(), 246 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(),
245 buffers.front()->is_key_frame())) { 247 buffers.front()->is_key_frame())) {
246 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp(); 248 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp();
247 MEDIA_LOG(ERROR, media_log_) 249 MEDIA_LOG(ERROR, media_log_)
248 << "Invalid same timestamp construct detected at" 250 << "Invalid same timestamp construct detected at"
249 << " time " << dts.InSecondsF(); 251 << " time " << dts.InSecondsF();
250 252
(...skipping 11 matching lines...) Expand all
262 264
263 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, 265 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
264 // create a new range with |buffers|. 266 // create a new range with |buffers|.
265 if (range_for_next_append_ != ranges_.end()) { 267 if (range_for_next_append_ != ranges_.end()) {
266 (*range_for_next_append_)->AppendBuffersToEnd(buffers); 268 (*range_for_next_append_)->AppendBuffersToEnd(buffers);
267 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); 269 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();
268 last_appended_buffer_duration_ = buffers.back()->duration(); 270 last_appended_buffer_duration_ = buffers.back()->duration();
269 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); 271 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
270 } else { 272 } else {
271 DecodeTimestamp new_range_start_time = std::min( 273 DecodeTimestamp new_range_start_time = std::min(
272 coded_frame_group_start_time_, buffers.front()->GetDecodeTimestamp()); 274 media_segment_start_time_, buffers.front()->GetDecodeTimestamp());
273 const BufferQueue* buffers_for_new_range = &buffers; 275 const BufferQueue* buffers_for_new_range = &buffers;
274 BufferQueue trimmed_buffers; 276 BufferQueue trimmed_buffers;
275 277
276 // If the new range is not being created because of a new coded frame group, 278 // If the new range is not being created because of a new media
277 // then we must make sure that we start with a key frame. This can happen 279 // segment, then we must make sure that we start with a key frame.
278 // if the GOP in the previous append gets destroyed by a Remove() call. 280 // This can happen if the GOP in the previous append gets destroyed
279 if (!new_coded_frame_group_) { 281 // by a Remove() call.
282 if (!new_media_segment_) {
280 BufferQueue::const_iterator itr = buffers.begin(); 283 BufferQueue::const_iterator itr = buffers.begin();
281 284
282 // Scan past all the non-key-frames. 285 // Scan past all the non-key-frames.
283 while (itr != buffers.end() && !(*itr)->is_key_frame()) { 286 while (itr != buffers.end() && !(*itr)->is_key_frame()) {
284 ++itr; 287 ++itr;
285 } 288 }
286 289
287 // If we didn't find a key frame, then update the last appended 290 // If we didn't find a key frame, then update the last appended
288 // buffer state and return. 291 // buffer state and return.
289 if (itr == buffers.end()) { 292 if (itr == buffers.end()) {
(...skipping 24 matching lines...) Expand all
314 *buffers_for_new_range, new_range_start_time, 317 *buffers_for_new_range, new_range_start_time,
315 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, 318 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
316 base::Unretained(this)))); 319 base::Unretained(this))));
317 last_appended_buffer_timestamp_ = 320 last_appended_buffer_timestamp_ =
318 buffers_for_new_range->back()->GetDecodeTimestamp(); 321 buffers_for_new_range->back()->GetDecodeTimestamp();
319 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration(); 322 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration();
320 last_appended_buffer_is_keyframe_ = 323 last_appended_buffer_is_keyframe_ =
321 buffers_for_new_range->back()->is_key_frame(); 324 buffers_for_new_range->back()->is_key_frame();
322 } 325 }
323 326
324 new_coded_frame_group_ = false; 327 new_media_segment_ = false;
325 328
326 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); 329 MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
327 330
328 // Seek to try to fulfill a previous call to Seek(). 331 // Seek to try to fulfill a previous call to Seek().
329 if (seek_pending_) { 332 if (seek_pending_) {
330 DCHECK(!selected_range_); 333 DCHECK(!selected_range_);
331 DCHECK(deleted_buffers.empty()); 334 DCHECK(deleted_buffers.empty());
332 Seek(seek_buffer_timestamp_); 335 Seek(seek_buffer_timestamp_);
333 } 336 }
334 337
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 557
555 prev_timestamp = current_timestamp; 558 prev_timestamp = current_timestamp;
556 prev_is_keyframe = current_is_keyframe; 559 prev_is_keyframe = current_is_keyframe;
557 } 560 }
558 return true; 561 return true;
559 } 562 }
560 563
561 bool SourceBufferStream::IsNextTimestampValid( 564 bool SourceBufferStream::IsNextTimestampValid(
562 DecodeTimestamp next_timestamp, bool next_is_keyframe) const { 565 DecodeTimestamp next_timestamp, bool next_is_keyframe) const {
563 return (last_appended_buffer_timestamp_ != next_timestamp) || 566 return (last_appended_buffer_timestamp_ != next_timestamp) ||
564 new_coded_frame_group_ || 567 new_media_segment_ ||
565 SourceBufferRange::AllowSameTimestamp( 568 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_,
566 last_appended_buffer_is_keyframe_, next_is_keyframe); 569 next_is_keyframe);
567 } 570 }
568 571
569 572
570 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const { 573 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
571 for (RangeList::const_iterator itr = ranges_.begin(); 574 for (RangeList::const_iterator itr = ranges_.begin();
572 itr != ranges_.end(); ++itr) { 575 itr != ranges_.end(); ++itr) {
573 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_) 576 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_)
574 return false; 577 return false;
575 } 578 }
576 return !selected_range_ || selected_range_->HasNextBufferPosition(); 579 return !selected_range_ || selected_range_->HasNextBufferPosition();
(...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1779 return false; 1782 return false;
1780 1783
1781 DCHECK_NE(have_splice_buffers, have_preroll_buffer); 1784 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
1782 splice_buffers_index_ = 0; 1785 splice_buffers_index_ = 0;
1783 pending_buffer_.swap(*out_buffer); 1786 pending_buffer_.swap(*out_buffer);
1784 pending_buffers_complete_ = false; 1787 pending_buffers_complete_ = false;
1785 return true; 1788 return true;
1786 } 1789 }
1787 1790
1788 } // namespace media 1791 } // 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