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

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

Issue 11471006: Log MediaSource parsing errors to the MediaLog so they can appear in chrome:media-internals. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix nit. Created 8 years 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') | 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 <deque> 8 #include <deque>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 // Checks to see if the specified |type| and |codecs| list are supported. 100 // Checks to see if the specified |type| and |codecs| list are supported.
101 // Returns true if |type| and all codecs listed in |codecs| are supported. 101 // Returns true if |type| and all codecs listed in |codecs| are supported.
102 // |factory_function| contains a function that can build a StreamParser 102 // |factory_function| contains a function that can build a StreamParser
103 // for this type. 103 // for this type.
104 // |has_audio| is true if an audio codec was specified. 104 // |has_audio| is true if an audio codec was specified.
105 // |has_video| is true if a video codec was specified. 105 // |has_video| is true if a video codec was specified.
106 // Returns false otherwise. The values of |factory_function|, |has_audio|, 106 // Returns false otherwise. The values of |factory_function|, |has_audio|,
107 // and |has_video| are undefined. 107 // and |has_video| are undefined.
108 static bool IsSupported(const std::string& type, 108 static bool IsSupported(const std::string& type,
109 std::vector<std::string>& codecs, 109 std::vector<std::string>& codecs,
110 const LogCB& log_cb,
110 ParserFactoryFunction* factory_function, 111 ParserFactoryFunction* factory_function,
111 bool* has_audio, 112 bool* has_audio,
112 bool* has_video) { 113 bool* has_video) {
113 *factory_function = NULL; 114 *factory_function = NULL;
114 *has_audio = false; 115 *has_audio = false;
115 *has_video = false; 116 *has_video = false;
116 117
117 // Search for the SupportedTypeInfo for |type|. 118 // Search for the SupportedTypeInfo for |type|.
118 for (size_t i = 0; i < arraysize(kSupportedTypeInfo); ++i) { 119 for (size_t i = 0; i < arraysize(kSupportedTypeInfo); ++i) {
119 const SupportedTypeInfo& type_info = kSupportedTypeInfo[i]; 120 const SupportedTypeInfo& type_info = kSupportedTypeInfo[i];
120 if (type == type_info.type) { 121 if (type == type_info.type) {
121 // Make sure all the codecs specified in |codecs| are 122 // Make sure all the codecs specified in |codecs| are
122 // in the supported type info. 123 // in the supported type info.
123 for (size_t j = 0; j < codecs.size(); ++j) { 124 for (size_t j = 0; j < codecs.size(); ++j) {
124 // Search the type info for a match. 125 // Search the type info for a match.
125 bool found_codec = false; 126 bool found_codec = false;
126 DemuxerStream::Type codec_type = DemuxerStream::UNKNOWN; 127 DemuxerStream::Type codec_type = DemuxerStream::UNKNOWN;
127 128
128 for (int k = 0; type_info.codecs[k]; ++k) { 129 for (int k = 0; type_info.codecs[k]; ++k) {
129 if (MatchPattern(codecs[j], type_info.codecs[k]->pattern)) { 130 if (MatchPattern(codecs[j], type_info.codecs[k]->pattern)) {
130 found_codec = true; 131 found_codec = true;
131 codec_type = type_info.codecs[k]->type; 132 codec_type = type_info.codecs[k]->type;
132 break; 133 break;
133 } 134 }
134 } 135 }
135 136
136 if (!found_codec) 137 if (!found_codec) {
138 MEDIA_LOG(log_cb) << "Codec '" << codecs[j]
139 <<"' is not supported for '" << type << "'";
137 return false; 140 return false;
141 }
138 142
139 switch (codec_type) { 143 switch (codec_type) {
140 case DemuxerStream::AUDIO: 144 case DemuxerStream::AUDIO:
141 *has_audio = true; 145 *has_audio = true;
142 break; 146 break;
143 case DemuxerStream::VIDEO: 147 case DemuxerStream::VIDEO:
144 *has_video = true; 148 *has_video = true;
145 break; 149 break;
146 default: 150 default:
147 DVLOG(1) << "Unsupported codec type '"<< codec_type << "' for " 151 MEDIA_LOG(log_cb) << "Unsupported codec type '"<< codec_type
148 << codecs[j]; 152 << "' for " << codecs[j];
149 return false; 153 return false;
150 } 154 }
151 } 155 }
152 156
153 *factory_function = type_info.factory_function; 157 *factory_function = type_info.factory_function;
154 158
155 // All codecs were supported by this |type|. 159 // All codecs were supported by this |type|.
156 return true; 160 return true;
157 } 161 }
158 } 162 }
159 163
160 // |type| didn't match any of the supported types. 164 // |type| didn't match any of the supported types.
161 return false; 165 return false;
162 } 166 }
163 167
164 class ChunkDemuxerStream : public DemuxerStream { 168 class ChunkDemuxerStream : public DemuxerStream {
165 public: 169 public:
166 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; 170 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
167 typedef std::deque<ReadCB> ReadCBQueue; 171 typedef std::deque<ReadCB> ReadCBQueue;
168 typedef std::deque<base::Closure> ClosureQueue; 172 typedef std::deque<base::Closure> ClosureQueue;
169 173
170 explicit ChunkDemuxerStream(const AudioDecoderConfig& audio_config); 174 ChunkDemuxerStream(const AudioDecoderConfig& audio_config,
171 explicit ChunkDemuxerStream(const VideoDecoderConfig& video_config); 175 const LogCB& log_cb);
176 ChunkDemuxerStream(const VideoDecoderConfig& video_config,
177 const LogCB& log_cb);
172 178
173 void StartWaitingForSeek(); 179 void StartWaitingForSeek();
174 void Seek(TimeDelta time); 180 void Seek(TimeDelta time);
175 void CancelPendingSeek(); 181 void CancelPendingSeek();
176 bool IsSeekPending() const; 182 bool IsSeekPending() const;
177 183
178 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, 184 // Add buffers to this stream. Buffers are stored in SourceBufferStreams,
179 // which handle ordering and overlap resolution. 185 // which handle ordering and overlap resolution.
180 // Returns true if buffers were successfully added. 186 // Returns true if buffers were successfully added.
181 bool Append(const StreamParser::BufferQueue& buffers); 187 bool Append(const StreamParser::BufferQueue& buffers);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 scoped_ptr<SourceBufferStream> stream_; 247 scoped_ptr<SourceBufferStream> stream_;
242 248
243 mutable base::Lock lock_; 249 mutable base::Lock lock_;
244 State state_; 250 State state_;
245 ReadCBQueue read_cbs_; 251 ReadCBQueue read_cbs_;
246 bool end_of_stream_; 252 bool end_of_stream_;
247 253
248 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); 254 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream);
249 }; 255 };
250 256
251 ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config) 257 ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config,
258 const LogCB& log_cb)
252 : type_(AUDIO), 259 : type_(AUDIO),
253 state_(RETURNING_DATA_FOR_READS), 260 state_(RETURNING_DATA_FOR_READS),
254 end_of_stream_(false) { 261 end_of_stream_(false) {
255 stream_.reset(new SourceBufferStream(audio_config)); 262 stream_.reset(new SourceBufferStream(audio_config, log_cb));
256 } 263 }
257 264
258 ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config) 265 ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config,
266 const LogCB& log_cb)
259 : type_(VIDEO), 267 : type_(VIDEO),
260 state_(RETURNING_DATA_FOR_READS), 268 state_(RETURNING_DATA_FOR_READS),
261 end_of_stream_(false) { 269 end_of_stream_(false) {
262 stream_.reset(new SourceBufferStream(video_config)); 270 stream_.reset(new SourceBufferStream(video_config, log_cb));
263 } 271 }
264 272
265 void ChunkDemuxerStream::StartWaitingForSeek() { 273 void ChunkDemuxerStream::StartWaitingForSeek() {
266 DVLOG(1) << "ChunkDemuxerStream::StartWaitingForSeek()"; 274 DVLOG(1) << "ChunkDemuxerStream::StartWaitingForSeek()";
267 ReadCBQueue read_cbs; 275 ReadCBQueue read_cbs;
268 { 276 {
269 base::AutoLock auto_lock(lock_); 277 base::AutoLock auto_lock(lock_);
270 if (state_ != CANCELED) 278 if (state_ != CANCELED)
271 end_of_stream_ = false; 279 end_of_stream_ = false;
272 ChangeState_Locked(WAITING_FOR_SEEK); 280 ChangeState_Locked(WAITING_FOR_SEEK);
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 *status = DemuxerStream::kOk; 534 *status = DemuxerStream::kOk;
527 *buffer = StreamParserBuffer::CreateEOSBuffer(); 535 *buffer = StreamParserBuffer::CreateEOSBuffer();
528 return true; 536 return true;
529 } 537 }
530 538
531 NOTREACHED(); 539 NOTREACHED();
532 return false; 540 return false;
533 } 541 }
534 542
535 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb, 543 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb,
536 const NeedKeyCB& need_key_cb) 544 const NeedKeyCB& need_key_cb,
545 const LogCB& log_cb)
537 : state_(WAITING_FOR_INIT), 546 : state_(WAITING_FOR_INIT),
538 host_(NULL), 547 host_(NULL),
539 open_cb_(open_cb), 548 open_cb_(open_cb),
540 need_key_cb_(need_key_cb) { 549 need_key_cb_(need_key_cb),
550 log_cb_(log_cb) {
541 DCHECK(!open_cb_.is_null()); 551 DCHECK(!open_cb_.is_null());
542 DCHECK(!need_key_cb_.is_null()); 552 DCHECK(!need_key_cb_.is_null());
543 } 553 }
544 554
545 void ChunkDemuxer::Initialize(DemuxerHost* host, const PipelineStatusCB& cb) { 555 void ChunkDemuxer::Initialize(DemuxerHost* host, const PipelineStatusCB& cb) {
546 DVLOG(1) << "Init()"; 556 DVLOG(1) << "Init()";
547 557
548 base::AutoLock auto_lock(lock_); 558 base::AutoLock auto_lock(lock_);
549 DCHECK_EQ(state_, WAITING_FOR_INIT); 559 DCHECK_EQ(state_, WAITING_FOR_INIT);
550 host_ = host; 560 host_ = host;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 DCHECK_GT(codecs.size(), 0u); 665 DCHECK_GT(codecs.size(), 0u);
656 base::AutoLock auto_lock(lock_); 666 base::AutoLock auto_lock(lock_);
657 667
658 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || 668 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) ||
659 stream_parser_map_.count(id) > 0u) 669 stream_parser_map_.count(id) > 0u)
660 return kReachedIdLimit; 670 return kReachedIdLimit;
661 671
662 bool has_audio = false; 672 bool has_audio = false;
663 bool has_video = false; 673 bool has_video = false;
664 ParserFactoryFunction factory_function = NULL; 674 ParserFactoryFunction factory_function = NULL;
665 if (!IsSupported(type, codecs, &factory_function, &has_audio, &has_video)) 675 std::string error;
676 if (!IsSupported(type, codecs, log_cb_, &factory_function, &has_audio,
677 &has_video)) {
666 return kNotSupported; 678 return kNotSupported;
679 }
667 680
668 if ((has_audio && !source_id_audio_.empty()) || 681 if ((has_audio && !source_id_audio_.empty()) ||
669 (has_video && !source_id_video_.empty())) 682 (has_video && !source_id_video_.empty()))
670 return kReachedIdLimit; 683 return kReachedIdLimit;
671 684
672 StreamParser::NewBuffersCB audio_cb; 685 StreamParser::NewBuffersCB audio_cb;
673 StreamParser::NewBuffersCB video_cb; 686 StreamParser::NewBuffersCB video_cb;
674 687
675 if (has_audio) { 688 if (has_audio) {
676 source_id_audio_ = id; 689 source_id_audio_ = id;
(...skipping 12 matching lines...) Expand all
689 702
690 stream_parser->Init( 703 stream_parser->Init(
691 base::Bind(&ChunkDemuxer::OnStreamParserInitDone, base::Unretained(this)), 704 base::Bind(&ChunkDemuxer::OnStreamParserInitDone, base::Unretained(this)),
692 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this), 705 base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this),
693 has_audio, has_video), 706 has_audio, has_video),
694 audio_cb, 707 audio_cb,
695 video_cb, 708 video_cb,
696 base::Bind(&ChunkDemuxer::OnNeedKey, base::Unretained(this)), 709 base::Bind(&ChunkDemuxer::OnNeedKey, base::Unretained(this)),
697 base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id), 710 base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id),
698 base::Bind(&ChunkDemuxer::OnEndOfMediaSegment, 711 base::Bind(&ChunkDemuxer::OnEndOfMediaSegment,
699 base::Unretained(this), id)); 712 base::Unretained(this), id),
713 log_cb_);
700 714
701 stream_parser_map_[id] = stream_parser.release(); 715 stream_parser_map_[id] = stream_parser.release();
702 SourceInfo info = { base::TimeDelta(), true }; 716 SourceInfo info = { base::TimeDelta(), true };
703 source_info_map_[id] = info; 717 source_info_map_[id] = info;
704 718
705 return kOk; 719 return kOk;
706 } 720 }
707 721
708 void ChunkDemuxer::RemoveId(const std::string& id) { 722 void ChunkDemuxer::RemoveId(const std::string& id) {
709 CHECK(IsValidId(id)); 723 CHECK(IsValidId(id));
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
1039 1053
1040 if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) { 1054 if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) {
1041 DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!"; 1055 DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!";
1042 return false; 1056 return false;
1043 } 1057 }
1044 1058
1045 // Signal an error if we get configuration info for stream types that weren't 1059 // Signal an error if we get configuration info for stream types that weren't
1046 // specified in AddId() or more configs after a stream is initialized. 1060 // specified in AddId() or more configs after a stream is initialized.
1047 // Only allow a single audio config for now. 1061 // Only allow a single audio config for now.
1048 if (has_audio != audio_config.IsValidConfig()) { 1062 if (has_audio != audio_config.IsValidConfig()) {
1049 DVLOG(1) << "OnNewConfigs() : Got unexpected audio config."; 1063 MEDIA_LOG(log_cb_)
1064 << "Initialization segment"
1065 << (audio_config.IsValidConfig() ? " has" : " does not have")
1066 << " an audio track, but the mimetype"
1067 << (has_audio ? " specifies" : " does not specify")
1068 << " an audio codec.";
1050 return false; 1069 return false;
1051 } 1070 }
1052 1071
1053 // Only allow a single video config for now. 1072 // Only allow a single video config for now.
1054 if (has_video != video_config.IsValidConfig()) { 1073 if (has_video != video_config.IsValidConfig()) {
1055 DVLOG(1) << "OnNewConfigs() : Got unexpected video config."; 1074 MEDIA_LOG(log_cb_)
1075 << "Initialization segment"
1076 << (video_config.IsValidConfig() ? " has" : " does not have")
1077 << " a video track, but the mimetype"
1078 << (has_video ? " specifies" : " does not specify")
1079 << " a video codec.";
1056 return false; 1080 return false;
1057 } 1081 }
1058 1082
1059 bool success = true; 1083 bool success = true;
1060 if (audio_config.IsValidConfig()) { 1084 if (audio_config.IsValidConfig()) {
1061 if (audio_) { 1085 if (audio_) {
1062 success &= audio_->UpdateAudioConfig(audio_config); 1086 success &= audio_->UpdateAudioConfig(audio_config);
1063 } else { 1087 } else {
1064 audio_ = new ChunkDemuxerStream(audio_config); 1088 audio_ = new ChunkDemuxerStream(audio_config, log_cb_);
1065 } 1089 }
1066 } 1090 }
1067 1091
1068 if (video_config.IsValidConfig()) { 1092 if (video_config.IsValidConfig()) {
1069 if (video_) { 1093 if (video_) {
1070 success &= video_->UpdateVideoConfig(video_config); 1094 success &= video_->UpdateVideoConfig(video_config);
1071 } else { 1095 } else {
1072 video_ = new ChunkDemuxerStream(video_config); 1096 video_ = new ChunkDemuxerStream(video_config, log_cb_);
1073 } 1097 }
1074 } 1098 }
1075 1099
1076 DVLOG(1) << "OnNewConfigs() : success " << success; 1100 DVLOG(1) << "OnNewConfigs() : success " << success;
1077 return success; 1101 return success;
1078 } 1102 }
1079 1103
1080 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { 1104 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) {
1081 lock_.AssertAcquired(); 1105 lock_.AssertAcquired();
1082 DCHECK_NE(state_, SHUTDOWN); 1106 DCHECK_NE(state_, SHUTDOWN);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1200 1224
1201 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { 1225 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const {
1202 if (audio_ && !video_) 1226 if (audio_ && !video_)
1203 return audio_->GetBufferedRanges(duration_); 1227 return audio_->GetBufferedRanges(duration_);
1204 else if (!audio_ && video_) 1228 else if (!audio_ && video_)
1205 return video_->GetBufferedRanges(duration_); 1229 return video_->GetBufferedRanges(duration_);
1206 return ComputeIntersection(); 1230 return ComputeIntersection();
1207 } 1231 }
1208 1232
1209 } // namespace media 1233 } // 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