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 |