| 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" | 9 #include "media/base/media_track.h" |
| 10 #include "media/base/media_tracks.h" | 10 #include "media/base/media_tracks.h" |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 : create_demuxer_stream_cb_(create_demuxer_stream_cb), | 93 : create_demuxer_stream_cb_(create_demuxer_stream_cb), |
| 94 timestamp_offset_during_append_(NULL), | 94 timestamp_offset_during_append_(NULL), |
| 95 parsing_media_segment_(false), | 95 parsing_media_segment_(false), |
| 96 media_segment_contained_audio_frame_(false), | 96 media_segment_contained_audio_frame_(false), |
| 97 media_segment_contained_video_frame_(false), | 97 media_segment_contained_video_frame_(false), |
| 98 stream_parser_(stream_parser.release()), | 98 stream_parser_(stream_parser.release()), |
| 99 audio_(NULL), | 99 audio_(NULL), |
| 100 video_(NULL), | 100 video_(NULL), |
| 101 frame_processor_(frame_processor.release()), | 101 frame_processor_(frame_processor.release()), |
| 102 media_log_(media_log), | 102 media_log_(media_log), |
| 103 state_(UNINITIALIZED), |
| 103 auto_update_timestamp_offset_(false) { | 104 auto_update_timestamp_offset_(false) { |
| 104 DCHECK(!create_demuxer_stream_cb_.is_null()); | 105 DCHECK(!create_demuxer_stream_cb_.is_null()); |
| 105 DCHECK(frame_processor_); | 106 DCHECK(frame_processor_); |
| 106 } | 107 } |
| 107 | 108 |
| 108 MediaSourceState::~MediaSourceState() { | 109 MediaSourceState::~MediaSourceState() { |
| 109 Shutdown(); | 110 Shutdown(); |
| 110 | 111 |
| 111 STLDeleteValues(&text_stream_map_); | 112 STLDeleteValues(&text_stream_map_); |
| 112 } | 113 } |
| 113 | 114 |
| 114 void MediaSourceState::Init( | 115 void MediaSourceState::Init( |
| 115 const StreamParser::InitCB& init_cb, | 116 const StreamParser::InitCB& init_cb, |
| 116 bool allow_audio, | 117 bool allow_audio, |
| 117 bool allow_video, | 118 bool allow_video, |
| 118 const StreamParser::EncryptedMediaInitDataCB& encrypted_media_init_data_cb, | 119 const StreamParser::EncryptedMediaInitDataCB& encrypted_media_init_data_cb, |
| 119 const NewTextTrackCB& new_text_track_cb) { | 120 const NewTextTrackCB& new_text_track_cb) { |
| 121 DCHECK_EQ(state_, UNINITIALIZED); |
| 120 new_text_track_cb_ = new_text_track_cb; | 122 new_text_track_cb_ = new_text_track_cb; |
| 121 init_cb_ = init_cb; | 123 init_cb_ = init_cb; |
| 122 | 124 |
| 125 state_ = PENDING_PARSER_CONFIG; |
| 123 stream_parser_->Init( | 126 stream_parser_->Init( |
| 124 base::Bind(&MediaSourceState::OnSourceInitDone, base::Unretained(this)), | 127 base::Bind(&MediaSourceState::OnSourceInitDone, base::Unretained(this)), |
| 125 base::Bind(&MediaSourceState::OnNewConfigs, base::Unretained(this), | 128 base::Bind(&MediaSourceState::OnNewConfigs, base::Unretained(this), |
| 126 allow_audio, allow_video), | 129 allow_audio, allow_video), |
| 127 base::Bind(&MediaSourceState::OnNewBuffers, base::Unretained(this)), | 130 base::Bind(&MediaSourceState::OnNewBuffers, base::Unretained(this)), |
| 128 new_text_track_cb_.is_null(), encrypted_media_init_data_cb, | 131 new_text_track_cb_.is_null(), encrypted_media_init_data_cb, |
| 129 base::Bind(&MediaSourceState::OnNewMediaSegment, base::Unretained(this)), | 132 base::Bind(&MediaSourceState::OnNewMediaSegment, base::Unretained(this)), |
| 130 base::Bind(&MediaSourceState::OnEndOfMediaSegment, | 133 base::Bind(&MediaSourceState::OnEndOfMediaSegment, |
| 131 base::Unretained(this)), | 134 base::Unretained(this)), |
| 132 media_log_); | 135 media_log_); |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 // in response to ChunkDemuxerStream::Read() calls. | 471 // in response to ChunkDemuxerStream::Read() calls. |
| 469 | 472 |
| 470 return false; | 473 return false; |
| 471 } | 474 } |
| 472 | 475 |
| 473 bool MediaSourceState::OnNewConfigs( | 476 bool MediaSourceState::OnNewConfigs( |
| 474 bool allow_audio, | 477 bool allow_audio, |
| 475 bool allow_video, | 478 bool allow_video, |
| 476 scoped_ptr<MediaTracks> tracks, | 479 scoped_ptr<MediaTracks> tracks, |
| 477 const StreamParser::TextTrackConfigMap& text_configs) { | 480 const StreamParser::TextTrackConfigMap& text_configs) { |
| 481 DCHECK_GE(state_, PENDING_PARSER_CONFIG); |
| 478 DCHECK(tracks.get()); | 482 DCHECK(tracks.get()); |
| 479 media_tracks_ = std::move(tracks); | 483 media_tracks_ = std::move(tracks); |
| 480 const AudioDecoderConfig& audio_config = media_tracks_->getFirstAudioConfig(); | 484 const AudioDecoderConfig& audio_config = media_tracks_->getFirstAudioConfig(); |
| 481 const VideoDecoderConfig& video_config = media_tracks_->getFirstVideoConfig(); | 485 const VideoDecoderConfig& video_config = media_tracks_->getFirstVideoConfig(); |
| 482 | 486 |
| 483 DVLOG(1) << "OnNewConfigs(" << allow_audio << ", " << allow_video << ", " | 487 DVLOG(1) << "OnNewConfigs(" << allow_audio << ", " << allow_video << ", " |
| 484 << audio_config.IsValidConfig() << ", " | 488 << audio_config.IsValidConfig() << ", " |
| 485 << video_config.IsValidConfig() << ")"; | 489 << video_config.IsValidConfig() << ")"; |
| 486 // MSE spec allows new configs to be emitted only during Append, but not | 490 // MSE spec allows new configs to be emitted only during Append, but not |
| 487 // during Flush or parser reset operations. | 491 // during Flush or parser reset operations. |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 break; | 646 break; |
| 643 } | 647 } |
| 644 } | 648 } |
| 645 } | 649 } |
| 646 } | 650 } |
| 647 | 651 |
| 648 frame_processor_->SetAllTrackBuffersNeedRandomAccessPoint(); | 652 frame_processor_->SetAllTrackBuffersNeedRandomAccessPoint(); |
| 649 | 653 |
| 650 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); | 654 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); |
| 651 if (success) { | 655 if (success) { |
| 656 if (state_ == PENDING_PARSER_CONFIG) |
| 657 state_ = PENDING_PARSER_INIT; |
| 652 DCHECK(!init_segment_received_cb_.is_null()); | 658 DCHECK(!init_segment_received_cb_.is_null()); |
| 653 init_segment_received_cb_.Run(std::move(media_tracks_)); | 659 init_segment_received_cb_.Run(std::move(media_tracks_)); |
| 654 } | 660 } |
| 655 | 661 |
| 656 return success; | 662 return success; |
| 657 } | 663 } |
| 658 | 664 |
| 659 void MediaSourceState::OnNewMediaSegment() { | 665 void MediaSourceState::OnNewMediaSegment() { |
| 660 DVLOG(2) << "OnNewMediaSegment()"; | 666 DVLOG(2) << "OnNewMediaSegment()"; |
| 667 DCHECK_EQ(state_, PARSER_INITIALIZED); |
| 661 parsing_media_segment_ = true; | 668 parsing_media_segment_ = true; |
| 662 media_segment_contained_audio_frame_ = false; | 669 media_segment_contained_audio_frame_ = false; |
| 663 media_segment_contained_video_frame_ = false; | 670 media_segment_contained_video_frame_ = false; |
| 664 } | 671 } |
| 665 | 672 |
| 666 void MediaSourceState::OnEndOfMediaSegment() { | 673 void MediaSourceState::OnEndOfMediaSegment() { |
| 667 DVLOG(2) << "OnEndOfMediaSegment()"; | 674 DVLOG(2) << "OnEndOfMediaSegment()"; |
| 675 DCHECK_EQ(state_, PARSER_INITIALIZED); |
| 668 parsing_media_segment_ = false; | 676 parsing_media_segment_ = false; |
| 669 | 677 |
| 670 const bool missing_audio = audio_ && !media_segment_contained_audio_frame_; | 678 const bool missing_audio = audio_ && !media_segment_contained_audio_frame_; |
| 671 const bool missing_video = video_ && !media_segment_contained_video_frame_; | 679 const bool missing_video = video_ && !media_segment_contained_video_frame_; |
| 672 if (!missing_audio && !missing_video) | 680 if (!missing_audio && !missing_video) |
| 673 return; | 681 return; |
| 674 | 682 |
| 675 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_missing_track_logs_, | 683 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_missing_track_logs_, |
| 676 kMaxMissingTrackInSegmentLogs) | 684 kMaxMissingTrackInSegmentLogs) |
| 677 << "Media segment did not contain any " | 685 << "Media segment did not contain any " |
| 678 << (missing_audio && missing_video ? "audio or video" | 686 << (missing_audio && missing_video ? "audio or video" |
| 679 : missing_audio ? "audio" : "video") | 687 : missing_audio ? "audio" : "video") |
| 680 << " coded frames, mismatching initialization segment. Therefore, MSE " | 688 << " coded frames, mismatching initialization segment. Therefore, MSE " |
| 681 "coded frame processing may not interoperably detect discontinuities " | 689 "coded frame processing may not interoperably detect discontinuities " |
| 682 "in appended media."; | 690 "in appended media."; |
| 683 } | 691 } |
| 684 | 692 |
| 685 bool MediaSourceState::OnNewBuffers( | 693 bool MediaSourceState::OnNewBuffers( |
| 686 const StreamParser::BufferQueue& audio_buffers, | 694 const StreamParser::BufferQueue& audio_buffers, |
| 687 const StreamParser::BufferQueue& video_buffers, | 695 const StreamParser::BufferQueue& video_buffers, |
| 688 const StreamParser::TextBufferQueueMap& text_map) { | 696 const StreamParser::TextBufferQueueMap& text_map) { |
| 689 DVLOG(2) << "OnNewBuffers()"; | 697 DVLOG(2) << "OnNewBuffers()"; |
| 698 DCHECK_EQ(state_, PARSER_INITIALIZED); |
| 690 DCHECK(timestamp_offset_during_append_); | 699 DCHECK(timestamp_offset_during_append_); |
| 691 DCHECK(parsing_media_segment_); | 700 DCHECK(parsing_media_segment_); |
| 692 | 701 |
| 693 media_segment_contained_audio_frame_ |= !audio_buffers.empty(); | 702 media_segment_contained_audio_frame_ |= !audio_buffers.empty(); |
| 694 media_segment_contained_video_frame_ |= !video_buffers.empty(); | 703 media_segment_contained_video_frame_ |= !video_buffers.empty(); |
| 695 | 704 |
| 696 const TimeDelta timestamp_offset_before_processing = | 705 const TimeDelta timestamp_offset_before_processing = |
| 697 *timestamp_offset_during_append_; | 706 *timestamp_offset_during_append_; |
| 698 | 707 |
| 699 // Calculate the new timestamp offset for audio/video tracks if the stream | 708 // Calculate the new timestamp offset for audio/video tracks if the stream |
| (...skipping 23 matching lines...) Expand all Loading... |
| 723 if (auto_update_timestamp_offset_ && | 732 if (auto_update_timestamp_offset_ && |
| 724 timestamp_offset_before_processing == *timestamp_offset_during_append_) { | 733 timestamp_offset_before_processing == *timestamp_offset_during_append_) { |
| 725 *timestamp_offset_during_append_ = new_timestamp_offset; | 734 *timestamp_offset_during_append_ = new_timestamp_offset; |
| 726 } | 735 } |
| 727 | 736 |
| 728 return true; | 737 return true; |
| 729 } | 738 } |
| 730 | 739 |
| 731 void MediaSourceState::OnSourceInitDone( | 740 void MediaSourceState::OnSourceInitDone( |
| 732 const StreamParser::InitParameters& params) { | 741 const StreamParser::InitParameters& params) { |
| 742 DCHECK_EQ(state_, PENDING_PARSER_INIT); |
| 743 state_ = PARSER_INITIALIZED; |
| 733 auto_update_timestamp_offset_ = params.auto_update_timestamp_offset; | 744 auto_update_timestamp_offset_ = params.auto_update_timestamp_offset; |
| 734 base::ResetAndReturn(&init_cb_).Run(params); | 745 base::ResetAndReturn(&init_cb_).Run(params); |
| 735 } | 746 } |
| 736 | 747 |
| 737 } // namespace media | 748 } // namespace media |
| OLD | NEW |