| OLD | NEW |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 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/media_source_state.h" | 5 #include "media/filters/media_source_state.h" |
| 6 | 6 |
| 7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "media/filters/chunk_demuxer.h" | 9 #include "media/filters/chunk_demuxer.h" |
| 10 #include "media/filters/frame_processor.h" | 10 #include "media/filters/frame_processor.h" |
| 11 #include "media/filters/source_buffer_stream.h" | 11 #include "media/filters/source_buffer_stream.h" |
| 12 | 12 |
| 13 namespace media { | 13 namespace media { |
| 14 | 14 |
| 15 enum { |
| 16 // Limits the number of MEDIA_LOG() calls warning the user that a muxed stream |
| 17 // media segment is missing a block from at least one of the audio or video |
| 18 // tracks. |
| 19 kMaxMissingTrackInSegmentLogs = 10, |
| 20 }; |
| 21 |
| 15 static TimeDelta EndTimestamp(const StreamParser::BufferQueue& queue) { | 22 static TimeDelta EndTimestamp(const StreamParser::BufferQueue& queue) { |
| 16 return queue.back()->timestamp() + queue.back()->duration(); | 23 return queue.back()->timestamp() + queue.back()->duration(); |
| 17 } | 24 } |
| 18 | 25 |
| 19 // List of time ranges for each SourceBuffer. | 26 // List of time ranges for each SourceBuffer. |
| 20 // static | 27 // static |
| 21 Ranges<TimeDelta> MediaSourceState::ComputeRangesIntersection( | 28 Ranges<TimeDelta> MediaSourceState::ComputeRangesIntersection( |
| 22 const RangesList& activeRanges, | 29 const RangesList& activeRanges, |
| 23 bool ended) { | 30 bool ended) { |
| 24 // TODO(servolk): Perhaps this can be removed in favor of blink implementation | 31 // TODO(servolk): Perhaps this can be removed in favor of blink implementation |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 | 85 |
| 79 MediaSourceState::MediaSourceState( | 86 MediaSourceState::MediaSourceState( |
| 80 scoped_ptr<StreamParser> stream_parser, | 87 scoped_ptr<StreamParser> stream_parser, |
| 81 scoped_ptr<FrameProcessor> frame_processor, | 88 scoped_ptr<FrameProcessor> frame_processor, |
| 82 const CreateDemuxerStreamCB& create_demuxer_stream_cb, | 89 const CreateDemuxerStreamCB& create_demuxer_stream_cb, |
| 83 const scoped_refptr<MediaLog>& media_log) | 90 const scoped_refptr<MediaLog>& media_log) |
| 84 : create_demuxer_stream_cb_(create_demuxer_stream_cb), | 91 : create_demuxer_stream_cb_(create_demuxer_stream_cb), |
| 85 timestamp_offset_during_append_(NULL), | 92 timestamp_offset_during_append_(NULL), |
| 86 new_media_segment_(false), | 93 new_media_segment_(false), |
| 87 parsing_media_segment_(false), | 94 parsing_media_segment_(false), |
| 95 media_segment_contained_audio_frame_(false), |
| 96 media_segment_contained_video_frame_(false), |
| 88 stream_parser_(stream_parser.release()), | 97 stream_parser_(stream_parser.release()), |
| 89 audio_(NULL), | 98 audio_(NULL), |
| 90 video_(NULL), | 99 video_(NULL), |
| 91 frame_processor_(frame_processor.release()), | 100 frame_processor_(frame_processor.release()), |
| 92 media_log_(media_log), | 101 media_log_(media_log), |
| 93 auto_update_timestamp_offset_(false) { | 102 auto_update_timestamp_offset_(false) { |
| 94 DCHECK(!create_demuxer_stream_cb_.is_null()); | 103 DCHECK(!create_demuxer_stream_cb_.is_null()); |
| 95 DCHECK(frame_processor_); | 104 DCHECK(frame_processor_); |
| 96 } | 105 } |
| 97 | 106 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 DCHECK(!timestamp_offset_during_append_); | 182 DCHECK(!timestamp_offset_during_append_); |
| 174 timestamp_offset_during_append_ = timestamp_offset; | 183 timestamp_offset_during_append_ = timestamp_offset; |
| 175 append_window_start_during_append_ = append_window_start; | 184 append_window_start_during_append_ = append_window_start; |
| 176 append_window_end_during_append_ = append_window_end; | 185 append_window_end_during_append_ = append_window_end; |
| 177 | 186 |
| 178 stream_parser_->Flush(); | 187 stream_parser_->Flush(); |
| 179 timestamp_offset_during_append_ = NULL; | 188 timestamp_offset_during_append_ = NULL; |
| 180 | 189 |
| 181 frame_processor_->Reset(); | 190 frame_processor_->Reset(); |
| 182 parsing_media_segment_ = false; | 191 parsing_media_segment_ = false; |
| 192 media_segment_contained_audio_frame_ = false; |
| 193 media_segment_contained_video_frame_ = false; |
| 183 } | 194 } |
| 184 | 195 |
| 185 void MediaSourceState::Remove(TimeDelta start, | 196 void MediaSourceState::Remove(TimeDelta start, |
| 186 TimeDelta end, | 197 TimeDelta end, |
| 187 TimeDelta duration) { | 198 TimeDelta duration) { |
| 188 if (audio_) | 199 if (audio_) |
| 189 audio_->Remove(start, end, duration); | 200 audio_->Remove(start, end, duration); |
| 190 | 201 |
| 191 if (video_) | 202 if (video_) |
| 192 video_->Remove(start, end, duration); | 203 video_->Remove(start, end, duration); |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 if (success) | 641 if (success) |
| 631 init_segment_received_cb_.Run(); | 642 init_segment_received_cb_.Run(); |
| 632 | 643 |
| 633 return success; | 644 return success; |
| 634 } | 645 } |
| 635 | 646 |
| 636 void MediaSourceState::OnNewMediaSegment() { | 647 void MediaSourceState::OnNewMediaSegment() { |
| 637 DVLOG(2) << "OnNewMediaSegment()"; | 648 DVLOG(2) << "OnNewMediaSegment()"; |
| 638 parsing_media_segment_ = true; | 649 parsing_media_segment_ = true; |
| 639 new_media_segment_ = true; | 650 new_media_segment_ = true; |
| 651 media_segment_contained_audio_frame_ = false; |
| 652 media_segment_contained_video_frame_ = false; |
| 640 } | 653 } |
| 641 | 654 |
| 642 void MediaSourceState::OnEndOfMediaSegment() { | 655 void MediaSourceState::OnEndOfMediaSegment() { |
| 643 DVLOG(2) << "OnEndOfMediaSegment()"; | 656 DVLOG(2) << "OnEndOfMediaSegment()"; |
| 644 parsing_media_segment_ = false; | 657 parsing_media_segment_ = false; |
| 645 new_media_segment_ = false; | 658 new_media_segment_ = false; |
| 659 |
| 660 const bool missing_audio = audio_ && !media_segment_contained_audio_frame_; |
| 661 const bool missing_video = video_ && !media_segment_contained_video_frame_; |
| 662 if (!missing_audio && !missing_video) |
| 663 return; |
| 664 |
| 665 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_missing_track_logs_, |
| 666 kMaxMissingTrackInSegmentLogs) |
| 667 << "Media segment did not contain any " |
| 668 << (missing_audio && missing_video ? "audio or video" |
| 669 : missing_audio ? "audio" : "video") |
| 670 << " coded frames, mismatching initialization segment. Therefore, MSE " |
| 671 "coded frame processing may not interoperably detect discontinuities " |
| 672 "in appended media."; |
| 646 } | 673 } |
| 647 | 674 |
| 648 bool MediaSourceState::OnNewBuffers( | 675 bool MediaSourceState::OnNewBuffers( |
| 649 const StreamParser::BufferQueue& audio_buffers, | 676 const StreamParser::BufferQueue& audio_buffers, |
| 650 const StreamParser::BufferQueue& video_buffers, | 677 const StreamParser::BufferQueue& video_buffers, |
| 651 const StreamParser::TextBufferQueueMap& text_map) { | 678 const StreamParser::TextBufferQueueMap& text_map) { |
| 652 DVLOG(2) << "OnNewBuffers()"; | 679 DVLOG(2) << "OnNewBuffers()"; |
| 653 DCHECK(timestamp_offset_during_append_); | 680 DCHECK(timestamp_offset_during_append_); |
| 654 DCHECK(parsing_media_segment_); | 681 DCHECK(parsing_media_segment_); |
| 655 | 682 |
| 683 media_segment_contained_audio_frame_ |= !audio_buffers.empty(); |
| 684 media_segment_contained_video_frame_ |= !video_buffers.empty(); |
| 685 |
| 656 const TimeDelta timestamp_offset_before_processing = | 686 const TimeDelta timestamp_offset_before_processing = |
| 657 *timestamp_offset_during_append_; | 687 *timestamp_offset_during_append_; |
| 658 | 688 |
| 659 // Calculate the new timestamp offset for audio/video tracks if the stream | 689 // Calculate the new timestamp offset for audio/video tracks if the stream |
| 660 // parser has requested automatic updates. | 690 // parser has requested automatic updates. |
| 661 TimeDelta new_timestamp_offset = timestamp_offset_before_processing; | 691 TimeDelta new_timestamp_offset = timestamp_offset_before_processing; |
| 662 if (auto_update_timestamp_offset_) { | 692 if (auto_update_timestamp_offset_) { |
| 663 const bool have_audio_buffers = !audio_buffers.empty(); | 693 const bool have_audio_buffers = !audio_buffers.empty(); |
| 664 const bool have_video_buffers = !video_buffers.empty(); | 694 const bool have_video_buffers = !video_buffers.empty(); |
| 665 if (have_audio_buffers && have_video_buffers) { | 695 if (have_audio_buffers && have_video_buffers) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 688 return true; | 718 return true; |
| 689 } | 719 } |
| 690 | 720 |
| 691 void MediaSourceState::OnSourceInitDone( | 721 void MediaSourceState::OnSourceInitDone( |
| 692 const StreamParser::InitParameters& params) { | 722 const StreamParser::InitParameters& params) { |
| 693 auto_update_timestamp_offset_ = params.auto_update_timestamp_offset; | 723 auto_update_timestamp_offset_ = params.auto_update_timestamp_offset; |
| 694 base::ResetAndReturn(&init_cb_).Run(params); | 724 base::ResetAndReturn(&init_cb_).Run(params); |
| 695 } | 725 } |
| 696 | 726 |
| 697 } // namespace media | 727 } // namespace media |
| OLD | NEW |