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 <list> | 9 #include <list> |
10 | 10 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 public: | 87 public: |
88 // Callback signature used to create ChunkDemuxerStreams. | 88 // Callback signature used to create ChunkDemuxerStreams. |
89 typedef base::Callback<ChunkDemuxerStream*( | 89 typedef base::Callback<ChunkDemuxerStream*( |
90 DemuxerStream::Type)> CreateDemuxerStreamCB; | 90 DemuxerStream::Type)> CreateDemuxerStreamCB; |
91 | 91 |
92 typedef ChunkDemuxer::InitSegmentReceivedCB InitSegmentReceivedCB; | 92 typedef ChunkDemuxer::InitSegmentReceivedCB InitSegmentReceivedCB; |
93 | 93 |
94 typedef base::Callback<void( | 94 typedef base::Callback<void( |
95 ChunkDemuxerStream*, const TextTrackConfig&)> NewTextTrackCB; | 95 ChunkDemuxerStream*, const TextTrackConfig&)> NewTextTrackCB; |
96 | 96 |
97 SourceState( | 97 SourceState(scoped_ptr<StreamParser> stream_parser, |
98 scoped_ptr<StreamParser> stream_parser, | 98 scoped_ptr<FrameProcessor> frame_processor, |
99 scoped_ptr<FrameProcessor> frame_processor, const LogCB& log_cb, | 99 const CreateDemuxerStreamCB& create_demuxer_stream_cb, |
100 const CreateDemuxerStreamCB& create_demuxer_stream_cb, | 100 const scoped_refptr<MediaLog>& media_log); |
101 const scoped_refptr<MediaLog>& media_log); | |
102 | 101 |
103 ~SourceState(); | 102 ~SourceState(); |
104 | 103 |
105 void Init(const StreamParser::InitCB& init_cb, | 104 void Init(const StreamParser::InitCB& init_cb, |
106 bool allow_audio, | 105 bool allow_audio, |
107 bool allow_video, | 106 bool allow_video, |
108 const StreamParser::EncryptedMediaInitDataCB& | 107 const StreamParser::EncryptedMediaInitDataCB& |
109 encrypted_media_init_data_cb, | 108 encrypted_media_init_data_cb, |
110 const NewTextTrackCB& new_text_track_cb); | 109 const NewTextTrackCB& new_text_track_cb); |
111 | 110 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 // The object used to parse appended data. | 226 // The object used to parse appended data. |
228 scoped_ptr<StreamParser> stream_parser_; | 227 scoped_ptr<StreamParser> stream_parser_; |
229 | 228 |
230 ChunkDemuxerStream* audio_; // Not owned by |this|. | 229 ChunkDemuxerStream* audio_; // Not owned by |this|. |
231 ChunkDemuxerStream* video_; // Not owned by |this|. | 230 ChunkDemuxerStream* video_; // Not owned by |this|. |
232 | 231 |
233 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; | 232 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; |
234 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. | 233 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. |
235 | 234 |
236 scoped_ptr<FrameProcessor> frame_processor_; | 235 scoped_ptr<FrameProcessor> frame_processor_; |
237 LogCB log_cb_; | |
238 scoped_refptr<MediaLog> media_log_; | 236 scoped_refptr<MediaLog> media_log_; |
239 StreamParser::InitCB init_cb_; | 237 StreamParser::InitCB init_cb_; |
240 | 238 |
241 // During Append(), OnNewConfigs() will trigger the initialization segment | 239 // During Append(), OnNewConfigs() will trigger the initialization segment |
242 // received algorithm. This callback is only non-NULL during the lifetime of | 240 // received algorithm. This callback is only non-NULL during the lifetime of |
243 // an Append() call. Note, the MSE spec explicitly disallows this algorithm | 241 // an Append() call. Note, the MSE spec explicitly disallows this algorithm |
244 // during an Abort(), since Abort() is allowed only to emit coded frames, and | 242 // during an Abort(), since Abort() is allowed only to emit coded frames, and |
245 // only if the parser is PARSING_MEDIA_SEGMENT (not an INIT segment). | 243 // only if the parser is PARSING_MEDIA_SEGMENT (not an INIT segment). |
246 InitSegmentReceivedCB init_segment_received_cb_; | 244 InitSegmentReceivedCB init_segment_received_cb_; |
247 | 245 |
248 // Indicates that timestampOffset should be updated automatically during | 246 // Indicates that timestampOffset should be updated automatically during |
249 // OnNewBuffers() based on the earliest end timestamp of the buffers provided. | 247 // OnNewBuffers() based on the earliest end timestamp of the buffers provided. |
250 // TODO(wolenetz): Refactor this function while integrating April 29, 2014 | 248 // TODO(wolenetz): Refactor this function while integrating April 29, 2014 |
251 // changes to MSE spec. See http://crbug.com/371499. | 249 // changes to MSE spec. See http://crbug.com/371499. |
252 bool auto_update_timestamp_offset_; | 250 bool auto_update_timestamp_offset_; |
253 | 251 |
254 DISALLOW_COPY_AND_ASSIGN(SourceState); | 252 DISALLOW_COPY_AND_ASSIGN(SourceState); |
255 }; | 253 }; |
256 | 254 |
257 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, | 255 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, |
258 scoped_ptr<FrameProcessor> frame_processor, | 256 scoped_ptr<FrameProcessor> frame_processor, |
259 const LogCB& log_cb, | |
260 const CreateDemuxerStreamCB& create_demuxer_stream_cb, | 257 const CreateDemuxerStreamCB& create_demuxer_stream_cb, |
261 const scoped_refptr<MediaLog>& media_log) | 258 const scoped_refptr<MediaLog>& media_log) |
262 : create_demuxer_stream_cb_(create_demuxer_stream_cb), | 259 : create_demuxer_stream_cb_(create_demuxer_stream_cb), |
263 timestamp_offset_during_append_(NULL), | 260 timestamp_offset_during_append_(NULL), |
264 new_media_segment_(false), | 261 new_media_segment_(false), |
265 parsing_media_segment_(false), | 262 parsing_media_segment_(false), |
266 stream_parser_(stream_parser.release()), | 263 stream_parser_(stream_parser.release()), |
267 audio_(NULL), | 264 audio_(NULL), |
268 video_(NULL), | 265 video_(NULL), |
269 frame_processor_(frame_processor.release()), | 266 frame_processor_(frame_processor.release()), |
270 log_cb_(log_cb), | |
271 media_log_(media_log), | 267 media_log_(media_log), |
272 auto_update_timestamp_offset_(false) { | 268 auto_update_timestamp_offset_(false) { |
273 DCHECK(!create_demuxer_stream_cb_.is_null()); | 269 DCHECK(!create_demuxer_stream_cb_.is_null()); |
274 DCHECK(frame_processor_); | 270 DCHECK(frame_processor_); |
275 } | 271 } |
276 | 272 |
277 SourceState::~SourceState() { | 273 SourceState::~SourceState() { |
278 Shutdown(); | 274 Shutdown(); |
279 | 275 |
280 STLDeleteValues(&text_stream_map_); | 276 STLDeleteValues(&text_stream_map_); |
281 } | 277 } |
282 | 278 |
283 void SourceState::Init( | 279 void SourceState::Init( |
284 const StreamParser::InitCB& init_cb, | 280 const StreamParser::InitCB& init_cb, |
285 bool allow_audio, | 281 bool allow_audio, |
286 bool allow_video, | 282 bool allow_video, |
287 const StreamParser::EncryptedMediaInitDataCB& encrypted_media_init_data_cb, | 283 const StreamParser::EncryptedMediaInitDataCB& encrypted_media_init_data_cb, |
288 const NewTextTrackCB& new_text_track_cb) { | 284 const NewTextTrackCB& new_text_track_cb) { |
289 new_text_track_cb_ = new_text_track_cb; | 285 new_text_track_cb_ = new_text_track_cb; |
290 init_cb_ = init_cb; | 286 init_cb_ = init_cb; |
291 | 287 |
292 stream_parser_->Init( | 288 stream_parser_->Init( |
293 base::Bind(&SourceState::OnSourceInitDone, base::Unretained(this)), | 289 base::Bind(&SourceState::OnSourceInitDone, base::Unretained(this)), |
294 base::Bind(&SourceState::OnNewConfigs, base::Unretained(this), | 290 base::Bind(&SourceState::OnNewConfigs, base::Unretained(this), |
295 allow_audio, allow_video), | 291 allow_audio, allow_video), |
296 base::Bind(&SourceState::OnNewBuffers, base::Unretained(this)), | 292 base::Bind(&SourceState::OnNewBuffers, base::Unretained(this)), |
297 new_text_track_cb_.is_null(), encrypted_media_init_data_cb, | 293 new_text_track_cb_.is_null(), encrypted_media_init_data_cb, |
298 base::Bind(&SourceState::OnNewMediaSegment, base::Unretained(this)), | 294 base::Bind(&SourceState::OnNewMediaSegment, base::Unretained(this)), |
299 base::Bind(&SourceState::OnEndOfMediaSegment, base::Unretained(this)), | 295 base::Bind(&SourceState::OnEndOfMediaSegment, base::Unretained(this)), |
300 log_cb_); | 296 media_log_); |
301 } | 297 } |
302 | 298 |
303 void SourceState::SetSequenceMode(bool sequence_mode) { | 299 void SourceState::SetSequenceMode(bool sequence_mode) { |
304 DCHECK(!parsing_media_segment_); | 300 DCHECK(!parsing_media_segment_); |
305 | 301 |
306 frame_processor_->SetSequenceMode(sequence_mode); | 302 frame_processor_->SetSequenceMode(sequence_mode); |
307 } | 303 } |
308 | 304 |
309 void SourceState::SetGroupStartTimestampIfInSequenceMode( | 305 void SourceState::SetGroupStartTimestampIfInSequenceMode( |
310 base::TimeDelta timestamp_offset) { | 306 base::TimeDelta timestamp_offset) { |
(...skipping 15 matching lines...) Expand all Loading... |
326 DCHECK(init_segment_received_cb_.is_null()); | 322 DCHECK(init_segment_received_cb_.is_null()); |
327 append_window_start_during_append_ = append_window_start; | 323 append_window_start_during_append_ = append_window_start; |
328 append_window_end_during_append_ = append_window_end; | 324 append_window_end_during_append_ = append_window_end; |
329 timestamp_offset_during_append_ = timestamp_offset; | 325 timestamp_offset_during_append_ = timestamp_offset; |
330 init_segment_received_cb_= init_segment_received_cb; | 326 init_segment_received_cb_= init_segment_received_cb; |
331 | 327 |
332 // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with | 328 // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with |
333 // append window and timestamp offset pointer. See http://crbug.com/351454. | 329 // append window and timestamp offset pointer. See http://crbug.com/351454. |
334 bool result = stream_parser_->Parse(data, length); | 330 bool result = stream_parser_->Parse(data, length); |
335 if (!result) { | 331 if (!result) { |
336 MEDIA_LOG(ERROR, log_cb_) | 332 MEDIA_LOG(ERROR, media_log_) |
337 << __FUNCTION__ << ": stream parsing failed." | 333 << __FUNCTION__ << ": stream parsing failed." |
338 << " Data size=" << length | 334 << " Data size=" << length |
339 << " append_window_start=" << append_window_start.InSecondsF() | 335 << " append_window_start=" << append_window_start.InSecondsF() |
340 << " append_window_end=" << append_window_end.InSecondsF(); | 336 << " append_window_end=" << append_window_end.InSecondsF(); |
341 } | 337 } |
342 timestamp_offset_during_append_ = NULL; | 338 timestamp_offset_during_append_ = NULL; |
343 init_segment_received_cb_.Reset(); | 339 init_segment_received_cb_.Reset(); |
344 return result; | 340 return result; |
345 } | 341 } |
346 | 342 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 DCHECK(!init_segment_received_cb_.is_null()); | 560 DCHECK(!init_segment_received_cb_.is_null()); |
565 | 561 |
566 if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) { | 562 if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) { |
567 DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!"; | 563 DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!"; |
568 return false; | 564 return false; |
569 } | 565 } |
570 | 566 |
571 // Signal an error if we get configuration info for stream types that weren't | 567 // Signal an error if we get configuration info for stream types that weren't |
572 // specified in AddId() or more configs after a stream is initialized. | 568 // specified in AddId() or more configs after a stream is initialized. |
573 if (allow_audio != audio_config.IsValidConfig()) { | 569 if (allow_audio != audio_config.IsValidConfig()) { |
574 MEDIA_LOG(ERROR, log_cb_) | 570 MEDIA_LOG(ERROR, media_log_) |
575 << "Initialization segment" | 571 << "Initialization segment" |
576 << (audio_config.IsValidConfig() ? " has" : " does not have") | 572 << (audio_config.IsValidConfig() ? " has" : " does not have") |
577 << " an audio track, but the mimetype" | 573 << " an audio track, but the mimetype" |
578 << (allow_audio ? " specifies" : " does not specify") | 574 << (allow_audio ? " specifies" : " does not specify") |
579 << " an audio codec."; | 575 << " an audio codec."; |
580 return false; | 576 return false; |
581 } | 577 } |
582 | 578 |
583 if (allow_video != video_config.IsValidConfig()) { | 579 if (allow_video != video_config.IsValidConfig()) { |
584 MEDIA_LOG(ERROR, log_cb_) | 580 MEDIA_LOG(ERROR, media_log_) |
585 << "Initialization segment" | 581 << "Initialization segment" |
586 << (video_config.IsValidConfig() ? " has" : " does not have") | 582 << (video_config.IsValidConfig() ? " has" : " does not have") |
587 << " a video track, but the mimetype" | 583 << " a video track, but the mimetype" |
588 << (allow_video ? " specifies" : " does not specify") | 584 << (allow_video ? " specifies" : " does not specify") |
589 << " a video codec."; | 585 << " a video codec."; |
590 return false; | 586 return false; |
591 } | 587 } |
592 | 588 |
593 bool success = true; | 589 bool success = true; |
594 if (audio_config.IsValidConfig()) { | 590 if (audio_config.IsValidConfig()) { |
(...skipping 14 matching lines...) Expand all Loading... |
609 return false; | 605 return false; |
610 } | 606 } |
611 | 607 |
612 if (!frame_processor_->AddTrack(FrameProcessor::kAudioTrackId, audio_)) { | 608 if (!frame_processor_->AddTrack(FrameProcessor::kAudioTrackId, audio_)) { |
613 DVLOG(1) << "Failed to add audio track to frame processor."; | 609 DVLOG(1) << "Failed to add audio track to frame processor."; |
614 return false; | 610 return false; |
615 } | 611 } |
616 } | 612 } |
617 | 613 |
618 frame_processor_->OnPossibleAudioConfigUpdate(audio_config); | 614 frame_processor_->OnPossibleAudioConfigUpdate(audio_config); |
619 success &= audio_->UpdateAudioConfig(audio_config, log_cb_); | 615 success &= audio_->UpdateAudioConfig(audio_config, media_log_); |
620 } | 616 } |
621 | 617 |
622 if (video_config.IsValidConfig()) { | 618 if (video_config.IsValidConfig()) { |
623 if (!video_) { | 619 if (!video_) { |
624 media_log_->SetBooleanProperty("found_video_stream", true); | 620 media_log_->SetBooleanProperty("found_video_stream", true); |
625 } | 621 } |
626 if (!video_ || | 622 if (!video_ || |
627 video_->video_decoder_config().codec() != video_config.codec()) { | 623 video_->video_decoder_config().codec() != video_config.codec()) { |
628 media_log_->SetStringProperty("video_codec_name", | 624 media_log_->SetStringProperty("video_codec_name", |
629 video_config.GetHumanReadableCodecName()); | 625 video_config.GetHumanReadableCodecName()); |
630 } | 626 } |
631 | 627 |
632 if (!video_) { | 628 if (!video_) { |
633 video_ = create_demuxer_stream_cb_.Run(DemuxerStream::VIDEO); | 629 video_ = create_demuxer_stream_cb_.Run(DemuxerStream::VIDEO); |
634 | 630 |
635 if (!video_) { | 631 if (!video_) { |
636 DVLOG(1) << "Failed to create a video stream."; | 632 DVLOG(1) << "Failed to create a video stream."; |
637 return false; | 633 return false; |
638 } | 634 } |
639 | 635 |
640 if (!frame_processor_->AddTrack(FrameProcessor::kVideoTrackId, video_)) { | 636 if (!frame_processor_->AddTrack(FrameProcessor::kVideoTrackId, video_)) { |
641 DVLOG(1) << "Failed to add video track to frame processor."; | 637 DVLOG(1) << "Failed to add video track to frame processor."; |
642 return false; | 638 return false; |
643 } | 639 } |
644 } | 640 } |
645 | 641 |
646 success &= video_->UpdateVideoConfig(video_config, log_cb_); | 642 success &= video_->UpdateVideoConfig(video_config, media_log_); |
647 } | 643 } |
648 | 644 |
649 typedef StreamParser::TextTrackConfigMap::const_iterator TextConfigItr; | 645 typedef StreamParser::TextTrackConfigMap::const_iterator TextConfigItr; |
650 if (text_stream_map_.empty()) { | 646 if (text_stream_map_.empty()) { |
651 for (TextConfigItr itr = text_configs.begin(); | 647 for (TextConfigItr itr = text_configs.begin(); |
652 itr != text_configs.end(); ++itr) { | 648 itr != text_configs.end(); ++itr) { |
653 ChunkDemuxerStream* const text_stream = | 649 ChunkDemuxerStream* const text_stream = |
654 create_demuxer_stream_cb_.Run(DemuxerStream::TEXT); | 650 create_demuxer_stream_cb_.Run(DemuxerStream::TEXT); |
655 if (!frame_processor_->AddTrack(itr->first, text_stream)) { | 651 if (!frame_processor_->AddTrack(itr->first, text_stream)) { |
656 success &= false; | 652 success &= false; |
657 MEDIA_LOG(ERROR, log_cb_) << "Failed to add text track ID " | 653 MEDIA_LOG(ERROR, media_log_) << "Failed to add text track ID " |
658 << itr->first << " to frame processor."; | 654 << itr->first << " to frame processor."; |
659 break; | 655 break; |
660 } | 656 } |
661 text_stream->UpdateTextConfig(itr->second, log_cb_); | 657 text_stream->UpdateTextConfig(itr->second, media_log_); |
662 text_stream_map_[itr->first] = text_stream; | 658 text_stream_map_[itr->first] = text_stream; |
663 new_text_track_cb_.Run(text_stream, itr->second); | 659 new_text_track_cb_.Run(text_stream, itr->second); |
664 } | 660 } |
665 } else { | 661 } else { |
666 const size_t text_count = text_stream_map_.size(); | 662 const size_t text_count = text_stream_map_.size(); |
667 if (text_configs.size() != text_count) { | 663 if (text_configs.size() != text_count) { |
668 success &= false; | 664 success &= false; |
669 MEDIA_LOG(ERROR, log_cb_) << "The number of text track configs changed."; | 665 MEDIA_LOG(ERROR, media_log_) |
| 666 << "The number of text track configs changed."; |
670 } else if (text_count == 1) { | 667 } else if (text_count == 1) { |
671 TextConfigItr config_itr = text_configs.begin(); | 668 TextConfigItr config_itr = text_configs.begin(); |
672 TextStreamMap::iterator stream_itr = text_stream_map_.begin(); | 669 TextStreamMap::iterator stream_itr = text_stream_map_.begin(); |
673 ChunkDemuxerStream* text_stream = stream_itr->second; | 670 ChunkDemuxerStream* text_stream = stream_itr->second; |
674 TextTrackConfig old_config = text_stream->text_track_config(); | 671 TextTrackConfig old_config = text_stream->text_track_config(); |
675 TextTrackConfig new_config(config_itr->second.kind(), | 672 TextTrackConfig new_config(config_itr->second.kind(), |
676 config_itr->second.label(), | 673 config_itr->second.label(), |
677 config_itr->second.language(), | 674 config_itr->second.language(), |
678 old_config.id()); | 675 old_config.id()); |
679 if (!new_config.Matches(old_config)) { | 676 if (!new_config.Matches(old_config)) { |
680 success &= false; | 677 success &= false; |
681 MEDIA_LOG(ERROR, log_cb_) | 678 MEDIA_LOG(ERROR, media_log_) |
682 << "New text track config does not match old one."; | 679 << "New text track config does not match old one."; |
683 } else { | 680 } else { |
684 StreamParser::TrackId old_id = stream_itr->first; | 681 StreamParser::TrackId old_id = stream_itr->first; |
685 StreamParser::TrackId new_id = config_itr->first; | 682 StreamParser::TrackId new_id = config_itr->first; |
686 if (new_id != old_id) { | 683 if (new_id != old_id) { |
687 if (frame_processor_->UpdateTrack(old_id, new_id)) { | 684 if (frame_processor_->UpdateTrack(old_id, new_id)) { |
688 text_stream_map_.clear(); | 685 text_stream_map_.clear(); |
689 text_stream_map_[config_itr->first] = text_stream; | 686 text_stream_map_[config_itr->first] = text_stream; |
690 } else { | 687 } else { |
691 success &= false; | 688 success &= false; |
692 MEDIA_LOG(ERROR, log_cb_) | 689 MEDIA_LOG(ERROR, media_log_) |
693 << "Error remapping single text track number"; | 690 << "Error remapping single text track number"; |
694 } | 691 } |
695 } | 692 } |
696 } | 693 } |
697 } else { | 694 } else { |
698 for (TextConfigItr config_itr = text_configs.begin(); | 695 for (TextConfigItr config_itr = text_configs.begin(); |
699 config_itr != text_configs.end(); ++config_itr) { | 696 config_itr != text_configs.end(); ++config_itr) { |
700 TextStreamMap::iterator stream_itr = | 697 TextStreamMap::iterator stream_itr = |
701 text_stream_map_.find(config_itr->first); | 698 text_stream_map_.find(config_itr->first); |
702 if (stream_itr == text_stream_map_.end()) { | 699 if (stream_itr == text_stream_map_.end()) { |
703 success &= false; | 700 success &= false; |
704 MEDIA_LOG(ERROR, log_cb_) | 701 MEDIA_LOG(ERROR, media_log_) |
705 << "Unexpected text track configuration for track ID " | 702 << "Unexpected text track configuration for track ID " |
706 << config_itr->first; | 703 << config_itr->first; |
707 break; | 704 break; |
708 } | 705 } |
709 | 706 |
710 const TextTrackConfig& new_config = config_itr->second; | 707 const TextTrackConfig& new_config = config_itr->second; |
711 ChunkDemuxerStream* stream = stream_itr->second; | 708 ChunkDemuxerStream* stream = stream_itr->second; |
712 TextTrackConfig old_config = stream->text_track_config(); | 709 TextTrackConfig old_config = stream->text_track_config(); |
713 if (!new_config.Matches(old_config)) { | 710 if (!new_config.Matches(old_config)) { |
714 success &= false; | 711 success &= false; |
715 MEDIA_LOG(ERROR, log_cb_) << "New text track config for track ID " | 712 MEDIA_LOG(ERROR, media_log_) << "New text track config for track ID " |
716 << config_itr->first | 713 << config_itr->first |
717 << " does not match old one."; | 714 << " does not match old one."; |
718 break; | 715 break; |
719 } | 716 } |
720 } | 717 } |
721 } | 718 } |
722 } | 719 } |
723 | 720 |
724 frame_processor_->SetAllTrackBuffersNeedRandomAccessPoint(); | 721 frame_processor_->SetAllTrackBuffersNeedRandomAccessPoint(); |
725 | 722 |
726 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); | 723 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); |
727 if (success) | 724 if (success) |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
917 return stream_->GetBufferedDuration(); | 914 return stream_->GetBufferedDuration(); |
918 } | 915 } |
919 | 916 |
920 void ChunkDemuxerStream::OnNewMediaSegment(DecodeTimestamp start_timestamp) { | 917 void ChunkDemuxerStream::OnNewMediaSegment(DecodeTimestamp start_timestamp) { |
921 DVLOG(2) << "ChunkDemuxerStream::OnNewMediaSegment(" | 918 DVLOG(2) << "ChunkDemuxerStream::OnNewMediaSegment(" |
922 << start_timestamp.InSecondsF() << ")"; | 919 << start_timestamp.InSecondsF() << ")"; |
923 base::AutoLock auto_lock(lock_); | 920 base::AutoLock auto_lock(lock_); |
924 stream_->OnNewMediaSegment(start_timestamp); | 921 stream_->OnNewMediaSegment(start_timestamp); |
925 } | 922 } |
926 | 923 |
927 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config, | 924 bool ChunkDemuxerStream::UpdateAudioConfig( |
928 const LogCB& log_cb) { | 925 const AudioDecoderConfig& config, |
| 926 const scoped_refptr<MediaLog>& media_log) { |
929 DCHECK(config.IsValidConfig()); | 927 DCHECK(config.IsValidConfig()); |
930 DCHECK_EQ(type_, AUDIO); | 928 DCHECK_EQ(type_, AUDIO); |
931 base::AutoLock auto_lock(lock_); | 929 base::AutoLock auto_lock(lock_); |
932 if (!stream_) { | 930 if (!stream_) { |
933 DCHECK_EQ(state_, UNINITIALIZED); | 931 DCHECK_EQ(state_, UNINITIALIZED); |
934 | 932 |
935 // On platforms which support splice frames, enable splice frames and | 933 // On platforms which support splice frames, enable splice frames and |
936 // partial append window support for most codecs (notably: not opus). | 934 // partial append window support for most codecs (notably: not opus). |
937 const bool codec_supported = config.codec() == kCodecMP3 || | 935 const bool codec_supported = config.codec() == kCodecMP3 || |
938 config.codec() == kCodecAAC || | 936 config.codec() == kCodecAAC || |
939 config.codec() == kCodecVorbis; | 937 config.codec() == kCodecVorbis; |
940 splice_frames_enabled_ = splice_frames_enabled_ && codec_supported; | 938 splice_frames_enabled_ = splice_frames_enabled_ && codec_supported; |
941 partial_append_window_trimming_enabled_ = | 939 partial_append_window_trimming_enabled_ = |
942 splice_frames_enabled_ && codec_supported; | 940 splice_frames_enabled_ && codec_supported; |
943 | 941 |
944 stream_.reset( | 942 stream_.reset( |
945 new SourceBufferStream(config, log_cb, splice_frames_enabled_)); | 943 new SourceBufferStream(config, media_log, splice_frames_enabled_)); |
946 return true; | 944 return true; |
947 } | 945 } |
948 | 946 |
949 return stream_->UpdateAudioConfig(config); | 947 return stream_->UpdateAudioConfig(config); |
950 } | 948 } |
951 | 949 |
952 bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config, | 950 bool ChunkDemuxerStream::UpdateVideoConfig( |
953 const LogCB& log_cb) { | 951 const VideoDecoderConfig& config, |
| 952 const scoped_refptr<MediaLog>& media_log) { |
954 DCHECK(config.IsValidConfig()); | 953 DCHECK(config.IsValidConfig()); |
955 DCHECK_EQ(type_, VIDEO); | 954 DCHECK_EQ(type_, VIDEO); |
956 base::AutoLock auto_lock(lock_); | 955 base::AutoLock auto_lock(lock_); |
957 | 956 |
958 if (!stream_) { | 957 if (!stream_) { |
959 DCHECK_EQ(state_, UNINITIALIZED); | 958 DCHECK_EQ(state_, UNINITIALIZED); |
960 stream_.reset( | 959 stream_.reset( |
961 new SourceBufferStream(config, log_cb, splice_frames_enabled_)); | 960 new SourceBufferStream(config, media_log, splice_frames_enabled_)); |
962 return true; | 961 return true; |
963 } | 962 } |
964 | 963 |
965 return stream_->UpdateVideoConfig(config); | 964 return stream_->UpdateVideoConfig(config); |
966 } | 965 } |
967 | 966 |
968 void ChunkDemuxerStream::UpdateTextConfig(const TextTrackConfig& config, | 967 void ChunkDemuxerStream::UpdateTextConfig( |
969 const LogCB& log_cb) { | 968 const TextTrackConfig& config, |
| 969 const scoped_refptr<MediaLog>& media_log) { |
970 DCHECK_EQ(type_, TEXT); | 970 DCHECK_EQ(type_, TEXT); |
971 base::AutoLock auto_lock(lock_); | 971 base::AutoLock auto_lock(lock_); |
972 DCHECK(!stream_); | 972 DCHECK(!stream_); |
973 DCHECK_EQ(state_, UNINITIALIZED); | 973 DCHECK_EQ(state_, UNINITIALIZED); |
974 stream_.reset(new SourceBufferStream(config, log_cb, splice_frames_enabled_)); | 974 stream_.reset( |
| 975 new SourceBufferStream(config, media_log, splice_frames_enabled_)); |
975 } | 976 } |
976 | 977 |
977 void ChunkDemuxerStream::MarkEndOfStream() { | 978 void ChunkDemuxerStream::MarkEndOfStream() { |
978 base::AutoLock auto_lock(lock_); | 979 base::AutoLock auto_lock(lock_); |
979 stream_->MarkEndOfStream(); | 980 stream_->MarkEndOfStream(); |
980 } | 981 } |
981 | 982 |
982 void ChunkDemuxerStream::UnmarkEndOfStream() { | 983 void ChunkDemuxerStream::UnmarkEndOfStream() { |
983 base::AutoLock auto_lock(lock_); | 984 base::AutoLock auto_lock(lock_); |
984 stream_->UnmarkEndOfStream(); | 985 stream_->UnmarkEndOfStream(); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 << type_; | 1097 << type_; |
1097 break; | 1098 break; |
1098 } | 1099 } |
1099 | 1100 |
1100 base::ResetAndReturn(&read_cb_).Run(status, buffer); | 1101 base::ResetAndReturn(&read_cb_).Run(status, buffer); |
1101 } | 1102 } |
1102 | 1103 |
1103 ChunkDemuxer::ChunkDemuxer( | 1104 ChunkDemuxer::ChunkDemuxer( |
1104 const base::Closure& open_cb, | 1105 const base::Closure& open_cb, |
1105 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, | 1106 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, |
1106 const LogCB& log_cb, | |
1107 const scoped_refptr<MediaLog>& media_log, | 1107 const scoped_refptr<MediaLog>& media_log, |
1108 bool splice_frames_enabled) | 1108 bool splice_frames_enabled) |
1109 : state_(WAITING_FOR_INIT), | 1109 : state_(WAITING_FOR_INIT), |
1110 cancel_next_seek_(false), | 1110 cancel_next_seek_(false), |
1111 host_(NULL), | 1111 host_(NULL), |
1112 open_cb_(open_cb), | 1112 open_cb_(open_cb), |
1113 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), | 1113 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), |
1114 enable_text_(false), | 1114 enable_text_(false), |
1115 log_cb_(log_cb), | |
1116 media_log_(media_log), | 1115 media_log_(media_log), |
1117 duration_(kNoTimestamp()), | 1116 duration_(kNoTimestamp()), |
1118 user_specified_duration_(-1), | 1117 user_specified_duration_(-1), |
1119 liveness_(DemuxerStream::LIVENESS_UNKNOWN), | 1118 liveness_(DemuxerStream::LIVENESS_UNKNOWN), |
1120 splice_frames_enabled_(splice_frames_enabled) { | 1119 splice_frames_enabled_(splice_frames_enabled) { |
1121 DCHECK(!open_cb_.is_null()); | 1120 DCHECK(!open_cb_.is_null()); |
1122 DCHECK(!encrypted_media_init_data_cb_.is_null()); | 1121 DCHECK(!encrypted_media_init_data_cb_.is_null()); |
1123 } | 1122 } |
1124 | 1123 |
1125 std::string ChunkDemuxer::GetDisplayName() const { | 1124 std::string ChunkDemuxer::GetDisplayName() const { |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1245 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, | 1244 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, |
1246 const std::string& type, | 1245 const std::string& type, |
1247 std::vector<std::string>& codecs) { | 1246 std::vector<std::string>& codecs) { |
1248 base::AutoLock auto_lock(lock_); | 1247 base::AutoLock auto_lock(lock_); |
1249 | 1248 |
1250 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id)) | 1249 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id)) |
1251 return kReachedIdLimit; | 1250 return kReachedIdLimit; |
1252 | 1251 |
1253 bool has_audio = false; | 1252 bool has_audio = false; |
1254 bool has_video = false; | 1253 bool has_video = false; |
1255 scoped_ptr<media::StreamParser> stream_parser( | 1254 scoped_ptr<media::StreamParser> stream_parser(StreamParserFactory::Create( |
1256 StreamParserFactory::Create(type, codecs, log_cb_, | 1255 type, codecs, media_log_, &has_audio, &has_video)); |
1257 &has_audio, &has_video)); | |
1258 | 1256 |
1259 if (!stream_parser) | 1257 if (!stream_parser) |
1260 return ChunkDemuxer::kNotSupported; | 1258 return ChunkDemuxer::kNotSupported; |
1261 | 1259 |
1262 if ((has_audio && !source_id_audio_.empty()) || | 1260 if ((has_audio && !source_id_audio_.empty()) || |
1263 (has_video && !source_id_video_.empty())) | 1261 (has_video && !source_id_video_.empty())) |
1264 return kReachedIdLimit; | 1262 return kReachedIdLimit; |
1265 | 1263 |
1266 if (has_audio) | 1264 if (has_audio) |
1267 source_id_audio_ = id; | 1265 source_id_audio_ = id; |
1268 | 1266 |
1269 if (has_video) | 1267 if (has_video) |
1270 source_id_video_ = id; | 1268 source_id_video_ = id; |
1271 | 1269 |
1272 scoped_ptr<FrameProcessor> frame_processor( | 1270 scoped_ptr<FrameProcessor> frame_processor( |
1273 new FrameProcessor(base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary, | 1271 new FrameProcessor(base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary, |
1274 base::Unretained(this)))); | 1272 base::Unretained(this)))); |
1275 | 1273 |
1276 scoped_ptr<SourceState> source_state( | 1274 scoped_ptr<SourceState> source_state(new SourceState( |
1277 new SourceState(stream_parser.Pass(), | 1275 stream_parser.Pass(), frame_processor.Pass(), |
1278 frame_processor.Pass(), log_cb_, | 1276 base::Bind(&ChunkDemuxer::CreateDemuxerStream, base::Unretained(this)), |
1279 base::Bind(&ChunkDemuxer::CreateDemuxerStream, | 1277 media_log_)); |
1280 base::Unretained(this)), | |
1281 media_log_)); | |
1282 | 1278 |
1283 SourceState::NewTextTrackCB new_text_track_cb; | 1279 SourceState::NewTextTrackCB new_text_track_cb; |
1284 | 1280 |
1285 if (enable_text_) { | 1281 if (enable_text_) { |
1286 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack, | 1282 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack, |
1287 base::Unretained(this)); | 1283 base::Unretained(this)); |
1288 } | 1284 } |
1289 | 1285 |
1290 source_state->Init( | 1286 source_state->Init( |
1291 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)), | 1287 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)), |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1654 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 1650 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
1655 return; | 1651 return; |
1656 } | 1652 } |
1657 | 1653 |
1658 if (params.duration != TimeDelta() && duration_ == kNoTimestamp()) | 1654 if (params.duration != TimeDelta() && duration_ == kNoTimestamp()) |
1659 UpdateDuration(params.duration); | 1655 UpdateDuration(params.duration); |
1660 | 1656 |
1661 if (!params.timeline_offset.is_null()) { | 1657 if (!params.timeline_offset.is_null()) { |
1662 if (!timeline_offset_.is_null() && | 1658 if (!timeline_offset_.is_null() && |
1663 params.timeline_offset != timeline_offset_) { | 1659 params.timeline_offset != timeline_offset_) { |
1664 MEDIA_LOG(ERROR, log_cb_) | 1660 MEDIA_LOG(ERROR, media_log_) |
1665 << "Timeline offset is not the same across all SourceBuffers."; | 1661 << "Timeline offset is not the same across all SourceBuffers."; |
1666 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 1662 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
1667 return; | 1663 return; |
1668 } | 1664 } |
1669 | 1665 |
1670 timeline_offset_ = params.timeline_offset; | 1666 timeline_offset_ = params.timeline_offset; |
1671 } | 1667 } |
1672 | 1668 |
1673 if (params.liveness != DemuxerStream::LIVENESS_UNKNOWN) { | 1669 if (params.liveness != DemuxerStream::LIVENESS_UNKNOWN) { |
1674 if (audio_) | 1670 if (audio_) |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1831 } | 1827 } |
1832 | 1828 |
1833 void ChunkDemuxer::ShutdownAllStreams() { | 1829 void ChunkDemuxer::ShutdownAllStreams() { |
1834 for (SourceStateMap::iterator itr = source_state_map_.begin(); | 1830 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1835 itr != source_state_map_.end(); ++itr) { | 1831 itr != source_state_map_.end(); ++itr) { |
1836 itr->second->Shutdown(); | 1832 itr->second->Shutdown(); |
1837 } | 1833 } |
1838 } | 1834 } |
1839 | 1835 |
1840 } // namespace media | 1836 } // namespace media |
OLD | NEW |