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

Side by Side Diff: media/filters/frame_processor.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/frame_processor.h ('k') | media/filters/frame_processor_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 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 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 // Step 8: Update the attribute to new mode. 190 // Step 8: Update the attribute to new mode.
191 sequence_mode_ = sequence_mode; 191 sequence_mode_ = sequence_mode;
192 } 192 }
193 193
194 bool FrameProcessor::ProcessFrames( 194 bool FrameProcessor::ProcessFrames(
195 const StreamParser::BufferQueue& audio_buffers, 195 const StreamParser::BufferQueue& audio_buffers,
196 const StreamParser::BufferQueue& video_buffers, 196 const StreamParser::BufferQueue& video_buffers,
197 const StreamParser::TextBufferQueueMap& text_map, 197 const StreamParser::TextBufferQueueMap& text_map,
198 base::TimeDelta append_window_start, 198 base::TimeDelta append_window_start,
199 base::TimeDelta append_window_end, 199 base::TimeDelta append_window_end,
200 bool* new_media_segment,
200 base::TimeDelta* timestamp_offset) { 201 base::TimeDelta* timestamp_offset) {
201 StreamParser::BufferQueue frames; 202 StreamParser::BufferQueue frames;
202 if (!MergeBufferQueues(audio_buffers, video_buffers, text_map, &frames)) { 203 if (!MergeBufferQueues(audio_buffers, video_buffers, text_map, &frames)) {
203 MEDIA_LOG(ERROR, media_log_) << "Parsed buffers not in DTS sequence"; 204 MEDIA_LOG(ERROR, media_log_) << "Parsed buffers not in DTS sequence";
204 return false; 205 return false;
205 } 206 }
206 207
207 DCHECK(!frames.empty()); 208 DCHECK(!frames.empty());
208 209
209 // Implements the coded frame processing algorithm's outer loop for step 1. 210 // Implements the coded frame processing algorithm's outer loop for step 1.
210 // Note that ProcessFrame() implements an inner loop for a single frame that 211 // Note that ProcessFrame() implements an inner loop for a single frame that
211 // handles "jump to the Loop Top step to restart processing of the current 212 // handles "jump to the Loop Top step to restart processing of the current
212 // coded frame" per April 1, 2014 MSE spec editor's draft: 213 // coded frame" per April 1, 2014 MSE spec editor's draft:
213 // https://dvcs.w3.org/hg/html-media/raw-file/d471a4412040/media-source/ 214 // https://dvcs.w3.org/hg/html-media/raw-file/d471a4412040/media-source/
214 // media-source.html#sourcebuffer-coded-frame-processing 215 // media-source.html#sourcebuffer-coded-frame-processing
215 // 1. For each coded frame in the media segment run the following steps: 216 // 1. For each coded frame in the media segment run the following steps:
216 for (StreamParser::BufferQueue::const_iterator frames_itr = frames.begin(); 217 for (StreamParser::BufferQueue::const_iterator frames_itr = frames.begin();
217 frames_itr != frames.end(); ++frames_itr) { 218 frames_itr != frames.end(); ++frames_itr) {
218 if (!ProcessFrame(*frames_itr, append_window_start, append_window_end, 219 if (!ProcessFrame(*frames_itr, append_window_start, append_window_end,
219 timestamp_offset)) { 220 timestamp_offset, new_media_segment)) {
220 FlushProcessedFrames(); 221 FlushProcessedFrames();
221 return false; 222 return false;
222 } 223 }
223 } 224 }
224 225
225 if (!FlushProcessedFrames()) 226 if (!FlushProcessedFrames())
226 return false; 227 return false;
227 228
228 // 2. - 4. Are handled by the WebMediaPlayer / Pipeline / Media Element. 229 // 2. - 4. Are handled by the WebMediaPlayer / Pipeline / Media Element.
229 230
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 } 284 }
284 } 285 }
285 286
286 void FrameProcessor::Reset() { 287 void FrameProcessor::Reset() {
287 DVLOG(2) << __FUNCTION__ << "()"; 288 DVLOG(2) << __FUNCTION__ << "()";
288 for (TrackBufferMap::iterator itr = track_buffers_.begin(); 289 for (TrackBufferMap::iterator itr = track_buffers_.begin();
289 itr != track_buffers_.end(); ++itr) { 290 itr != track_buffers_.end(); ++itr) {
290 itr->second->Reset(); 291 itr->second->Reset();
291 } 292 }
292 293
293 // Maintain current |in_coded_frame_group_| state for Reset() during 294 if (sequence_mode_) {
294 // sequence mode. Reset it here only if in segments mode. 295 DCHECK(kNoTimestamp() != group_end_timestamp_);
295 if (!sequence_mode_) { 296 group_start_timestamp_ = group_end_timestamp_;
296 in_coded_frame_group_ = false;
297 return;
298 } 297 }
299
300 // Sequence mode
301 DCHECK(kNoTimestamp() != group_end_timestamp_);
302 group_start_timestamp_ = group_end_timestamp_;
303 } 298 }
304 299
305 void FrameProcessor::OnPossibleAudioConfigUpdate( 300 void FrameProcessor::OnPossibleAudioConfigUpdate(
306 const AudioDecoderConfig& config) { 301 const AudioDecoderConfig& config) {
307 DCHECK(config.IsValidConfig()); 302 DCHECK(config.IsValidConfig());
308 303
309 // Always clear the preroll buffer when a config update is received. 304 // Always clear the preroll buffer when a config update is received.
310 audio_preroll_buffer_ = NULL; 305 audio_preroll_buffer_ = NULL;
311 306
312 if (config.Matches(current_audio_config_)) 307 if (config.Matches(current_audio_config_))
313 return; 308 return;
314 309
315 current_audio_config_ = config; 310 current_audio_config_ = config;
316 sample_duration_ = base::TimeDelta::FromSecondsD( 311 sample_duration_ = base::TimeDelta::FromSecondsD(
317 1.0 / current_audio_config_.samples_per_second()); 312 1.0 / current_audio_config_.samples_per_second());
318 } 313 }
319 314
320 MseTrackBuffer* FrameProcessor::FindTrack(StreamParser::TrackId id) { 315 MseTrackBuffer* FrameProcessor::FindTrack(StreamParser::TrackId id) {
321 TrackBufferMap::iterator itr = track_buffers_.find(id); 316 TrackBufferMap::iterator itr = track_buffers_.find(id);
322 if (itr == track_buffers_.end()) 317 if (itr == track_buffers_.end())
323 return NULL; 318 return NULL;
324 319
325 return itr->second; 320 return itr->second;
326 } 321 }
327 322
328 void FrameProcessor::NotifyStartOfCodedFrameGroup( 323 void FrameProcessor::NotifyNewMediaSegmentStarting(
329 DecodeTimestamp start_timestamp) { 324 DecodeTimestamp segment_timestamp) {
330 DVLOG(2) << __FUNCTION__ << "(" << start_timestamp.InSecondsF() << ")"; 325 DVLOG(2) << __FUNCTION__ << "(" << segment_timestamp.InSecondsF() << ")";
331 326
332 for (TrackBufferMap::iterator itr = track_buffers_.begin(); 327 for (TrackBufferMap::iterator itr = track_buffers_.begin();
333 itr != track_buffers_.end(); 328 itr != track_buffers_.end();
334 ++itr) { 329 ++itr) {
335 itr->second->stream()->OnStartOfCodedFrameGroup(start_timestamp); 330 itr->second->stream()->OnNewMediaSegment(segment_timestamp);
336 } 331 }
337 } 332 }
338 333
339 bool FrameProcessor::FlushProcessedFrames() { 334 bool FrameProcessor::FlushProcessedFrames() {
340 DVLOG(2) << __FUNCTION__ << "()"; 335 DVLOG(2) << __FUNCTION__ << "()";
341 336
342 bool result = true; 337 bool result = true;
343 for (TrackBufferMap::iterator itr = track_buffers_.begin(); 338 for (TrackBufferMap::iterator itr = track_buffers_.begin();
344 itr != track_buffers_.end(); 339 itr != track_buffers_.end();
345 ++itr) { 340 ++itr) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 processed_buffer = true; 441 processed_buffer = true;
447 } 442 }
448 443
449 return processed_buffer; 444 return processed_buffer;
450 } 445 }
451 446
452 bool FrameProcessor::ProcessFrame( 447 bool FrameProcessor::ProcessFrame(
453 const scoped_refptr<StreamParserBuffer>& frame, 448 const scoped_refptr<StreamParserBuffer>& frame,
454 base::TimeDelta append_window_start, 449 base::TimeDelta append_window_start,
455 base::TimeDelta append_window_end, 450 base::TimeDelta append_window_end,
456 base::TimeDelta* timestamp_offset) { 451 base::TimeDelta* timestamp_offset,
452 bool* new_media_segment) {
457 // Implements the loop within step 1 of the coded frame processing algorithm 453 // Implements the loop within step 1 of the coded frame processing algorithm
458 // for a single input frame per April 1, 2014 MSE spec editor's draft: 454 // for a single input frame per April 1, 2014 MSE spec editor's draft:
459 // https://dvcs.w3.org/hg/html-media/raw-file/d471a4412040/media-source/ 455 // https://dvcs.w3.org/hg/html-media/raw-file/d471a4412040/media-source/
460 // media-source.html#sourcebuffer-coded-frame-processing 456 // media-source.html#sourcebuffer-coded-frame-processing
461 457
462 while (true) { 458 while (true) {
463 // 1. Loop Top: Let presentation timestamp be a double precision floating 459 // 1. Loop Top: Let presentation timestamp be a double precision floating
464 // point representation of the coded frame's presentation timestamp in 460 // point representation of the coded frame's presentation timestamp in
465 // seconds. 461 // seconds.
466 // 2. Let decode timestamp be a double precision floating point 462 // 2. Let decode timestamp be a double precision floating point
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 << ", and parser track id " << frame->track_id(); 580 << ", and parser track id " << frame->track_id();
585 return false; 581 return false;
586 } 582 }
587 583
588 // 7. If last decode timestamp for track buffer is set and decode timestamp 584 // 7. If last decode timestamp for track buffer is set and decode timestamp
589 // is less than last decode timestamp 585 // is less than last decode timestamp
590 // OR 586 // OR
591 // If last decode timestamp for track buffer is set and the difference 587 // If last decode timestamp for track buffer is set and the difference
592 // between decode timestamp and last decode timestamp is greater than 2 588 // between decode timestamp and last decode timestamp is greater than 2
593 // times last frame duration: 589 // times last frame duration:
594 DecodeTimestamp track_last_decode_timestamp = 590 DecodeTimestamp last_decode_timestamp =
595 track_buffer->last_decode_timestamp(); 591 track_buffer->last_decode_timestamp();
596 if (track_last_decode_timestamp != kNoDecodeTimestamp()) { 592 if (last_decode_timestamp != kNoDecodeTimestamp()) {
597 base::TimeDelta track_dts_delta = 593 base::TimeDelta dts_delta = decode_timestamp - last_decode_timestamp;
598 decode_timestamp - track_last_decode_timestamp; 594 if (dts_delta < base::TimeDelta() ||
599 if (track_dts_delta < base::TimeDelta() || 595 dts_delta > 2 * track_buffer->last_frame_duration()) {
600 track_dts_delta > 2 * track_buffer->last_frame_duration()) {
601 DCHECK(in_coded_frame_group_);
602 // 7.1. If mode equals "segments": Set group end timestamp to 596 // 7.1. If mode equals "segments": Set group end timestamp to
603 // presentation timestamp. 597 // presentation timestamp.
604 // If mode equals "sequence": Set group start timestamp equal to 598 // If mode equals "sequence": Set group start timestamp equal to
605 // the group end timestamp. 599 // the group end timestamp.
606 if (!sequence_mode_) { 600 if (!sequence_mode_) {
607 group_end_timestamp_ = presentation_timestamp; 601 group_end_timestamp_ = presentation_timestamp;
608 // This triggers a discontinuity so we need to treat the next frames 602 // This triggers a discontinuity so we need to treat the next frames
609 // appended within the append window as if they were the beginning of 603 // appended within the append window as if they were the beginning of
610 // a new coded frame group. 604 // a new segment.
611 in_coded_frame_group_ = false; 605 *new_media_segment = true;
612 } else { 606 } else {
613 DVLOG(3) << __FUNCTION__ << " : Sequence mode discontinuity, GETS: " 607 DVLOG(3) << __FUNCTION__ << " : Sequence mode discontinuity, GETS: "
614 << group_end_timestamp_.InSecondsF(); 608 << group_end_timestamp_.InSecondsF();
615 DCHECK(kNoTimestamp() != group_end_timestamp_); 609 DCHECK(kNoTimestamp() != group_end_timestamp_);
616 group_start_timestamp_ = group_end_timestamp_; 610 group_start_timestamp_ = group_end_timestamp_;
617 } 611 }
618 612
619 // 7.2. - 7.5.: 613 // 7.2. - 7.5.:
620 Reset(); 614 Reset();
621 615
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 DVLOG(3) << __FUNCTION__ 685 DVLOG(3) << __FUNCTION__
692 << ": Dropping frame that is not a random access point"; 686 << ": Dropping frame that is not a random access point";
693 return true; 687 return true;
694 } 688 }
695 689
696 // 12.2. Set the need random access point flag on track buffer to false. 690 // 12.2. Set the need random access point flag on track buffer to false.
697 track_buffer->set_needs_random_access_point(false); 691 track_buffer->set_needs_random_access_point(false);
698 } 692 }
699 693
700 // We now have a processed buffer to append to the track buffer's stream. 694 // We now have a processed buffer to append to the track buffer's stream.
701 // If it is the first in a new coded frame group (such as following a 695 // If it is the first in a new media segment or following a discontinuity,
702 // discontinuity), notify all the track buffers' streams that a coded frame 696 // notify all the track buffers' streams that a new segment is beginning.
703 // group is starting. 697 if (*new_media_segment) {
704 if (!in_coded_frame_group_) { 698 // First, complete the append to track buffer streams of previous media
705 // First, complete the append to track buffer streams of the previous 699 // segment's frames, if any.
706 // coded frame group's frames, if any.
707 if (!FlushProcessedFrames()) 700 if (!FlushProcessedFrames())
708 return false; 701 return false;
709 702
703 *new_media_segment = false;
704
710 // TODO(acolwell/wolenetz): This should be changed to a presentation 705 // TODO(acolwell/wolenetz): This should be changed to a presentation
711 // timestamp. See http://crbug.com/402502 706 // timestamp. See http://crbug.com/402502
712 NotifyStartOfCodedFrameGroup(decode_timestamp); 707 NotifyNewMediaSegmentStarting(decode_timestamp);
713 in_coded_frame_group_ = true;
714 } 708 }
715 709
716 DVLOG(3) << __FUNCTION__ << ": Sending processed frame to stream, " 710 DVLOG(3) << __FUNCTION__ << ": Sending processed frame to stream, "
717 << "PTS=" << presentation_timestamp.InSecondsF() 711 << "PTS=" << presentation_timestamp.InSecondsF()
718 << ", DTS=" << decode_timestamp.InSecondsF(); 712 << ", DTS=" << decode_timestamp.InSecondsF();
719 713
720 // Steps 13-18: Note, we optimize by appending groups of contiguous 714 // Steps 13-18: Note, we optimize by appending groups of contiguous
721 // processed frames for each track buffer at end of ProcessFrames() or prior 715 // processed frames for each track buffer at end of ProcessFrames() or prior
722 // to NotifyStartOfCodedFrameGroup(). 716 // to NotifyNewMediaSegmentStarting().
717 // TODO(wolenetz): Refactor SourceBufferStream to conform to spec GC timing.
718 // See http://crbug.com/371197.
723 track_buffer->EnqueueProcessedFrame(frame); 719 track_buffer->EnqueueProcessedFrame(frame);
724 720
725 // 19. Set last decode timestamp for track buffer to decode timestamp. 721 // 19. Set last decode timestamp for track buffer to decode timestamp.
726 track_buffer->set_last_decode_timestamp(decode_timestamp); 722 track_buffer->set_last_decode_timestamp(decode_timestamp);
727 723
728 // 20. Set last frame duration for track buffer to frame duration. 724 // 20. Set last frame duration for track buffer to frame duration.
729 track_buffer->set_last_frame_duration(frame_duration); 725 track_buffer->set_last_frame_duration(frame_duration);
730 726
731 // 21. If highest presentation timestamp for track buffer is unset or frame 727 // 21. If highest presentation timestamp for track buffer is unset or frame
732 // end timestamp is greater than highest presentation timestamp, then 728 // end timestamp is greater than highest presentation timestamp, then
733 // set highest presentation timestamp for track buffer to frame end 729 // set highest presentation timestamp for track buffer to frame end
734 // timestamp. 730 // timestamp.
735 track_buffer->SetHighestPresentationTimestampIfIncreased( 731 track_buffer->SetHighestPresentationTimestampIfIncreased(
736 frame_end_timestamp); 732 frame_end_timestamp);
737 733
738 // 22. If frame end timestamp is greater than group end timestamp, then set 734 // 22. If frame end timestamp is greater than group end timestamp, then set
739 // group end timestamp equal to frame end timestamp. 735 // group end timestamp equal to frame end timestamp.
740 if (frame_end_timestamp > group_end_timestamp_) 736 if (frame_end_timestamp > group_end_timestamp_)
741 group_end_timestamp_ = frame_end_timestamp; 737 group_end_timestamp_ = frame_end_timestamp;
742 DCHECK(group_end_timestamp_ >= base::TimeDelta()); 738 DCHECK(group_end_timestamp_ >= base::TimeDelta());
743 739
744 return true; 740 return true;
745 } 741 }
746 742
747 NOTREACHED(); 743 NOTREACHED();
748 return false; 744 return false;
749 } 745 }
750 746
751 } // namespace media 747 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/frame_processor.h ('k') | media/filters/frame_processor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698