cc: Fix logic for detecting when raster tasks were throttled
[chromium-blink-merge.git] / media / webm / webm_tracks_parser.cc
blob771480fdf55aa7594753db23cbd2e91e0d0a1c64
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
3 // found in the LICENSE file.
5 #include "media/webm/webm_tracks_parser.h"
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h"
10 #include "media/base/buffers.h"
11 #include "media/webm/webm_constants.h"
12 #include "media/webm/webm_content_encodings.h"
14 namespace media {
16 static TextKind CodecIdToTextKind(const std::string& codec_id) {
17 if (codec_id == kWebMCodecSubtitles)
18 return kTextSubtitles;
20 if (codec_id == kWebMCodecCaptions)
21 return kTextCaptions;
23 if (codec_id == kWebMCodecDescriptions)
24 return kTextDescriptions;
26 if (codec_id == kWebMCodecMetadata)
27 return kTextMetadata;
29 return kTextNone;
32 WebMTracksParser::WebMTracksParser(const LogCB& log_cb, bool ignore_text_tracks)
33 : track_type_(-1),
34 track_num_(-1),
35 track_uid_(-1),
36 seek_preroll_(-1),
37 codec_delay_(-1),
38 audio_track_num_(-1),
39 video_track_num_(-1),
40 ignore_text_tracks_(ignore_text_tracks),
41 log_cb_(log_cb),
42 audio_client_(log_cb),
43 video_client_(log_cb) {
46 WebMTracksParser::~WebMTracksParser() {}
48 int WebMTracksParser::Parse(const uint8* buf, int size) {
49 track_type_ =-1;
50 track_num_ = -1;
51 track_uid_ = -1;
52 track_name_.clear();
53 track_language_.clear();
54 audio_track_num_ = -1;
55 audio_decoder_config_ = AudioDecoderConfig();
56 video_track_num_ = -1;
57 video_decoder_config_ = VideoDecoderConfig();
58 text_tracks_.clear();
59 ignored_tracks_.clear();
61 WebMListParser parser(kWebMIdTracks, this);
62 int result = parser.Parse(buf, size);
64 if (result <= 0)
65 return result;
67 // For now we do all or nothing parsing.
68 return parser.IsParsingComplete() ? result : 0;
71 WebMParserClient* WebMTracksParser::OnListStart(int id) {
72 if (id == kWebMIdContentEncodings) {
73 DCHECK(!track_content_encodings_client_.get());
74 track_content_encodings_client_.reset(
75 new WebMContentEncodingsClient(log_cb_));
76 return track_content_encodings_client_->OnListStart(id);
79 if (id == kWebMIdTrackEntry) {
80 track_type_ = -1;
81 track_num_ = -1;
82 track_name_.clear();
83 track_language_.clear();
84 codec_id_ = "";
85 codec_private_.clear();
86 audio_client_.Reset();
87 video_client_.Reset();
88 return this;
91 if (id == kWebMIdAudio)
92 return &audio_client_;
94 if (id == kWebMIdVideo)
95 return &video_client_;
97 return this;
100 bool WebMTracksParser::OnListEnd(int id) {
101 if (id == kWebMIdContentEncodings) {
102 DCHECK(track_content_encodings_client_.get());
103 return track_content_encodings_client_->OnListEnd(id);
106 if (id == kWebMIdTrackEntry) {
107 if (track_type_ == -1 || track_num_ == -1 || track_uid_ == -1) {
108 MEDIA_LOG(log_cb_) << "Missing TrackEntry data for "
109 << " TrackType " << track_type_
110 << " TrackNum " << track_num_
111 << " TrackUID " << track_uid_;
112 return false;
115 if (track_type_ != kWebMTrackTypeAudio &&
116 track_type_ != kWebMTrackTypeVideo &&
117 track_type_ != kWebMTrackTypeSubtitlesOrCaptions &&
118 track_type_ != kWebMTrackTypeDescriptionsOrMetadata) {
119 MEDIA_LOG(log_cb_) << "Unexpected TrackType " << track_type_;
120 return false;
123 TextKind text_track_kind = kTextNone;
124 if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions) {
125 text_track_kind = CodecIdToTextKind(codec_id_);
126 if (text_track_kind == kTextNone) {
127 MEDIA_LOG(log_cb_) << "Missing TrackEntry CodecID"
128 << " TrackNum " << track_num_;
129 return false;
132 if (text_track_kind != kTextSubtitles &&
133 text_track_kind != kTextCaptions) {
134 MEDIA_LOG(log_cb_) << "Wrong TrackEntry CodecID"
135 << " TrackNum " << track_num_;
136 return false;
138 } else if (track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
139 text_track_kind = CodecIdToTextKind(codec_id_);
140 if (text_track_kind == kTextNone) {
141 MEDIA_LOG(log_cb_) << "Missing TrackEntry CodecID"
142 << " TrackNum " << track_num_;
143 return false;
146 if (text_track_kind != kTextDescriptions &&
147 text_track_kind != kTextMetadata) {
148 MEDIA_LOG(log_cb_) << "Wrong TrackEntry CodecID"
149 << " TrackNum " << track_num_;
150 return false;
154 std::string encryption_key_id;
155 if (track_content_encodings_client_) {
156 DCHECK(!track_content_encodings_client_->content_encodings().empty());
157 // If we have multiple ContentEncoding in one track. Always choose the
158 // key id in the first ContentEncoding as the key id of the track.
159 encryption_key_id = track_content_encodings_client_->
160 content_encodings()[0]->encryption_key_id();
163 if (track_type_ == kWebMTrackTypeAudio) {
164 if (audio_track_num_ == -1) {
165 audio_track_num_ = track_num_;
166 audio_encryption_key_id_ = encryption_key_id;
168 DCHECK(!audio_decoder_config_.IsValidConfig());
169 if (!audio_client_.InitializeConfig(
170 codec_id_, codec_private_, seek_preroll_, codec_delay_,
171 !audio_encryption_key_id_.empty(), &audio_decoder_config_)) {
172 return false;
174 } else {
175 MEDIA_LOG(log_cb_) << "Ignoring audio track " << track_num_;
176 ignored_tracks_.insert(track_num_);
178 } else if (track_type_ == kWebMTrackTypeVideo) {
179 if (video_track_num_ == -1) {
180 video_track_num_ = track_num_;
181 video_encryption_key_id_ = encryption_key_id;
183 DCHECK(!video_decoder_config_.IsValidConfig());
184 if (!video_client_.InitializeConfig(
185 codec_id_, codec_private_, !video_encryption_key_id_.empty(),
186 &video_decoder_config_)) {
187 return false;
189 } else {
190 MEDIA_LOG(log_cb_) << "Ignoring video track " << track_num_;
191 ignored_tracks_.insert(track_num_);
193 } else if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions ||
194 track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
195 if (ignore_text_tracks_) {
196 MEDIA_LOG(log_cb_) << "Ignoring text track " << track_num_;
197 ignored_tracks_.insert(track_num_);
198 } else {
199 std::string track_uid = base::Int64ToString(track_uid_);
200 text_tracks_[track_num_] = TextTrackConfig(text_track_kind,
201 track_name_,
202 track_language_,
203 track_uid);
205 } else {
206 MEDIA_LOG(log_cb_) << "Unexpected TrackType " << track_type_;
207 return false;
210 track_type_ = -1;
211 track_num_ = -1;
212 track_uid_ = -1;
213 track_name_.clear();
214 track_language_.clear();
215 codec_id_ = "";
216 codec_private_.clear();
217 track_content_encodings_client_.reset();
219 audio_client_.Reset();
220 video_client_.Reset();
221 return true;
224 return true;
227 bool WebMTracksParser::OnUInt(int id, int64 val) {
228 int64* dst = NULL;
230 switch (id) {
231 case kWebMIdTrackNumber:
232 dst = &track_num_;
233 break;
234 case kWebMIdTrackType:
235 dst = &track_type_;
236 break;
237 case kWebMIdTrackUID:
238 dst = &track_uid_;
239 break;
240 case kWebMIdSeekPreRoll:
241 dst = &seek_preroll_;
242 break;
243 case kWebMIdCodecDelay:
244 dst = &codec_delay_;
245 break;
246 default:
247 return true;
250 if (*dst != -1) {
251 MEDIA_LOG(log_cb_) << "Multiple values for id " << std::hex << id
252 << " specified";
253 return false;
256 *dst = val;
257 return true;
260 bool WebMTracksParser::OnFloat(int id, double val) {
261 return true;
264 bool WebMTracksParser::OnBinary(int id, const uint8* data, int size) {
265 if (id == kWebMIdCodecPrivate) {
266 if (!codec_private_.empty()) {
267 MEDIA_LOG(log_cb_) << "Multiple CodecPrivate fields in a track.";
268 return false;
271 codec_private_.assign(data, data + size);
272 return true;
274 return true;
277 bool WebMTracksParser::OnString(int id, const std::string& str) {
278 if (id == kWebMIdCodecID) {
279 if (!codec_id_.empty()) {
280 MEDIA_LOG(log_cb_) << "Multiple CodecID fields in a track";
281 return false;
284 codec_id_ = str;
285 return true;
288 if (id == kWebMIdName) {
289 track_name_ = str;
290 return true;
293 if (id == kWebMIdLanguage) {
294 track_language_ = str;
295 return true;
298 return true;
301 } // namespace media