| 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 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 void FrameProcessor::SetSequenceMode(bool sequence_mode) { | 178 void FrameProcessor::SetSequenceMode(bool sequence_mode) { |
| 179 DVLOG(2) << __FUNCTION__ << "(" << sequence_mode << ")"; | 179 DVLOG(2) << __FUNCTION__ << "(" << 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_) { |
| 189 // We're switching from 'sequence' to 'segments' mode. Be safe and signal a |
| 190 // new coded frame group on the next frame emitted. |
| 191 coded_frame_group_last_dts_ = kNoDecodeTimestamp(); |
| 188 } | 192 } |
| 189 | 193 |
| 190 // Step 8: Update the attribute to new mode. | 194 // Step 8: Update the attribute to new mode. |
| 191 sequence_mode_ = sequence_mode; | 195 sequence_mode_ = sequence_mode; |
| 192 } | 196 } |
| 193 | 197 |
| 194 bool FrameProcessor::ProcessFrames( | 198 bool FrameProcessor::ProcessFrames( |
| 195 const StreamParser::BufferQueue& audio_buffers, | 199 const StreamParser::BufferQueue& audio_buffers, |
| 196 const StreamParser::BufferQueue& video_buffers, | 200 const StreamParser::BufferQueue& video_buffers, |
| 197 const StreamParser::TextBufferQueueMap& text_map, | 201 const StreamParser::TextBufferQueueMap& text_map, |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 } | 289 } |
| 286 } | 290 } |
| 287 | 291 |
| 288 void FrameProcessor::Reset() { | 292 void FrameProcessor::Reset() { |
| 289 DVLOG(2) << __FUNCTION__ << "()"; | 293 DVLOG(2) << __FUNCTION__ << "()"; |
| 290 for (TrackBufferMap::iterator itr = track_buffers_.begin(); | 294 for (TrackBufferMap::iterator itr = track_buffers_.begin(); |
| 291 itr != track_buffers_.end(); ++itr) { | 295 itr != track_buffers_.end(); ++itr) { |
| 292 itr->second->Reset(); | 296 itr->second->Reset(); |
| 293 } | 297 } |
| 294 | 298 |
| 295 // Maintain current |in_coded_frame_group_| state for Reset() during | 299 // Maintain current |coded_frame_group_last_dts_| state for Reset() during |
| 296 // sequence mode. Reset it here only if in segments 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 |
| 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_|. |
| 297 if (!sequence_mode_) { | 304 if (!sequence_mode_) { |
| 298 in_coded_frame_group_ = false; | 305 coded_frame_group_last_dts_ = kNoDecodeTimestamp(); |
| 299 return; | 306 return; |
| 300 } | 307 } |
| 301 | 308 |
| 302 // Sequence mode | 309 // Sequence mode |
| 303 DCHECK(kNoTimestamp() != group_end_timestamp_); | 310 DCHECK(kNoTimestamp() != group_end_timestamp_); |
| 304 group_start_timestamp_ = group_end_timestamp_; | 311 group_start_timestamp_ = group_end_timestamp_; |
| 305 } | 312 } |
| 306 | 313 |
| 307 void FrameProcessor::OnPossibleAudioConfigUpdate( | 314 void FrameProcessor::OnPossibleAudioConfigUpdate( |
| 308 const AudioDecoderConfig& config) { | 315 const AudioDecoderConfig& config) { |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 // If last decode timestamp for track buffer is set and the difference | 601 // If last decode timestamp for track buffer is set and the difference |
| 595 // between decode timestamp and last decode timestamp is greater than 2 | 602 // between decode timestamp and last decode timestamp is greater than 2 |
| 596 // times last frame duration: | 603 // times last frame duration: |
| 597 DecodeTimestamp track_last_decode_timestamp = | 604 DecodeTimestamp track_last_decode_timestamp = |
| 598 track_buffer->last_decode_timestamp(); | 605 track_buffer->last_decode_timestamp(); |
| 599 if (track_last_decode_timestamp != kNoDecodeTimestamp()) { | 606 if (track_last_decode_timestamp != kNoDecodeTimestamp()) { |
| 600 base::TimeDelta track_dts_delta = | 607 base::TimeDelta track_dts_delta = |
| 601 decode_timestamp - track_last_decode_timestamp; | 608 decode_timestamp - track_last_decode_timestamp; |
| 602 if (track_dts_delta < base::TimeDelta() || | 609 if (track_dts_delta < base::TimeDelta() || |
| 603 track_dts_delta > 2 * track_buffer->last_frame_duration()) { | 610 track_dts_delta > 2 * track_buffer->last_frame_duration()) { |
| 604 DCHECK(in_coded_frame_group_); | 611 DCHECK(coded_frame_group_last_dts_ != kNoDecodeTimestamp()); |
| 605 // 6.1. If mode equals "segments": Set group end timestamp to | 612 // 6.1. If mode equals "segments": Set group end timestamp to |
| 606 // presentation timestamp. | 613 // presentation timestamp. |
| 607 // If mode equals "sequence": Set group start timestamp equal to | 614 // If mode equals "sequence": Set group start timestamp equal to |
| 608 // the group end timestamp. | 615 // the group end timestamp. |
| 609 if (!sequence_mode_) { | 616 if (!sequence_mode_) { |
| 610 group_end_timestamp_ = presentation_timestamp; | 617 group_end_timestamp_ = presentation_timestamp; |
| 611 // This triggers a discontinuity so we need to treat the next frames | 618 // This triggers a discontinuity so we need to treat the next frames |
| 612 // appended within the append window as if they were the beginning of | 619 // appended within the append window as if they were the beginning of |
| 613 // a new coded frame group. | 620 // a new coded frame group. |coded_frame_group_last_dts_| is reset in |
| 614 in_coded_frame_group_ = false; | 621 // Reset(), below, for "segments" mode. |
| 615 } else { | 622 } else { |
| 616 DVLOG(3) << __FUNCTION__ << " : Sequence mode discontinuity, GETS: " | 623 DVLOG(3) << __FUNCTION__ << " : Sequence mode discontinuity, GETS: " |
| 617 << group_end_timestamp_.InSecondsF(); | 624 << group_end_timestamp_.InSecondsF(); |
| 618 DCHECK(kNoTimestamp() != group_end_timestamp_); | 625 // Reset(), below, performs the "Set group start timestamp equal to |
| 619 group_start_timestamp_ = group_end_timestamp_; | 626 // the group end timestamp" operation for "sequence" mode. |
| 620 } | 627 } |
| 621 | 628 |
| 622 // 6.2. - 6.5.: | 629 // 6.2. - 6.5.: |
| 623 Reset(); | 630 Reset(); |
| 624 | 631 |
| 625 // 6.6. Jump to the Loop Top step above to restart processing of the | 632 // 6.6. Jump to the Loop Top step above to restart processing of the |
| 626 // current coded frame. | 633 // current coded frame. |
| 627 DVLOG(3) << __FUNCTION__ << ": Discontinuity: reprocessing frame"; | 634 DVLOG(3) << __FUNCTION__ << ": Discontinuity: reprocessing frame"; |
| 628 continue; | 635 continue; |
| 629 } | 636 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 } | 704 } |
| 698 | 705 |
| 699 // 10.2. Set the need random access point flag on track buffer to false. | 706 // 10.2. Set the need random access point flag on track buffer to false. |
| 700 track_buffer->set_needs_random_access_point(false); | 707 track_buffer->set_needs_random_access_point(false); |
| 701 } | 708 } |
| 702 | 709 |
| 703 // We now have a processed buffer to append to the track buffer's stream. | 710 // We now have a processed buffer to append to the track buffer's stream. |
| 704 // If it is the first in a new coded frame group (such as following a | 711 // If it is the first in a new coded frame group (such as following a |
| 705 // discontinuity), notify all the track buffers' streams that a coded frame | 712 // discontinuity), notify all the track buffers' streams that a coded frame |
| 706 // group is starting. | 713 // group is starting. |
| 707 if (!in_coded_frame_group_) { | 714 // If in 'sequence' appendMode, also check to make sure we don't need to |
| 715 // signal the start of a new coded frame group in the case where |
| 716 // timestampOffset adjustments by the app may cause this coded frame to be |
| 717 // in the timeline prior to the last frame processed. |
| 718 if (coded_frame_group_last_dts_ == kNoDecodeTimestamp() || |
| 719 (sequence_mode_ && coded_frame_group_last_dts_ > decode_timestamp)) { |
| 708 // First, complete the append to track buffer streams of the previous | 720 // First, complete the append to track buffer streams of the previous |
| 709 // coded frame group's frames, if any. | 721 // coded frame group's frames, if any. |
| 710 if (!FlushProcessedFrames()) | 722 if (!FlushProcessedFrames()) |
| 711 return false; | 723 return false; |
| 712 | 724 |
| 713 // TODO(acolwell/wolenetz): This should be changed to a presentation | 725 // TODO(wolenetz): This should be changed to a presentation timestamp. See |
| 714 // timestamp. See http://crbug.com/402502 | 726 // http://crbug.com/402502 |
| 715 NotifyStartOfCodedFrameGroup(decode_timestamp); | 727 NotifyStartOfCodedFrameGroup(decode_timestamp); |
| 716 in_coded_frame_group_ = true; | |
| 717 } | 728 } |
| 718 | 729 |
| 730 coded_frame_group_last_dts_ = decode_timestamp; |
| 731 |
| 719 DVLOG(3) << __FUNCTION__ << ": Sending processed frame to stream, " | 732 DVLOG(3) << __FUNCTION__ << ": Sending processed frame to stream, " |
| 720 << "PTS=" << presentation_timestamp.InSecondsF() | 733 << "PTS=" << presentation_timestamp.InSecondsF() |
| 721 << ", DTS=" << decode_timestamp.InSecondsF(); | 734 << ", DTS=" << decode_timestamp.InSecondsF(); |
| 722 | 735 |
| 723 // Steps 11-16: Note, we optimize by appending groups of contiguous | 736 // Steps 11-16: Note, we optimize by appending groups of contiguous |
| 724 // processed frames for each track buffer at end of ProcessFrames() or prior | 737 // processed frames for each track buffer at end of ProcessFrames() or prior |
| 725 // to NotifyStartOfCodedFrameGroup(). | 738 // to NotifyStartOfCodedFrameGroup(). |
| 726 track_buffer->EnqueueProcessedFrame(frame); | 739 track_buffer->EnqueueProcessedFrame(frame); |
| 727 | 740 |
| 728 // 17. Set last decode timestamp for track buffer to decode timestamp. | 741 // 17. Set last decode timestamp for track buffer to decode timestamp. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 747 // Step 21 is currently handled differently. See MediaSourceState's | 760 // Step 21 is currently handled differently. See MediaSourceState's |
| 748 // |auto_update_timestamp_offset_|. | 761 // |auto_update_timestamp_offset_|. |
| 749 return true; | 762 return true; |
| 750 } | 763 } |
| 751 | 764 |
| 752 NOTREACHED(); | 765 NOTREACHED(); |
| 753 return false; | 766 return false; |
| 754 } | 767 } |
| 755 | 768 |
| 756 } // namespace media | 769 } // namespace media |
| OLD | NEW |