| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 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/source_buffer_state.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "media/base/media_switches.h" | 12 #include "media/base/media_switches.h" |
| 13 #include "media/base/media_track.h" | 13 #include "media/base/media_track.h" |
| 14 #include "media/base/media_tracks.h" | 14 #include "media/base/media_tracks.h" |
| 15 #include "media/base/mime_util.h" | 15 #include "media/base/mime_util.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 } | 52 } |
| 53 bytestream_ids.insert(track_id); | 53 bytestream_ids.insert(track_id); |
| 54 } | 54 } |
| 55 return true; | 55 return true; |
| 56 } | 56 } |
| 57 | 57 |
| 58 } // namespace | 58 } // namespace |
| 59 | 59 |
| 60 // List of time ranges for each SourceBuffer. | 60 // List of time ranges for each SourceBuffer. |
| 61 // static | 61 // static |
| 62 Ranges<TimeDelta> MediaSourceState::ComputeRangesIntersection( | 62 Ranges<TimeDelta> SourceBufferState::ComputeRangesIntersection( |
| 63 const RangesList& active_ranges, | 63 const RangesList& active_ranges, |
| 64 bool ended) { | 64 bool ended) { |
| 65 // TODO(servolk): Perhaps this can be removed in favor of blink implementation | 65 // TODO(servolk): Perhaps this can be removed in favor of blink implementation |
| 66 // (MediaSource::buffered)? Currently this is only used on Android and for | 66 // (MediaSource::buffered)? Currently this is only used on Android and for |
| 67 // updating DemuxerHost's buffered ranges during AppendData() as well as | 67 // updating DemuxerHost's buffered ranges during AppendData() as well as |
| 68 // SourceBuffer.buffered property implementation. | 68 // SourceBuffer.buffered property implementation. |
| 69 // Implementation of HTMLMediaElement.buffered algorithm in MSE spec. | 69 // Implementation of HTMLMediaElement.buffered algorithm in MSE spec. |
| 70 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sourc
e.html#dom-htmlmediaelement.buffered | 70 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-sourc
e.html#dom-htmlmediaelement.buffered |
| 71 | 71 |
| 72 // Step 1: If activeSourceBuffers.length equals 0 then return an empty | 72 // Step 1: If activeSourceBuffers.length equals 0 then return an empty |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 // Step 5.3: Let new intersection ranges equal the intersection between | 108 // Step 5.3: Let new intersection ranges equal the intersection between |
| 109 // the intersection ranges and the source ranges. | 109 // the intersection ranges and the source ranges. |
| 110 // Step 5.4: Replace the ranges in intersection ranges with the new | 110 // Step 5.4: Replace the ranges in intersection ranges with the new |
| 111 // intersection ranges. | 111 // intersection ranges. |
| 112 intersection_ranges = intersection_ranges.IntersectionWith(source_ranges); | 112 intersection_ranges = intersection_ranges.IntersectionWith(source_ranges); |
| 113 } | 113 } |
| 114 | 114 |
| 115 return intersection_ranges; | 115 return intersection_ranges; |
| 116 } | 116 } |
| 117 | 117 |
| 118 MediaSourceState::MediaSourceState( | 118 SourceBufferState::SourceBufferState( |
| 119 std::unique_ptr<StreamParser> stream_parser, | 119 std::unique_ptr<StreamParser> stream_parser, |
| 120 std::unique_ptr<FrameProcessor> frame_processor, | 120 std::unique_ptr<FrameProcessor> frame_processor, |
| 121 const CreateDemuxerStreamCB& create_demuxer_stream_cb, | 121 const CreateDemuxerStreamCB& create_demuxer_stream_cb, |
| 122 const scoped_refptr<MediaLog>& media_log) | 122 const scoped_refptr<MediaLog>& media_log) |
| 123 : create_demuxer_stream_cb_(create_demuxer_stream_cb), | 123 : create_demuxer_stream_cb_(create_demuxer_stream_cb), |
| 124 timestamp_offset_during_append_(NULL), | 124 timestamp_offset_during_append_(NULL), |
| 125 parsing_media_segment_(false), | 125 parsing_media_segment_(false), |
| 126 stream_parser_(stream_parser.release()), | 126 stream_parser_(stream_parser.release()), |
| 127 frame_processor_(frame_processor.release()), | 127 frame_processor_(frame_processor.release()), |
| 128 media_log_(media_log), | 128 media_log_(media_log), |
| 129 state_(UNINITIALIZED), | 129 state_(UNINITIALIZED), |
| 130 auto_update_timestamp_offset_(false) { | 130 auto_update_timestamp_offset_(false) { |
| 131 DCHECK(!create_demuxer_stream_cb_.is_null()); | 131 DCHECK(!create_demuxer_stream_cb_.is_null()); |
| 132 DCHECK(frame_processor_); | 132 DCHECK(frame_processor_); |
| 133 } | 133 } |
| 134 | 134 |
| 135 MediaSourceState::~MediaSourceState() { | 135 SourceBufferState::~SourceBufferState() { |
| 136 Shutdown(); | 136 Shutdown(); |
| 137 } | 137 } |
| 138 | 138 |
| 139 void MediaSourceState::Init( | 139 void SourceBufferState::Init( |
| 140 const StreamParser::InitCB& init_cb, | 140 const StreamParser::InitCB& init_cb, |
| 141 const std::string& expected_codecs, | 141 const std::string& expected_codecs, |
| 142 const StreamParser::EncryptedMediaInitDataCB& encrypted_media_init_data_cb, | 142 const StreamParser::EncryptedMediaInitDataCB& encrypted_media_init_data_cb, |
| 143 const NewTextTrackCB& new_text_track_cb) { | 143 const NewTextTrackCB& new_text_track_cb) { |
| 144 DCHECK_EQ(state_, UNINITIALIZED); | 144 DCHECK_EQ(state_, UNINITIALIZED); |
| 145 new_text_track_cb_ = new_text_track_cb; | 145 new_text_track_cb_ = new_text_track_cb; |
| 146 init_cb_ = init_cb; | 146 init_cb_ = init_cb; |
| 147 | 147 |
| 148 std::vector<std::string> expected_codecs_parsed; | 148 std::vector<std::string> expected_codecs_parsed; |
| 149 ParseCodecString(expected_codecs, &expected_codecs_parsed, false); | 149 ParseCodecString(expected_codecs, &expected_codecs_parsed, false); |
| 150 | 150 |
| 151 std::vector<AudioCodec> expected_acodecs; | 151 std::vector<AudioCodec> expected_acodecs; |
| 152 std::vector<VideoCodec> expected_vcodecs; | 152 std::vector<VideoCodec> expected_vcodecs; |
| 153 for (const auto& codec_id : expected_codecs_parsed) { | 153 for (const auto& codec_id : expected_codecs_parsed) { |
| 154 AudioCodec acodec = StringToAudioCodec(codec_id); | 154 AudioCodec acodec = StringToAudioCodec(codec_id); |
| 155 if (acodec != kUnknownAudioCodec) { | 155 if (acodec != kUnknownAudioCodec) { |
| 156 expected_audio_codecs_.push_back(acodec); | 156 expected_audio_codecs_.push_back(acodec); |
| 157 continue; | 157 continue; |
| 158 } | 158 } |
| 159 VideoCodec vcodec = StringToVideoCodec(codec_id); | 159 VideoCodec vcodec = StringToVideoCodec(codec_id); |
| 160 if (vcodec != kUnknownVideoCodec) { | 160 if (vcodec != kUnknownVideoCodec) { |
| 161 expected_video_codecs_.push_back(vcodec); | 161 expected_video_codecs_.push_back(vcodec); |
| 162 continue; | 162 continue; |
| 163 } | 163 } |
| 164 MEDIA_LOG(INFO, media_log_) << "Unrecognized media codec: " << codec_id; | 164 MEDIA_LOG(INFO, media_log_) << "Unrecognized media codec: " << codec_id; |
| 165 } | 165 } |
| 166 | 166 |
| 167 state_ = PENDING_PARSER_CONFIG; | 167 state_ = PENDING_PARSER_CONFIG; |
| 168 stream_parser_->Init( | 168 stream_parser_->Init( |
| 169 base::Bind(&MediaSourceState::OnSourceInitDone, base::Unretained(this)), | 169 base::Bind(&SourceBufferState::OnSourceInitDone, base::Unretained(this)), |
| 170 base::Bind(&MediaSourceState::OnNewConfigs, base::Unretained(this), | 170 base::Bind(&SourceBufferState::OnNewConfigs, base::Unretained(this), |
| 171 expected_codecs), | 171 expected_codecs), |
| 172 base::Bind(&MediaSourceState::OnNewBuffers, base::Unretained(this)), | 172 base::Bind(&SourceBufferState::OnNewBuffers, base::Unretained(this)), |
| 173 new_text_track_cb_.is_null(), encrypted_media_init_data_cb, | 173 new_text_track_cb_.is_null(), encrypted_media_init_data_cb, |
| 174 base::Bind(&MediaSourceState::OnNewMediaSegment, base::Unretained(this)), | 174 base::Bind(&SourceBufferState::OnNewMediaSegment, base::Unretained(this)), |
| 175 base::Bind(&MediaSourceState::OnEndOfMediaSegment, | 175 base::Bind(&SourceBufferState::OnEndOfMediaSegment, |
| 176 base::Unretained(this)), | 176 base::Unretained(this)), |
| 177 media_log_); | 177 media_log_); |
| 178 } | 178 } |
| 179 | 179 |
| 180 void MediaSourceState::SetSequenceMode(bool sequence_mode) { | 180 void SourceBufferState::SetSequenceMode(bool sequence_mode) { |
| 181 DCHECK(!parsing_media_segment_); | 181 DCHECK(!parsing_media_segment_); |
| 182 | 182 |
| 183 frame_processor_->SetSequenceMode(sequence_mode); | 183 frame_processor_->SetSequenceMode(sequence_mode); |
| 184 } | 184 } |
| 185 | 185 |
| 186 void MediaSourceState::SetGroupStartTimestampIfInSequenceMode( | 186 void SourceBufferState::SetGroupStartTimestampIfInSequenceMode( |
| 187 base::TimeDelta timestamp_offset) { | 187 base::TimeDelta timestamp_offset) { |
| 188 DCHECK(!parsing_media_segment_); | 188 DCHECK(!parsing_media_segment_); |
| 189 | 189 |
| 190 frame_processor_->SetGroupStartTimestampIfInSequenceMode(timestamp_offset); | 190 frame_processor_->SetGroupStartTimestampIfInSequenceMode(timestamp_offset); |
| 191 } | 191 } |
| 192 | 192 |
| 193 void MediaSourceState::SetTracksWatcher( | 193 void SourceBufferState::SetTracksWatcher( |
| 194 const Demuxer::MediaTracksUpdatedCB& tracks_updated_cb) { | 194 const Demuxer::MediaTracksUpdatedCB& tracks_updated_cb) { |
| 195 DCHECK(init_segment_received_cb_.is_null()); | 195 DCHECK(init_segment_received_cb_.is_null()); |
| 196 DCHECK(!tracks_updated_cb.is_null()); | 196 DCHECK(!tracks_updated_cb.is_null()); |
| 197 init_segment_received_cb_ = tracks_updated_cb; | 197 init_segment_received_cb_ = tracks_updated_cb; |
| 198 } | 198 } |
| 199 | 199 |
| 200 bool MediaSourceState::Append(const uint8_t* data, | 200 bool SourceBufferState::Append(const uint8_t* data, |
| 201 size_t length, | 201 size_t length, |
| 202 TimeDelta append_window_start, | 202 TimeDelta append_window_start, |
| 203 TimeDelta append_window_end, | 203 TimeDelta append_window_end, |
| 204 TimeDelta* timestamp_offset) { | 204 TimeDelta* timestamp_offset) { |
| 205 append_in_progress_ = true; | 205 append_in_progress_ = true; |
| 206 DCHECK(timestamp_offset); | 206 DCHECK(timestamp_offset); |
| 207 DCHECK(!timestamp_offset_during_append_); | 207 DCHECK(!timestamp_offset_during_append_); |
| 208 append_window_start_during_append_ = append_window_start; | 208 append_window_start_during_append_ = append_window_start; |
| 209 append_window_end_during_append_ = append_window_end; | 209 append_window_end_during_append_ = append_window_end; |
| 210 timestamp_offset_during_append_ = timestamp_offset; | 210 timestamp_offset_during_append_ = timestamp_offset; |
| 211 | 211 |
| 212 // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with | 212 // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with |
| 213 // append window and timestamp offset pointer. See http://crbug.com/351454. | 213 // append window and timestamp offset pointer. See http://crbug.com/351454. |
| 214 bool result = stream_parser_->Parse(data, length); | 214 bool result = stream_parser_->Parse(data, length); |
| 215 if (!result) { | 215 if (!result) { |
| 216 MEDIA_LOG(ERROR, media_log_) | 216 MEDIA_LOG(ERROR, media_log_) |
| 217 << __func__ << ": stream parsing failed. Data size=" << length | 217 << __func__ << ": stream parsing failed. Data size=" << length |
| 218 << " append_window_start=" << append_window_start.InSecondsF() | 218 << " append_window_start=" << append_window_start.InSecondsF() |
| 219 << " append_window_end=" << append_window_end.InSecondsF(); | 219 << " append_window_end=" << append_window_end.InSecondsF(); |
| 220 } | 220 } |
| 221 timestamp_offset_during_append_ = NULL; | 221 timestamp_offset_during_append_ = NULL; |
| 222 append_in_progress_ = false; | 222 append_in_progress_ = false; |
| 223 return result; | 223 return result; |
| 224 } | 224 } |
| 225 | 225 |
| 226 void MediaSourceState::ResetParserState(TimeDelta append_window_start, | 226 void SourceBufferState::ResetParserState(TimeDelta append_window_start, |
| 227 TimeDelta append_window_end, | 227 TimeDelta append_window_end, |
| 228 base::TimeDelta* timestamp_offset) { | 228 base::TimeDelta* timestamp_offset) { |
| 229 DCHECK(timestamp_offset); | 229 DCHECK(timestamp_offset); |
| 230 DCHECK(!timestamp_offset_during_append_); | 230 DCHECK(!timestamp_offset_during_append_); |
| 231 timestamp_offset_during_append_ = timestamp_offset; | 231 timestamp_offset_during_append_ = timestamp_offset; |
| 232 append_window_start_during_append_ = append_window_start; | 232 append_window_start_during_append_ = append_window_start; |
| 233 append_window_end_during_append_ = append_window_end; | 233 append_window_end_during_append_ = append_window_end; |
| 234 | 234 |
| 235 stream_parser_->Flush(); | 235 stream_parser_->Flush(); |
| 236 timestamp_offset_during_append_ = NULL; | 236 timestamp_offset_during_append_ = NULL; |
| 237 | 237 |
| 238 frame_processor_->Reset(); | 238 frame_processor_->Reset(); |
| 239 parsing_media_segment_ = false; | 239 parsing_media_segment_ = false; |
| 240 media_segment_has_data_for_track_.clear(); | 240 media_segment_has_data_for_track_.clear(); |
| 241 } | 241 } |
| 242 | 242 |
| 243 void MediaSourceState::Remove(TimeDelta start, | 243 void SourceBufferState::Remove(TimeDelta start, |
| 244 TimeDelta end, | 244 TimeDelta end, |
| 245 TimeDelta duration) { | 245 TimeDelta duration) { |
| 246 for (const auto& it : audio_streams_) { | 246 for (const auto& it : audio_streams_) { |
| 247 it.second->Remove(start, end, duration); | 247 it.second->Remove(start, end, duration); |
| 248 } | 248 } |
| 249 | 249 |
| 250 for (const auto& it : video_streams_) { | 250 for (const auto& it : video_streams_) { |
| 251 it.second->Remove(start, end, duration); | 251 it.second->Remove(start, end, duration); |
| 252 } | 252 } |
| 253 | 253 |
| 254 for (const auto& it : text_streams_) { | 254 for (const auto& it : text_streams_) { |
| 255 it.second->Remove(start, end, duration); | 255 it.second->Remove(start, end, duration); |
| 256 } | 256 } |
| 257 } | 257 } |
| 258 | 258 |
| 259 bool MediaSourceState::EvictCodedFrames(DecodeTimestamp media_time, | 259 bool SourceBufferState::EvictCodedFrames(DecodeTimestamp media_time, |
| 260 size_t newDataSize) { | 260 size_t newDataSize) { |
| 261 size_t total_buffered_size = 0; | 261 size_t total_buffered_size = 0; |
| 262 for (const auto& it : audio_streams_) | 262 for (const auto& it : audio_streams_) |
| 263 total_buffered_size += it.second->GetBufferedSize(); | 263 total_buffered_size += it.second->GetBufferedSize(); |
| 264 for (const auto& it : video_streams_) | 264 for (const auto& it : video_streams_) |
| 265 total_buffered_size += it.second->GetBufferedSize(); | 265 total_buffered_size += it.second->GetBufferedSize(); |
| 266 for (const auto& it : text_streams_) | 266 for (const auto& it : text_streams_) |
| 267 total_buffered_size += it.second->GetBufferedSize(); | 267 total_buffered_size += it.second->GetBufferedSize(); |
| 268 | 268 |
| 269 DVLOG(3) << __func__ << " media_time=" << media_time.InSecondsF() | 269 DVLOG(3) << __func__ << " media_time=" << media_time.InSecondsF() |
| 270 << " newDataSize=" << newDataSize | 270 << " newDataSize=" << newDataSize |
| (...skipping 28 matching lines...) Expand all Loading... |
| 299 uint64_t estimated_new_size = newDataSize * curr_size / total_buffered_size; | 299 uint64_t estimated_new_size = newDataSize * curr_size / total_buffered_size; |
| 300 DCHECK_LE(estimated_new_size, SIZE_MAX); | 300 DCHECK_LE(estimated_new_size, SIZE_MAX); |
| 301 success &= it.second->EvictCodedFrames( | 301 success &= it.second->EvictCodedFrames( |
| 302 media_time, static_cast<size_t>(estimated_new_size)); | 302 media_time, static_cast<size_t>(estimated_new_size)); |
| 303 } | 303 } |
| 304 | 304 |
| 305 DVLOG(3) << __func__ << " success=" << success; | 305 DVLOG(3) << __func__ << " success=" << success; |
| 306 return success; | 306 return success; |
| 307 } | 307 } |
| 308 | 308 |
| 309 Ranges<TimeDelta> MediaSourceState::GetBufferedRanges(TimeDelta duration, | 309 Ranges<TimeDelta> SourceBufferState::GetBufferedRanges(TimeDelta duration, |
| 310 bool ended) const { | 310 bool ended) const { |
| 311 RangesList ranges_list; | 311 RangesList ranges_list; |
| 312 for (const auto& it : audio_streams_) | 312 for (const auto& it : audio_streams_) |
| 313 ranges_list.push_back(it.second->GetBufferedRanges(duration)); | 313 ranges_list.push_back(it.second->GetBufferedRanges(duration)); |
| 314 | 314 |
| 315 for (const auto& it : video_streams_) | 315 for (const auto& it : video_streams_) |
| 316 ranges_list.push_back(it.second->GetBufferedRanges(duration)); | 316 ranges_list.push_back(it.second->GetBufferedRanges(duration)); |
| 317 | 317 |
| 318 for (const auto& it : text_streams_) | 318 for (const auto& it : text_streams_) |
| 319 ranges_list.push_back(it.second->GetBufferedRanges(duration)); | 319 ranges_list.push_back(it.second->GetBufferedRanges(duration)); |
| 320 | 320 |
| 321 return ComputeRangesIntersection(ranges_list, ended); | 321 return ComputeRangesIntersection(ranges_list, ended); |
| 322 } | 322 } |
| 323 | 323 |
| 324 TimeDelta MediaSourceState::GetHighestPresentationTimestamp() const { | 324 TimeDelta SourceBufferState::GetHighestPresentationTimestamp() const { |
| 325 TimeDelta max_pts; | 325 TimeDelta max_pts; |
| 326 | 326 |
| 327 for (const auto& it : audio_streams_) { | 327 for (const auto& it : audio_streams_) { |
| 328 max_pts = std::max(max_pts, it.second->GetHighestPresentationTimestamp()); | 328 max_pts = std::max(max_pts, it.second->GetHighestPresentationTimestamp()); |
| 329 } | 329 } |
| 330 | 330 |
| 331 for (const auto& it : video_streams_) { | 331 for (const auto& it : video_streams_) { |
| 332 max_pts = std::max(max_pts, it.second->GetHighestPresentationTimestamp()); | 332 max_pts = std::max(max_pts, it.second->GetHighestPresentationTimestamp()); |
| 333 } | 333 } |
| 334 | 334 |
| 335 for (const auto& it : text_streams_) { | 335 for (const auto& it : text_streams_) { |
| 336 max_pts = std::max(max_pts, it.second->GetHighestPresentationTimestamp()); | 336 max_pts = std::max(max_pts, it.second->GetHighestPresentationTimestamp()); |
| 337 } | 337 } |
| 338 | 338 |
| 339 return max_pts; | 339 return max_pts; |
| 340 } | 340 } |
| 341 | 341 |
| 342 TimeDelta MediaSourceState::GetMaxBufferedDuration() const { | 342 TimeDelta SourceBufferState::GetMaxBufferedDuration() const { |
| 343 TimeDelta max_duration; | 343 TimeDelta max_duration; |
| 344 | 344 |
| 345 for (const auto& it : audio_streams_) { | 345 for (const auto& it : audio_streams_) { |
| 346 max_duration = std::max(max_duration, it.second->GetBufferedDuration()); | 346 max_duration = std::max(max_duration, it.second->GetBufferedDuration()); |
| 347 } | 347 } |
| 348 | 348 |
| 349 for (const auto& it : video_streams_) { | 349 for (const auto& it : video_streams_) { |
| 350 max_duration = std::max(max_duration, it.second->GetBufferedDuration()); | 350 max_duration = std::max(max_duration, it.second->GetBufferedDuration()); |
| 351 } | 351 } |
| 352 | 352 |
| 353 for (const auto& it : text_streams_) { | 353 for (const auto& it : text_streams_) { |
| 354 max_duration = std::max(max_duration, it.second->GetBufferedDuration()); | 354 max_duration = std::max(max_duration, it.second->GetBufferedDuration()); |
| 355 } | 355 } |
| 356 | 356 |
| 357 return max_duration; | 357 return max_duration; |
| 358 } | 358 } |
| 359 | 359 |
| 360 void MediaSourceState::StartReturningData() { | 360 void SourceBufferState::StartReturningData() { |
| 361 for (const auto& it : audio_streams_) { | 361 for (const auto& it : audio_streams_) { |
| 362 it.second->StartReturningData(); | 362 it.second->StartReturningData(); |
| 363 } | 363 } |
| 364 | 364 |
| 365 for (const auto& it : video_streams_) { | 365 for (const auto& it : video_streams_) { |
| 366 it.second->StartReturningData(); | 366 it.second->StartReturningData(); |
| 367 } | 367 } |
| 368 | 368 |
| 369 for (const auto& it : text_streams_) { | 369 for (const auto& it : text_streams_) { |
| 370 it.second->StartReturningData(); | 370 it.second->StartReturningData(); |
| 371 } | 371 } |
| 372 } | 372 } |
| 373 | 373 |
| 374 void MediaSourceState::AbortReads() { | 374 void SourceBufferState::AbortReads() { |
| 375 for (const auto& it : audio_streams_) { | 375 for (const auto& it : audio_streams_) { |
| 376 it.second->AbortReads(); | 376 it.second->AbortReads(); |
| 377 } | 377 } |
| 378 | 378 |
| 379 for (const auto& it : video_streams_) { | 379 for (const auto& it : video_streams_) { |
| 380 it.second->AbortReads(); | 380 it.second->AbortReads(); |
| 381 } | 381 } |
| 382 | 382 |
| 383 for (const auto& it : text_streams_) { | 383 for (const auto& it : text_streams_) { |
| 384 it.second->AbortReads(); | 384 it.second->AbortReads(); |
| 385 } | 385 } |
| 386 } | 386 } |
| 387 | 387 |
| 388 void MediaSourceState::Seek(TimeDelta seek_time) { | 388 void SourceBufferState::Seek(TimeDelta seek_time) { |
| 389 for (const auto& it : audio_streams_) { | 389 for (const auto& it : audio_streams_) { |
| 390 it.second->Seek(seek_time); | 390 it.second->Seek(seek_time); |
| 391 } | 391 } |
| 392 | 392 |
| 393 for (const auto& it : video_streams_) { | 393 for (const auto& it : video_streams_) { |
| 394 it.second->Seek(seek_time); | 394 it.second->Seek(seek_time); |
| 395 } | 395 } |
| 396 | 396 |
| 397 for (const auto& it : text_streams_) { | 397 for (const auto& it : text_streams_) { |
| 398 it.second->Seek(seek_time); | 398 it.second->Seek(seek_time); |
| 399 } | 399 } |
| 400 } | 400 } |
| 401 | 401 |
| 402 void MediaSourceState::CompletePendingReadIfPossible() { | 402 void SourceBufferState::CompletePendingReadIfPossible() { |
| 403 for (const auto& it : audio_streams_) { | 403 for (const auto& it : audio_streams_) { |
| 404 it.second->CompletePendingReadIfPossible(); | 404 it.second->CompletePendingReadIfPossible(); |
| 405 } | 405 } |
| 406 | 406 |
| 407 for (const auto& it : video_streams_) { | 407 for (const auto& it : video_streams_) { |
| 408 it.second->CompletePendingReadIfPossible(); | 408 it.second->CompletePendingReadIfPossible(); |
| 409 } | 409 } |
| 410 | 410 |
| 411 for (const auto& it : text_streams_) { | 411 for (const auto& it : text_streams_) { |
| 412 it.second->CompletePendingReadIfPossible(); | 412 it.second->CompletePendingReadIfPossible(); |
| 413 } | 413 } |
| 414 } | 414 } |
| 415 | 415 |
| 416 void MediaSourceState::OnSetDuration(TimeDelta duration) { | 416 void SourceBufferState::OnSetDuration(TimeDelta duration) { |
| 417 for (const auto& it : audio_streams_) { | 417 for (const auto& it : audio_streams_) { |
| 418 it.second->OnSetDuration(duration); | 418 it.second->OnSetDuration(duration); |
| 419 } | 419 } |
| 420 | 420 |
| 421 for (const auto& it : video_streams_) { | 421 for (const auto& it : video_streams_) { |
| 422 it.second->OnSetDuration(duration); | 422 it.second->OnSetDuration(duration); |
| 423 } | 423 } |
| 424 | 424 |
| 425 for (const auto& it : text_streams_) { | 425 for (const auto& it : text_streams_) { |
| 426 it.second->OnSetDuration(duration); | 426 it.second->OnSetDuration(duration); |
| 427 } | 427 } |
| 428 } | 428 } |
| 429 | 429 |
| 430 void MediaSourceState::MarkEndOfStream() { | 430 void SourceBufferState::MarkEndOfStream() { |
| 431 for (const auto& it : audio_streams_) { | 431 for (const auto& it : audio_streams_) { |
| 432 it.second->MarkEndOfStream(); | 432 it.second->MarkEndOfStream(); |
| 433 } | 433 } |
| 434 | 434 |
| 435 for (const auto& it : video_streams_) { | 435 for (const auto& it : video_streams_) { |
| 436 it.second->MarkEndOfStream(); | 436 it.second->MarkEndOfStream(); |
| 437 } | 437 } |
| 438 | 438 |
| 439 for (const auto& it : text_streams_) { | 439 for (const auto& it : text_streams_) { |
| 440 it.second->MarkEndOfStream(); | 440 it.second->MarkEndOfStream(); |
| 441 } | 441 } |
| 442 } | 442 } |
| 443 | 443 |
| 444 void MediaSourceState::UnmarkEndOfStream() { | 444 void SourceBufferState::UnmarkEndOfStream() { |
| 445 for (const auto& it : audio_streams_) { | 445 for (const auto& it : audio_streams_) { |
| 446 it.second->UnmarkEndOfStream(); | 446 it.second->UnmarkEndOfStream(); |
| 447 } | 447 } |
| 448 | 448 |
| 449 for (const auto& it : video_streams_) { | 449 for (const auto& it : video_streams_) { |
| 450 it.second->UnmarkEndOfStream(); | 450 it.second->UnmarkEndOfStream(); |
| 451 } | 451 } |
| 452 | 452 |
| 453 for (const auto& it : text_streams_) { | 453 for (const auto& it : text_streams_) { |
| 454 it.second->UnmarkEndOfStream(); | 454 it.second->UnmarkEndOfStream(); |
| 455 } | 455 } |
| 456 } | 456 } |
| 457 | 457 |
| 458 void MediaSourceState::Shutdown() { | 458 void SourceBufferState::Shutdown() { |
| 459 for (const auto& it : audio_streams_) { | 459 for (const auto& it : audio_streams_) { |
| 460 it.second->Shutdown(); | 460 it.second->Shutdown(); |
| 461 } | 461 } |
| 462 | 462 |
| 463 for (const auto& it : video_streams_) { | 463 for (const auto& it : video_streams_) { |
| 464 it.second->Shutdown(); | 464 it.second->Shutdown(); |
| 465 } | 465 } |
| 466 | 466 |
| 467 for (const auto& it : text_streams_) { | 467 for (const auto& it : text_streams_) { |
| 468 it.second->Shutdown(); | 468 it.second->Shutdown(); |
| 469 } | 469 } |
| 470 } | 470 } |
| 471 | 471 |
| 472 void MediaSourceState::SetMemoryLimits(DemuxerStream::Type type, | 472 void SourceBufferState::SetMemoryLimits(DemuxerStream::Type type, |
| 473 size_t memory_limit) { | 473 size_t memory_limit) { |
| 474 switch (type) { | 474 switch (type) { |
| 475 case DemuxerStream::AUDIO: | 475 case DemuxerStream::AUDIO: |
| 476 for (const auto& it : audio_streams_) { | 476 for (const auto& it : audio_streams_) { |
| 477 it.second->SetStreamMemoryLimit(memory_limit); | 477 it.second->SetStreamMemoryLimit(memory_limit); |
| 478 } | 478 } |
| 479 break; | 479 break; |
| 480 case DemuxerStream::VIDEO: | 480 case DemuxerStream::VIDEO: |
| 481 for (const auto& it : video_streams_) { | 481 for (const auto& it : video_streams_) { |
| 482 it.second->SetStreamMemoryLimit(memory_limit); | 482 it.second->SetStreamMemoryLimit(memory_limit); |
| 483 } | 483 } |
| 484 break; | 484 break; |
| 485 case DemuxerStream::TEXT: | 485 case DemuxerStream::TEXT: |
| 486 for (const auto& it : text_streams_) { | 486 for (const auto& it : text_streams_) { |
| 487 it.second->SetStreamMemoryLimit(memory_limit); | 487 it.second->SetStreamMemoryLimit(memory_limit); |
| 488 } | 488 } |
| 489 break; | 489 break; |
| 490 case DemuxerStream::UNKNOWN: | 490 case DemuxerStream::UNKNOWN: |
| 491 case DemuxerStream::NUM_TYPES: | 491 case DemuxerStream::NUM_TYPES: |
| 492 NOTREACHED(); | 492 NOTREACHED(); |
| 493 break; | 493 break; |
| 494 } | 494 } |
| 495 } | 495 } |
| 496 | 496 |
| 497 bool MediaSourceState::IsSeekWaitingForData() const { | 497 bool SourceBufferState::IsSeekWaitingForData() const { |
| 498 for (const auto& it : audio_streams_) { | 498 for (const auto& it : audio_streams_) { |
| 499 if (it.second->IsSeekWaitingForData()) | 499 if (it.second->IsSeekWaitingForData()) |
| 500 return true; | 500 return true; |
| 501 } | 501 } |
| 502 | 502 |
| 503 for (const auto& it : video_streams_) { | 503 for (const auto& it : video_streams_) { |
| 504 if (it.second->IsSeekWaitingForData()) | 504 if (it.second->IsSeekWaitingForData()) |
| 505 return true; | 505 return true; |
| 506 } | 506 } |
| 507 | 507 |
| 508 // NOTE: We are intentionally not checking the text tracks | 508 // NOTE: We are intentionally not checking the text tracks |
| 509 // because text tracks are discontinuous and may not have data | 509 // because text tracks are discontinuous and may not have data |
| 510 // for the seek position. This is ok and playback should not be | 510 // for the seek position. This is ok and playback should not be |
| 511 // stalled because we don't have cues. If cues, with timestamps after | 511 // stalled because we don't have cues. If cues, with timestamps after |
| 512 // the seek time, eventually arrive they will be delivered properly | 512 // the seek time, eventually arrive they will be delivered properly |
| 513 // in response to ChunkDemuxerStream::Read() calls. | 513 // in response to ChunkDemuxerStream::Read() calls. |
| 514 | 514 |
| 515 return false; | 515 return false; |
| 516 } | 516 } |
| 517 | 517 |
| 518 bool MediaSourceState::OnNewConfigs( | 518 bool SourceBufferState::OnNewConfigs( |
| 519 std::string expected_codecs, | 519 std::string expected_codecs, |
| 520 std::unique_ptr<MediaTracks> tracks, | 520 std::unique_ptr<MediaTracks> tracks, |
| 521 const StreamParser::TextTrackConfigMap& text_configs) { | 521 const StreamParser::TextTrackConfigMap& text_configs) { |
| 522 DCHECK(tracks.get()); | 522 DCHECK(tracks.get()); |
| 523 DVLOG(1) << __func__ << " expected_codecs=" << expected_codecs | 523 DVLOG(1) << __func__ << " expected_codecs=" << expected_codecs |
| 524 << " tracks=" << tracks->tracks().size(); | 524 << " tracks=" << tracks->tracks().size(); |
| 525 DCHECK_GE(state_, PENDING_PARSER_CONFIG); | 525 DCHECK_GE(state_, PENDING_PARSER_CONFIG); |
| 526 | 526 |
| 527 // Check that there is no clashing bytestream track ids. | 527 // Check that there is no clashing bytestream track ids. |
| 528 if (!CheckBytestreamTrackIds(*tracks, text_configs)) { | 528 if (!CheckBytestreamTrackIds(*tracks, text_configs)) { |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 if (success) { | 767 if (success) { |
| 768 if (state_ == PENDING_PARSER_CONFIG) | 768 if (state_ == PENDING_PARSER_CONFIG) |
| 769 state_ = PENDING_PARSER_INIT; | 769 state_ = PENDING_PARSER_INIT; |
| 770 DCHECK(!init_segment_received_cb_.is_null()); | 770 DCHECK(!init_segment_received_cb_.is_null()); |
| 771 init_segment_received_cb_.Run(std::move(tracks)); | 771 init_segment_received_cb_.Run(std::move(tracks)); |
| 772 } | 772 } |
| 773 | 773 |
| 774 return success; | 774 return success; |
| 775 } | 775 } |
| 776 | 776 |
| 777 void MediaSourceState::SetStreamMemoryLimits() { | 777 void SourceBufferState::SetStreamMemoryLimits() { |
| 778 auto cmd_line = base::CommandLine::ForCurrentProcess(); | 778 auto cmd_line = base::CommandLine::ForCurrentProcess(); |
| 779 | 779 |
| 780 std::string audio_buf_limit_switch = | 780 std::string audio_buf_limit_switch = |
| 781 cmd_line->GetSwitchValueASCII(switches::kMSEAudioBufferSizeLimit); | 781 cmd_line->GetSwitchValueASCII(switches::kMSEAudioBufferSizeLimit); |
| 782 unsigned audio_buf_size_limit = 0; | 782 unsigned audio_buf_size_limit = 0; |
| 783 if (base::StringToUint(audio_buf_limit_switch, &audio_buf_size_limit) && | 783 if (base::StringToUint(audio_buf_limit_switch, &audio_buf_size_limit) && |
| 784 audio_buf_size_limit > 0) { | 784 audio_buf_size_limit > 0) { |
| 785 MEDIA_LOG(INFO, media_log_) | 785 MEDIA_LOG(INFO, media_log_) |
| 786 << "Custom audio per-track SourceBuffer size limit=" | 786 << "Custom audio per-track SourceBuffer size limit=" |
| 787 << audio_buf_size_limit; | 787 << audio_buf_size_limit; |
| 788 for (const auto& it : audio_streams_) { | 788 for (const auto& it : audio_streams_) { |
| 789 it.second->SetStreamMemoryLimit(audio_buf_size_limit); | 789 it.second->SetStreamMemoryLimit(audio_buf_size_limit); |
| 790 } | 790 } |
| 791 } | 791 } |
| 792 | 792 |
| 793 std::string video_buf_limit_switch = | 793 std::string video_buf_limit_switch = |
| 794 cmd_line->GetSwitchValueASCII(switches::kMSEVideoBufferSizeLimit); | 794 cmd_line->GetSwitchValueASCII(switches::kMSEVideoBufferSizeLimit); |
| 795 unsigned video_buf_size_limit = 0; | 795 unsigned video_buf_size_limit = 0; |
| 796 if (base::StringToUint(video_buf_limit_switch, &video_buf_size_limit) && | 796 if (base::StringToUint(video_buf_limit_switch, &video_buf_size_limit) && |
| 797 video_buf_size_limit > 0) { | 797 video_buf_size_limit > 0) { |
| 798 MEDIA_LOG(INFO, media_log_) | 798 MEDIA_LOG(INFO, media_log_) |
| 799 << "Custom video per-track SourceBuffer size limit=" | 799 << "Custom video per-track SourceBuffer size limit=" |
| 800 << video_buf_size_limit; | 800 << video_buf_size_limit; |
| 801 for (const auto& it : video_streams_) { | 801 for (const auto& it : video_streams_) { |
| 802 it.second->SetStreamMemoryLimit(video_buf_size_limit); | 802 it.second->SetStreamMemoryLimit(video_buf_size_limit); |
| 803 } | 803 } |
| 804 } | 804 } |
| 805 } | 805 } |
| 806 | 806 |
| 807 void MediaSourceState::OnNewMediaSegment() { | 807 void SourceBufferState::OnNewMediaSegment() { |
| 808 DVLOG(2) << "OnNewMediaSegment()"; | 808 DVLOG(2) << "OnNewMediaSegment()"; |
| 809 DCHECK_EQ(state_, PARSER_INITIALIZED); | 809 DCHECK_EQ(state_, PARSER_INITIALIZED); |
| 810 parsing_media_segment_ = true; | 810 parsing_media_segment_ = true; |
| 811 media_segment_has_data_for_track_.clear(); | 811 media_segment_has_data_for_track_.clear(); |
| 812 } | 812 } |
| 813 | 813 |
| 814 void MediaSourceState::OnEndOfMediaSegment() { | 814 void SourceBufferState::OnEndOfMediaSegment() { |
| 815 DVLOG(2) << "OnEndOfMediaSegment()"; | 815 DVLOG(2) << "OnEndOfMediaSegment()"; |
| 816 DCHECK_EQ(state_, PARSER_INITIALIZED); | 816 DCHECK_EQ(state_, PARSER_INITIALIZED); |
| 817 parsing_media_segment_ = false; | 817 parsing_media_segment_ = false; |
| 818 | 818 |
| 819 for (const auto& it : audio_streams_) { | 819 for (const auto& it : audio_streams_) { |
| 820 if (!media_segment_has_data_for_track_[it.first]) { | 820 if (!media_segment_has_data_for_track_[it.first]) { |
| 821 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_missing_track_logs_, | 821 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_missing_track_logs_, |
| 822 kMaxMissingTrackInSegmentLogs) | 822 kMaxMissingTrackInSegmentLogs) |
| 823 << "Media segment did not contain any coded frames for track " | 823 << "Media segment did not contain any coded frames for track " |
| 824 << it.first << ", mismatching initialization segment. Therefore, MSE" | 824 << it.first << ", mismatching initialization segment. Therefore, MSE" |
| 825 " coded frame processing may not interoperably detect" | 825 " coded frame processing may not interoperably detect" |
| 826 " discontinuities in appended media."; | 826 " discontinuities in appended media."; |
| 827 } | 827 } |
| 828 } | 828 } |
| 829 for (const auto& it : video_streams_) { | 829 for (const auto& it : video_streams_) { |
| 830 if (!media_segment_has_data_for_track_[it.first]) { | 830 if (!media_segment_has_data_for_track_[it.first]) { |
| 831 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_missing_track_logs_, | 831 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_missing_track_logs_, |
| 832 kMaxMissingTrackInSegmentLogs) | 832 kMaxMissingTrackInSegmentLogs) |
| 833 << "Media segment did not contain any coded frames for track " | 833 << "Media segment did not contain any coded frames for track " |
| 834 << it.first << ", mismatching initialization segment. Therefore, MSE" | 834 << it.first << ", mismatching initialization segment. Therefore, MSE" |
| 835 " coded frame processing may not interoperably detect" | 835 " coded frame processing may not interoperably detect" |
| 836 " discontinuities in appended media."; | 836 " discontinuities in appended media."; |
| 837 } | 837 } |
| 838 } | 838 } |
| 839 } | 839 } |
| 840 | 840 |
| 841 bool MediaSourceState::OnNewBuffers( | 841 bool SourceBufferState::OnNewBuffers( |
| 842 const StreamParser::BufferQueueMap& buffer_queue_map) { | 842 const StreamParser::BufferQueueMap& buffer_queue_map) { |
| 843 DVLOG(2) << __func__ << " buffer_queues=" << buffer_queue_map.size(); | 843 DVLOG(2) << __func__ << " buffer_queues=" << buffer_queue_map.size(); |
| 844 DCHECK_EQ(state_, PARSER_INITIALIZED); | 844 DCHECK_EQ(state_, PARSER_INITIALIZED); |
| 845 DCHECK(timestamp_offset_during_append_); | 845 DCHECK(timestamp_offset_during_append_); |
| 846 DCHECK(parsing_media_segment_); | 846 DCHECK(parsing_media_segment_); |
| 847 | 847 |
| 848 for (const auto& it : buffer_queue_map) { | 848 for (const auto& it : buffer_queue_map) { |
| 849 const StreamParser::BufferQueue& bufq = it.second; | 849 const StreamParser::BufferQueue& bufq = it.second; |
| 850 DCHECK(!bufq.empty()); | 850 DCHECK(!bufq.empty()); |
| 851 media_segment_has_data_for_track_[it.first] = true; | 851 media_segment_has_data_for_track_[it.first] = true; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 879 } | 879 } |
| 880 | 880 |
| 881 // Only update the timestamp offset if the frame processor hasn't already. | 881 // Only update the timestamp offset if the frame processor hasn't already. |
| 882 if (auto_update_timestamp_offset_ && | 882 if (auto_update_timestamp_offset_ && |
| 883 timestamp_offset_before_processing == *timestamp_offset_during_append_) { | 883 timestamp_offset_before_processing == *timestamp_offset_during_append_) { |
| 884 *timestamp_offset_during_append_ = new_timestamp_offset; | 884 *timestamp_offset_during_append_ = new_timestamp_offset; |
| 885 } | 885 } |
| 886 | 886 |
| 887 return true; | 887 return true; |
| 888 } | 888 } |
| 889 void MediaSourceState::OnSourceInitDone( | 889 void SourceBufferState::OnSourceInitDone( |
| 890 const StreamParser::InitParameters& params) { | 890 const StreamParser::InitParameters& params) { |
| 891 DCHECK_EQ(state_, PENDING_PARSER_INIT); | 891 DCHECK_EQ(state_, PENDING_PARSER_INIT); |
| 892 state_ = PARSER_INITIALIZED; | 892 state_ = PARSER_INITIALIZED; |
| 893 auto_update_timestamp_offset_ = params.auto_update_timestamp_offset; | 893 auto_update_timestamp_offset_ = params.auto_update_timestamp_offset; |
| 894 base::ResetAndReturn(&init_cb_).Run(params); | 894 base::ResetAndReturn(&init_cb_).Run(params); |
| 895 } | 895 } |
| 896 | 896 |
| 897 } // namespace media | 897 } // namespace media |
| OLD | NEW |