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

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

Issue 13652012: Refactor ChunkDemuxer code so all source state is in a SourceState class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address CR comments. Created 7 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | no next file » | 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 <deque> 8 #include <deque>
9 #include <limits> 9 #include <limits>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/callback_helpers.h" 12 #include "base/callback_helpers.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/message_loop_proxy.h" 14 #include "base/message_loop_proxy.h"
15 #include "media/base/audio_decoder_config.h" 15 #include "media/base/audio_decoder_config.h"
16 #include "media/base/stream_parser_buffer.h" 16 #include "media/base/stream_parser_buffer.h"
17 #include "media/base/video_decoder_config.h" 17 #include "media/base/video_decoder_config.h"
18 #include "media/filters/stream_parser_factory.h" 18 #include "media/filters/stream_parser_factory.h"
19 19
20 using base::TimeDelta; 20 using base::TimeDelta;
21 21
22 namespace media { 22 namespace media {
23 23
24 // Contains state belonging to a source id.
25 class SourceState {
26 public:
27 explicit SourceState(scoped_ptr<StreamParser> stream_parser);
28
29 void Init(const StreamParser::InitCB& init_cb,
30 const StreamParser::NewConfigCB& config_cb,
31 const StreamParser::NewBuffersCB& audio_cb,
32 const StreamParser::NewBuffersCB& video_cb,
33 const StreamParser::NeedKeyCB& need_key_cb,
34 const StreamParser::NewMediaSegmentCB& new_segment_cb,
35 const LogCB& log_cb);
36
37 // Appends new data to the StreamParser.
38 // Returns true if the data was successfully appended. Returns false if an
39 // error occurred.
40 bool Append(const uint8* data, size_t length);
41
42 // Aborts the current append sequence and resets the parser.
43 void Abort();
44
45 // Sets |timestamp_offset_| if possible.
46 // Returns if the offset was set. Returns false if the offset could not be
47 // updated at this time.
48 bool SetTimestampOffset(TimeDelta timestamp_offset);
49
50 TimeDelta timestamp_offset() const { return timestamp_offset_; }
51
52 private:
53 // Called by the |stream_parser_| at the beginning of a new media segment.
54 // |timestamp| is the timestamp on the first buffer in the segment.
55 // It modifies the state of this object and then calls |new_segment_cb| with
56 // modified version of |timestamp|.
57 void OnNewMediaSegment(const StreamParser::NewMediaSegmentCB& new_segment_cb,
58 TimeDelta timestamp);
59
60 // Called by the |stream_parser_| at the end of a media segment.
61 void OnEndOfMediaSegment();
62
63 // Called by the |stream_parser_| when new buffers have been parsed. It
64 // applies |timestamp_offset_| to all buffers in |buffers| and then calls
65 // |new_buffers_cb| with the modified buffers.
66 // Returns true on a successful call. Returns false if an error occured while
67 // processing the buffers.
68 bool OnBuffers(const StreamParser::NewBuffersCB& new_buffers_cb,
69 const StreamParser::BufferQueue& buffers);
70
71 // Helper function that adds |timestamp_offset_| to each buffer in |buffers|.
72 void AdjustBufferTimestamps(const StreamParser::BufferQueue& buffers);
73
74 // The offset to apply to media segment timestamps.
75 TimeDelta timestamp_offset_;
76
77 // Keeps track of whether |timestamp_offset_| can be modified.
78 bool can_update_offset_;
79
80 // The object used to parse appended data.
81 scoped_ptr<StreamParser> stream_parser_;
82
83 DISALLOW_COPY_AND_ASSIGN(SourceState);
84 };
85
86 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser)
87 : can_update_offset_(true),
88 stream_parser_(stream_parser.release()) {
89 }
90
91 void SourceState::Init(const StreamParser::InitCB& init_cb,
92 const StreamParser::NewConfigCB& config_cb,
93 const StreamParser::NewBuffersCB& audio_cb,
94 const StreamParser::NewBuffersCB& video_cb,
95 const StreamParser::NeedKeyCB& need_key_cb,
96 const StreamParser::NewMediaSegmentCB& new_segment_cb,
97 const LogCB& log_cb) {
98 stream_parser_->Init(init_cb, config_cb,
99 base::Bind(&SourceState::OnBuffers,
100 base::Unretained(this), audio_cb),
101 base::Bind(&SourceState::OnBuffers,
102 base::Unretained(this), video_cb),
103 need_key_cb,
104 base::Bind(&SourceState::OnNewMediaSegment,
105 base::Unretained(this), new_segment_cb),
106 base::Bind(&SourceState::OnEndOfMediaSegment,
107 base::Unretained(this)),
108 log_cb);
109 }
110
111 bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) {
112 if (!can_update_offset_)
113 return false;
114
115 timestamp_offset_ = timestamp_offset;
116 return true;
117 }
118
119 bool SourceState::Append(const uint8* data, size_t length) {
120 return stream_parser_->Parse(data, length);
121 }
122
123 void SourceState::Abort() {
124 stream_parser_->Flush();
125 can_update_offset_ = true;
126 }
127
128 void SourceState::AdjustBufferTimestamps(
129 const StreamParser::BufferQueue& buffers) {
130 if (timestamp_offset_ == TimeDelta())
131 return;
132
133 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
134 itr != buffers.end(); ++itr) {
135 (*itr)->SetDecodeTimestamp(
136 (*itr)->GetDecodeTimestamp() + timestamp_offset_);
137 (*itr)->SetTimestamp((*itr)->GetTimestamp() + timestamp_offset_);
138 }
139 }
140
141 void SourceState::OnNewMediaSegment(
142 const StreamParser::NewMediaSegmentCB& new_segment_cb,
143 TimeDelta timestamp) {
144 DCHECK(timestamp != kNoTimestamp());
145 DVLOG(2) << "OnNewMediaSegment(" << timestamp.InSecondsF() << ")";
146
147 can_update_offset_ = false;
148 new_segment_cb.Run(timestamp + timestamp_offset_);
149 }
150
151 void SourceState::OnEndOfMediaSegment() {
152 DVLOG(2) << "OnEndOfMediaSegment()";
153 can_update_offset_ = true;
154 }
155
156 bool SourceState::OnBuffers(const StreamParser::NewBuffersCB& new_buffers_cb,
157 const StreamParser::BufferQueue& buffers) {
158 if (new_buffers_cb.is_null())
159 return false;
160
161 AdjustBufferTimestamps(buffers);
162
163 return new_buffers_cb.Run(buffers);
164 }
24 165
25 class ChunkDemuxerStream : public DemuxerStream { 166 class ChunkDemuxerStream : public DemuxerStream {
26 public: 167 public:
27 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; 168 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
28 typedef std::deque<ReadCB> ReadCBQueue; 169 typedef std::deque<ReadCB> ReadCBQueue;
29 typedef std::deque<base::Closure> ClosureQueue; 170 typedef std::deque<base::Closure> ClosureQueue;
30 171
31 ChunkDemuxerStream(const AudioDecoderConfig& audio_config, 172 ChunkDemuxerStream(const AudioDecoderConfig& audio_config,
32 const LogCB& log_cb); 173 const LogCB& log_cb);
33 ChunkDemuxerStream(const VideoDecoderConfig& video_config, 174 ChunkDemuxerStream(const VideoDecoderConfig& video_config,
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 if (!cb.is_null()) 667 if (!cb.is_null())
527 cb.Run(PIPELINE_OK); 668 cb.Run(PIPELINE_OK);
528 } 669 }
529 670
530 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, 671 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
531 const std::string& type, 672 const std::string& type,
532 std::vector<std::string>& codecs) { 673 std::vector<std::string>& codecs) {
533 DCHECK_GT(codecs.size(), 0u); 674 DCHECK_GT(codecs.size(), 0u);
534 base::AutoLock auto_lock(lock_); 675 base::AutoLock auto_lock(lock_);
535 676
536 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || 677 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id))
537 stream_parser_map_.count(id) > 0u)
538 return kReachedIdLimit; 678 return kReachedIdLimit;
539 679
540 bool has_audio = false; 680 bool has_audio = false;
541 bool has_video = false; 681 bool has_video = false;
542 scoped_ptr<media::StreamParser> stream_parser( 682 scoped_ptr<media::StreamParser> stream_parser(
543 StreamParserFactory::Create(type, codecs, log_cb_, 683 StreamParserFactory::Create(type, codecs, log_cb_,
544 &has_audio, &has_video)); 684 &has_audio, &has_video));
545 685
546 if (!stream_parser) 686 if (!stream_parser)
547 return ChunkDemuxer::kNotSupported; 687 return ChunkDemuxer::kNotSupported;
(...skipping 10 matching lines...) Expand all
558 audio_cb = base::Bind(&ChunkDemuxer::OnAudioBuffers, 698 audio_cb = base::Bind(&ChunkDemuxer::OnAudioBuffers,
559 base::Unretained(this)); 699 base::Unretained(this));
560 } 700 }
561 701
562 if (has_video) { 702 if (has_video) {
563 source_id_video_ = id; 703 source_id_video_ = id;
564 video_cb = base::Bind(&ChunkDemuxer::OnVideoBuffers, 704 video_cb = base::Bind(&ChunkDemuxer::OnVideoBuffers,
565 base::Unretained(this)); 705 base::Unretained(this));
566 } 706 }
567 707
568 stream_parser->Init( 708 scoped_ptr<SourceState> source_state(new SourceState(stream_parser.Pass()));
569 base::Bind(&ChunkDemuxer::OnStreamParserInitDone, base::Unretained(this)), 709 source_state->Init(
710 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)),
570 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this), 711 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this),
571 has_audio, has_video), 712 has_audio, has_video),
572 audio_cb, 713 audio_cb,
573 video_cb, 714 video_cb,
574 base::Bind(&ChunkDemuxer::OnNeedKey, base::Unretained(this)), 715 base::Bind(&ChunkDemuxer::OnNeedKey, base::Unretained(this)),
575 base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id), 716 base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id),
576 base::Bind(&ChunkDemuxer::OnEndOfMediaSegment,
577 base::Unretained(this), id),
578 log_cb_); 717 log_cb_);
579 718
580 stream_parser_map_[id] = stream_parser.release(); 719 source_state_map_[id] = source_state.release();
581 SourceInfo info = { base::TimeDelta(), true };
582 source_info_map_[id] = info;
583
584 return kOk; 720 return kOk;
585 } 721 }
586 722
587 void ChunkDemuxer::RemoveId(const std::string& id) { 723 void ChunkDemuxer::RemoveId(const std::string& id) {
588 base::AutoLock auto_lock(lock_); 724 base::AutoLock auto_lock(lock_);
589 CHECK(IsValidId(id)); 725 CHECK(IsValidId(id));
590 726
591 delete stream_parser_map_[id]; 727 delete source_state_map_[id];
592 stream_parser_map_.erase(id); 728 source_state_map_.erase(id);
593 source_info_map_.erase(id);
594 729
595 if (source_id_audio_ == id) { 730 if (source_id_audio_ == id) {
596 if (audio_) 731 if (audio_)
597 audio_->Shutdown(); 732 audio_->Shutdown();
598 source_id_audio_.clear(); 733 source_id_audio_.clear();
599 } 734 }
600 735
601 if (source_id_video_ == id) { 736 if (source_id_video_ == id) {
602 if (video_) 737 if (video_)
603 video_->Shutdown(); 738 video_->Shutdown();
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 } 817 }
683 818
684 if (length == 0u) 819 if (length == 0u)
685 return; 820 return;
686 821
687 DCHECK(data); 822 DCHECK(data);
688 823
689 switch (state_) { 824 switch (state_) {
690 case INITIALIZING: 825 case INITIALIZING:
691 DCHECK(IsValidId(id)); 826 DCHECK(IsValidId(id));
692 if (!stream_parser_map_[id]->Parse(data, length)) { 827 if (!source_state_map_[id]->Append(data, length)) {
693 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 828 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
694 return; 829 return;
695 } 830 }
696 break; 831 break;
697 832
698 case INITIALIZED: { 833 case INITIALIZED: {
699 DCHECK(IsValidId(id)); 834 DCHECK(IsValidId(id));
700 if (!stream_parser_map_[id]->Parse(data, length)) { 835 if (!source_state_map_[id]->Append(data, length)) {
701 ReportError_Locked(PIPELINE_ERROR_DECODE); 836 ReportError_Locked(PIPELINE_ERROR_DECODE);
702 return; 837 return;
703 } 838 }
704 } break; 839 } break;
705 840
706 case PARSE_ERROR: 841 case PARSE_ERROR:
707 DVLOG(1) << "AppendData(): Ignoring data after a parse error."; 842 DVLOG(1) << "AppendData(): Ignoring data after a parse error.";
708 return; 843 return;
709 844
710 case WAITING_FOR_INIT: 845 case WAITING_FOR_INIT:
(...skipping 17 matching lines...) Expand all
728 863
729 if (!cb.is_null()) 864 if (!cb.is_null())
730 cb.Run(PIPELINE_OK); 865 cb.Run(PIPELINE_OK);
731 } 866 }
732 867
733 void ChunkDemuxer::Abort(const std::string& id) { 868 void ChunkDemuxer::Abort(const std::string& id) {
734 DVLOG(1) << "Abort(" << id << ")"; 869 DVLOG(1) << "Abort(" << id << ")";
735 base::AutoLock auto_lock(lock_); 870 base::AutoLock auto_lock(lock_);
736 DCHECK(!id.empty()); 871 DCHECK(!id.empty());
737 CHECK(IsValidId(id)); 872 CHECK(IsValidId(id));
738 stream_parser_map_[id]->Flush(); 873 source_state_map_[id]->Abort();
739 source_info_map_[id].can_update_offset = true;
740 } 874 }
741 875
742 double ChunkDemuxer::GetDuration() { 876 double ChunkDemuxer::GetDuration() {
743 base::AutoLock auto_lock(lock_); 877 base::AutoLock auto_lock(lock_);
744 return GetDuration_Locked(); 878 return GetDuration_Locked();
745 } 879 }
746 880
747 double ChunkDemuxer::GetDuration_Locked() { 881 double ChunkDemuxer::GetDuration_Locked() {
748 lock_.AssertAcquired(); 882 lock_.AssertAcquired();
749 if (duration_ == kNoTimestamp()) 883 if (duration_ == kNoTimestamp())
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 934
801 if (video_) 935 if (video_)
802 video_->OnSetDuration(duration_); 936 video_->OnSetDuration(duration_);
803 } 937 }
804 938
805 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { 939 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) {
806 base::AutoLock auto_lock(lock_); 940 base::AutoLock auto_lock(lock_);
807 DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")"; 941 DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")";
808 CHECK(IsValidId(id)); 942 CHECK(IsValidId(id));
809 943
810 if (!source_info_map_[id].can_update_offset) 944 return source_state_map_[id]->SetTimestampOffset(offset);
811 return false;
812
813 source_info_map_[id].timestamp_offset = offset;
814 return true;
815 } 945 }
816 946
817 bool ChunkDemuxer::EndOfStream(PipelineStatus status) { 947 bool ChunkDemuxer::EndOfStream(PipelineStatus status) {
818 DVLOG(1) << "EndOfStream(" << status << ")"; 948 DVLOG(1) << "EndOfStream(" << status << ")";
819 base::AutoLock auto_lock(lock_); 949 base::AutoLock auto_lock(lock_);
820 DCHECK_NE(state_, WAITING_FOR_INIT); 950 DCHECK_NE(state_, WAITING_FOR_INIT);
821 DCHECK_NE(state_, ENDED); 951 DCHECK_NE(state_, ENDED);
822 952
823 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) 953 if (state_ == SHUTDOWN || state_ == PARSE_ERROR)
824 return true; 954 return true;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 1003
874 void ChunkDemuxer::ChangeState_Locked(State new_state) { 1004 void ChunkDemuxer::ChangeState_Locked(State new_state) {
875 lock_.AssertAcquired(); 1005 lock_.AssertAcquired();
876 DVLOG(1) << "ChunkDemuxer::ChangeState_Locked() : " 1006 DVLOG(1) << "ChunkDemuxer::ChangeState_Locked() : "
877 << state_ << " -> " << new_state; 1007 << state_ << " -> " << new_state;
878 state_ = new_state; 1008 state_ = new_state;
879 } 1009 }
880 1010
881 ChunkDemuxer::~ChunkDemuxer() { 1011 ChunkDemuxer::~ChunkDemuxer() {
882 DCHECK_NE(state_, INITIALIZED); 1012 DCHECK_NE(state_, INITIALIZED);
883 for (StreamParserMap::iterator it = stream_parser_map_.begin(); 1013 for (SourceStateMap::iterator it = source_state_map_.begin();
884 it != stream_parser_map_.end(); ++it) { 1014 it != source_state_map_.end(); ++it) {
885 delete it->second; 1015 delete it->second;
886 } 1016 }
887 stream_parser_map_.clear(); 1017 source_state_map_.clear();
888 } 1018 }
889 1019
890 void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { 1020 void ChunkDemuxer::ReportError_Locked(PipelineStatus error) {
891 DVLOG(1) << "ReportError_Locked(" << error << ")"; 1021 DVLOG(1) << "ReportError_Locked(" << error << ")";
892 lock_.AssertAcquired(); 1022 lock_.AssertAcquired();
893 DCHECK_NE(error, PIPELINE_OK); 1023 DCHECK_NE(error, PIPELINE_OK);
894 1024
895 ChangeState_Locked(PARSE_ERROR); 1025 ChangeState_Locked(PARSE_ERROR);
896 1026
897 PipelineStatusCB cb; 1027 PipelineStatusCB cb;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
931 1061
932 return seek_pending; 1062 return seek_pending;
933 } 1063 }
934 1064
935 bool ChunkDemuxer::CanEndOfStream_Locked() const { 1065 bool ChunkDemuxer::CanEndOfStream_Locked() const {
936 lock_.AssertAcquired(); 1066 lock_.AssertAcquired();
937 return (!audio_ || audio_->CanEndOfStream()) && 1067 return (!audio_ || audio_->CanEndOfStream()) &&
938 (!video_ || video_->CanEndOfStream()); 1068 (!video_ || video_->CanEndOfStream());
939 } 1069 }
940 1070
941 void ChunkDemuxer::OnStreamParserInitDone(bool success, TimeDelta duration) { 1071 void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) {
942 DVLOG(1) << "OnStreamParserInitDone(" << success << ", " 1072 DVLOG(1) << "OnSourceInitDone(" << success << ", "
943 << duration.InSecondsF() << ")"; 1073 << duration.InSecondsF() << ")";
944 lock_.AssertAcquired(); 1074 lock_.AssertAcquired();
945 DCHECK_EQ(state_, INITIALIZING); 1075 DCHECK_EQ(state_, INITIALIZING);
946 if (!success || (!audio_ && !video_)) { 1076 if (!success || (!audio_ && !video_)) {
947 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 1077 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
948 return; 1078 return;
949 } 1079 }
950 1080
951 if (duration != base::TimeDelta() && duration_ == kNoTimestamp()) 1081 if (duration != base::TimeDelta() && duration_ == kNoTimestamp())
952 UpdateDuration(duration); 1082 UpdateDuration(duration);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 } 1159 }
1030 1160
1031 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { 1161 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) {
1032 lock_.AssertAcquired(); 1162 lock_.AssertAcquired();
1033 DCHECK_NE(state_, SHUTDOWN); 1163 DCHECK_NE(state_, SHUTDOWN);
1034 1164
1035 if (!audio_) 1165 if (!audio_)
1036 return false; 1166 return false;
1037 1167
1038 CHECK(IsValidId(source_id_audio_)); 1168 CHECK(IsValidId(source_id_audio_));
1039 AdjustBufferTimestamps(
1040 buffers, source_info_map_[source_id_audio_].timestamp_offset);
1041
1042 if (!audio_->Append(buffers)) 1169 if (!audio_->Append(buffers))
1043 return false; 1170 return false;
1044 1171
1045 IncreaseDurationIfNecessary(buffers, audio_); 1172 IncreaseDurationIfNecessary(buffers, audio_);
1046 return true; 1173 return true;
1047 } 1174 }
1048 1175
1049 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { 1176 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) {
1050 lock_.AssertAcquired(); 1177 lock_.AssertAcquired();
1051 DCHECK_NE(state_, SHUTDOWN); 1178 DCHECK_NE(state_, SHUTDOWN);
1052 1179
1053 if (!video_) 1180 if (!video_)
1054 return false; 1181 return false;
1055 1182
1056 CHECK(IsValidId(source_id_video_)); 1183 CHECK(IsValidId(source_id_video_));
1057 AdjustBufferTimestamps(
1058 buffers, source_info_map_[source_id_video_].timestamp_offset);
1059
1060 if (!video_->Append(buffers)) 1184 if (!video_->Append(buffers))
1061 return false; 1185 return false;
1062 1186
1063 IncreaseDurationIfNecessary(buffers, video_); 1187 IncreaseDurationIfNecessary(buffers, video_);
1064 return true; 1188 return true;
1065 } 1189 }
1066 1190
1067 // TODO(acolwell): Remove bool from StreamParser::NeedKeyCB so that 1191 // TODO(acolwell): Remove bool from StreamParser::NeedKeyCB so that
1068 // this method can be removed and need_key_cb_ can be passed directly 1192 // this method can be removed and need_key_cb_ can be passed directly
1069 // to the parser. 1193 // to the parser.
1070 bool ChunkDemuxer::OnNeedKey(const std::string& type, 1194 bool ChunkDemuxer::OnNeedKey(const std::string& type,
1071 scoped_array<uint8> init_data, 1195 scoped_array<uint8> init_data,
1072 int init_data_size) { 1196 int init_data_size) {
1073 lock_.AssertAcquired(); 1197 lock_.AssertAcquired();
1074 need_key_cb_.Run(type, init_data.Pass(), init_data_size); 1198 need_key_cb_.Run(type, init_data.Pass(), init_data_size);
1075 return true; 1199 return true;
1076 } 1200 }
1077 1201
1078 void ChunkDemuxer::OnNewMediaSegment(const std::string& source_id, 1202 void ChunkDemuxer::OnNewMediaSegment(const std::string& source_id,
1079 TimeDelta timestamp) { 1203 TimeDelta timestamp) {
1080 DCHECK(timestamp != kNoTimestamp()); 1204 DCHECK(timestamp != kNoTimestamp());
1081 DVLOG(2) << "OnNewMediaSegment(" << source_id << ", " 1205 DVLOG(2) << "OnNewMediaSegment(" << source_id << ", "
1082 << timestamp.InSecondsF() << ")"; 1206 << timestamp.InSecondsF() << ")";
1083 lock_.AssertAcquired(); 1207 lock_.AssertAcquired();
1084 1208
1085 CHECK(IsValidId(source_id)); 1209 CHECK(IsValidId(source_id));
1086 source_info_map_[source_id].can_update_offset = false;
1087 base::TimeDelta start_timestamp =
1088 timestamp + source_info_map_[source_id].timestamp_offset;
1089
1090 if (audio_ && source_id == source_id_audio_) 1210 if (audio_ && source_id == source_id_audio_)
1091 audio_->OnNewMediaSegment(start_timestamp); 1211 audio_->OnNewMediaSegment(timestamp);
1092 if (video_ && source_id == source_id_video_) 1212 if (video_ && source_id == source_id_video_)
1093 video_->OnNewMediaSegment(start_timestamp); 1213 video_->OnNewMediaSegment(timestamp);
1094 }
1095
1096 void ChunkDemuxer::OnEndOfMediaSegment(const std::string& source_id) {
1097 DVLOG(2) << "OnEndOfMediaSegment(" << source_id << ")";
1098 CHECK(IsValidId(source_id));
1099 source_info_map_[source_id].can_update_offset = true;
1100 }
1101
1102 void ChunkDemuxer::AdjustBufferTimestamps(
1103 const StreamParser::BufferQueue& buffers,
1104 base::TimeDelta timestamp_offset) {
1105 if (timestamp_offset == base::TimeDelta())
1106 return;
1107
1108 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
1109 itr != buffers.end(); ++itr) {
1110 (*itr)->SetDecodeTimestamp(
1111 (*itr)->GetDecodeTimestamp() + timestamp_offset);
1112 (*itr)->SetTimestamp((*itr)->GetTimestamp() + timestamp_offset);
1113 }
1114 } 1214 }
1115 1215
1116 bool ChunkDemuxer::IsValidId(const std::string& source_id) const { 1216 bool ChunkDemuxer::IsValidId(const std::string& source_id) const {
1117 lock_.AssertAcquired(); 1217 lock_.AssertAcquired();
1118 return source_info_map_.count(source_id) > 0u && 1218 return source_state_map_.count(source_id) > 0u;
1119 stream_parser_map_.count(source_id) > 0u;
1120 } 1219 }
1121 1220
1122 void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) { 1221 void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) {
1123 DCHECK(duration_ != new_duration); 1222 DCHECK(duration_ != new_duration);
1124 user_specified_duration_ = -1; 1223 user_specified_duration_ = -1;
1125 duration_ = new_duration; 1224 duration_ = new_duration;
1126 host_->SetDuration(new_duration); 1225 host_->SetDuration(new_duration);
1127 } 1226 }
1128 1227
1129 void ChunkDemuxer::IncreaseDurationIfNecessary( 1228 void ChunkDemuxer::IncreaseDurationIfNecessary(
(...skipping 23 matching lines...) Expand all
1153 1252
1154 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { 1253 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const {
1155 if (audio_ && !video_) 1254 if (audio_ && !video_)
1156 return audio_->GetBufferedRanges(duration_); 1255 return audio_->GetBufferedRanges(duration_);
1157 else if (!audio_ && video_) 1256 else if (!audio_ && video_)
1158 return video_->GetBufferedRanges(duration_); 1257 return video_->GetBufferedRanges(duration_);
1159 return ComputeIntersection(); 1258 return ComputeIntersection();
1160 } 1259 }
1161 1260
1162 } // namespace media 1261 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698