| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/chunk_demuxer.h" | 5 #include "media/filters/chunk_demuxer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/callback_helpers.h" | 12 #include "base/callback_helpers.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/memory/ptr_util.h" |
| 15 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/stl_util.h" | |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "media/base/audio_decoder_config.h" | 18 #include "media/base/audio_decoder_config.h" |
| 19 #include "media/base/bind_to_current_loop.h" | 19 #include "media/base/bind_to_current_loop.h" |
| 20 #include "media/base/media_tracks.h" | 20 #include "media/base/media_tracks.h" |
| 21 #include "media/base/mime_util.h" | 21 #include "media/base/mime_util.h" |
| 22 #include "media/base/stream_parser_buffer.h" | 22 #include "media/base/stream_parser_buffer.h" |
| 23 #include "media/base/timestamp_constants.h" | 23 #include "media/base/timestamp_constants.h" |
| 24 #include "media/base/video_codecs.h" | 24 #include "media/base/video_codecs.h" |
| 25 #include "media/base/video_decoder_config.h" | 25 #include "media/base/video_decoder_config.h" |
| 26 #include "media/filters/frame_processor.h" | 26 #include "media/filters/frame_processor.h" |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 std::string expected_mss_codecs = codecs; | 614 std::string expected_mss_codecs = codecs; |
| 615 if (codecs == "" && type == "audio/aac") | 615 if (codecs == "" && type == "audio/aac") |
| 616 expected_mss_codecs = "aac"; | 616 expected_mss_codecs = "aac"; |
| 617 if (codecs == "" && (type == "audio/mpeg" || type == "audio/mp3")) | 617 if (codecs == "" && (type == "audio/mpeg" || type == "audio/mp3")) |
| 618 expected_mss_codecs = "mp3"; | 618 expected_mss_codecs = "mp3"; |
| 619 | 619 |
| 620 source_state->Init( | 620 source_state->Init( |
| 621 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this), id), | 621 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this), id), |
| 622 expected_mss_codecs, encrypted_media_init_data_cb_, new_text_track_cb); | 622 expected_mss_codecs, encrypted_media_init_data_cb_, new_text_track_cb); |
| 623 | 623 |
| 624 source_state_map_[id] = source_state.release(); | 624 source_state_map_[id] = std::move(source_state); |
| 625 return kOk; | 625 return kOk; |
| 626 } | 626 } |
| 627 | 627 |
| 628 void ChunkDemuxer::SetTracksWatcher( | 628 void ChunkDemuxer::SetTracksWatcher( |
| 629 const std::string& id, | 629 const std::string& id, |
| 630 const MediaTracksUpdatedCB& tracks_updated_cb) { | 630 const MediaTracksUpdatedCB& tracks_updated_cb) { |
| 631 base::AutoLock auto_lock(lock_); | 631 base::AutoLock auto_lock(lock_); |
| 632 CHECK(IsValidId(id)); | 632 CHECK(IsValidId(id)); |
| 633 source_state_map_[id]->SetTracksWatcher(tracks_updated_cb); | 633 source_state_map_[id]->SetTracksWatcher(tracks_updated_cb); |
| 634 } | 634 } |
| 635 | 635 |
| 636 void ChunkDemuxer::RemoveId(const std::string& id) { | 636 void ChunkDemuxer::RemoveId(const std::string& id) { |
| 637 DVLOG(1) << __func__ << " id=" << id; | 637 DVLOG(1) << __func__ << " id=" << id; |
| 638 base::AutoLock auto_lock(lock_); | 638 base::AutoLock auto_lock(lock_); |
| 639 CHECK(IsValidId(id)); | 639 CHECK(IsValidId(id)); |
| 640 | 640 |
| 641 delete source_state_map_[id]; | |
| 642 source_state_map_.erase(id); | 641 source_state_map_.erase(id); |
| 643 pending_source_init_ids_.erase(id); | 642 pending_source_init_ids_.erase(id); |
| 644 // Remove demuxer streams created for this id. | 643 // Remove demuxer streams created for this id. |
| 645 for (const ChunkDemuxerStream* s : id_to_streams_map_[id]) { | 644 for (const ChunkDemuxerStream* s : id_to_streams_map_[id]) { |
| 646 bool stream_found = false; | 645 bool stream_found = false; |
| 647 for (size_t i = 0; i < audio_streams_.size(); ++i) { | 646 for (size_t i = 0; i < audio_streams_.size(); ++i) { |
| 648 if (audio_streams_[i].get() == s) { | 647 if (audio_streams_[i].get() == s) { |
| 649 stream_found = true; | 648 stream_found = true; |
| 650 removed_streams_.push_back(std::move(audio_streams_[i])); | 649 removed_streams_.push_back(std::move(audio_streams_[i])); |
| 651 audio_streams_.erase(audio_streams_.begin() + i); | 650 audio_streams_.erase(audio_streams_.begin() + i); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 664 } | 663 } |
| 665 CHECK(stream_found); | 664 CHECK(stream_found); |
| 666 } | 665 } |
| 667 id_to_streams_map_.erase(id); | 666 id_to_streams_map_.erase(id); |
| 668 } | 667 } |
| 669 | 668 |
| 670 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const { | 669 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const { |
| 671 base::AutoLock auto_lock(lock_); | 670 base::AutoLock auto_lock(lock_); |
| 672 DCHECK(!id.empty()); | 671 DCHECK(!id.empty()); |
| 673 | 672 |
| 674 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id); | 673 auto itr = source_state_map_.find(id); |
| 675 | 674 |
| 676 DCHECK(itr != source_state_map_.end()); | 675 DCHECK(itr != source_state_map_.end()); |
| 677 return itr->second->GetBufferedRanges(duration_, state_ == ENDED); | 676 return itr->second->GetBufferedRanges(duration_, state_ == ENDED); |
| 678 } | 677 } |
| 679 | 678 |
| 680 base::TimeDelta ChunkDemuxer::GetHighestPresentationTimestamp( | 679 base::TimeDelta ChunkDemuxer::GetHighestPresentationTimestamp( |
| 681 const std::string& id) const { | 680 const std::string& id) const { |
| 682 base::AutoLock auto_lock(lock_); | 681 base::AutoLock auto_lock(lock_); |
| 683 DCHECK(!id.empty()); | 682 DCHECK(!id.empty()); |
| 684 | 683 |
| 685 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id); | 684 auto itr = source_state_map_.find(id); |
| 686 | 685 |
| 687 DCHECK(itr != source_state_map_.end()); | 686 DCHECK(itr != source_state_map_.end()); |
| 688 return itr->second->GetHighestPresentationTimestamp(); | 687 return itr->second->GetHighestPresentationTimestamp(); |
| 689 } | 688 } |
| 690 | 689 |
| 691 void ChunkDemuxer::OnEnabledAudioTracksChanged( | 690 void ChunkDemuxer::OnEnabledAudioTracksChanged( |
| 692 const std::vector<MediaTrack::Id>& track_ids, | 691 const std::vector<MediaTrack::Id>& track_ids, |
| 693 base::TimeDelta currTime) { | 692 base::TimeDelta currTime) { |
| 694 base::AutoLock auto_lock(lock_); | 693 base::AutoLock auto_lock(lock_); |
| 695 std::set<DemuxerStream*> enabled_streams; | 694 std::set<DemuxerStream*> enabled_streams; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 << " newDataSize=" << newDataSize; | 749 << " newDataSize=" << newDataSize; |
| 751 base::AutoLock auto_lock(lock_); | 750 base::AutoLock auto_lock(lock_); |
| 752 | 751 |
| 753 // Note: The direct conversion from PTS to DTS is safe here, since we don't | 752 // Note: The direct conversion from PTS to DTS is safe here, since we don't |
| 754 // need to know currentTime precisely for GC. GC only needs to know which GOP | 753 // need to know currentTime precisely for GC. GC only needs to know which GOP |
| 755 // currentTime points to. | 754 // currentTime points to. |
| 756 DecodeTimestamp media_time_dts = | 755 DecodeTimestamp media_time_dts = |
| 757 DecodeTimestamp::FromPresentationTime(currentMediaTime); | 756 DecodeTimestamp::FromPresentationTime(currentMediaTime); |
| 758 | 757 |
| 759 DCHECK(!id.empty()); | 758 DCHECK(!id.empty()); |
| 760 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id); | 759 auto itr = source_state_map_.find(id); |
| 761 if (itr == source_state_map_.end()) { | 760 if (itr == source_state_map_.end()) { |
| 762 LOG(WARNING) << __func__ << " stream " << id << " not found"; | 761 LOG(WARNING) << __func__ << " stream " << id << " not found"; |
| 763 return false; | 762 return false; |
| 764 } | 763 } |
| 765 return itr->second->EvictCodedFrames(media_time_dts, newDataSize); | 764 return itr->second->EvictCodedFrames(media_time_dts, newDataSize); |
| 766 } | 765 } |
| 767 | 766 |
| 768 bool ChunkDemuxer::AppendData(const std::string& id, | 767 bool ChunkDemuxer::AppendData(const std::string& id, |
| 769 const uint8_t* data, | 768 const uint8_t* data, |
| 770 size_t length, | 769 size_t length, |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 917 duration_td = TimeDelta::FromMicroseconds( | 916 duration_td = TimeDelta::FromMicroseconds( |
| 918 duration * base::Time::kMicrosecondsPerSecond); | 917 duration * base::Time::kMicrosecondsPerSecond); |
| 919 } | 918 } |
| 920 | 919 |
| 921 DCHECK(duration_td > TimeDelta()); | 920 DCHECK(duration_td > TimeDelta()); |
| 922 | 921 |
| 923 user_specified_duration_ = duration; | 922 user_specified_duration_ = duration; |
| 924 duration_ = duration_td; | 923 duration_ = duration_td; |
| 925 host_->SetDuration(duration_); | 924 host_->SetDuration(duration_); |
| 926 | 925 |
| 927 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); | 926 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 928 itr != source_state_map_.end(); ++itr) { | 927 ++itr) { |
| 929 itr->second->OnSetDuration(duration_); | 928 itr->second->OnSetDuration(duration_); |
| 930 } | 929 } |
| 931 } | 930 } |
| 932 | 931 |
| 933 bool ChunkDemuxer::IsParsingMediaSegment(const std::string& id) { | 932 bool ChunkDemuxer::IsParsingMediaSegment(const std::string& id) { |
| 934 base::AutoLock auto_lock(lock_); | 933 base::AutoLock auto_lock(lock_); |
| 935 DVLOG(1) << "IsParsingMediaSegment(" << id << ")"; | 934 DVLOG(1) << "IsParsingMediaSegment(" << id << ")"; |
| 936 CHECK(IsValidId(id)); | 935 CHECK(IsValidId(id)); |
| 937 | 936 |
| 938 return source_state_map_[id]->parsing_media_segment(); | 937 return source_state_map_[id]->parsing_media_segment(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 970 | 969 |
| 971 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) | 970 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) |
| 972 return; | 971 return; |
| 973 | 972 |
| 974 if (state_ == INITIALIZING) { | 973 if (state_ == INITIALIZING) { |
| 975 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 974 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
| 976 return; | 975 return; |
| 977 } | 976 } |
| 978 | 977 |
| 979 bool old_waiting_for_data = IsSeekWaitingForData_Locked(); | 978 bool old_waiting_for_data = IsSeekWaitingForData_Locked(); |
| 980 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); | 979 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 981 itr != source_state_map_.end(); ++itr) { | 980 ++itr) { |
| 982 itr->second->MarkEndOfStream(); | 981 itr->second->MarkEndOfStream(); |
| 983 } | 982 } |
| 984 | 983 |
| 985 CompletePendingReadsIfPossible(); | 984 CompletePendingReadsIfPossible(); |
| 986 | 985 |
| 987 // Give a chance to resume the pending seek process. | 986 // Give a chance to resume the pending seek process. |
| 988 if (status != PIPELINE_OK) { | 987 if (status != PIPELINE_OK) { |
| 989 DCHECK(status == CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR || | 988 DCHECK(status == CHUNK_DEMUXER_ERROR_EOS_STATUS_DECODE_ERROR || |
| 990 status == CHUNK_DEMUXER_ERROR_EOS_STATUS_NETWORK_ERROR); | 989 status == CHUNK_DEMUXER_ERROR_EOS_STATUS_NETWORK_ERROR); |
| 991 ReportError_Locked(status); | 990 ReportError_Locked(status); |
| 992 return; | 991 return; |
| 993 } | 992 } |
| 994 | 993 |
| 995 ChangeState_Locked(ENDED); | 994 ChangeState_Locked(ENDED); |
| 996 DecreaseDurationIfNecessary(); | 995 DecreaseDurationIfNecessary(); |
| 997 | 996 |
| 998 if (old_waiting_for_data && !IsSeekWaitingForData_Locked() && | 997 if (old_waiting_for_data && !IsSeekWaitingForData_Locked() && |
| 999 !seek_cb_.is_null()) { | 998 !seek_cb_.is_null()) { |
| 1000 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); | 999 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); |
| 1001 } | 1000 } |
| 1002 } | 1001 } |
| 1003 | 1002 |
| 1004 void ChunkDemuxer::UnmarkEndOfStream() { | 1003 void ChunkDemuxer::UnmarkEndOfStream() { |
| 1005 DVLOG(1) << "UnmarkEndOfStream()"; | 1004 DVLOG(1) << "UnmarkEndOfStream()"; |
| 1006 base::AutoLock auto_lock(lock_); | 1005 base::AutoLock auto_lock(lock_); |
| 1007 DCHECK_EQ(state_, ENDED); | 1006 DCHECK_EQ(state_, ENDED); |
| 1008 | 1007 |
| 1009 ChangeState_Locked(INITIALIZED); | 1008 ChangeState_Locked(INITIALIZED); |
| 1010 | 1009 |
| 1011 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); | 1010 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 1012 itr != source_state_map_.end(); ++itr) { | 1011 ++itr) { |
| 1013 itr->second->UnmarkEndOfStream(); | 1012 itr->second->UnmarkEndOfStream(); |
| 1014 } | 1013 } |
| 1015 } | 1014 } |
| 1016 | 1015 |
| 1017 void ChunkDemuxer::Shutdown() { | 1016 void ChunkDemuxer::Shutdown() { |
| 1018 DVLOG(1) << "Shutdown()"; | 1017 DVLOG(1) << "Shutdown()"; |
| 1019 base::AutoLock auto_lock(lock_); | 1018 base::AutoLock auto_lock(lock_); |
| 1020 | 1019 |
| 1021 if (state_ == SHUTDOWN) | 1020 if (state_ == SHUTDOWN) |
| 1022 return; | 1021 return; |
| 1023 | 1022 |
| 1024 ShutdownAllStreams(); | 1023 ShutdownAllStreams(); |
| 1025 | 1024 |
| 1026 ChangeState_Locked(SHUTDOWN); | 1025 ChangeState_Locked(SHUTDOWN); |
| 1027 | 1026 |
| 1028 if (!seek_cb_.is_null()) | 1027 if (!seek_cb_.is_null()) |
| 1029 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_ERROR_ABORT); | 1028 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_ERROR_ABORT); |
| 1030 } | 1029 } |
| 1031 | 1030 |
| 1032 void ChunkDemuxer::SetMemoryLimitsForTest(DemuxerStream::Type type, | 1031 void ChunkDemuxer::SetMemoryLimitsForTest(DemuxerStream::Type type, |
| 1033 size_t memory_limit) { | 1032 size_t memory_limit) { |
| 1034 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); | 1033 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 1035 itr != source_state_map_.end(); ++itr) { | 1034 ++itr) { |
| 1036 itr->second->SetMemoryLimits(type, memory_limit); | 1035 itr->second->SetMemoryLimits(type, memory_limit); |
| 1037 } | 1036 } |
| 1038 } | 1037 } |
| 1039 | 1038 |
| 1040 void ChunkDemuxer::ChangeState_Locked(State new_state) { | 1039 void ChunkDemuxer::ChangeState_Locked(State new_state) { |
| 1041 lock_.AssertAcquired(); | 1040 lock_.AssertAcquired(); |
| 1042 DVLOG(1) << "ChunkDemuxer::ChangeState_Locked() : " | 1041 DVLOG(1) << "ChunkDemuxer::ChangeState_Locked() : " |
| 1043 << state_ << " -> " << new_state; | 1042 << state_ << " -> " << new_state; |
| 1044 state_ = new_state; | 1043 state_ = new_state; |
| 1045 } | 1044 } |
| 1046 | 1045 |
| 1047 ChunkDemuxer::~ChunkDemuxer() { | 1046 ChunkDemuxer::~ChunkDemuxer() { |
| 1048 DCHECK_NE(state_, INITIALIZED); | 1047 DCHECK_NE(state_, INITIALIZED); |
| 1049 | |
| 1050 base::STLDeleteValues(&source_state_map_); | |
| 1051 } | 1048 } |
| 1052 | 1049 |
| 1053 void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { | 1050 void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { |
| 1054 DVLOG(1) << "ReportError_Locked(" << error << ")"; | 1051 DVLOG(1) << "ReportError_Locked(" << error << ")"; |
| 1055 lock_.AssertAcquired(); | 1052 lock_.AssertAcquired(); |
| 1056 DCHECK_NE(error, PIPELINE_OK); | 1053 DCHECK_NE(error, PIPELINE_OK); |
| 1057 | 1054 |
| 1058 ChangeState_Locked(PARSE_ERROR); | 1055 ChangeState_Locked(PARSE_ERROR); |
| 1059 | 1056 |
| 1060 PipelineStatusCB cb; | 1057 PipelineStatusCB cb; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1072 cb.Run(error); | 1069 cb.Run(error); |
| 1073 return; | 1070 return; |
| 1074 } | 1071 } |
| 1075 | 1072 |
| 1076 base::AutoUnlock auto_unlock(lock_); | 1073 base::AutoUnlock auto_unlock(lock_); |
| 1077 host_->OnDemuxerError(error); | 1074 host_->OnDemuxerError(error); |
| 1078 } | 1075 } |
| 1079 | 1076 |
| 1080 bool ChunkDemuxer::IsSeekWaitingForData_Locked() const { | 1077 bool ChunkDemuxer::IsSeekWaitingForData_Locked() const { |
| 1081 lock_.AssertAcquired(); | 1078 lock_.AssertAcquired(); |
| 1082 for (MediaSourceStateMap::const_iterator itr = source_state_map_.begin(); | 1079 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 1083 itr != source_state_map_.end(); ++itr) { | 1080 ++itr) { |
| 1084 if (itr->second->IsSeekWaitingForData()) | 1081 if (itr->second->IsSeekWaitingForData()) |
| 1085 return true; | 1082 return true; |
| 1086 } | 1083 } |
| 1087 | 1084 |
| 1088 return false; | 1085 return false; |
| 1089 } | 1086 } |
| 1090 | 1087 |
| 1091 void ChunkDemuxer::OnSourceInitDone( | 1088 void ChunkDemuxer::OnSourceInitDone( |
| 1092 const std::string& source_id, | 1089 const std::string& source_id, |
| 1093 const StreamParser::InitParameters& params) { | 1090 const StreamParser::InitParameters& params) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1168 ChunkDemuxerStream* ChunkDemuxer::CreateDemuxerStream( | 1165 ChunkDemuxerStream* ChunkDemuxer::CreateDemuxerStream( |
| 1169 const std::string& source_id, | 1166 const std::string& source_id, |
| 1170 DemuxerStream::Type type) { | 1167 DemuxerStream::Type type) { |
| 1171 // New ChunkDemuxerStreams can be created only during initialization segment | 1168 // New ChunkDemuxerStreams can be created only during initialization segment |
| 1172 // processing, which happens when a new chunk of data is appended and the | 1169 // processing, which happens when a new chunk of data is appended and the |
| 1173 // lock_ must be held by ChunkDemuxer::AppendData. | 1170 // lock_ must be held by ChunkDemuxer::AppendData. |
| 1174 lock_.AssertAcquired(); | 1171 lock_.AssertAcquired(); |
| 1175 | 1172 |
| 1176 MediaTrack::Id media_track_id = GenerateMediaTrackId(); | 1173 MediaTrack::Id media_track_id = GenerateMediaTrackId(); |
| 1177 | 1174 |
| 1175 OwnedChunkDemuxerStreamVector* owning_vector = nullptr; |
| 1178 switch (type) { | 1176 switch (type) { |
| 1179 case DemuxerStream::AUDIO: { | 1177 case DemuxerStream::AUDIO: |
| 1180 std::unique_ptr<ChunkDemuxerStream> audio_stream(new ChunkDemuxerStream( | 1178 owning_vector = &audio_streams_; |
| 1181 DemuxerStream::AUDIO, splice_frames_enabled_, media_track_id)); | 1179 break; |
| 1182 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) == | 1180 |
| 1183 track_id_to_demux_stream_map_.end()); | 1181 case DemuxerStream::VIDEO: |
| 1184 track_id_to_demux_stream_map_[media_track_id] = audio_stream.get(); | 1182 owning_vector = &video_streams_; |
| 1185 id_to_streams_map_[source_id].push_back(audio_stream.get()); | 1183 break; |
| 1186 audio_streams_.push_back(std::move(audio_stream)); | 1184 |
| 1187 return audio_streams_.back().get(); | 1185 case DemuxerStream::TEXT: |
| 1188 } | 1186 owning_vector = &text_streams_; |
| 1189 case DemuxerStream::VIDEO: { | 1187 break; |
| 1190 std::unique_ptr<ChunkDemuxerStream> video_stream(new ChunkDemuxerStream( | 1188 |
| 1191 DemuxerStream::VIDEO, splice_frames_enabled_, media_track_id)); | |
| 1192 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) == | |
| 1193 track_id_to_demux_stream_map_.end()); | |
| 1194 track_id_to_demux_stream_map_[media_track_id] = video_stream.get(); | |
| 1195 id_to_streams_map_[source_id].push_back(video_stream.get()); | |
| 1196 video_streams_.push_back(std::move(video_stream)); | |
| 1197 return video_streams_.back().get(); | |
| 1198 } | |
| 1199 case DemuxerStream::TEXT: { | |
| 1200 ChunkDemuxerStream* text_stream = new ChunkDemuxerStream( | |
| 1201 DemuxerStream::TEXT, splice_frames_enabled_, media_track_id); | |
| 1202 id_to_streams_map_[source_id].push_back(text_stream); | |
| 1203 return text_stream; | |
| 1204 } | |
| 1205 case DemuxerStream::UNKNOWN: | 1189 case DemuxerStream::UNKNOWN: |
| 1206 case DemuxerStream::NUM_TYPES: | 1190 case DemuxerStream::NUM_TYPES: |
| 1207 NOTREACHED(); | 1191 NOTREACHED(); |
| 1208 return NULL; | 1192 return nullptr; |
| 1209 } | 1193 } |
| 1210 NOTREACHED(); | 1194 |
| 1211 return NULL; | 1195 std::unique_ptr<ChunkDemuxerStream> stream = |
| 1196 base::MakeUnique<ChunkDemuxerStream>(type, splice_frames_enabled_, |
| 1197 media_track_id); |
| 1198 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) == |
| 1199 track_id_to_demux_stream_map_.end()); |
| 1200 track_id_to_demux_stream_map_[media_track_id] = stream.get(); |
| 1201 id_to_streams_map_[source_id].push_back(stream.get()); |
| 1202 owning_vector->push_back(std::move(stream)); |
| 1203 return owning_vector->back().get(); |
| 1212 } | 1204 } |
| 1213 | 1205 |
| 1214 void ChunkDemuxer::OnNewTextTrack(ChunkDemuxerStream* text_stream, | 1206 void ChunkDemuxer::OnNewTextTrack(ChunkDemuxerStream* text_stream, |
| 1215 const TextTrackConfig& config) { | 1207 const TextTrackConfig& config) { |
| 1216 lock_.AssertAcquired(); | 1208 lock_.AssertAcquired(); |
| 1217 DCHECK_NE(state_, SHUTDOWN); | 1209 DCHECK_NE(state_, SHUTDOWN); |
| 1218 host_->AddTextStream(text_stream, config); | 1210 host_->AddTextStream(text_stream, config); |
| 1219 } | 1211 } |
| 1220 | 1212 |
| 1221 bool ChunkDemuxer::IsValidId(const std::string& source_id) const { | 1213 bool ChunkDemuxer::IsValidId(const std::string& source_id) const { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1248 << " -> " << new_duration.InSecondsF(); | 1240 << " -> " << new_duration.InSecondsF(); |
| 1249 | 1241 |
| 1250 UpdateDuration(new_duration); | 1242 UpdateDuration(new_duration); |
| 1251 } | 1243 } |
| 1252 | 1244 |
| 1253 void ChunkDemuxer::DecreaseDurationIfNecessary() { | 1245 void ChunkDemuxer::DecreaseDurationIfNecessary() { |
| 1254 lock_.AssertAcquired(); | 1246 lock_.AssertAcquired(); |
| 1255 | 1247 |
| 1256 TimeDelta max_duration; | 1248 TimeDelta max_duration; |
| 1257 | 1249 |
| 1258 for (MediaSourceStateMap::const_iterator itr = source_state_map_.begin(); | 1250 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 1259 itr != source_state_map_.end(); ++itr) { | 1251 ++itr) { |
| 1260 max_duration = std::max(max_duration, | 1252 max_duration = std::max(max_duration, |
| 1261 itr->second->GetMaxBufferedDuration()); | 1253 itr->second->GetMaxBufferedDuration()); |
| 1262 } | 1254 } |
| 1263 | 1255 |
| 1264 if (max_duration.is_zero()) | 1256 if (max_duration.is_zero()) |
| 1265 return; | 1257 return; |
| 1266 | 1258 |
| 1267 if (max_duration < duration_) | 1259 if (max_duration < duration_) |
| 1268 UpdateDuration(max_duration); | 1260 UpdateDuration(max_duration); |
| 1269 } | 1261 } |
| 1270 | 1262 |
| 1271 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { | 1263 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { |
| 1272 base::AutoLock auto_lock(lock_); | 1264 base::AutoLock auto_lock(lock_); |
| 1273 return GetBufferedRanges_Locked(); | 1265 return GetBufferedRanges_Locked(); |
| 1274 } | 1266 } |
| 1275 | 1267 |
| 1276 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges_Locked() const { | 1268 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges_Locked() const { |
| 1277 lock_.AssertAcquired(); | 1269 lock_.AssertAcquired(); |
| 1278 | 1270 |
| 1279 bool ended = state_ == ENDED; | 1271 bool ended = state_ == ENDED; |
| 1280 // TODO(acolwell): When we start allowing SourceBuffers that are not active, | 1272 // TODO(acolwell): When we start allowing SourceBuffers that are not active, |
| 1281 // we'll need to update this loop to only add ranges from active sources. | 1273 // we'll need to update this loop to only add ranges from active sources. |
| 1282 MediaSourceState::RangesList ranges_list; | 1274 MediaSourceState::RangesList ranges_list; |
| 1283 for (MediaSourceStateMap::const_iterator itr = source_state_map_.begin(); | 1275 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 1284 itr != source_state_map_.end(); ++itr) { | 1276 ++itr) { |
| 1285 ranges_list.push_back(itr->second->GetBufferedRanges(duration_, ended)); | 1277 ranges_list.push_back(itr->second->GetBufferedRanges(duration_, ended)); |
| 1286 } | 1278 } |
| 1287 | 1279 |
| 1288 return MediaSourceState::ComputeRangesIntersection(ranges_list, ended); | 1280 return MediaSourceState::ComputeRangesIntersection(ranges_list, ended); |
| 1289 } | 1281 } |
| 1290 | 1282 |
| 1291 void ChunkDemuxer::StartReturningData() { | 1283 void ChunkDemuxer::StartReturningData() { |
| 1292 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); | 1284 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 1293 itr != source_state_map_.end(); ++itr) { | 1285 ++itr) { |
| 1294 itr->second->StartReturningData(); | 1286 itr->second->StartReturningData(); |
| 1295 } | 1287 } |
| 1296 } | 1288 } |
| 1297 | 1289 |
| 1298 void ChunkDemuxer::AbortPendingReads_Locked() { | 1290 void ChunkDemuxer::AbortPendingReads_Locked() { |
| 1299 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); | 1291 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 1300 itr != source_state_map_.end(); ++itr) { | 1292 ++itr) { |
| 1301 itr->second->AbortReads(); | 1293 itr->second->AbortReads(); |
| 1302 } | 1294 } |
| 1303 } | 1295 } |
| 1304 | 1296 |
| 1305 void ChunkDemuxer::SeekAllSources(TimeDelta seek_time) { | 1297 void ChunkDemuxer::SeekAllSources(TimeDelta seek_time) { |
| 1306 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); | 1298 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 1307 itr != source_state_map_.end(); ++itr) { | 1299 ++itr) { |
| 1308 itr->second->Seek(seek_time); | 1300 itr->second->Seek(seek_time); |
| 1309 } | 1301 } |
| 1310 } | 1302 } |
| 1311 | 1303 |
| 1312 void ChunkDemuxer::CompletePendingReadsIfPossible() { | 1304 void ChunkDemuxer::CompletePendingReadsIfPossible() { |
| 1313 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); | 1305 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 1314 itr != source_state_map_.end(); ++itr) { | 1306 ++itr) { |
| 1315 itr->second->CompletePendingReadIfPossible(); | 1307 itr->second->CompletePendingReadIfPossible(); |
| 1316 } | 1308 } |
| 1317 } | 1309 } |
| 1318 | 1310 |
| 1319 void ChunkDemuxer::ShutdownAllStreams() { | 1311 void ChunkDemuxer::ShutdownAllStreams() { |
| 1320 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); | 1312 for (auto itr = source_state_map_.begin(); itr != source_state_map_.end(); |
| 1321 itr != source_state_map_.end(); ++itr) { | 1313 ++itr) { |
| 1322 itr->second->Shutdown(); | 1314 itr->second->Shutdown(); |
| 1323 } | 1315 } |
| 1324 } | 1316 } |
| 1325 | 1317 |
| 1326 } // namespace media | 1318 } // namespace media |
| OLD | NEW |