| 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/base/media_track.h" |
| 10 #include "media/base/media_tracks.h" |
| 9 #include "media/filters/chunk_demuxer.h" | 11 #include "media/filters/chunk_demuxer.h" |
| 10 #include "media/filters/frame_processor.h" | 12 #include "media/filters/frame_processor.h" |
| 11 #include "media/filters/source_buffer_stream.h" | 13 #include "media/filters/source_buffer_stream.h" |
| 12 | 14 |
| 13 namespace media { | 15 namespace media { |
| 14 | 16 |
| 15 enum { | 17 enum { |
| 16 // Limits the number of MEDIA_LOG() calls warning the user that a muxed stream | 18 // 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 | 19 // media segment is missing a block from at least one of the audio or video |
| 18 // tracks. | 20 // tracks. |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 frame_processor_->SetSequenceMode(sequence_mode); | 138 frame_processor_->SetSequenceMode(sequence_mode); |
| 137 } | 139 } |
| 138 | 140 |
| 139 void MediaSourceState::SetGroupStartTimestampIfInSequenceMode( | 141 void MediaSourceState::SetGroupStartTimestampIfInSequenceMode( |
| 140 base::TimeDelta timestamp_offset) { | 142 base::TimeDelta timestamp_offset) { |
| 141 DCHECK(!parsing_media_segment_); | 143 DCHECK(!parsing_media_segment_); |
| 142 | 144 |
| 143 frame_processor_->SetGroupStartTimestampIfInSequenceMode(timestamp_offset); | 145 frame_processor_->SetGroupStartTimestampIfInSequenceMode(timestamp_offset); |
| 144 } | 146 } |
| 145 | 147 |
| 146 bool MediaSourceState::Append( | 148 void MediaSourceState::SetTracksWatcher( |
| 147 const uint8_t* data, | 149 const Demuxer::MediaTracksUpdatedCB& tracks_updated_cb) { |
| 148 size_t length, | 150 DCHECK(init_segment_received_cb_.is_null()); |
| 149 TimeDelta append_window_start, | 151 init_segment_received_cb_ = tracks_updated_cb; |
| 150 TimeDelta append_window_end, | 152 DCHECK(!init_segment_received_cb_.is_null()); |
| 151 TimeDelta* timestamp_offset, | 153 } |
| 152 const InitSegmentReceivedCB& init_segment_received_cb) { | 154 |
| 155 bool MediaSourceState::Append(const uint8_t* data, |
| 156 size_t length, |
| 157 TimeDelta append_window_start, |
| 158 TimeDelta append_window_end, |
| 159 TimeDelta* timestamp_offset) { |
| 160 append_in_progress_ = true; |
| 153 DCHECK(timestamp_offset); | 161 DCHECK(timestamp_offset); |
| 154 DCHECK(!timestamp_offset_during_append_); | 162 DCHECK(!timestamp_offset_during_append_); |
| 155 DCHECK(!init_segment_received_cb.is_null()); | |
| 156 DCHECK(init_segment_received_cb_.is_null()); | |
| 157 append_window_start_during_append_ = append_window_start; | 163 append_window_start_during_append_ = append_window_start; |
| 158 append_window_end_during_append_ = append_window_end; | 164 append_window_end_during_append_ = append_window_end; |
| 159 timestamp_offset_during_append_ = timestamp_offset; | 165 timestamp_offset_during_append_ = timestamp_offset; |
| 160 init_segment_received_cb_ = init_segment_received_cb; | |
| 161 | 166 |
| 162 // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with | 167 // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with |
| 163 // append window and timestamp offset pointer. See http://crbug.com/351454. | 168 // append window and timestamp offset pointer. See http://crbug.com/351454. |
| 164 bool result = stream_parser_->Parse(data, length); | 169 bool result = stream_parser_->Parse(data, length); |
| 165 if (!result) { | 170 if (!result) { |
| 166 MEDIA_LOG(ERROR, media_log_) | 171 MEDIA_LOG(ERROR, media_log_) |
| 167 << __FUNCTION__ << ": stream parsing failed." | 172 << __FUNCTION__ << ": stream parsing failed." |
| 168 << " Data size=" << length | 173 << " Data size=" << length |
| 169 << " append_window_start=" << append_window_start.InSecondsF() | 174 << " append_window_start=" << append_window_start.InSecondsF() |
| 170 << " append_window_end=" << append_window_end.InSecondsF(); | 175 << " append_window_end=" << append_window_end.InSecondsF(); |
| 171 } | 176 } |
| 172 timestamp_offset_during_append_ = NULL; | 177 timestamp_offset_during_append_ = NULL; |
| 173 init_segment_received_cb_.Reset(); | 178 append_in_progress_ = false; |
| 174 return result; | 179 return result; |
| 175 } | 180 } |
| 176 | 181 |
| 177 void MediaSourceState::ResetParserState(TimeDelta append_window_start, | 182 void MediaSourceState::ResetParserState(TimeDelta append_window_start, |
| 178 TimeDelta append_window_end, | 183 TimeDelta append_window_end, |
| 179 base::TimeDelta* timestamp_offset) { | 184 base::TimeDelta* timestamp_offset) { |
| 180 DCHECK(timestamp_offset); | 185 DCHECK(timestamp_offset); |
| 181 DCHECK(!timestamp_offset_during_append_); | 186 DCHECK(!timestamp_offset_during_append_); |
| 182 timestamp_offset_during_append_ = timestamp_offset; | 187 timestamp_offset_during_append_ = timestamp_offset; |
| 183 append_window_start_during_append_ = append_window_start; | 188 append_window_start_during_append_ = append_window_start; |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 // stalled because we don't have cues. If cues, with timestamps after | 466 // stalled because we don't have cues. If cues, with timestamps after |
| 462 // the seek time, eventually arrive they will be delivered properly | 467 // the seek time, eventually arrive they will be delivered properly |
| 463 // in response to ChunkDemuxerStream::Read() calls. | 468 // in response to ChunkDemuxerStream::Read() calls. |
| 464 | 469 |
| 465 return false; | 470 return false; |
| 466 } | 471 } |
| 467 | 472 |
| 468 bool MediaSourceState::OnNewConfigs( | 473 bool MediaSourceState::OnNewConfigs( |
| 469 bool allow_audio, | 474 bool allow_audio, |
| 470 bool allow_video, | 475 bool allow_video, |
| 471 const AudioDecoderConfig& audio_config, | 476 scoped_ptr<MediaTracks> tracks, |
| 472 const VideoDecoderConfig& video_config, | |
| 473 const StreamParser::TextTrackConfigMap& text_configs) { | 477 const StreamParser::TextTrackConfigMap& text_configs) { |
| 478 DCHECK(tracks); |
| 479 media_tracks_ = std::move(tracks); |
| 480 const AudioDecoderConfig& audio_config = media_tracks_->getFirstAudioConfig(); |
| 481 const VideoDecoderConfig& video_config = media_tracks_->getFirstVideoConfig(); |
| 482 |
| 474 DVLOG(1) << "OnNewConfigs(" << allow_audio << ", " << allow_video << ", " | 483 DVLOG(1) << "OnNewConfigs(" << allow_audio << ", " << allow_video << ", " |
| 475 << audio_config.IsValidConfig() << ", " | 484 << audio_config.IsValidConfig() << ", " |
| 476 << video_config.IsValidConfig() << ")"; | 485 << video_config.IsValidConfig() << ")"; |
| 477 DCHECK(!init_segment_received_cb_.is_null()); | 486 // MSE spec allows new configs to be emitted only during Append, but not |
| 487 // during Flush or parser reset operations. |
| 488 CHECK(append_in_progress_); |
| 478 | 489 |
| 479 if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) { | 490 if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) { |
| 480 DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!"; | 491 DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!"; |
| 481 return false; | 492 return false; |
| 482 } | 493 } |
| 483 | 494 |
| 484 // Signal an error if we get configuration info for stream types that weren't | 495 // Signal an error if we get configuration info for stream types that weren't |
| 485 // specified in AddId() or more configs after a stream is initialized. | 496 // specified in AddId() or more configs after a stream is initialized. |
| 486 if (allow_audio != audio_config.IsValidConfig()) { | 497 if (allow_audio != audio_config.IsValidConfig()) { |
| 487 MEDIA_LOG(ERROR, media_log_) | 498 MEDIA_LOG(ERROR, media_log_) |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 << " does not match old one."; | 641 << " does not match old one."; |
| 631 break; | 642 break; |
| 632 } | 643 } |
| 633 } | 644 } |
| 634 } | 645 } |
| 635 } | 646 } |
| 636 | 647 |
| 637 frame_processor_->SetAllTrackBuffersNeedRandomAccessPoint(); | 648 frame_processor_->SetAllTrackBuffersNeedRandomAccessPoint(); |
| 638 | 649 |
| 639 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); | 650 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); |
| 640 if (success) | 651 if (success) { |
| 641 init_segment_received_cb_.Run(); | 652 DCHECK(!init_segment_received_cb_.is_null()); |
| 653 init_segment_received_cb_.Run(std::move(media_tracks_)); |
| 654 } |
| 642 | 655 |
| 643 return success; | 656 return success; |
| 644 } | 657 } |
| 645 | 658 |
| 646 void MediaSourceState::OnNewMediaSegment() { | 659 void MediaSourceState::OnNewMediaSegment() { |
| 647 DVLOG(2) << "OnNewMediaSegment()"; | 660 DVLOG(2) << "OnNewMediaSegment()"; |
| 648 parsing_media_segment_ = true; | 661 parsing_media_segment_ = true; |
| 649 media_segment_contained_audio_frame_ = false; | 662 media_segment_contained_audio_frame_ = false; |
| 650 media_segment_contained_video_frame_ = false; | 663 media_segment_contained_video_frame_ = false; |
| 651 } | 664 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 return true; | 728 return true; |
| 716 } | 729 } |
| 717 | 730 |
| 718 void MediaSourceState::OnSourceInitDone( | 731 void MediaSourceState::OnSourceInitDone( |
| 719 const StreamParser::InitParameters& params) { | 732 const StreamParser::InitParameters& params) { |
| 720 auto_update_timestamp_offset_ = params.auto_update_timestamp_offset; | 733 auto_update_timestamp_offset_ = params.auto_update_timestamp_offset; |
| 721 base::ResetAndReturn(&init_cb_).Run(params); | 734 base::ResetAndReturn(&init_cb_).Run(params); |
| 722 } | 735 } |
| 723 | 736 |
| 724 } // namespace media | 737 } // namespace media |
| OLD | NEW |