Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(374)

Side by Side Diff: media/filters/chunk_demuxer.cc

Issue 2226443002: Support multiple media tracks in MSE / ChunkDemuxer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Replace pending_source_init_done_count_ with pending_source_init_ids_ set Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
10 #include <utility> 9 #include <utility>
11 10
12 #include "base/bind.h" 11 #include "base/bind.h"
13 #include "base/callback_helpers.h" 12 #include "base/callback_helpers.h"
14 #include "base/location.h" 13 #include "base/location.h"
15 #include "base/macros.h" 14 #include "base/macros.h"
16 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.h"
17 #include "base/stl_util.h" 16 #include "base/stl_util.h"
18 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
19 #include "media/base/audio_decoder_config.h" 18 #include "media/base/audio_decoder_config.h"
20 #include "media/base/bind_to_current_loop.h" 19 #include "media/base/bind_to_current_loop.h"
21 #include "media/base/media_tracks.h" 20 #include "media/base/media_tracks.h"
21 #include "media/base/mime_util.h"
22 #include "media/base/stream_parser_buffer.h" 22 #include "media/base/stream_parser_buffer.h"
23 #include "media/base/timestamp_constants.h" 23 #include "media/base/timestamp_constants.h"
24 #include "media/base/video_codecs.h" 24 #include "media/base/video_codecs.h"
25 #include "media/base/video_decoder_config.h" 25 #include "media/base/video_decoder_config.h"
26 #include "media/filters/frame_processor.h" 26 #include "media/filters/frame_processor.h"
27 #include "media/filters/stream_parser_factory.h" 27 #include "media/filters/stream_parser_factory.h"
28 28
29 using base::TimeDelta; 29 using base::TimeDelta;
30 30
31 namespace media { 31 namespace media {
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, 402 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
403 const scoped_refptr<MediaLog>& media_log, 403 const scoped_refptr<MediaLog>& media_log,
404 bool splice_frames_enabled) 404 bool splice_frames_enabled)
405 : state_(WAITING_FOR_INIT), 405 : state_(WAITING_FOR_INIT),
406 cancel_next_seek_(false), 406 cancel_next_seek_(false),
407 host_(NULL), 407 host_(NULL),
408 open_cb_(open_cb), 408 open_cb_(open_cb),
409 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), 409 encrypted_media_init_data_cb_(encrypted_media_init_data_cb),
410 enable_text_(false), 410 enable_text_(false),
411 media_log_(media_log), 411 media_log_(media_log),
412 pending_source_init_done_count_(0),
413 duration_(kNoTimestamp), 412 duration_(kNoTimestamp),
414 user_specified_duration_(-1), 413 user_specified_duration_(-1),
415 liveness_(DemuxerStream::LIVENESS_UNKNOWN), 414 liveness_(DemuxerStream::LIVENESS_UNKNOWN),
416 splice_frames_enabled_(splice_frames_enabled), 415 splice_frames_enabled_(splice_frames_enabled),
417 detected_audio_track_count_(0), 416 detected_audio_track_count_(0),
418 detected_video_track_count_(0), 417 detected_video_track_count_(0),
419 detected_text_track_count_(0) { 418 detected_text_track_count_(0) {
420 DCHECK(!open_cb_.is_null()); 419 DCHECK(!open_cb_.is_null());
421 DCHECK(!encrypted_media_init_data_cb_.is_null()); 420 DCHECK(!encrypted_media_init_data_cb_.is_null());
422 } 421 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 } 483 }
485 484
486 // Demuxer implementation. 485 // Demuxer implementation.
487 base::Time ChunkDemuxer::GetTimelineOffset() const { 486 base::Time ChunkDemuxer::GetTimelineOffset() const {
488 return timeline_offset_; 487 return timeline_offset_;
489 } 488 }
490 489
491 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) { 490 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) {
492 DCHECK_NE(type, DemuxerStream::TEXT); 491 DCHECK_NE(type, DemuxerStream::TEXT);
493 base::AutoLock auto_lock(lock_); 492 base::AutoLock auto_lock(lock_);
494 if (type == DemuxerStream::VIDEO)
495 return video_.get();
496 493
497 if (type == DemuxerStream::AUDIO) 494 if (type == DemuxerStream::AUDIO)
498 return audio_.get(); 495 for (const auto& s : audio_streams_)
496 if (s->enabled())
497 return s.get();
498
499 if (type == DemuxerStream::VIDEO)
500 for (const auto& s : video_streams_)
501 if (s->enabled())
502 return s.get();
499 503
500 return NULL; 504 return NULL;
501 } 505 }
502 506
503 TimeDelta ChunkDemuxer::GetStartTime() const { 507 TimeDelta ChunkDemuxer::GetStartTime() const {
504 return TimeDelta(); 508 return TimeDelta();
505 } 509 }
506 510
507 int64_t ChunkDemuxer::GetMemoryUsage() const { 511 int64_t ChunkDemuxer::GetMemoryUsage() const {
508 base::AutoLock auto_lock(lock_); 512 base::AutoLock auto_lock(lock_);
509 return (audio_ ? audio_->GetBufferedSize() : 0) + 513 int64_t mem = 0;
510 (video_ ? video_->GetBufferedSize() : 0); 514 for (const auto& s : audio_streams_)
515 mem += s->GetBufferedSize();
516 for (const auto& s : video_streams_)
517 mem += s->GetBufferedSize();
518 return mem;
511 } 519 }
512 520
513 void ChunkDemuxer::AbortPendingReads() { 521 void ChunkDemuxer::AbortPendingReads() {
514 base::AutoLock auto_lock(lock_); 522 base::AutoLock auto_lock(lock_);
515 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN || 523 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN ||
516 state_ == PARSE_ERROR) 524 state_ == PARSE_ERROR)
517 << state_; 525 << state_;
518 526
519 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) 527 if (state_ == SHUTDOWN || state_ == PARSE_ERROR)
520 return; 528 return;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 if (seek_cb_.is_null()) { 562 if (seek_cb_.is_null()) {
555 cancel_next_seek_ = true; 563 cancel_next_seek_ = true;
556 return; 564 return;
557 } 565 }
558 566
559 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); 567 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
560 } 568 }
561 569
562 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, 570 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
563 const std::string& type, 571 const std::string& type,
564 std::vector<std::string>& codecs) { 572 const std::string& codecs) {
573 DVLOG(1) << __func__ << " id=" << id << " mime_type=" << type
574 << " codecs=" << codecs;
565 base::AutoLock auto_lock(lock_); 575 base::AutoLock auto_lock(lock_);
566 576
567 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id)) 577 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id))
568 return kReachedIdLimit; 578 return kReachedIdLimit;
569 579
570 bool has_audio = false; 580 std::vector<std::string> parsed_codec_ids;
571 bool has_video = false; 581 media::ParseCodecString(codecs, &parsed_codec_ids, false);
582
572 std::unique_ptr<media::StreamParser> stream_parser( 583 std::unique_ptr<media::StreamParser> stream_parser(
573 StreamParserFactory::Create(type, codecs, media_log_, &has_audio, 584 StreamParserFactory::Create(type, parsed_codec_ids, media_log_));
574 &has_video));
575 585
576 if (!stream_parser) 586 if (!stream_parser)
577 return ChunkDemuxer::kNotSupported; 587 return ChunkDemuxer::kNotSupported;
578 588
579 if ((has_audio && !source_id_audio_.empty()) ||
580 (has_video && !source_id_video_.empty()))
581 return kReachedIdLimit;
582
583 if (has_audio)
584 source_id_audio_ = id;
585
586 if (has_video)
587 source_id_video_ = id;
588
589 std::unique_ptr<FrameProcessor> frame_processor( 589 std::unique_ptr<FrameProcessor> frame_processor(
590 new FrameProcessor(base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary, 590 new FrameProcessor(base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary,
591 base::Unretained(this)), 591 base::Unretained(this)),
592 media_log_)); 592 media_log_));
593 593
594 std::unique_ptr<MediaSourceState> source_state(new MediaSourceState( 594 std::unique_ptr<MediaSourceState> source_state(new MediaSourceState(
595 std::move(stream_parser), std::move(frame_processor), 595 std::move(stream_parser), std::move(frame_processor),
596 base::Bind(&ChunkDemuxer::CreateDemuxerStream, base::Unretained(this)), 596 base::Bind(&ChunkDemuxer::CreateDemuxerStream, base::Unretained(this)),
597 media_log_)); 597 media_log_));
598 598
599 MediaSourceState::NewTextTrackCB new_text_track_cb; 599 MediaSourceState::NewTextTrackCB new_text_track_cb;
600 600
601 if (enable_text_) { 601 if (enable_text_) {
602 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack, 602 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack,
603 base::Unretained(this)); 603 base::Unretained(this));
604 } 604 }
605 605
606 pending_source_init_done_count_++; 606 pending_source_init_ids_.insert(id);
607
608 std::string expected_mss_codecs = codecs;
609 if (codecs == "" && type == "audio/aac")
610 expected_mss_codecs = "aac";
611 if (codecs == "" && (type == "audio/mpeg" || type == "audio/mp3"))
612 expected_mss_codecs = "mp3";
607 613
608 source_state->Init( 614 source_state->Init(
609 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)), 615 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this), id),
610 has_audio, has_video, encrypted_media_init_data_cb_, new_text_track_cb); 616 expected_mss_codecs, encrypted_media_init_data_cb_, new_text_track_cb);
611 617
612 source_state_map_[id] = source_state.release(); 618 source_state_map_[id] = source_state.release();
613 return kOk; 619 return kOk;
614 } 620 }
615 621
616 void ChunkDemuxer::SetTracksWatcher( 622 void ChunkDemuxer::SetTracksWatcher(
617 const std::string& id, 623 const std::string& id,
618 const MediaTracksUpdatedCB& tracks_updated_cb) { 624 const MediaTracksUpdatedCB& tracks_updated_cb) {
619 base::AutoLock auto_lock(lock_); 625 base::AutoLock auto_lock(lock_);
620 CHECK(IsValidId(id)); 626 CHECK(IsValidId(id));
621 source_state_map_[id]->SetTracksWatcher(tracks_updated_cb); 627 source_state_map_[id]->SetTracksWatcher(tracks_updated_cb);
622 } 628 }
623 629
624 void ChunkDemuxer::RemoveId(const std::string& id) { 630 void ChunkDemuxer::RemoveId(const std::string& id) {
wolenetz 2016/09/12 21:41:06 Another (possibly pre-existing) issue : addId(x wi
servolk 2016/09/13 02:09:30 Indeed, this is another pre-existing issue. We cou
servolk 2016/09/13 17:14:48 Well, this has caused a few more test failures in
625 base::AutoLock auto_lock(lock_); 631 base::AutoLock auto_lock(lock_);
626 CHECK(IsValidId(id)); 632 CHECK(IsValidId(id));
627 633
628 delete source_state_map_[id]; 634 delete source_state_map_[id];
629 source_state_map_.erase(id); 635 source_state_map_.erase(id);
630 636 pending_source_init_ids_.erase(id);
631 if (source_id_audio_ == id)
632 source_id_audio_.clear();
633
634 if (source_id_video_ == id)
635 source_id_video_.clear();
636 } 637 }
637 638
638 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const { 639 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const {
639 base::AutoLock auto_lock(lock_); 640 base::AutoLock auto_lock(lock_);
640 DCHECK(!id.empty()); 641 DCHECK(!id.empty());
641 642
642 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id); 643 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id);
643 644
644 DCHECK(itr != source_state_map_.end()); 645 DCHECK(itr != source_state_map_.end());
645 return itr->second->GetBufferedRanges(duration_, state_ == ENDED); 646 return itr->second->GetBufferedRanges(duration_, state_ == ENDED);
646 } 647 }
647 648
648 base::TimeDelta ChunkDemuxer::GetHighestPresentationTimestamp( 649 base::TimeDelta ChunkDemuxer::GetHighestPresentationTimestamp(
649 const std::string& id) const { 650 const std::string& id) const {
650 base::AutoLock auto_lock(lock_); 651 base::AutoLock auto_lock(lock_);
651 DCHECK(!id.empty()); 652 DCHECK(!id.empty());
652 653
653 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id); 654 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id);
654 655
655 DCHECK(itr != source_state_map_.end()); 656 DCHECK(itr != source_state_map_.end());
656 return itr->second->GetHighestPresentationTimestamp(); 657 return itr->second->GetHighestPresentationTimestamp();
657 } 658 }
658 659
659 void ChunkDemuxer::OnEnabledAudioTracksChanged( 660 void ChunkDemuxer::OnEnabledAudioTracksChanged(
660 const std::vector<MediaTrack::Id>& track_ids, 661 const std::vector<MediaTrack::Id>& track_ids,
661 base::TimeDelta currTime) { 662 base::TimeDelta currTime) {
662 // Note: We intentionally don't lock here, since we are not accessing any 663 base::AutoLock auto_lock(lock_);
663 // members directly. 664 std::set<DemuxerStream*> enabled_streams;
664 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO); 665 for (const auto& id : track_ids) {
665 bool enabled = false; 666 DemuxerStream* stream = track_id_to_demux_stream_map_[id];
666 CHECK(audio_stream); 667 DCHECK(stream);
667 DCHECK_LE(track_ids.size(), 1u); 668 DCHECK_EQ(DemuxerStream::AUDIO, stream->type());
668 if (track_ids.size() > 0) { 669 enabled_streams.insert(stream);
669 #if DCHECK_IS_ON()
670 base::AutoLock auto_lock(lock_);
671 DCHECK(track_id_to_demux_stream_map_[track_ids[0]] == audio_stream);
672 #endif
673 enabled = true;
674 } 670 }
675 DVLOG(1) << __func__ << ": " << (enabled ? "enabling" : "disabling") 671
676 << " audio stream"; 672 // First disable all streams that need to be disabled and then enable streams
677 audio_stream->set_enabled(enabled, currTime); 673 // that are enabled.
674 for (const auto& stream : audio_streams_) {
675 if (enabled_streams.find(stream.get()) == enabled_streams.end()) {
676 DVLOG(1) << __func__ << ": disabling stream " << stream.get();
677 stream->set_enabled(false, currTime);
678 }
679 }
680 for (const auto& stream : enabled_streams) {
681 DVLOG(1) << __func__ << ": enabling stream " << stream;
682 stream->set_enabled(true, currTime);
683 }
678 } 684 }
679 685
680 void ChunkDemuxer::OnSelectedVideoTrackChanged( 686 void ChunkDemuxer::OnSelectedVideoTrackChanged(
681 const std::vector<MediaTrack::Id>& track_ids, 687 const std::vector<MediaTrack::Id>& track_ids,
682 base::TimeDelta currTime) { 688 base::TimeDelta currTime) {
683 // Note: We intentionally don't lock here, since we are not accessing any
684 // members directly.
685 DemuxerStream* video_stream = GetStream(DemuxerStream::VIDEO);
686 bool enabled = false;
687 CHECK(video_stream);
688 DCHECK_LE(track_ids.size(), 1u); 689 DCHECK_LE(track_ids.size(), 1u);
689 if (track_ids.size() > 0) { 690
690 #if DCHECK_IS_ON() 691 base::AutoLock auto_lock(lock_);
691 base::AutoLock auto_lock(lock_); 692 DemuxerStream* selected_stream = nullptr;
692 DCHECK(track_id_to_demux_stream_map_[track_ids[0]] == video_stream); 693 if (!track_ids.empty()) {
693 #endif 694 selected_stream = track_id_to_demux_stream_map_[track_ids[0]];
694 enabled = true; 695 DCHECK(selected_stream);
696 DCHECK_EQ(DemuxerStream::VIDEO, selected_stream->type());
695 } 697 }
696 DVLOG(1) << __func__ << ": " << (enabled ? "enabling" : "disabling") 698
697 << " video stream"; 699 // First disable all streams that need to be disabled and then enable the
698 video_stream->set_enabled(enabled, currTime); 700 // stream that needs to be enabled (if any).
701 for (const auto& stream : video_streams_) {
702 if (stream->type() == DemuxerStream::VIDEO &&
703 stream.get() != selected_stream) {
704 DVLOG(1) << __func__ << ": disabling stream " << stream.get();
705 stream->set_enabled(false, currTime);
706 }
707 }
708 if (selected_stream) {
709 DVLOG(1) << __func__ << ": enabling stream " << selected_stream;
710 selected_stream->set_enabled(true, currTime);
711 }
699 } 712 }
700 713
701 bool ChunkDemuxer::EvictCodedFrames(const std::string& id, 714 bool ChunkDemuxer::EvictCodedFrames(const std::string& id,
702 base::TimeDelta currentMediaTime, 715 base::TimeDelta currentMediaTime,
703 size_t newDataSize) { 716 size_t newDataSize) {
704 DVLOG(1) << __func__ << "(" << id << ")" 717 DVLOG(1) << __func__ << "(" << id << ")"
705 << " media_time=" << currentMediaTime.InSecondsF() 718 << " media_time=" << currentMediaTime.InSecondsF()
706 << " newDataSize=" << newDataSize; 719 << " newDataSize=" << newDataSize;
707 base::AutoLock auto_lock(lock_); 720 base::AutoLock auto_lock(lock_);
708 721
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
1038 for (MediaSourceStateMap::const_iterator itr = source_state_map_.begin(); 1051 for (MediaSourceStateMap::const_iterator itr = source_state_map_.begin();
1039 itr != source_state_map_.end(); ++itr) { 1052 itr != source_state_map_.end(); ++itr) {
1040 if (itr->second->IsSeekWaitingForData()) 1053 if (itr->second->IsSeekWaitingForData())
1041 return true; 1054 return true;
1042 } 1055 }
1043 1056
1044 return false; 1057 return false;
1045 } 1058 }
1046 1059
1047 void ChunkDemuxer::OnSourceInitDone( 1060 void ChunkDemuxer::OnSourceInitDone(
1061 const std::string& source_id,
1048 const StreamParser::InitParameters& params) { 1062 const StreamParser::InitParameters& params) {
1049 DVLOG(1) << "OnSourceInitDone(" << params.duration.InSecondsF() << ")"; 1063 DVLOG(1) << "OnSourceInitDone source_id=" << source_id
1064 << " duration=" << params.duration.InSecondsF();
1050 lock_.AssertAcquired(); 1065 lock_.AssertAcquired();
1051 DCHECK_EQ(state_, INITIALIZING); 1066 DCHECK_EQ(state_, INITIALIZING);
wolenetz 2016/09/12 21:41:06 nit: also DCHECK that source_id is in pending_sour
servolk 2016/09/13 02:09:30 Done.
1052 if (!audio_ && !video_) { 1067 if (audio_streams_.empty() && video_streams_.empty()) {
1053 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 1068 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
1054 return; 1069 return;
1055 } 1070 }
1056 1071
1057 if (!params.duration.is_zero() && duration_ == kNoTimestamp) 1072 if (!params.duration.is_zero() && duration_ == kNoTimestamp)
1058 UpdateDuration(params.duration); 1073 UpdateDuration(params.duration);
1059 1074
1060 if (!params.timeline_offset.is_null()) { 1075 if (!params.timeline_offset.is_null()) {
1061 if (!timeline_offset_.is_null() && 1076 if (!timeline_offset_.is_null() &&
1062 params.timeline_offset != timeline_offset_) { 1077 params.timeline_offset != timeline_offset_) {
1063 MEDIA_LOG(ERROR, media_log_) 1078 MEDIA_LOG(ERROR, media_log_)
1064 << "Timeline offset is not the same across all SourceBuffers."; 1079 << "Timeline offset is not the same across all SourceBuffers.";
1065 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 1080 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
1066 return; 1081 return;
1067 } 1082 }
1068 1083
1069 timeline_offset_ = params.timeline_offset; 1084 timeline_offset_ = params.timeline_offset;
1070 } 1085 }
1071 1086
1072 if (params.liveness != DemuxerStream::LIVENESS_UNKNOWN) { 1087 if (params.liveness != DemuxerStream::LIVENESS_UNKNOWN) {
1073 if (audio_) 1088 for (const auto& s : audio_streams_)
1074 audio_->SetLiveness(params.liveness); 1089 s->SetLiveness(params.liveness);
1075 if (video_) 1090 for (const auto& s : video_streams_)
1076 video_->SetLiveness(params.liveness); 1091 s->SetLiveness(params.liveness);
1077 } 1092 }
1078 1093
1079 detected_audio_track_count_ += params.detected_audio_track_count; 1094 detected_audio_track_count_ += params.detected_audio_track_count;
1080 detected_video_track_count_ += params.detected_video_track_count; 1095 detected_video_track_count_ += params.detected_video_track_count;
1081 detected_text_track_count_ += params.detected_text_track_count; 1096 detected_text_track_count_ += params.detected_text_track_count;
1082 1097
1083 // Wait until all streams have initialized. 1098 // Wait until all streams have initialized.
1084 pending_source_init_done_count_--; 1099 pending_source_init_ids_.erase(source_id);
1085 1100 if (!pending_source_init_ids_.empty())
1086 if (pending_source_init_done_count_ > 0)
1087 return; 1101 return;
1088 1102
1089 DCHECK_EQ(0, pending_source_init_done_count_);
1090 DCHECK((source_id_audio_.empty() == !audio_) &&
1091 (source_id_video_.empty() == !video_));
1092
1093 // Record detected track counts by type corresponding to an MSE playback. 1103 // Record detected track counts by type corresponding to an MSE playback.
1094 // Counts are split into 50 buckets, capped into [0,100] range. 1104 // Counts are split into 50 buckets, capped into [0,100] range.
1095 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Audio", 1105 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Audio",
1096 detected_audio_track_count_); 1106 detected_audio_track_count_);
1097 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Video", 1107 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Video",
1098 detected_video_track_count_); 1108 detected_video_track_count_);
1099 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Text", 1109 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Text",
1100 detected_text_track_count_); 1110 detected_text_track_count_);
1101 1111
1102 if (video_) { 1112 for (const auto& s : video_streams_) {
1103 media_log_->RecordRapporWithSecurityOrigin( 1113 media_log_->RecordRapporWithSecurityOrigin(
1104 "Media.OriginUrl.MSE.VideoCodec." + 1114 "Media.OriginUrl.MSE.VideoCodec." +
1105 GetCodecName(video_->video_decoder_config().codec())); 1115 GetCodecName(s->video_decoder_config().codec()));
1106 } 1116 }
1107 1117
1108 SeekAllSources(GetStartTime()); 1118 SeekAllSources(GetStartTime());
1109 StartReturningData(); 1119 StartReturningData();
1110 1120
1111 if (duration_ == kNoTimestamp) 1121 if (duration_ == kNoTimestamp)
1112 duration_ = kInfiniteDuration; 1122 duration_ = kInfiniteDuration;
1113 1123
1114 // The demuxer is now initialized after the |start_timestamp_| was set. 1124 // The demuxer is now initialized after the |start_timestamp_| was set.
1115 ChangeState_Locked(INITIALIZED); 1125 ChangeState_Locked(INITIALIZED);
1116 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 1126 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
1117 } 1127 }
1118 1128
1119 // static 1129 // static
1120 MediaTrack::Id ChunkDemuxer::GenerateMediaTrackId() { 1130 MediaTrack::Id ChunkDemuxer::GenerateMediaTrackId() {
1121 static unsigned g_track_count = 0; 1131 static unsigned g_track_count = 0;
1122 return base::UintToString(++g_track_count); 1132 return base::UintToString(++g_track_count);
1123 } 1133 }
1124 1134
1125 ChunkDemuxerStream* ChunkDemuxer::CreateDemuxerStream( 1135 ChunkDemuxerStream* ChunkDemuxer::CreateDemuxerStream(
1126 DemuxerStream::Type type) { 1136 DemuxerStream::Type type) {
1127 // New ChunkDemuxerStreams can be created only during initialization segment 1137 // New ChunkDemuxerStreams can be created only during initialization segment
1128 // processing, which happens when a new chunk of data is appended and the 1138 // processing, which happens when a new chunk of data is appended and the
1129 // lock_ must be held by ChunkDemuxer::AppendData. 1139 // lock_ must be held by ChunkDemuxer::AppendData.
1130 lock_.AssertAcquired(); 1140 lock_.AssertAcquired();
1131 1141
1132 MediaTrack::Id media_track_id = GenerateMediaTrackId(); 1142 MediaTrack::Id media_track_id = GenerateMediaTrackId();
1133 1143
1134 switch (type) { 1144 switch (type) {
1135 case DemuxerStream::AUDIO: 1145 case DemuxerStream::AUDIO: {
1136 if (audio_) 1146 std::unique_ptr<ChunkDemuxerStream> audio_stream(new ChunkDemuxerStream(
1137 return NULL;
1138 audio_.reset(new ChunkDemuxerStream(
1139 DemuxerStream::AUDIO, splice_frames_enabled_, media_track_id)); 1147 DemuxerStream::AUDIO, splice_frames_enabled_, media_track_id));
1140 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) == 1148 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) ==
1141 track_id_to_demux_stream_map_.end()); 1149 track_id_to_demux_stream_map_.end());
1142 track_id_to_demux_stream_map_[media_track_id] = audio_.get(); 1150 track_id_to_demux_stream_map_[media_track_id] = audio_stream.get();
1143 return audio_.get(); 1151 audio_streams_.push_back(std::move(audio_stream));
1144 break; 1152 return audio_streams_.back().get();
1145 case DemuxerStream::VIDEO: 1153 }
1146 if (video_) 1154 case DemuxerStream::VIDEO: {
1147 return NULL; 1155 std::unique_ptr<ChunkDemuxerStream> video_stream(new ChunkDemuxerStream(
1148 video_.reset(new ChunkDemuxerStream(
1149 DemuxerStream::VIDEO, splice_frames_enabled_, media_track_id)); 1156 DemuxerStream::VIDEO, splice_frames_enabled_, media_track_id));
1150 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) == 1157 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) ==
1151 track_id_to_demux_stream_map_.end()); 1158 track_id_to_demux_stream_map_.end());
1152 track_id_to_demux_stream_map_[media_track_id] = video_.get(); 1159 track_id_to_demux_stream_map_[media_track_id] = video_stream.get();
1153 return video_.get(); 1160 video_streams_.push_back(std::move(video_stream));
1154 break; 1161 return video_streams_.back().get();
1155 case DemuxerStream::TEXT: { 1162 }
1163 case DemuxerStream::TEXT:
1156 return new ChunkDemuxerStream(DemuxerStream::TEXT, splice_frames_enabled_, 1164 return new ChunkDemuxerStream(DemuxerStream::TEXT, splice_frames_enabled_,
1157 media_track_id); 1165 media_track_id);
1158 break;
1159 }
1160 case DemuxerStream::UNKNOWN: 1166 case DemuxerStream::UNKNOWN:
1161 case DemuxerStream::NUM_TYPES: 1167 case DemuxerStream::NUM_TYPES:
1162 NOTREACHED(); 1168 NOTREACHED();
1163 return NULL; 1169 return NULL;
1164 } 1170 }
1165 NOTREACHED(); 1171 NOTREACHED();
1166 return NULL; 1172 return NULL;
1167 } 1173 }
1168 1174
1169 void ChunkDemuxer::OnNewTextTrack(ChunkDemuxerStream* text_stream, 1175 void ChunkDemuxer::OnNewTextTrack(ChunkDemuxerStream* text_stream,
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 } 1278 }
1273 1279
1274 void ChunkDemuxer::ShutdownAllStreams() { 1280 void ChunkDemuxer::ShutdownAllStreams() {
1275 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); 1281 for (MediaSourceStateMap::iterator itr = source_state_map_.begin();
1276 itr != source_state_map_.end(); ++itr) { 1282 itr != source_state_map_.end(); ++itr) {
1277 itr->second->Shutdown(); 1283 itr->second->Shutdown();
1278 } 1284 }
1279 } 1285 }
1280 1286
1281 } // namespace media 1287 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698