 Chromium Code Reviews
 Chromium Code Reviews Issue 1670033002:
  Reland: MSE: Relax the 'media segment must begin with keyframe' requirement  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 1670033002:
  Reland: MSE: Relax the 'media segment must begin with keyframe' requirement  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| 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 19 matching lines...) Expand all Loading... | |
| 30 // important for debugging splice generation. | 30 // important for debugging splice generation. | 
| 31 const int kMaxSpliceGenerationWarningLogs = 50; | 31 const int kMaxSpliceGenerationWarningLogs = 50; | 
| 32 const int kMaxSpliceGenerationSuccessLogs = 20; | 32 const int kMaxSpliceGenerationSuccessLogs = 20; | 
| 33 | 33 | 
| 34 // Limit the number of MEDIA_LOG() logs for track buffer time gaps. | 34 // Limit the number of MEDIA_LOG() logs for track buffer time gaps. | 
| 35 const int kMaxTrackBufferGapWarningLogs = 20; | 35 const int kMaxTrackBufferGapWarningLogs = 20; | 
| 36 | 36 | 
| 37 // Limit the number of MEDIA_LOG() logs for MSE GC algorithm warnings. | 37 // Limit the number of MEDIA_LOG() logs for MSE GC algorithm warnings. | 
| 38 const int kMaxGarbageCollectAlgorithmWarningLogs = 20; | 38 const int kMaxGarbageCollectAlgorithmWarningLogs = 20; | 
| 39 | 39 | 
| 40 // Limit the number of MEDIA_LOG() logs for same DTS for non-keyframe followed | |
| 41 // by keyframe. Prior to relaxing the "media segments must begin with a | |
| 42 // keyframe" requirement, we issued decode error for this situation. That was | |
| 43 // likely too strict, and now that the keyframe requirement is relaxed, we have | |
| 44 // no knowledge of media segment boundaries here. Now, we log but don't trigger | |
| 45 // decode error, since we allow these sequences which may cause extra decoder | |
| 46 // work or other side-effects. | |
| 47 const int kMaxStrangeSameTimestampsLogs = 20; | |
| 48 | |
| 40 // Helper method that returns true if |ranges| is sorted in increasing order, | 49 // Helper method that returns true if |ranges| is sorted in increasing order, | 
| 41 // false otherwise. | 50 // false otherwise. | 
| 42 bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) { | 51 bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) { | 
| 43 DecodeTimestamp prev = kNoDecodeTimestamp(); | 52 DecodeTimestamp prev = kNoDecodeTimestamp(); | 
| 44 for (std::list<SourceBufferRange*>::const_iterator itr = | 53 for (std::list<SourceBufferRange*>::const_iterator itr = | 
| 45 ranges.begin(); itr != ranges.end(); ++itr) { | 54 ranges.begin(); itr != ranges.end(); ++itr) { | 
| 46 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp()) | 55 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp()) | 
| 47 return false; | 56 return false; | 
| 48 prev = (*itr)->GetEndTimestamp(); | 57 prev = (*itr)->GetEndTimestamp(); | 
| 49 } | 58 } | 
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 return SourceBufferRange::NO_GAPS_ALLOWED; | 139 return SourceBufferRange::NO_GAPS_ALLOWED; | 
| 131 } | 140 } | 
| 132 | 141 | 
| 133 } // namespace | 142 } // namespace | 
| 134 | 143 | 
| 135 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, | 144 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, | 
| 136 const scoped_refptr<MediaLog>& media_log, | 145 const scoped_refptr<MediaLog>& media_log, | 
| 137 bool splice_frames_enabled) | 146 bool splice_frames_enabled) | 
| 138 : media_log_(media_log), | 147 : media_log_(media_log), | 
| 139 seek_buffer_timestamp_(kNoTimestamp()), | 148 seek_buffer_timestamp_(kNoTimestamp()), | 
| 140 media_segment_start_time_(kNoDecodeTimestamp()), | 149 coded_frame_group_start_time_(kNoDecodeTimestamp()), | 
| 141 range_for_next_append_(ranges_.end()), | 150 range_for_next_append_(ranges_.end()), | 
| 142 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 151 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 
| 143 max_interbuffer_distance_(kNoTimestamp()), | 152 max_interbuffer_distance_(kNoTimestamp()), | 
| 144 memory_limit_(kSourceBufferAudioMemoryLimit), | 153 memory_limit_(kSourceBufferAudioMemoryLimit), | 
| 145 splice_frames_enabled_(splice_frames_enabled) { | 154 splice_frames_enabled_(splice_frames_enabled) { | 
| 146 DCHECK(audio_config.IsValidConfig()); | 155 DCHECK(audio_config.IsValidConfig()); | 
| 147 audio_configs_.push_back(audio_config); | 156 audio_configs_.push_back(audio_config); | 
| 148 } | 157 } | 
| 149 | 158 | 
| 150 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 159 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 
| 151 const scoped_refptr<MediaLog>& media_log, | 160 const scoped_refptr<MediaLog>& media_log, | 
| 152 bool splice_frames_enabled) | 161 bool splice_frames_enabled) | 
| 153 : media_log_(media_log), | 162 : media_log_(media_log), | 
| 154 seek_buffer_timestamp_(kNoTimestamp()), | 163 seek_buffer_timestamp_(kNoTimestamp()), | 
| 155 media_segment_start_time_(kNoDecodeTimestamp()), | 164 coded_frame_group_start_time_(kNoDecodeTimestamp()), | 
| 156 range_for_next_append_(ranges_.end()), | 165 range_for_next_append_(ranges_.end()), | 
| 157 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 166 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 
| 158 max_interbuffer_distance_(kNoTimestamp()), | 167 max_interbuffer_distance_(kNoTimestamp()), | 
| 159 memory_limit_(kSourceBufferVideoMemoryLimit), | 168 memory_limit_(kSourceBufferVideoMemoryLimit), | 
| 160 splice_frames_enabled_(splice_frames_enabled) { | 169 splice_frames_enabled_(splice_frames_enabled) { | 
| 161 DCHECK(video_config.IsValidConfig()); | 170 DCHECK(video_config.IsValidConfig()); | 
| 162 video_configs_.push_back(video_config); | 171 video_configs_.push_back(video_config); | 
| 163 } | 172 } | 
| 164 | 173 | 
| 165 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 174 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 
| 166 const scoped_refptr<MediaLog>& media_log, | 175 const scoped_refptr<MediaLog>& media_log, | 
| 167 bool splice_frames_enabled) | 176 bool splice_frames_enabled) | 
| 168 : media_log_(media_log), | 177 : media_log_(media_log), | 
| 169 text_track_config_(text_config), | 178 text_track_config_(text_config), | 
| 170 seek_buffer_timestamp_(kNoTimestamp()), | 179 seek_buffer_timestamp_(kNoTimestamp()), | 
| 171 media_segment_start_time_(kNoDecodeTimestamp()), | 180 coded_frame_group_start_time_(kNoDecodeTimestamp()), | 
| 172 range_for_next_append_(ranges_.end()), | 181 range_for_next_append_(ranges_.end()), | 
| 173 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 182 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 
| 174 max_interbuffer_distance_(kNoTimestamp()), | 183 max_interbuffer_distance_(kNoTimestamp()), | 
| 175 memory_limit_(kSourceBufferAudioMemoryLimit), | 184 memory_limit_(kSourceBufferAudioMemoryLimit), | 
| 176 splice_frames_enabled_(splice_frames_enabled) {} | 185 splice_frames_enabled_(splice_frames_enabled) {} | 
| 177 | 186 | 
| 178 SourceBufferStream::~SourceBufferStream() { | 187 SourceBufferStream::~SourceBufferStream() { | 
| 179 while (!ranges_.empty()) { | 188 while (!ranges_.empty()) { | 
| 180 delete ranges_.front(); | 189 delete ranges_.front(); | 
| 181 ranges_.pop_front(); | 190 ranges_.pop_front(); | 
| 182 } | 191 } | 
| 183 } | 192 } | 
| 184 | 193 | 
| 185 void SourceBufferStream::OnNewMediaSegment( | 194 void SourceBufferStream::OnStartOfCodedFrameGroup( | 
| 186 DecodeTimestamp media_segment_start_time) { | 195 DecodeTimestamp coded_frame_group_start_time) { | 
| 187 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 196 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << " (" | 
| 188 << " (" << media_segment_start_time.InSecondsF() << ")"; | 197 << coded_frame_group_start_time.InSecondsF() << ")"; | 
| 189 DCHECK(!end_of_stream_); | 198 DCHECK(!end_of_stream_); | 
| 190 media_segment_start_time_ = media_segment_start_time; | 199 coded_frame_group_start_time_ = coded_frame_group_start_time; | 
| 191 new_media_segment_ = true; | 200 new_coded_frame_group_ = true; | 
| 192 | 201 | 
| 193 RangeList::iterator last_range = range_for_next_append_; | 202 RangeList::iterator last_range = range_for_next_append_; | 
| 194 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time); | 203 range_for_next_append_ = FindExistingRangeFor(coded_frame_group_start_time); | 
| 195 | 204 | 
| 196 // Only reset |last_appended_buffer_timestamp_| if this new media segment is | 205 // Only reset |last_appended_buffer_timestamp_| if this new coded frame group | 
| 197 // not adjacent to the previous media segment appended to the stream. | 206 // is not adjacent to the previous coded frame group appended to the stream. | 
| 198 if (range_for_next_append_ == ranges_.end() || | 207 if (range_for_next_append_ == ranges_.end() || | 
| 199 !AreAdjacentInSequence(last_appended_buffer_timestamp_, | 208 !AreAdjacentInSequence(last_appended_buffer_timestamp_, | 
| 200 media_segment_start_time)) { | 209 coded_frame_group_start_time)) { | 
| 201 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); | 210 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); | 
| 202 last_appended_buffer_duration_ = kNoTimestamp(); | 211 last_appended_buffer_duration_ = kNoTimestamp(); | 
| 203 last_appended_buffer_is_keyframe_ = false; | 212 last_appended_buffer_is_keyframe_ = false; | 
| 204 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range"; | 213 DVLOG(3) << __FUNCTION__ << " next appended buffers will " | 
| 214 << (range_for_next_append_ == ranges_.end() | |
| 215 ? "be in a new range" | |
| 216 : "overlap an existing range"); | |
| 205 } else if (last_range != ranges_.end()) { | 217 } else if (last_range != ranges_.end()) { | 
| 206 DCHECK(last_range == range_for_next_append_); | 218 DCHECK(last_range == range_for_next_append_); | 
| 207 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " | 219 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " | 
| 208 << "unless intervening remove makes discontinuity"; | 220 << "unless intervening remove makes discontinuity"; | 
| 209 } | 221 } | 
| 210 } | 222 } | 
| 211 | 223 | 
| 212 bool SourceBufferStream::Append(const BufferQueue& buffers) { | 224 bool SourceBufferStream::Append(const BufferQueue& buffers) { | 
| 213 TRACE_EVENT2("media", "SourceBufferStream::Append", | 225 TRACE_EVENT2("media", "SourceBufferStream::Append", | 
| 214 "stream type", GetStreamTypeName(), | 226 "stream type", GetStreamTypeName(), | 
| 215 "buffers to append", buffers.size()); | 227 "buffers to append", buffers.size()); | 
| 216 | 228 | 
| 217 DCHECK(!buffers.empty()); | 229 DCHECK(!buffers.empty()); | 
| 218 DCHECK(media_segment_start_time_ != kNoDecodeTimestamp()); | 230 DCHECK(coded_frame_group_start_time_ != kNoDecodeTimestamp()); | 
| 219 DCHECK(media_segment_start_time_ <= buffers.front()->GetDecodeTimestamp()); | 231 DCHECK(coded_frame_group_start_time_ <= | 
| 232 buffers.front()->GetDecodeTimestamp()); | |
| 220 DCHECK(!end_of_stream_); | 233 DCHECK(!end_of_stream_); | 
| 221 | 234 | 
| 222 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 235 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 
| 223 << ": buffers " << BufferQueueToLogString(buffers); | 236 << ": buffers " << BufferQueueToLogString(buffers); | 
| 224 | 237 | 
| 225 // New media segments must begin with a keyframe. | 238 // New coded frame groups emitted by the coded frame processor must begin with | 
| 226 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412. | 239 // a keyframe. TODO(wolenetz): Change this to [DCHECK + MEDIA_LOG(ERROR...) + | 
| 227 if (new_media_segment_ && !buffers.front()->is_key_frame()) { | 240 // 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 " | 241 // https://crbug.com/580621. | 
| 229 "frame. Support for such segments will be " | 242 CHECK(!new_coded_frame_group_ || buffers.front()->is_key_frame()); | 
| 230 "available in a future version. Please see " | 243 | 
| 231 "https://crbug.com/229412."; | 244 // Buffers within a coded frame group should be monotonically increasing. | 
| 245 if (!IsMonotonicallyIncreasing(buffers)) { | |
| 232 return false; | 246 return false; | 
| 233 } | 247 } | 
| 234 | 248 | 
| 235 // Buffers within a media segment should be monotonically increasing. | 249 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()) { | 250 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) { | 
| 241 MEDIA_LOG(ERROR, media_log_) | 251 MEDIA_LOG(ERROR, media_log_) | 
| 242 << "Cannot append a media segment with negative timestamps."; | 252 << "Cannot append a coded frame group with negative timestamps."; | 
| 243 return false; | 253 return false; | 
| 244 } | 254 } | 
| 245 | 255 | 
| 246 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(), | |
| 247 buffers.front()->is_key_frame())) { | |
| 248 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp(); | |
| 249 MEDIA_LOG(ERROR, media_log_) | |
| 250 << "Invalid same timestamp construct detected at" | |
| 251 << " time " << dts.InSecondsF(); | |
| 252 | |
| 253 return false; | |
| 254 } | |
| 255 | |
| 256 UpdateMaxInterbufferDistance(buffers); | 256 UpdateMaxInterbufferDistance(buffers); | 
| 257 SetConfigIds(buffers); | 257 SetConfigIds(buffers); | 
| 258 | 258 | 
| 259 // Save a snapshot of stream state before range modifications are made. | 259 // Save a snapshot of stream state before range modifications are made. | 
| 260 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); | 260 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); | 
| 261 BufferQueue deleted_buffers; | 261 BufferQueue deleted_buffers; | 
| 262 | 262 | 
| 263 PrepareRangesForNextAppend(buffers, &deleted_buffers); | 263 PrepareRangesForNextAppend(buffers, &deleted_buffers); | 
| 264 | 264 | 
| 265 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, | 265 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, | 
| 266 // create a new range with |buffers|. | 266 // create a new range with |buffers|. | 
| 267 if (range_for_next_append_ != ranges_.end()) { | 267 if (range_for_next_append_ != ranges_.end()) { | 
| 268 (*range_for_next_append_)->AppendBuffersToEnd(buffers); | 268 if (new_coded_frame_group_ && (!splice_frames_enabled_ || | 
| 269 buffers.front()->splice_buffers().empty())) { | |
| 270 // If the first append to this stream in a new coded frame group continues | |
| 271 // a previous range, use the new group's start time instead of the first | |
| 272 // new buffer's timestamp as the proof of adjacency to the existing range. | |
| 273 // A large gap (larger than our normal buffer adjacency test) can occur in | |
| 274 // a muxed set of streams (which share a common coded frame group start | |
| 275 // time) with a significantly jagged start across the streams. | |
| 276 // Don't do this logic if there was a splice frame generated for the first | |
| 277 // new buffer, since splices are guaranteed to be in the same range and | |
| 278 // adjacent, and since the splice frame's timestamp can be less than | |
| 279 // |coded_frame_group_start_time_| due to the splicing. | |
| 280 (*range_for_next_append_) | |
| 281 ->AppendBuffersToEnd(buffers, coded_frame_group_start_time_); | |
| 282 } else { | |
| 283 // Otherwise, use the first new buffer's timestamp as the proof of | |
| 284 // adjacency. | |
| 285 (*range_for_next_append_) | |
| 286 ->AppendBuffersToEnd(buffers, kNoDecodeTimestamp()); | |
| 287 } | |
| 288 | |
| 269 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 289 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 
| 270 last_appended_buffer_duration_ = buffers.back()->duration(); | 290 last_appended_buffer_duration_ = buffers.back()->duration(); | 
| 271 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); | 291 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); | 
| 272 } else { | 292 } else { | 
| 273 DecodeTimestamp new_range_start_time = std::min( | 293 DecodeTimestamp new_range_start_time = std::min( | 
| 274 media_segment_start_time_, buffers.front()->GetDecodeTimestamp()); | 294 coded_frame_group_start_time_, buffers.front()->GetDecodeTimestamp()); | 
| 275 const BufferQueue* buffers_for_new_range = &buffers; | 295 const BufferQueue* buffers_for_new_range = &buffers; | 
| 276 BufferQueue trimmed_buffers; | 296 BufferQueue trimmed_buffers; | 
| 277 | 297 | 
| 278 // If the new range is not being created because of a new media | 298 // 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. | 299 // 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 | 300 // if the GOP in the previous append gets destroyed by a Remove() call. | 
| 281 // by a Remove() call. | 301 if (!new_coded_frame_group_) { | 
| 282 if (!new_media_segment_) { | |
| 283 BufferQueue::const_iterator itr = buffers.begin(); | 302 BufferQueue::const_iterator itr = buffers.begin(); | 
| 284 | 303 | 
| 285 // Scan past all the non-key-frames. | 304 // Scan past all the non-key-frames. | 
| 286 while (itr != buffers.end() && !(*itr)->is_key_frame()) { | 305 while (itr != buffers.end() && !(*itr)->is_key_frame()) { | 
| 287 ++itr; | 306 ++itr; | 
| 288 } | 307 } | 
| 289 | 308 | 
| 290 // If we didn't find a key frame, then update the last appended | 309 // If we didn't find a key frame, then update the last appended | 
| 291 // buffer state and return. | 310 // buffer state and return. | 
| 292 if (itr == buffers.end()) { | 311 if (itr == buffers.end()) { | 
| 293 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 312 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 
| 294 last_appended_buffer_duration_ = buffers.back()->duration(); | 313 last_appended_buffer_duration_ = buffers.back()->duration(); | 
| 295 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); | 314 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); | 
| 296 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 315 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 
| 297 << ": new buffers in the middle of media segment depend on" | 316 << ": new buffers in the middle of coded frame group depend on" | 
| 298 "keyframe that has been removed, and contain no keyframes." | 317 "keyframe that has been removed, and contain no keyframes." | 
| 299 "Skipping further processing."; | 318 "Skipping further processing."; | 
| 300 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 319 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 
| 301 << ": done. ranges_=" << RangesToString(ranges_); | 320 << ": done. ranges_=" << RangesToString(ranges_); | 
| 302 return true; | 321 return true; | 
| 303 } else if (itr != buffers.begin()) { | 322 } else if (itr != buffers.begin()) { | 
| 304 // Copy the first key frame and everything after it into | 323 // Copy the first key frame and everything after it into | 
| 305 // |trimmed_buffers|. | 324 // |trimmed_buffers|. | 
| 306 trimmed_buffers.assign(itr, buffers.end()); | 325 trimmed_buffers.assign(itr, buffers.end()); | 
| 307 buffers_for_new_range = &trimmed_buffers; | 326 buffers_for_new_range = &trimmed_buffers; | 
| 308 } | 327 } | 
| 309 | 328 | 
| 310 new_range_start_time = | 329 new_range_start_time = | 
| 311 buffers_for_new_range->front()->GetDecodeTimestamp(); | 330 buffers_for_new_range->front()->GetDecodeTimestamp(); | 
| 312 } | 331 } | 
| 313 | 332 | 
| 314 range_for_next_append_ = | 333 range_for_next_append_ = | 
| 315 AddToRanges(new SourceBufferRange( | 334 AddToRanges(new SourceBufferRange( | 
| 316 TypeToGapPolicy(GetType()), | 335 TypeToGapPolicy(GetType()), | 
| 317 *buffers_for_new_range, new_range_start_time, | 336 *buffers_for_new_range, new_range_start_time, | 
| 318 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, | 337 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, | 
| 319 base::Unretained(this)))); | 338 base::Unretained(this)))); | 
| 320 last_appended_buffer_timestamp_ = | 339 last_appended_buffer_timestamp_ = | 
| 321 buffers_for_new_range->back()->GetDecodeTimestamp(); | 340 buffers_for_new_range->back()->GetDecodeTimestamp(); | 
| 322 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration(); | 341 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration(); | 
| 323 last_appended_buffer_is_keyframe_ = | 342 last_appended_buffer_is_keyframe_ = | 
| 324 buffers_for_new_range->back()->is_key_frame(); | 343 buffers_for_new_range->back()->is_key_frame(); | 
| 325 } | 344 } | 
| 326 | 345 | 
| 327 new_media_segment_ = false; | 346 new_coded_frame_group_ = false; | 
| 328 | 347 | 
| 329 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); | 348 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); | 
| 330 | 349 | 
| 331 // Seek to try to fulfill a previous call to Seek(). | 350 // Seek to try to fulfill a previous call to Seek(). | 
| 332 if (seek_pending_) { | 351 if (seek_pending_) { | 
| 333 DCHECK(!selected_range_); | 352 DCHECK(!selected_range_); | 
| 334 DCHECK(deleted_buffers.empty()); | 353 DCHECK(deleted_buffers.empty()); | 
| 335 Seek(seek_buffer_timestamp_); | 354 Seek(seek_buffer_timestamp_); | 
| 336 } | 355 } | 
| 337 | 356 | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 406 // stream, yet we also had output no buffer since the last Seek. | 425 // stream, yet we also had output no buffer since the last Seek. | 
| 407 // Re-seek to prevent stall. | 426 // Re-seek to prevent stall. | 
| 408 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 427 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 
| 409 << ": re-seeking to " << seek_buffer_timestamp_ | 428 << ": re-seeking to " << seek_buffer_timestamp_ | 
| 410 << " to prevent stall if this time becomes buffered again"; | 429 << " to prevent stall if this time becomes buffered again"; | 
| 411 Seek(seek_buffer_timestamp_); | 430 Seek(seek_buffer_timestamp_); | 
| 412 } | 431 } | 
| 413 } | 432 } | 
| 414 } | 433 } | 
| 415 | 434 | 
| 435 DecodeTimestamp SourceBufferStream::PotentialNextAppendTimestamp() const { | |
| 436 // The next potential append will either be just at or after | |
| 437 // |last_appended_buffer_timestamp_| (if known), or if unknown and we are | |
| 438 // still at the beginning of a new coded frame group, then will be into the | |
| 439 // range (if any) to which |coded_frame_group_start_time_| belongs. | |
| 440 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp()) { | |
| 441 return last_appended_buffer_timestamp_ + | |
| 442 base::TimeDelta::FromInternalValue(1); | |
| 
chcunningham
2016/02/12 22:46:40
What if the next timestamp is the same as the last
 
chcunningham
2016/02/12 23:25:36
We chatted. Please make a todo && crbug. This is a
 
wolenetz
2016/02/24 00:34:46
I think this +1us was useful when we previously ha
 
chcunningham
2016/02/24 19:06:26
Acknowledged.
 | |
| 443 } | |
| 444 | |
| 445 if (new_coded_frame_group_) | |
| 446 return coded_frame_group_start_time_; | |
| 447 | |
| 448 // If we still don't know a potential next append timestamp, then we have | |
| 449 // removed the ranged to which it previously belonged and have not completed a | |
| 450 // subsequent append or received a subsequent OnStartOfCodedFrameGroup() | |
| 451 // signal. | |
| 452 return kNoDecodeTimestamp(); | |
| 453 } | |
| 454 | |
| 416 void SourceBufferStream::RemoveInternal(DecodeTimestamp start, | 455 void SourceBufferStream::RemoveInternal(DecodeTimestamp start, | 
| 417 DecodeTimestamp end, | 456 DecodeTimestamp end, | 
| 418 bool exclude_start, | 457 bool exclude_start, | 
| 419 BufferQueue* deleted_buffers) { | 458 BufferQueue* deleted_buffers) { | 
| 420 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << " (" | 459 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << " (" | 
| 421 << start.InSecondsF() << ", " << end.InSecondsF() << ", " | 460 << start.InSecondsF() << ", " << end.InSecondsF() << ", " | 
| 422 << exclude_start << ")"; | 461 << exclude_start << ")"; | 
| 423 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName() | 462 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName() | 
| 424 << ": before remove ranges_=" << RangesToString(ranges_); | 463 << ": before remove ranges_=" << RangesToString(ranges_); | 
| 425 | 464 | 
| 426 DCHECK(start >= DecodeTimestamp()); | 465 DCHECK(start >= DecodeTimestamp()); | 
| 427 DCHECK(start < end) << "start " << start.InSecondsF() | 466 DCHECK(start < end) << "start " << start.InSecondsF() | 
| 428 << " end " << end.InSecondsF(); | 467 << " end " << end.InSecondsF(); | 
| 429 DCHECK(deleted_buffers); | 468 DCHECK(deleted_buffers); | 
| 430 | 469 | 
| 431 RangeList::iterator itr = ranges_.begin(); | 470 RangeList::iterator itr = ranges_.begin(); | 
| 432 | 471 | 
| 433 while (itr != ranges_.end()) { | 472 while (itr != ranges_.end()) { | 
| 434 SourceBufferRange* range = *itr; | 473 SourceBufferRange* range = *itr; | 
| 435 if (range->GetStartTimestamp() >= end) | 474 if (range->GetStartTimestamp() >= end) | 
| 436 break; | 475 break; | 
| 437 | 476 | 
| 438 // Split off any remaining GOPs starting at or after |end| and add it to | 477 // Split off any remaining GOPs starting at or after |end| and add it to | 
| 439 // |ranges_|. | 478 // |ranges_|. | 
| 440 SourceBufferRange* new_range = range->SplitRange(end); | 479 SourceBufferRange* new_range = range->SplitRange(end); | 
| 441 if (new_range) { | 480 if (new_range) { | 
| 442 itr = ranges_.insert(++itr, new_range); | 481 itr = ranges_.insert(++itr, new_range); | 
| 482 | |
| 483 // Update |range_for_next_append_| if it was previously |range| and should | |
| 484 // be |new_range| now. | |
| 485 if (range_for_next_append_ != ranges_.end() && | |
| 486 *range_for_next_append_ == range) { | |
| 487 DecodeTimestamp potential_next_append_timestamp = | |
| 488 PotentialNextAppendTimestamp(); | |
| 489 if (potential_next_append_timestamp != kNoDecodeTimestamp() && | |
| 490 new_range->BelongsToRange(potential_next_append_timestamp)) { | |
| 491 range_for_next_append_ = itr; | |
| 492 } | |
| 493 } | |
| 494 | |
| 443 --itr; | 495 --itr; | 
| 444 | 496 | 
| 445 // Update the selected range if the next buffer position was transferred | 497 // Update the selected range if the next buffer position was transferred | 
| 446 // to |new_range|. | 498 // to |new_range|. | 
| 447 if (new_range->HasNextBufferPosition()) | 499 if (new_range->HasNextBufferPosition()) | 
| 448 SetSelectedRange(new_range); | 500 SetSelectedRange(new_range); | 
| 449 } | 501 } | 
| 450 | 502 | 
| 451 // Truncate the current range so that it only contains data before | 503 // Truncate the current range so that it only contains data before | 
| 452 // the removal range. | 504 // the removal range. | 
| (...skipping 16 matching lines...) Expand all Loading... | |
| 469 // range then delete it and move on. | 521 // range then delete it and move on. | 
| 470 if (delete_range) { | 522 if (delete_range) { | 
| 471 DeleteAndRemoveRange(&itr); | 523 DeleteAndRemoveRange(&itr); | 
| 472 continue; | 524 continue; | 
| 473 } | 525 } | 
| 474 | 526 | 
| 475 // Clear |range_for_next_append_| if we determine that the removal | 527 // Clear |range_for_next_append_| if we determine that the removal | 
| 476 // operation makes it impossible for the next append to be added | 528 // operation makes it impossible for the next append to be added | 
| 477 // to the current range. | 529 // to the current range. | 
| 478 if (range_for_next_append_ != ranges_.end() && | 530 if (range_for_next_append_ != ranges_.end() && | 
| 479 *range_for_next_append_ == range && | 531 *range_for_next_append_ == range) { | 
| 480 last_appended_buffer_timestamp_ != kNoDecodeTimestamp()) { | |
| 481 DecodeTimestamp potential_next_append_timestamp = | 532 DecodeTimestamp potential_next_append_timestamp = | 
| 482 last_appended_buffer_timestamp_ + | 533 PotentialNextAppendTimestamp(); | 
| 483 base::TimeDelta::FromInternalValue(1); | |
| 484 | 534 | 
| 485 if (!range->BelongsToRange(potential_next_append_timestamp)) { | 535 if (!range->BelongsToRange(potential_next_append_timestamp)) { | 
| 486 DVLOG(1) << "Resetting range_for_next_append_ since the next append" | 536 DVLOG(1) << "Resetting range_for_next_append_ since the next append" | 
| 487 << " can't add to the current range."; | 537 << " can't add to the current range."; | 
| 488 range_for_next_append_ = | 538 range_for_next_append_ = | 
| 489 FindExistingRangeFor(potential_next_append_timestamp); | 539 FindExistingRangeFor(potential_next_append_timestamp); | 
| 490 } | 540 } | 
| 491 } | 541 } | 
| 492 | 542 | 
| 493 // Move on to the next range. | 543 // Move on to the next range. | 
| (...skipping 21 matching lines...) Expand all Loading... | |
| 515 bool SourceBufferStream::ShouldSeekToStartOfBuffered( | 565 bool SourceBufferStream::ShouldSeekToStartOfBuffered( | 
| 516 base::TimeDelta seek_timestamp) const { | 566 base::TimeDelta seek_timestamp) const { | 
| 517 if (ranges_.empty()) | 567 if (ranges_.empty()) | 
| 518 return false; | 568 return false; | 
| 519 base::TimeDelta beginning_of_buffered = | 569 base::TimeDelta beginning_of_buffered = | 
| 520 ranges_.front()->GetStartTimestamp().ToPresentationTime(); | 570 ranges_.front()->GetStartTimestamp().ToPresentationTime(); | 
| 521 return (seek_timestamp <= beginning_of_buffered && | 571 return (seek_timestamp <= beginning_of_buffered && | 
| 522 beginning_of_buffered < kSeekToStartFudgeRoom()); | 572 beginning_of_buffered < kSeekToStartFudgeRoom()); | 
| 523 } | 573 } | 
| 524 | 574 | 
| 525 bool SourceBufferStream::IsMonotonicallyIncreasing( | 575 bool SourceBufferStream::IsMonotonicallyIncreasing(const BufferQueue& buffers) { | 
| 526 const BufferQueue& buffers) const { | |
| 527 DCHECK(!buffers.empty()); | 576 DCHECK(!buffers.empty()); | 
| 528 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_; | 577 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_; | 
| 529 bool prev_is_keyframe = last_appended_buffer_is_keyframe_; | 578 bool prev_is_keyframe = last_appended_buffer_is_keyframe_; | 
| 530 for (BufferQueue::const_iterator itr = buffers.begin(); | 579 for (BufferQueue::const_iterator itr = buffers.begin(); | 
| 531 itr != buffers.end(); ++itr) { | 580 itr != buffers.end(); ++itr) { | 
| 532 DecodeTimestamp current_timestamp = (*itr)->GetDecodeTimestamp(); | 581 DecodeTimestamp current_timestamp = (*itr)->GetDecodeTimestamp(); | 
| 533 bool current_is_keyframe = (*itr)->is_key_frame(); | 582 bool current_is_keyframe = (*itr)->is_key_frame(); | 
| 534 DCHECK(current_timestamp != kNoDecodeTimestamp()); | 583 DCHECK(current_timestamp != kNoDecodeTimestamp()); | 
| 535 DCHECK((*itr)->duration() >= base::TimeDelta()) | 584 DCHECK((*itr)->duration() >= base::TimeDelta()) | 
| 536 << "Packet with invalid duration." | 585 << "Packet with invalid duration." | 
| 537 << " pts " << (*itr)->timestamp().InSecondsF() | 586 << " pts " << (*itr)->timestamp().InSecondsF() | 
| 538 << " dts " << (*itr)->GetDecodeTimestamp().InSecondsF() | 587 << " dts " << (*itr)->GetDecodeTimestamp().InSecondsF() | 
| 539 << " dur " << (*itr)->duration().InSecondsF(); | 588 << " dur " << (*itr)->duration().InSecondsF(); | 
| 540 | 589 | 
| 541 if (prev_timestamp != kNoDecodeTimestamp()) { | 590 if (prev_timestamp != kNoDecodeTimestamp()) { | 
| 542 if (current_timestamp < prev_timestamp) { | 591 if (current_timestamp < prev_timestamp) { | 
| 543 MEDIA_LOG(ERROR, media_log_) | 592 MEDIA_LOG(ERROR, media_log_) | 
| 544 << "Buffers did not monotonically increase."; | 593 << "Buffers did not monotonically increase."; | 
| 545 return false; | 594 return false; | 
| 546 } | 595 } | 
| 547 | 596 | 
| 548 if (current_timestamp == prev_timestamp && | 597 if (current_timestamp == prev_timestamp && | 
| 549 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe, | 598 SourceBufferRange::IsUncommonSameTimestampSequence( | 
| 550 current_is_keyframe)) { | 599 prev_is_keyframe, current_is_keyframe)) { | 
| 551 MEDIA_LOG(ERROR, media_log_) << "Unexpected combination of buffers with" | 600 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_strange_same_timestamps_logs_, | 
| 552 << " the same timestamp detected at " | 601 kMaxStrangeSameTimestampsLogs) | 
| 553 << current_timestamp.InSecondsF(); | 602 << "Detected an append sequence with keyframe following a " | 
| 554 return false; | 603 "non-keyframe, both with the same decode timestamp of " | 
| 604 << current_timestamp.InSecondsF(); | |
| 555 } | 605 } | 
| 556 } | 606 } | 
| 557 | 607 | 
| 558 prev_timestamp = current_timestamp; | 608 prev_timestamp = current_timestamp; | 
| 559 prev_is_keyframe = current_is_keyframe; | 609 prev_is_keyframe = current_is_keyframe; | 
| 560 } | 610 } | 
| 561 return true; | 611 return true; | 
| 562 } | 612 } | 
| 563 | 613 | 
| 564 bool SourceBufferStream::IsNextTimestampValid( | |
| 565 DecodeTimestamp next_timestamp, bool next_is_keyframe) const { | |
| 566 return (last_appended_buffer_timestamp_ != next_timestamp) || | |
| 567 new_media_segment_ || | |
| 568 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_, | |
| 569 next_is_keyframe); | |
| 570 } | |
| 571 | |
| 572 | |
| 573 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const { | 614 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const { | 
| 574 for (RangeList::const_iterator itr = ranges_.begin(); | 615 for (RangeList::const_iterator itr = ranges_.begin(); | 
| 575 itr != ranges_.end(); ++itr) { | 616 itr != ranges_.end(); ++itr) { | 
| 576 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_) | 617 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_) | 
| 577 return false; | 618 return false; | 
| 578 } | 619 } | 
| 579 return !selected_range_ || selected_range_->HasNextBufferPosition(); | 620 return !selected_range_ || selected_range_->HasNextBufferPosition(); | 
| 580 } | 621 } | 
| 581 | 622 | 
| 582 void SourceBufferStream::UpdateMaxInterbufferDistance( | 623 void SourceBufferStream::UpdateMaxInterbufferDistance( | 
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 920 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) { | 961 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) { | 
| 921 DCHECK(deleted_buffers); | 962 DCHECK(deleted_buffers); | 
| 922 | 963 | 
| 923 // Handle splices between the existing buffers and the new buffers. If a | 964 // Handle splices between the existing buffers and the new buffers. If a | 
| 924 // splice is generated the timestamp and duration of the first buffer in | 965 // splice is generated the timestamp and duration of the first buffer in | 
| 925 // |new_buffers| will be modified. | 966 // |new_buffers| will be modified. | 
| 926 if (splice_frames_enabled_) | 967 if (splice_frames_enabled_) | 
| 927 GenerateSpliceFrame(new_buffers); | 968 GenerateSpliceFrame(new_buffers); | 
| 928 | 969 | 
| 929 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_; | 970 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_; | 
| 930 bool prev_is_keyframe = last_appended_buffer_is_keyframe_; | |
| 931 DecodeTimestamp next_timestamp = new_buffers.front()->GetDecodeTimestamp(); | 971 DecodeTimestamp next_timestamp = new_buffers.front()->GetDecodeTimestamp(); | 
| 932 bool next_is_keyframe = new_buffers.front()->is_key_frame(); | |
| 933 | 972 | 
| 934 if (prev_timestamp != kNoDecodeTimestamp() && | 973 if (prev_timestamp != kNoDecodeTimestamp() && | 
| 935 prev_timestamp != next_timestamp) { | 974 prev_timestamp != next_timestamp) { | 
| 936 // Clean up the old buffers between the last appended buffer and the | 975 // Clean up the old buffers between the last appended buffer and the | 
| 937 // beginning of |new_buffers|. | 976 // beginning of |new_buffers|. | 
| 938 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers); | 977 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers); | 
| 939 } | 978 } | 
| 940 | 979 | 
| 941 // Make the delete range exclusive if we are dealing with an allowed same | 980 // Always make the start of the delete range exclusive for same timestamp | 
| 942 // timestamp situation. This prevents the first buffer in the current append | 981 // across the last buffer in the previous append and the first buffer in the | 
| 943 // from deleting the last buffer in the previous append if both buffers | 982 // current append. Never be exclusive if a splice frame was generated because | 
| 944 // have the same timestamp. | 983 // we don't generate splice frames for same timestamp situations. | 
| 945 // | |
| 946 // The delete range should never be exclusive if a splice frame was generated | |
| 947 // because we don't generate splice frames for same timestamp situations. | |
| 948 DCHECK(new_buffers.front()->splice_timestamp() != | 984 DCHECK(new_buffers.front()->splice_timestamp() != | 
| 949 new_buffers.front()->timestamp()); | 985 new_buffers.front()->timestamp()); | 
| 950 const bool exclude_start = | 986 const bool exclude_start = new_buffers.front()->splice_buffers().empty() && | 
| 951 new_buffers.front()->splice_buffers().empty() && | 987 prev_timestamp == next_timestamp; | 
| 952 prev_timestamp == next_timestamp && | |
| 953 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe, next_is_keyframe); | |
| 954 | 988 | 
| 955 // Delete the buffers that |new_buffers| overlaps. | 989 // Delete the buffers that |new_buffers| overlaps. | 
| 956 DecodeTimestamp start = new_buffers.front()->GetDecodeTimestamp(); | 990 DecodeTimestamp start = new_buffers.front()->GetDecodeTimestamp(); | 
| 991 if (new_coded_frame_group_) { | |
| 992 // Extend the deletion range earlier to the coded frame group start time if | |
| 993 // this is the first append in a new coded frame group. Note that |start| | |
| 994 // could already be less than |coded_frame_group_start_time_| if a splice | |
| 995 // was generated. | |
| 996 DCHECK(coded_frame_group_start_time_ != kNoDecodeTimestamp()); | |
| 997 start = std::min(coded_frame_group_start_time_, start); | |
| 998 } | |
| 957 DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp(); | 999 DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp(); | 
| 958 base::TimeDelta duration = new_buffers.back()->duration(); | 1000 base::TimeDelta duration = new_buffers.back()->duration(); | 
| 959 | 1001 | 
| 960 // Set end time for remove to include the duration of last buffer. If the | 1002 // Set end time for remove to include the duration of last buffer. If the | 
| 961 // duration is estimated, use 1 microsecond instead to ensure frames are not | 1003 // duration is estimated, use 1 microsecond instead to ensure frames are not | 
| 962 // accidentally removed due to over-estimation. | 1004 // accidentally removed due to over-estimation. | 
| 963 if (duration != kNoTimestamp() && duration > base::TimeDelta() && | 1005 if (duration != kNoTimestamp() && duration > base::TimeDelta() && | 
| 964 !new_buffers.back()->is_duration_estimated()) { | 1006 !new_buffers.back()->is_duration_estimated()) { | 
| 965 end += duration; | 1007 end += duration; | 
| 966 } else { | 1008 } else { | 
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1782 return false; | 1824 return false; | 
| 1783 | 1825 | 
| 1784 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1826 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 
| 1785 splice_buffers_index_ = 0; | 1827 splice_buffers_index_ = 0; | 
| 1786 pending_buffer_.swap(*out_buffer); | 1828 pending_buffer_.swap(*out_buffer); | 
| 1787 pending_buffers_complete_ = false; | 1829 pending_buffers_complete_ = false; | 
| 1788 return true; | 1830 return true; | 
| 1789 } | 1831 } | 
| 1790 | 1832 | 
| 1791 } // namespace media | 1833 } // namespace media | 
| OLD | NEW |