OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |