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

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: A few clean ups 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> 9 #include <set>
wolenetz 2016/09/06 21:20:50 nit: why did this change?
servolk 2016/09/07 01:35:10 Because I don't see std::list being used explicitl
wolenetz 2016/09/12 21:41:05 Acknowledged.
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/callback_helpers.h" 13 #include "base/callback_helpers.h"
14 #include "base/location.h" 14 #include "base/location.h"
15 #include "base/macros.h" 15 #include "base/macros.h"
16 #include "base/metrics/histogram_macros.h" 16 #include "base/metrics/histogram_macros.h"
17 #include "base/stl_util.h" 17 #include "base/stl_util.h"
18 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "media/base/audio_decoder_config.h" 19 #include "media/base/audio_decoder_config.h"
20 #include "media/base/bind_to_current_loop.h" 20 #include "media/base/bind_to_current_loop.h"
21 #include "media/base/media_tracks.h" 21 #include "media/base/media_tracks.h"
22 #include "media/base/mime_util.h"
22 #include "media/base/stream_parser_buffer.h" 23 #include "media/base/stream_parser_buffer.h"
23 #include "media/base/timestamp_constants.h" 24 #include "media/base/timestamp_constants.h"
24 #include "media/base/video_codecs.h" 25 #include "media/base/video_codecs.h"
25 #include "media/base/video_decoder_config.h" 26 #include "media/base/video_decoder_config.h"
26 #include "media/filters/frame_processor.h" 27 #include "media/filters/frame_processor.h"
27 #include "media/filters/stream_parser_factory.h" 28 #include "media/filters/stream_parser_factory.h"
28 29
29 using base::TimeDelta; 30 using base::TimeDelta;
30 31
31 namespace media { 32 namespace media {
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 } 485 }
485 486
486 // Demuxer implementation. 487 // Demuxer implementation.
487 base::Time ChunkDemuxer::GetTimelineOffset() const { 488 base::Time ChunkDemuxer::GetTimelineOffset() const {
488 return timeline_offset_; 489 return timeline_offset_;
489 } 490 }
490 491
491 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) { 492 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) {
492 DCHECK_NE(type, DemuxerStream::TEXT); 493 DCHECK_NE(type, DemuxerStream::TEXT);
493 base::AutoLock auto_lock(lock_); 494 base::AutoLock auto_lock(lock_);
494 if (type == DemuxerStream::VIDEO)
495 return video_.get();
496 495
497 if (type == DemuxerStream::AUDIO) 496 if (type == DemuxerStream::AUDIO)
498 return audio_.get(); 497 for (const auto& s : audio_streams_)
498 if (s->enabled())
499 return s.get();
500
501 if (type == DemuxerStream::VIDEO)
502 for (const auto& s : video_streams_)
503 if (s->enabled())
504 return s.get();
499 505
500 return NULL; 506 return NULL;
501 } 507 }
502 508
503 TimeDelta ChunkDemuxer::GetStartTime() const { 509 TimeDelta ChunkDemuxer::GetStartTime() const {
504 return TimeDelta(); 510 return TimeDelta();
505 } 511 }
506 512
507 int64_t ChunkDemuxer::GetMemoryUsage() const { 513 int64_t ChunkDemuxer::GetMemoryUsage() const {
508 base::AutoLock auto_lock(lock_); 514 base::AutoLock auto_lock(lock_);
509 return (audio_ ? audio_->GetBufferedSize() : 0) + 515 int64_t mem = 0;
510 (video_ ? video_->GetBufferedSize() : 0); 516 for (const auto& s : audio_streams_)
517 mem += s->GetBufferedSize();
518 for (const auto& s : video_streams_)
519 mem += s->GetBufferedSize();
520 return mem;
511 } 521 }
512 522
513 void ChunkDemuxer::AbortPendingReads() { 523 void ChunkDemuxer::AbortPendingReads() {
514 base::AutoLock auto_lock(lock_); 524 base::AutoLock auto_lock(lock_);
515 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN || 525 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN ||
516 state_ == PARSE_ERROR) 526 state_ == PARSE_ERROR)
517 << state_; 527 << state_;
518 528
519 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) 529 if (state_ == SHUTDOWN || state_ == PARSE_ERROR)
520 return; 530 return;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 if (seek_cb_.is_null()) { 564 if (seek_cb_.is_null()) {
555 cancel_next_seek_ = true; 565 cancel_next_seek_ = true;
556 return; 566 return;
557 } 567 }
558 568
559 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); 569 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
560 } 570 }
561 571
562 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, 572 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
563 const std::string& type, 573 const std::string& type,
564 std::vector<std::string>& codecs) { 574 const std::string& codecs) {
575 DVLOG(1) << __func__ << " id=" << id << " mime_type=" << type
576 << " codecs=" << codecs;
565 base::AutoLock auto_lock(lock_); 577 base::AutoLock auto_lock(lock_);
566 578
567 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id)) 579 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id))
568 return kReachedIdLimit; 580 return kReachedIdLimit;
569 581
570 bool has_audio = false; 582 std::vector<std::string> parsed_codec_ids;
571 bool has_video = false; 583 media::ParseCodecString(codecs, &parsed_codec_ids, false);
584
572 std::unique_ptr<media::StreamParser> stream_parser( 585 std::unique_ptr<media::StreamParser> stream_parser(
573 StreamParserFactory::Create(type, codecs, media_log_, &has_audio, 586 StreamParserFactory::Create(type, parsed_codec_ids, media_log_));
574 &has_video));
575 587
576 if (!stream_parser) 588 if (!stream_parser)
577 return ChunkDemuxer::kNotSupported; 589 return ChunkDemuxer::kNotSupported;
578 590
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( 591 std::unique_ptr<FrameProcessor> frame_processor(
590 new FrameProcessor(base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary, 592 new FrameProcessor(base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary,
591 base::Unretained(this)), 593 base::Unretained(this)),
592 media_log_)); 594 media_log_));
593 595
594 std::unique_ptr<MediaSourceState> source_state(new MediaSourceState( 596 std::unique_ptr<MediaSourceState> source_state(new MediaSourceState(
595 std::move(stream_parser), std::move(frame_processor), 597 std::move(stream_parser), std::move(frame_processor),
596 base::Bind(&ChunkDemuxer::CreateDemuxerStream, base::Unretained(this)), 598 base::Bind(&ChunkDemuxer::CreateDemuxerStream, base::Unretained(this)),
597 media_log_)); 599 media_log_));
598 600
599 MediaSourceState::NewTextTrackCB new_text_track_cb; 601 MediaSourceState::NewTextTrackCB new_text_track_cb;
600 602
601 if (enable_text_) { 603 if (enable_text_) {
602 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack, 604 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack,
603 base::Unretained(this)); 605 base::Unretained(this));
604 } 606 }
605 607
606 pending_source_init_done_count_++; 608 pending_source_init_done_count_++;
wolenetz 2016/09/06 21:20:50 Hmm. I think we may have some exacerbation of prev
servolk 2016/09/07 01:35:10 Well, it's not exacerbation, it's actually exactly
wolenetz 2016/09/12 21:41:05 First point and map: SGTM. I'll review that. Secon
607 609
610 std::string expected_mss_codecs = codecs;
wolenetz 2016/09/06 21:20:49 The parsing and expectation matching is confusing
servolk 2016/09/07 01:35:10 Well, we can only do the matching in the OnNewConf
wolenetz 2016/09/12 21:41:05 Would using the previous logic and something like
611 if (codecs == "" && type == "audio/aac")
612 expected_mss_codecs = "aac";
613 if (codecs == "" && (type == "audio/mpeg" || type == "audio/mp3"))
614 expected_mss_codecs = "mp3";
615
608 source_state->Init( 616 source_state->Init(
609 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)), 617 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)),
610 has_audio, has_video, encrypted_media_init_data_cb_, new_text_track_cb); 618 expected_mss_codecs, encrypted_media_init_data_cb_, new_text_track_cb);
611 619
612 source_state_map_[id] = source_state.release(); 620 source_state_map_[id] = source_state.release();
613 return kOk; 621 return kOk;
614 } 622 }
615 623
616 void ChunkDemuxer::SetTracksWatcher( 624 void ChunkDemuxer::SetTracksWatcher(
617 const std::string& id, 625 const std::string& id,
618 const MediaTracksUpdatedCB& tracks_updated_cb) { 626 const MediaTracksUpdatedCB& tracks_updated_cb) {
619 base::AutoLock auto_lock(lock_); 627 base::AutoLock auto_lock(lock_);
620 CHECK(IsValidId(id)); 628 CHECK(IsValidId(id));
621 source_state_map_[id]->SetTracksWatcher(tracks_updated_cb); 629 source_state_map_[id]->SetTracksWatcher(tracks_updated_cb);
622 } 630 }
623 631
624 void ChunkDemuxer::RemoveId(const std::string& id) { 632 void ChunkDemuxer::RemoveId(const std::string& id) {
625 base::AutoLock auto_lock(lock_); 633 base::AutoLock auto_lock(lock_);
626 CHECK(IsValidId(id)); 634 CHECK(IsValidId(id));
627 635
628 delete source_state_map_[id]; 636 delete source_state_map_[id];
629 source_state_map_.erase(id); 637 source_state_map_.erase(id);
630
631 if (source_id_audio_ == id)
632 source_id_audio_.clear();
633
634 if (source_id_video_ == id)
635 source_id_video_.clear();
636 } 638 }
637 639
638 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const { 640 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const {
639 base::AutoLock auto_lock(lock_); 641 base::AutoLock auto_lock(lock_);
640 DCHECK(!id.empty()); 642 DCHECK(!id.empty());
641 643
642 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id); 644 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id);
643 645
644 DCHECK(itr != source_state_map_.end()); 646 DCHECK(itr != source_state_map_.end());
645 return itr->second->GetBufferedRanges(duration_, state_ == ENDED); 647 return itr->second->GetBufferedRanges(duration_, state_ == ENDED);
646 } 648 }
647 649
648 base::TimeDelta ChunkDemuxer::GetHighestPresentationTimestamp( 650 base::TimeDelta ChunkDemuxer::GetHighestPresentationTimestamp(
649 const std::string& id) const { 651 const std::string& id) const {
650 base::AutoLock auto_lock(lock_); 652 base::AutoLock auto_lock(lock_);
651 DCHECK(!id.empty()); 653 DCHECK(!id.empty());
652 654
653 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id); 655 MediaSourceStateMap::const_iterator itr = source_state_map_.find(id);
654 656
655 DCHECK(itr != source_state_map_.end()); 657 DCHECK(itr != source_state_map_.end());
656 return itr->second->GetHighestPresentationTimestamp(); 658 return itr->second->GetHighestPresentationTimestamp();
657 } 659 }
658 660
659 void ChunkDemuxer::OnEnabledAudioTracksChanged( 661 void ChunkDemuxer::OnEnabledAudioTracksChanged(
660 const std::vector<MediaTrack::Id>& track_ids, 662 const std::vector<MediaTrack::Id>& track_ids,
661 base::TimeDelta currTime) { 663 base::TimeDelta currTime) {
662 // Note: We intentionally don't lock here, since we are not accessing any 664 base::AutoLock auto_lock(lock_);
663 // members directly. 665 std::set<DemuxerStream*> enabled_streams;
664 DemuxerStream* audio_stream = GetStream(DemuxerStream::AUDIO); 666 for (const auto& id : track_ids) {
665 bool enabled = false; 667 DemuxerStream* stream = track_id_to_demux_stream_map_[id];
666 CHECK(audio_stream); 668 DCHECK(stream);
667 DCHECK_LE(track_ids.size(), 1u); 669 DCHECK_EQ(DemuxerStream::AUDIO, stream->type());
668 if (track_ids.size() > 0) { 670 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 } 671 }
675 DVLOG(1) << __func__ << ": " << (enabled ? "enabling" : "disabling") 672
676 << " audio stream"; 673 // First disable all streams that need to be disabled and then enable streams
677 audio_stream->set_enabled(enabled, currTime); 674 // that are enabled.
675 for (const auto& stream : audio_streams_) {
676 if (enabled_streams.find(stream.get()) == enabled_streams.end()) {
677 DVLOG(1) << __func__ << ": disabling stream " << stream.get();
678 stream->set_enabled(false, currTime);
679 }
680 }
681 for (const auto& stream : enabled_streams) {
682 DVLOG(1) << __func__ << ": enabling stream " << stream;
683 stream->set_enabled(true, currTime);
684 }
678 } 685 }
679 686
680 void ChunkDemuxer::OnSelectedVideoTrackChanged( 687 void ChunkDemuxer::OnSelectedVideoTrackChanged(
681 const std::vector<MediaTrack::Id>& track_ids, 688 const std::vector<MediaTrack::Id>& track_ids,
682 base::TimeDelta currTime) { 689 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); 690 DCHECK_LE(track_ids.size(), 1u);
689 if (track_ids.size() > 0) { 691
690 #if DCHECK_IS_ON() 692 base::AutoLock auto_lock(lock_);
691 base::AutoLock auto_lock(lock_); 693 DemuxerStream* selected_stream = nullptr;
692 DCHECK(track_id_to_demux_stream_map_[track_ids[0]] == video_stream); 694 if (!track_ids.empty()) {
693 #endif 695 selected_stream = track_id_to_demux_stream_map_[track_ids[0]];
694 enabled = true; 696 DCHECK(selected_stream);
697 DCHECK_EQ(DemuxerStream::VIDEO, selected_stream->type());
695 } 698 }
696 DVLOG(1) << __func__ << ": " << (enabled ? "enabling" : "disabling") 699
697 << " video stream"; 700 // First disable all streams that need to be disabled and then enable the
698 video_stream->set_enabled(enabled, currTime); 701 // stream that needs to be enabled (if any).
702 for (const auto& stream : video_streams_) {
703 if (stream->type() == DemuxerStream::VIDEO &&
704 stream.get() != selected_stream) {
705 DVLOG(1) << __func__ << ": disabling stream " << stream.get();
706 stream->set_enabled(false, currTime);
707 }
708 }
709 if (selected_stream) {
710 DVLOG(1) << __func__ << ": enabling stream " << selected_stream;
711 selected_stream->set_enabled(true, currTime);
712 }
699 } 713 }
700 714
701 bool ChunkDemuxer::EvictCodedFrames(const std::string& id, 715 bool ChunkDemuxer::EvictCodedFrames(const std::string& id,
702 base::TimeDelta currentMediaTime, 716 base::TimeDelta currentMediaTime,
703 size_t newDataSize) { 717 size_t newDataSize) {
704 DVLOG(1) << __func__ << "(" << id << ")" 718 DVLOG(1) << __func__ << "(" << id << ")"
705 << " media_time=" << currentMediaTime.InSecondsF() 719 << " media_time=" << currentMediaTime.InSecondsF()
706 << " newDataSize=" << newDataSize; 720 << " newDataSize=" << newDataSize;
707 base::AutoLock auto_lock(lock_); 721 base::AutoLock auto_lock(lock_);
708 722
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
1042 } 1056 }
1043 1057
1044 return false; 1058 return false;
1045 } 1059 }
1046 1060
1047 void ChunkDemuxer::OnSourceInitDone( 1061 void ChunkDemuxer::OnSourceInitDone(
1048 const StreamParser::InitParameters& params) { 1062 const StreamParser::InitParameters& params) {
1049 DVLOG(1) << "OnSourceInitDone(" << params.duration.InSecondsF() << ")"; 1063 DVLOG(1) << "OnSourceInitDone(" << params.duration.InSecondsF() << ")";
1050 lock_.AssertAcquired(); 1064 lock_.AssertAcquired();
1051 DCHECK_EQ(state_, INITIALIZING); 1065 DCHECK_EQ(state_, INITIALIZING);
1052 if (!audio_ && !video_) { 1066 if (audio_streams_.empty() && video_streams_.empty()) {
1053 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 1067 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
1054 return; 1068 return;
1055 } 1069 }
1056 1070
1057 if (!params.duration.is_zero() && duration_ == kNoTimestamp) 1071 if (!params.duration.is_zero() && duration_ == kNoTimestamp)
1058 UpdateDuration(params.duration); 1072 UpdateDuration(params.duration);
1059 1073
1060 if (!params.timeline_offset.is_null()) { 1074 if (!params.timeline_offset.is_null()) {
1061 if (!timeline_offset_.is_null() && 1075 if (!timeline_offset_.is_null() &&
1062 params.timeline_offset != timeline_offset_) { 1076 params.timeline_offset != timeline_offset_) {
1063 MEDIA_LOG(ERROR, media_log_) 1077 MEDIA_LOG(ERROR, media_log_)
1064 << "Timeline offset is not the same across all SourceBuffers."; 1078 << "Timeline offset is not the same across all SourceBuffers.";
1065 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 1079 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
wolenetz 2016/09/06 21:20:50 This patchset allows (see above) AddId(z) + append
servolk 2016/09/07 01:35:10 Nope, see my explanation in the other comment. Add
wolenetz 2016/09/12 21:41:05 Acknowledged.
1066 return; 1080 return;
1067 } 1081 }
1068 1082
1069 timeline_offset_ = params.timeline_offset; 1083 timeline_offset_ = params.timeline_offset;
1070 } 1084 }
1071 1085
1072 if (params.liveness != DemuxerStream::LIVENESS_UNKNOWN) { 1086 if (params.liveness != DemuxerStream::LIVENESS_UNKNOWN) {
wolenetz 2016/09/06 21:20:50 Hmm. We appear to be exacerbating previously confu
servolk 2016/09/07 01:35:10 I believe this shouldn't be a problem, as HAVE_MET
wolenetz 2016/09/12 21:41:05 Ack, though IIUC, this code now allows a video tra
1073 if (audio_) 1087 for (const auto& s : audio_streams_)
1074 audio_->SetLiveness(params.liveness); 1088 s->SetLiveness(params.liveness);
1075 if (video_) 1089 for (const auto& s : video_streams_)
1076 video_->SetLiveness(params.liveness); 1090 s->SetLiveness(params.liveness);
1077 } 1091 }
1078 1092
1079 detected_audio_track_count_ += params.detected_audio_track_count; 1093 detected_audio_track_count_ += params.detected_audio_track_count;
1080 detected_video_track_count_ += params.detected_video_track_count; 1094 detected_video_track_count_ += params.detected_video_track_count;
1081 detected_text_track_count_ += params.detected_text_track_count; 1095 detected_text_track_count_ += params.detected_text_track_count;
1082 1096
1083 // Wait until all streams have initialized. 1097 // Wait until all streams have initialized.
1084 pending_source_init_done_count_--; 1098 pending_source_init_done_count_--;
wolenetz 2016/09/06 21:20:50 See comment above. Once we've reached 0 here, the
servolk 2016/09/07 01:35:10 Yep, as I've explained above I believe we can solv
wolenetz 2016/09/12 21:41:05 Ack.
1085 1099
1086 if (pending_source_init_done_count_ > 0) 1100 if (pending_source_init_done_count_ > 0)
1087 return; 1101 return;
1088 1102
1089 DCHECK_EQ(0, pending_source_init_done_count_); 1103 DCHECK_EQ(0, pending_source_init_done_count_);
1090 DCHECK((source_id_audio_.empty() == !audio_) &&
1091 (source_id_video_.empty() == !video_));
1092 1104
1093 // Record detected track counts by type corresponding to an MSE playback. 1105 // Record detected track counts by type corresponding to an MSE playback.
1094 // Counts are split into 50 buckets, capped into [0,100] range. 1106 // Counts are split into 50 buckets, capped into [0,100] range.
1095 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Audio", 1107 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Audio",
1096 detected_audio_track_count_); 1108 detected_audio_track_count_);
1097 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Video", 1109 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Video",
1098 detected_video_track_count_); 1110 detected_video_track_count_);
1099 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Text", 1111 UMA_HISTOGRAM_COUNTS_100("Media.MSE.DetectedTrackCount.Text",
1100 detected_text_track_count_); 1112 detected_text_track_count_);
1101 1113
1102 if (video_) { 1114 for (const auto& s : video_streams_) {
1103 media_log_->RecordRapporWithSecurityOrigin( 1115 media_log_->RecordRapporWithSecurityOrigin(
1104 "Media.OriginUrl.MSE.VideoCodec." + 1116 "Media.OriginUrl.MSE.VideoCodec." +
1105 GetCodecName(video_->video_decoder_config().codec())); 1117 GetCodecName(s->video_decoder_config().codec()));
1106 } 1118 }
1107 1119
1108 SeekAllSources(GetStartTime()); 1120 SeekAllSources(GetStartTime());
1109 StartReturningData(); 1121 StartReturningData();
1110 1122
1111 if (duration_ == kNoTimestamp) 1123 if (duration_ == kNoTimestamp)
1112 duration_ = kInfiniteDuration; 1124 duration_ = kInfiniteDuration;
1113 1125
1114 // The demuxer is now initialized after the |start_timestamp_| was set. 1126 // The demuxer is now initialized after the |start_timestamp_| was set.
1115 ChangeState_Locked(INITIALIZED); 1127 ChangeState_Locked(INITIALIZED);
1116 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 1128 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
1117 } 1129 }
1118 1130
1119 // static 1131 // static
1120 MediaTrack::Id ChunkDemuxer::GenerateMediaTrackId() { 1132 MediaTrack::Id ChunkDemuxer::GenerateMediaTrackId() {
1121 static unsigned g_track_count = 0; 1133 static unsigned g_track_count = 0;
1122 return base::UintToString(++g_track_count); 1134 return base::UintToString(++g_track_count);
1123 } 1135 }
1124 1136
1125 ChunkDemuxerStream* ChunkDemuxer::CreateDemuxerStream( 1137 ChunkDemuxerStream* ChunkDemuxer::CreateDemuxerStream(
1126 DemuxerStream::Type type) { 1138 DemuxerStream::Type type) {
1127 // New ChunkDemuxerStreams can be created only during initialization segment 1139 // New ChunkDemuxerStreams can be created only during initialization segment
1128 // processing, which happens when a new chunk of data is appended and the 1140 // processing, which happens when a new chunk of data is appended and the
1129 // lock_ must be held by ChunkDemuxer::AppendData. 1141 // lock_ must be held by ChunkDemuxer::AppendData.
1130 lock_.AssertAcquired(); 1142 lock_.AssertAcquired();
1131 1143
1132 MediaTrack::Id media_track_id = GenerateMediaTrackId(); 1144 MediaTrack::Id media_track_id = GenerateMediaTrackId();
1133 1145
1134 switch (type) { 1146 switch (type) {
1135 case DemuxerStream::AUDIO: 1147 case DemuxerStream::AUDIO: {
1136 if (audio_) 1148 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)); 1149 DemuxerStream::AUDIO, splice_frames_enabled_, media_track_id));
1140 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) == 1150 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) ==
1141 track_id_to_demux_stream_map_.end()); 1151 track_id_to_demux_stream_map_.end());
1142 track_id_to_demux_stream_map_[media_track_id] = audio_.get(); 1152 track_id_to_demux_stream_map_[media_track_id] = audio_stream.get();
1143 return audio_.get(); 1153 audio_streams_.push_back(std::move(audio_stream));
1144 break; 1154 return audio_streams_.back().get();
1145 case DemuxerStream::VIDEO: 1155 } break;
wolenetz 2016/09/06 21:20:49 inconsistent {...}break; vs {... break;}
servolk 2016/09/07 01:35:10 Actually I just noticed that the break is redundan
wolenetz 2016/09/12 21:41:05 Acknowledged.
1146 if (video_) 1156 case DemuxerStream::VIDEO: {
1147 return NULL; 1157 std::unique_ptr<ChunkDemuxerStream> video_stream(new ChunkDemuxerStream(
1148 video_.reset(new ChunkDemuxerStream(
1149 DemuxerStream::VIDEO, splice_frames_enabled_, media_track_id)); 1158 DemuxerStream::VIDEO, splice_frames_enabled_, media_track_id));
1150 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) == 1159 DCHECK(track_id_to_demux_stream_map_.find(media_track_id) ==
1151 track_id_to_demux_stream_map_.end()); 1160 track_id_to_demux_stream_map_.end());
1152 track_id_to_demux_stream_map_[media_track_id] = video_.get(); 1161 track_id_to_demux_stream_map_[media_track_id] = video_stream.get();
1153 return video_.get(); 1162 video_streams_.push_back(std::move(video_stream));
1154 break; 1163 return video_streams_.back().get();
1164 } break;
wolenetz 2016/09/06 21:20:50 ditto
servolk 2016/09/07 01:35:10 Done.
wolenetz 2016/09/12 21:41:05 Acknowledged.
1155 case DemuxerStream::TEXT: { 1165 case DemuxerStream::TEXT: {
1156 return new ChunkDemuxerStream(DemuxerStream::TEXT, splice_frames_enabled_, 1166 return new ChunkDemuxerStream(DemuxerStream::TEXT, splice_frames_enabled_,
1157 media_track_id); 1167 media_track_id);
1158 break; 1168 break;
1159 } 1169 }
1160 case DemuxerStream::UNKNOWN: 1170 case DemuxerStream::UNKNOWN:
1161 case DemuxerStream::NUM_TYPES: 1171 case DemuxerStream::NUM_TYPES:
1162 NOTREACHED(); 1172 NOTREACHED();
1163 return NULL; 1173 return NULL;
1164 } 1174 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 } 1282 }
1273 1283
1274 void ChunkDemuxer::ShutdownAllStreams() { 1284 void ChunkDemuxer::ShutdownAllStreams() {
1275 for (MediaSourceStateMap::iterator itr = source_state_map_.begin(); 1285 for (MediaSourceStateMap::iterator itr = source_state_map_.begin();
1276 itr != source_state_map_.end(); ++itr) { 1286 itr != source_state_map_.end(); ++itr) {
1277 itr->second->Shutdown(); 1287 itr->second->Shutdown();
1278 } 1288 }
1279 } 1289 }
1280 1290
1281 } // namespace media 1291 } // 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