| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/frame_processor.h" | 5 #include "media/filters/frame_processor.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <cstdlib> | 9 #include <cstdlib> |
| 10 | 10 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 MseTrackBuffer::MseTrackBuffer(ChunkDemuxerStream* stream) | 116 MseTrackBuffer::MseTrackBuffer(ChunkDemuxerStream* stream) |
| 117 : last_decode_timestamp_(kNoDecodeTimestamp()), | 117 : last_decode_timestamp_(kNoDecodeTimestamp()), |
| 118 last_frame_duration_(kNoTimestamp), | 118 last_frame_duration_(kNoTimestamp), |
| 119 highest_presentation_timestamp_(kNoTimestamp), | 119 highest_presentation_timestamp_(kNoTimestamp), |
| 120 needs_random_access_point_(true), | 120 needs_random_access_point_(true), |
| 121 stream_(stream) { | 121 stream_(stream) { |
| 122 DCHECK(stream_); | 122 DCHECK(stream_); |
| 123 } | 123 } |
| 124 | 124 |
| 125 MseTrackBuffer::~MseTrackBuffer() { | 125 MseTrackBuffer::~MseTrackBuffer() { |
| 126 DVLOG(2) << __FUNCTION__ << "()"; | 126 DVLOG(2) << __func__ << "()"; |
| 127 } | 127 } |
| 128 | 128 |
| 129 void MseTrackBuffer::Reset() { | 129 void MseTrackBuffer::Reset() { |
| 130 DVLOG(2) << __FUNCTION__ << "()"; | 130 DVLOG(2) << __func__ << "()"; |
| 131 | 131 |
| 132 last_decode_timestamp_ = kNoDecodeTimestamp(); | 132 last_decode_timestamp_ = kNoDecodeTimestamp(); |
| 133 last_frame_duration_ = kNoTimestamp; | 133 last_frame_duration_ = kNoTimestamp; |
| 134 highest_presentation_timestamp_ = kNoTimestamp; | 134 highest_presentation_timestamp_ = kNoTimestamp; |
| 135 needs_random_access_point_ = true; | 135 needs_random_access_point_ = true; |
| 136 } | 136 } |
| 137 | 137 |
| 138 void MseTrackBuffer::SetHighestPresentationTimestampIfIncreased( | 138 void MseTrackBuffer::SetHighestPresentationTimestampIfIncreased( |
| 139 base::TimeDelta timestamp) { | 139 base::TimeDelta timestamp) { |
| 140 if (highest_presentation_timestamp_ == kNoTimestamp || | 140 if (highest_presentation_timestamp_ == kNoTimestamp || |
| 141 timestamp > highest_presentation_timestamp_) { | 141 timestamp > highest_presentation_timestamp_) { |
| 142 highest_presentation_timestamp_ = timestamp; | 142 highest_presentation_timestamp_ = timestamp; |
| 143 } | 143 } |
| 144 } | 144 } |
| 145 | 145 |
| 146 void MseTrackBuffer::EnqueueProcessedFrame( | 146 void MseTrackBuffer::EnqueueProcessedFrame( |
| 147 const scoped_refptr<StreamParserBuffer>& frame) { | 147 const scoped_refptr<StreamParserBuffer>& frame) { |
| 148 processed_frames_.push_back(frame); | 148 processed_frames_.push_back(frame); |
| 149 } | 149 } |
| 150 | 150 |
| 151 bool MseTrackBuffer::FlushProcessedFrames() { | 151 bool MseTrackBuffer::FlushProcessedFrames() { |
| 152 if (processed_frames_.empty()) | 152 if (processed_frames_.empty()) |
| 153 return true; | 153 return true; |
| 154 | 154 |
| 155 bool result = stream_->Append(processed_frames_); | 155 bool result = stream_->Append(processed_frames_); |
| 156 processed_frames_.clear(); | 156 processed_frames_.clear(); |
| 157 | 157 |
| 158 DVLOG_IF(3, !result) << __FUNCTION__ | 158 DVLOG_IF(3, !result) << __func__ |
| 159 << "(): Failure appending processed frames to stream"; | 159 << "(): Failure appending processed frames to stream"; |
| 160 | 160 |
| 161 return result; | 161 return result; |
| 162 } | 162 } |
| 163 | 163 |
| 164 FrameProcessor::FrameProcessor(const UpdateDurationCB& update_duration_cb, | 164 FrameProcessor::FrameProcessor(const UpdateDurationCB& update_duration_cb, |
| 165 const scoped_refptr<MediaLog>& media_log) | 165 const scoped_refptr<MediaLog>& media_log) |
| 166 : group_start_timestamp_(kNoTimestamp), | 166 : group_start_timestamp_(kNoTimestamp), |
| 167 update_duration_cb_(update_duration_cb), | 167 update_duration_cb_(update_duration_cb), |
| 168 media_log_(media_log) { | 168 media_log_(media_log) { |
| 169 DVLOG(2) << __FUNCTION__ << "()"; | 169 DVLOG(2) << __func__ << "()"; |
| 170 DCHECK(!update_duration_cb.is_null()); | 170 DCHECK(!update_duration_cb.is_null()); |
| 171 } | 171 } |
| 172 | 172 |
| 173 FrameProcessor::~FrameProcessor() { | 173 FrameProcessor::~FrameProcessor() { |
| 174 DVLOG(2) << __FUNCTION__ << "()"; | 174 DVLOG(2) << __func__ << "()"; |
| 175 STLDeleteValues(&track_buffers_); | 175 STLDeleteValues(&track_buffers_); |
| 176 } | 176 } |
| 177 | 177 |
| 178 void FrameProcessor::SetSequenceMode(bool sequence_mode) { | 178 void FrameProcessor::SetSequenceMode(bool sequence_mode) { |
| 179 DVLOG(2) << __FUNCTION__ << "(" << sequence_mode << ")"; | 179 DVLOG(2) << __func__ << "(" << sequence_mode << ")"; |
| 180 // Per June 9, 2016 MSE spec editor's draft: | 180 // Per June 9, 2016 MSE spec editor's draft: |
| 181 // https://rawgit.com/w3c/media-source/d8f901f22/ | 181 // https://rawgit.com/w3c/media-source/d8f901f22/ |
| 182 // index.html#widl-SourceBuffer-mode | 182 // index.html#widl-SourceBuffer-mode |
| 183 // Step 7: If the new mode equals "sequence", then set the group start | 183 // Step 7: If the new mode equals "sequence", then set the group start |
| 184 // timestamp to the group end timestamp. | 184 // timestamp to the group end timestamp. |
| 185 if (sequence_mode) { | 185 if (sequence_mode) { |
| 186 DCHECK(kNoTimestamp != group_end_timestamp_); | 186 DCHECK(kNoTimestamp != group_end_timestamp_); |
| 187 group_start_timestamp_ = group_end_timestamp_; | 187 group_start_timestamp_ = group_end_timestamp_; |
| 188 } else if (sequence_mode_) { | 188 } else if (sequence_mode_) { |
| 189 // We're switching from 'sequence' to 'segments' mode. Be safe and signal a | 189 // We're switching from 'sequence' to 'segments' mode. Be safe and signal a |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 // 5. If the media segment contains data beyond the current duration, then run | 234 // 5. If the media segment contains data beyond the current duration, then run |
| 235 // the duration change algorithm with new duration set to the maximum of | 235 // the duration change algorithm with new duration set to the maximum of |
| 236 // the current duration and the group end timestamp. | 236 // the current duration and the group end timestamp. |
| 237 update_duration_cb_.Run(group_end_timestamp_); | 237 update_duration_cb_.Run(group_end_timestamp_); |
| 238 | 238 |
| 239 return true; | 239 return true; |
| 240 } | 240 } |
| 241 | 241 |
| 242 void FrameProcessor::SetGroupStartTimestampIfInSequenceMode( | 242 void FrameProcessor::SetGroupStartTimestampIfInSequenceMode( |
| 243 base::TimeDelta timestamp_offset) { | 243 base::TimeDelta timestamp_offset) { |
| 244 DVLOG(2) << __FUNCTION__ << "(" << timestamp_offset.InSecondsF() << ")"; | 244 DVLOG(2) << __func__ << "(" << timestamp_offset.InSecondsF() << ")"; |
| 245 DCHECK(kNoTimestamp != timestamp_offset); | 245 DCHECK(kNoTimestamp != timestamp_offset); |
| 246 if (sequence_mode_) | 246 if (sequence_mode_) |
| 247 group_start_timestamp_ = timestamp_offset; | 247 group_start_timestamp_ = timestamp_offset; |
| 248 | 248 |
| 249 // Changes to timestampOffset should invalidate the preroll buffer. | 249 // Changes to timestampOffset should invalidate the preroll buffer. |
| 250 audio_preroll_buffer_ = NULL; | 250 audio_preroll_buffer_ = NULL; |
| 251 } | 251 } |
| 252 | 252 |
| 253 bool FrameProcessor::AddTrack(StreamParser::TrackId id, | 253 bool FrameProcessor::AddTrack(StreamParser::TrackId id, |
| 254 ChunkDemuxerStream* stream) { | 254 ChunkDemuxerStream* stream) { |
| 255 DVLOG(2) << __FUNCTION__ << "(): id=" << id; | 255 DVLOG(2) << __func__ << "(): id=" << id; |
| 256 | 256 |
| 257 MseTrackBuffer* existing_track = FindTrack(id); | 257 MseTrackBuffer* existing_track = FindTrack(id); |
| 258 DCHECK(!existing_track); | 258 DCHECK(!existing_track); |
| 259 if (existing_track) { | 259 if (existing_track) { |
| 260 MEDIA_LOG(ERROR, media_log_) << "Failure adding track with duplicate ID " | 260 MEDIA_LOG(ERROR, media_log_) << "Failure adding track with duplicate ID " |
| 261 << id; | 261 << id; |
| 262 return false; | 262 return false; |
| 263 } | 263 } |
| 264 | 264 |
| 265 track_buffers_[id] = new MseTrackBuffer(stream); | 265 track_buffers_[id] = new MseTrackBuffer(stream); |
| 266 return true; | 266 return true; |
| 267 } | 267 } |
| 268 | 268 |
| 269 bool FrameProcessor::UpdateTrack(StreamParser::TrackId old_id, | 269 bool FrameProcessor::UpdateTrack(StreamParser::TrackId old_id, |
| 270 StreamParser::TrackId new_id) { | 270 StreamParser::TrackId new_id) { |
| 271 DVLOG(2) << __FUNCTION__ << "() : old_id=" << old_id << ", new_id=" << new_id; | 271 DVLOG(2) << __func__ << "() : old_id=" << old_id << ", new_id=" << new_id; |
| 272 | 272 |
| 273 if (old_id == new_id || !FindTrack(old_id) || FindTrack(new_id)) { | 273 if (old_id == new_id || !FindTrack(old_id) || FindTrack(new_id)) { |
| 274 MEDIA_LOG(ERROR, media_log_) << "Failure updating track id from " << old_id | 274 MEDIA_LOG(ERROR, media_log_) << "Failure updating track id from " << old_id |
| 275 << " to " << new_id; | 275 << " to " << new_id; |
| 276 return false; | 276 return false; |
| 277 } | 277 } |
| 278 | 278 |
| 279 track_buffers_[new_id] = track_buffers_[old_id]; | 279 track_buffers_[new_id] = track_buffers_[old_id]; |
| 280 CHECK_EQ(1u, track_buffers_.erase(old_id)); | 280 CHECK_EQ(1u, track_buffers_.erase(old_id)); |
| 281 return true; | 281 return true; |
| 282 } | 282 } |
| 283 | 283 |
| 284 void FrameProcessor::SetAllTrackBuffersNeedRandomAccessPoint() { | 284 void FrameProcessor::SetAllTrackBuffersNeedRandomAccessPoint() { |
| 285 for (TrackBufferMap::iterator itr = track_buffers_.begin(); | 285 for (TrackBufferMap::iterator itr = track_buffers_.begin(); |
| 286 itr != track_buffers_.end(); | 286 itr != track_buffers_.end(); |
| 287 ++itr) { | 287 ++itr) { |
| 288 itr->second->set_needs_random_access_point(true); | 288 itr->second->set_needs_random_access_point(true); |
| 289 } | 289 } |
| 290 } | 290 } |
| 291 | 291 |
| 292 void FrameProcessor::Reset() { | 292 void FrameProcessor::Reset() { |
| 293 DVLOG(2) << __FUNCTION__ << "()"; | 293 DVLOG(2) << __func__ << "()"; |
| 294 for (TrackBufferMap::iterator itr = track_buffers_.begin(); | 294 for (TrackBufferMap::iterator itr = track_buffers_.begin(); |
| 295 itr != track_buffers_.end(); ++itr) { | 295 itr != track_buffers_.end(); ++itr) { |
| 296 itr->second->Reset(); | 296 itr->second->Reset(); |
| 297 } | 297 } |
| 298 | 298 |
| 299 // Maintain current |coded_frame_group_last_dts_| state for Reset() during | 299 // Maintain current |coded_frame_group_last_dts_| state for Reset() during |
| 300 // sequence mode. Reset it here only if in segments mode. In sequence mode, | 300 // sequence mode. Reset it here only if in segments mode. In sequence mode, |
| 301 // the current coded frame group may be continued across Reset() operations to | 301 // the current coded frame group may be continued across Reset() operations to |
| 302 // allow the stream to coaelesce what might otherwise be gaps in the buffered | 302 // allow the stream to coaelesce what might otherwise be gaps in the buffered |
| 303 // ranges. See also the declaration for |coded_frame_group_last_dts_|. | 303 // ranges. See also the declaration for |coded_frame_group_last_dts_|. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 329 MseTrackBuffer* FrameProcessor::FindTrack(StreamParser::TrackId id) { | 329 MseTrackBuffer* FrameProcessor::FindTrack(StreamParser::TrackId id) { |
| 330 TrackBufferMap::iterator itr = track_buffers_.find(id); | 330 TrackBufferMap::iterator itr = track_buffers_.find(id); |
| 331 if (itr == track_buffers_.end()) | 331 if (itr == track_buffers_.end()) |
| 332 return NULL; | 332 return NULL; |
| 333 | 333 |
| 334 return itr->second; | 334 return itr->second; |
| 335 } | 335 } |
| 336 | 336 |
| 337 void FrameProcessor::NotifyStartOfCodedFrameGroup( | 337 void FrameProcessor::NotifyStartOfCodedFrameGroup( |
| 338 DecodeTimestamp start_timestamp) { | 338 DecodeTimestamp start_timestamp) { |
| 339 DVLOG(2) << __FUNCTION__ << "(" << start_timestamp.InSecondsF() << ")"; | 339 DVLOG(2) << __func__ << "(" << start_timestamp.InSecondsF() << ")"; |
| 340 | 340 |
| 341 for (TrackBufferMap::iterator itr = track_buffers_.begin(); | 341 for (TrackBufferMap::iterator itr = track_buffers_.begin(); |
| 342 itr != track_buffers_.end(); | 342 itr != track_buffers_.end(); |
| 343 ++itr) { | 343 ++itr) { |
| 344 itr->second->stream()->OnStartOfCodedFrameGroup(start_timestamp); | 344 itr->second->stream()->OnStartOfCodedFrameGroup(start_timestamp); |
| 345 } | 345 } |
| 346 } | 346 } |
| 347 | 347 |
| 348 bool FrameProcessor::FlushProcessedFrames() { | 348 bool FrameProcessor::FlushProcessedFrames() { |
| 349 DVLOG(2) << __FUNCTION__ << "()"; | 349 DVLOG(2) << __func__ << "()"; |
| 350 | 350 |
| 351 bool result = true; | 351 bool result = true; |
| 352 for (TrackBufferMap::iterator itr = track_buffers_.begin(); | 352 for (TrackBufferMap::iterator itr = track_buffers_.begin(); |
| 353 itr != track_buffers_.end(); | 353 itr != track_buffers_.end(); |
| 354 ++itr) { | 354 ++itr) { |
| 355 if (!itr->second->FlushProcessedFrames()) | 355 if (!itr->second->FlushProcessedFrames()) |
| 356 result = false; | 356 result = false; |
| 357 } | 357 } |
| 358 | 358 |
| 359 return result; | 359 return result; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 // seconds. | 476 // seconds. |
| 477 // 1.2. Let decode timestamp be a double precision floating point | 477 // 1.2. Let decode timestamp be a double precision floating point |
| 478 // representation of the coded frame's decode timestamp in seconds. | 478 // representation of the coded frame's decode timestamp in seconds. |
| 479 // 2. Let frame duration be a double precision floating point representation | 479 // 2. Let frame duration be a double precision floating point representation |
| 480 // of the coded frame's duration in seconds. | 480 // of the coded frame's duration in seconds. |
| 481 // We use base::TimeDelta and DecodeTimestamp instead of double. | 481 // We use base::TimeDelta and DecodeTimestamp instead of double. |
| 482 base::TimeDelta presentation_timestamp = frame->timestamp(); | 482 base::TimeDelta presentation_timestamp = frame->timestamp(); |
| 483 DecodeTimestamp decode_timestamp = frame->GetDecodeTimestamp(); | 483 DecodeTimestamp decode_timestamp = frame->GetDecodeTimestamp(); |
| 484 base::TimeDelta frame_duration = frame->duration(); | 484 base::TimeDelta frame_duration = frame->duration(); |
| 485 | 485 |
| 486 DVLOG(3) << __FUNCTION__ << ": Processing frame " | 486 DVLOG(3) << __func__ << ": Processing frame Type=" << frame->type() |
| 487 << "Type=" << frame->type() | |
| 488 << ", TrackID=" << frame->track_id() | 487 << ", TrackID=" << frame->track_id() |
| 489 << ", PTS=" << presentation_timestamp.InSecondsF() | 488 << ", PTS=" << presentation_timestamp.InSecondsF() |
| 490 << ", DTS=" << decode_timestamp.InSecondsF() | 489 << ", DTS=" << decode_timestamp.InSecondsF() |
| 491 << ", DUR=" << frame_duration.InSecondsF() | 490 << ", DUR=" << frame_duration.InSecondsF() |
| 492 << ", RAP=" << frame->is_key_frame(); | 491 << ", RAP=" << frame->is_key_frame(); |
| 493 | 492 |
| 494 // Sanity check the timestamps. | 493 // Sanity check the timestamps. |
| 495 if (presentation_timestamp == kNoTimestamp) { | 494 if (presentation_timestamp == kNoTimestamp) { |
| 496 MEDIA_LOG(ERROR, media_log_) << "Unknown PTS for " << frame->GetTypeName() | 495 MEDIA_LOG(ERROR, media_log_) << "Unknown PTS for " << frame->GetTypeName() |
| 497 << " frame"; | 496 << " frame"; |
| 498 return false; | 497 return false; |
| 499 } | 498 } |
| 500 if (decode_timestamp == kNoDecodeTimestamp()) { | 499 if (decode_timestamp == kNoDecodeTimestamp()) { |
| 501 MEDIA_LOG(ERROR, media_log_) << "Unknown DTS for " << frame->GetTypeName() | 500 MEDIA_LOG(ERROR, media_log_) << "Unknown DTS for " << frame->GetTypeName() |
| 502 << " frame"; | 501 << " frame"; |
| 503 return false; | 502 return false; |
| 504 } | 503 } |
| 505 if (decode_timestamp.ToPresentationTime() > presentation_timestamp) { | 504 if (decode_timestamp.ToPresentationTime() > presentation_timestamp) { |
| 506 // TODO(wolenetz): Determine whether DTS>PTS should really be allowed. See | 505 // TODO(wolenetz): Determine whether DTS>PTS should really be allowed. See |
| 507 // http://crbug.com/354518. | 506 // http://crbug.com/354518. |
| 508 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_dts_beyond_pts_warnings_, | 507 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_dts_beyond_pts_warnings_, |
| 509 kMaxDtsBeyondPtsWarnings) | 508 kMaxDtsBeyondPtsWarnings) |
| 510 << "Parsed " << frame->GetTypeName() << " frame has DTS " | 509 << "Parsed " << frame->GetTypeName() << " frame has DTS " |
| 511 << decode_timestamp.InMicroseconds() | 510 << decode_timestamp.InMicroseconds() |
| 512 << "us, which is after the frame's PTS " | 511 << "us, which is after the frame's PTS " |
| 513 << presentation_timestamp.InMicroseconds() << "us"; | 512 << presentation_timestamp.InMicroseconds() << "us"; |
| 514 DVLOG(2) << __FUNCTION__ << ": WARNING: Frame DTS(" | 513 DVLOG(2) << __func__ << ": WARNING: Frame DTS(" |
| 515 << decode_timestamp.InSecondsF() << ") > PTS(" | 514 << decode_timestamp.InSecondsF() << ") > PTS(" |
| 516 << presentation_timestamp.InSecondsF() | 515 << presentation_timestamp.InSecondsF() |
| 517 << "), frame type=" << frame->GetTypeName(); | 516 << "), frame type=" << frame->GetTypeName(); |
| 518 } | 517 } |
| 519 | 518 |
| 520 // All stream parsers must emit valid (non-negative) frame durations. | 519 // All stream parsers must emit valid (non-negative) frame durations. |
| 521 // Note that duration of 0 can occur for at least WebM alt-ref frames. | 520 // Note that duration of 0 can occur for at least WebM alt-ref frames. |
| 522 if (frame_duration == kNoTimestamp) { | 521 if (frame_duration == kNoTimestamp) { |
| 523 MEDIA_LOG(ERROR, media_log_) | 522 MEDIA_LOG(ERROR, media_log_) |
| 524 << "Unknown duration for " << frame->GetTypeName() << " frame at PTS " | 523 << "Unknown duration for " << frame->GetTypeName() << " frame at PTS " |
| 525 << presentation_timestamp.InMicroseconds() << "us"; | 524 << presentation_timestamp.InMicroseconds() << "us"; |
| 526 return false; | 525 return false; |
| 527 } | 526 } |
| 528 if (frame_duration < base::TimeDelta()) { | 527 if (frame_duration < base::TimeDelta()) { |
| 529 MEDIA_LOG(ERROR, media_log_) | 528 MEDIA_LOG(ERROR, media_log_) |
| 530 << "Negative duration " << frame_duration.InMicroseconds() | 529 << "Negative duration " << frame_duration.InMicroseconds() |
| 531 << "us for " << frame->GetTypeName() << " frame at PTS " | 530 << "us for " << frame->GetTypeName() << " frame at PTS " |
| 532 << presentation_timestamp.InMicroseconds() << "us"; | 531 << presentation_timestamp.InMicroseconds() << "us"; |
| 533 return false; | 532 return false; |
| 534 } | 533 } |
| 535 | 534 |
| 536 // 3. If mode equals "sequence" and group start timestamp is set, then run | 535 // 3. If mode equals "sequence" and group start timestamp is set, then run |
| 537 // the following steps: | 536 // the following steps: |
| 538 if (sequence_mode_ && group_start_timestamp_ != kNoTimestamp) { | 537 if (sequence_mode_ && group_start_timestamp_ != kNoTimestamp) { |
| 539 // 3.1. Set timestampOffset equal to group start timestamp - | 538 // 3.1. Set timestampOffset equal to group start timestamp - |
| 540 // presentation timestamp. | 539 // presentation timestamp. |
| 541 *timestamp_offset = group_start_timestamp_ - presentation_timestamp; | 540 *timestamp_offset = group_start_timestamp_ - presentation_timestamp; |
| 542 | 541 |
| 543 DVLOG(3) << __FUNCTION__ << ": updated timestampOffset is now " | 542 DVLOG(3) << __func__ << ": updated timestampOffset is now " |
| 544 << timestamp_offset->InSecondsF(); | 543 << timestamp_offset->InSecondsF(); |
| 545 | 544 |
| 546 // 3.2. Set group end timestamp equal to group start timestamp. | 545 // 3.2. Set group end timestamp equal to group start timestamp. |
| 547 group_end_timestamp_ = group_start_timestamp_; | 546 group_end_timestamp_ = group_start_timestamp_; |
| 548 | 547 |
| 549 // 3.3. Set the need random access point flag on all track buffers to | 548 // 3.3. Set the need random access point flag on all track buffers to |
| 550 // true. | 549 // true. |
| 551 SetAllTrackBuffersNeedRandomAccessPoint(); | 550 SetAllTrackBuffersNeedRandomAccessPoint(); |
| 552 | 551 |
| 553 // 3.4. Unset group start timestamp. | 552 // 3.4. Unset group start timestamp. |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 // presentation timestamp. | 612 // presentation timestamp. |
| 614 // If mode equals "sequence": Set group start timestamp equal to | 613 // If mode equals "sequence": Set group start timestamp equal to |
| 615 // the group end timestamp. | 614 // the group end timestamp. |
| 616 if (!sequence_mode_) { | 615 if (!sequence_mode_) { |
| 617 group_end_timestamp_ = presentation_timestamp; | 616 group_end_timestamp_ = presentation_timestamp; |
| 618 // This triggers a discontinuity so we need to treat the next frames | 617 // This triggers a discontinuity so we need to treat the next frames |
| 619 // appended within the append window as if they were the beginning of | 618 // appended within the append window as if they were the beginning of |
| 620 // a new coded frame group. |coded_frame_group_last_dts_| is reset in | 619 // a new coded frame group. |coded_frame_group_last_dts_| is reset in |
| 621 // Reset(), below, for "segments" mode. | 620 // Reset(), below, for "segments" mode. |
| 622 } else { | 621 } else { |
| 623 DVLOG(3) << __FUNCTION__ << " : Sequence mode discontinuity, GETS: " | 622 DVLOG(3) << __func__ << " : Sequence mode discontinuity, GETS: " |
| 624 << group_end_timestamp_.InSecondsF(); | 623 << group_end_timestamp_.InSecondsF(); |
| 625 // Reset(), below, performs the "Set group start timestamp equal to | 624 // Reset(), below, performs the "Set group start timestamp equal to |
| 626 // the group end timestamp" operation for "sequence" mode. | 625 // the group end timestamp" operation for "sequence" mode. |
| 627 } | 626 } |
| 628 | 627 |
| 629 // 6.2. - 6.5.: | 628 // 6.2. - 6.5.: |
| 630 Reset(); | 629 Reset(); |
| 631 | 630 |
| 632 // 6.6. Jump to the Loop Top step above to restart processing of the | 631 // 6.6. Jump to the Loop Top step above to restart processing of the |
| 633 // current coded frame. | 632 // current coded frame. |
| 634 DVLOG(3) << __FUNCTION__ << ": Discontinuity: reprocessing frame"; | 633 DVLOG(3) << __func__ << ": Discontinuity: reprocessing frame"; |
| 635 continue; | 634 continue; |
| 636 } | 635 } |
| 637 } | 636 } |
| 638 | 637 |
| 639 // 7. Let frame end timestamp equal the sum of presentation timestamp and | 638 // 7. Let frame end timestamp equal the sum of presentation timestamp and |
| 640 // frame duration. | 639 // frame duration. |
| 641 base::TimeDelta frame_end_timestamp = | 640 base::TimeDelta frame_end_timestamp = |
| 642 presentation_timestamp + frame_duration; | 641 presentation_timestamp + frame_duration; |
| 643 | 642 |
| 644 // 8. If presentation timestamp is less than appendWindowStart, then set | 643 // 8. If presentation timestamp is less than appendWindowStart, then set |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 return false; | 690 return false; |
| 692 } | 691 } |
| 693 | 692 |
| 694 // 10. If the need random access point flag on track buffer equals true, | 693 // 10. If the need random access point flag on track buffer equals true, |
| 695 // then run the following steps: | 694 // then run the following steps: |
| 696 if (track_buffer->needs_random_access_point()) { | 695 if (track_buffer->needs_random_access_point()) { |
| 697 // 10.1. If the coded frame is not a random access point, then drop the | 696 // 10.1. If the coded frame is not a random access point, then drop the |
| 698 // coded frame and jump to the top of the loop to start processing | 697 // coded frame and jump to the top of the loop to start processing |
| 699 // the next coded frame. | 698 // the next coded frame. |
| 700 if (!frame->is_key_frame()) { | 699 if (!frame->is_key_frame()) { |
| 701 DVLOG(3) << __FUNCTION__ | 700 DVLOG(3) << __func__ |
| 702 << ": Dropping frame that is not a random access point"; | 701 << ": Dropping frame that is not a random access point"; |
| 703 return true; | 702 return true; |
| 704 } | 703 } |
| 705 | 704 |
| 706 // 10.2. Set the need random access point flag on track buffer to false. | 705 // 10.2. Set the need random access point flag on track buffer to false. |
| 707 track_buffer->set_needs_random_access_point(false); | 706 track_buffer->set_needs_random_access_point(false); |
| 708 } | 707 } |
| 709 | 708 |
| 710 // We now have a processed buffer to append to the track buffer's stream. | 709 // We now have a processed buffer to append to the track buffer's stream. |
| 711 // If it is the first in a new coded frame group (such as following a | 710 // If it is the first in a new coded frame group (such as following a |
| (...skipping 10 matching lines...) Expand all Loading... |
| 722 if (!FlushProcessedFrames()) | 721 if (!FlushProcessedFrames()) |
| 723 return false; | 722 return false; |
| 724 | 723 |
| 725 // TODO(wolenetz): This should be changed to a presentation timestamp. See | 724 // TODO(wolenetz): This should be changed to a presentation timestamp. See |
| 726 // http://crbug.com/402502 | 725 // http://crbug.com/402502 |
| 727 NotifyStartOfCodedFrameGroup(decode_timestamp); | 726 NotifyStartOfCodedFrameGroup(decode_timestamp); |
| 728 } | 727 } |
| 729 | 728 |
| 730 coded_frame_group_last_dts_ = decode_timestamp; | 729 coded_frame_group_last_dts_ = decode_timestamp; |
| 731 | 730 |
| 732 DVLOG(3) << __FUNCTION__ << ": Sending processed frame to stream, " | 731 DVLOG(3) << __func__ << ": Sending processed frame to stream, " |
| 733 << "PTS=" << presentation_timestamp.InSecondsF() | 732 << "PTS=" << presentation_timestamp.InSecondsF() |
| 734 << ", DTS=" << decode_timestamp.InSecondsF(); | 733 << ", DTS=" << decode_timestamp.InSecondsF(); |
| 735 | 734 |
| 736 // Steps 11-16: Note, we optimize by appending groups of contiguous | 735 // Steps 11-16: Note, we optimize by appending groups of contiguous |
| 737 // processed frames for each track buffer at end of ProcessFrames() or prior | 736 // processed frames for each track buffer at end of ProcessFrames() or prior |
| 738 // to NotifyStartOfCodedFrameGroup(). | 737 // to NotifyStartOfCodedFrameGroup(). |
| 739 track_buffer->EnqueueProcessedFrame(frame); | 738 track_buffer->EnqueueProcessedFrame(frame); |
| 740 | 739 |
| 741 // 17. Set last decode timestamp for track buffer to decode timestamp. | 740 // 17. Set last decode timestamp for track buffer to decode timestamp. |
| 742 track_buffer->set_last_decode_timestamp(decode_timestamp); | 741 track_buffer->set_last_decode_timestamp(decode_timestamp); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 760 // Step 21 is currently handled differently. See MediaSourceState's | 759 // Step 21 is currently handled differently. See MediaSourceState's |
| 761 // |auto_update_timestamp_offset_|. | 760 // |auto_update_timestamp_offset_|. |
| 762 return true; | 761 return true; |
| 763 } | 762 } |
| 764 | 763 |
| 765 NOTREACHED(); | 764 NOTREACHED(); |
| 766 return false; | 765 return false; |
| 767 } | 766 } |
| 768 | 767 |
| 769 } // namespace media | 768 } // namespace media |
| OLD | NEW |