Ensure callback objects held by the Indexed DB
[chromium-blink-merge.git] / media / webm / webm_tracks_parser.cc
blobaa28d6feef958d1c5b073c5a1a2a393b1338f5f3
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_util.h"
9 #include "media/base/buffers.h"
10 #include "media/webm/webm_constants.h"
11 #include "media/webm/webm_content_encodings.h"
13 namespace media {
15 static TextKind CodecIdToTextKind(const std::string& codec_id) {
16 if (codec_id == kWebMCodecSubtitles)
17 return kTextSubtitles;
19 if (codec_id == kWebMCodecCaptions)
20 return kTextCaptions;
22 if (codec_id == kWebMCodecDescriptions)
23 return kTextDescriptions;
25 if (codec_id == kWebMCodecMetadata)
26 return kTextMetadata;
28 return kTextNone;
31 WebMTracksParser::WebMTracksParser(const LogCB& log_cb, bool ignore_text_tracks)
32 : track_type_(-1),
33 track_num_(-1),
34 seek_preroll_(-1),
35 codec_delay_(-1),
36 audio_track_num_(-1),
37 video_track_num_(-1),
38 ignore_text_tracks_(ignore_text_tracks),
39 log_cb_(log_cb),
40 audio_client_(log_cb),
41 video_client_(log_cb) {
44 WebMTracksParser::~WebMTracksParser() {}
46 int WebMTracksParser::Parse(const uint8* buf, int size) {
47 track_type_ =-1;
48 track_num_ = -1;
49 track_name_.clear();
50 track_language_.clear();
51 audio_track_num_ = -1;
52 audio_decoder_config_ = AudioDecoderConfig();
53 video_track_num_ = -1;
54 video_decoder_config_ = VideoDecoderConfig();
55 text_tracks_.clear();
56 ignored_tracks_.clear();
58 WebMListParser parser(kWebMIdTracks, this);
59 int result = parser.Parse(buf, size);
61 if (result <= 0)
62 return result;
64 // For now we do all or nothing parsing.
65 return parser.IsParsingComplete() ? result : 0;
68 WebMParserClient* WebMTracksParser::OnListStart(int id) {
69 if (id == kWebMIdContentEncodings) {
70 DCHECK(!track_content_encodings_client_.get());
71 track_content_encodings_client_.reset(
72 new WebMContentEncodingsClient(log_cb_));
73 return track_content_encodings_client_->OnListStart(id);
76 if (id == kWebMIdTrackEntry) {
77 track_type_ = -1;
78 track_num_ = -1;
79 track_name_.clear();
80 track_language_.clear();
81 codec_id_ = "";
82 codec_private_.clear();
83 audio_client_.Reset();
84 video_client_.Reset();
85 return this;
88 if (id == kWebMIdAudio)
89 return &audio_client_;
91 if (id == kWebMIdVideo)
92 return &video_client_;
94 return this;
97 bool WebMTracksParser::OnListEnd(int id) {
98 if (id == kWebMIdContentEncodings) {
99 DCHECK(track_content_encodings_client_.get());
100 return track_content_encodings_client_->OnListEnd(id);
103 if (id == kWebMIdTrackEntry) {
104 if (track_type_ == -1 || track_num_ == -1) {
105 MEDIA_LOG(log_cb_) << "Missing TrackEntry data for "
106 << " TrackType " << track_type_
107 << " TrackNum " << track_num_;
108 return false;
111 if (track_type_ != kWebMTrackTypeAudio &&
112 track_type_ != kWebMTrackTypeVideo &&
113 track_type_ != kWebMTrackTypeSubtitlesOrCaptions &&
114 track_type_ != kWebMTrackTypeDescriptionsOrMetadata) {
115 MEDIA_LOG(log_cb_) << "Unexpected TrackType " << track_type_;
116 return false;
119 TextKind text_track_kind = kTextNone;
120 if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions) {
121 text_track_kind = CodecIdToTextKind(codec_id_);
122 if (text_track_kind == kTextNone) {
123 MEDIA_LOG(log_cb_) << "Missing TrackEntry CodecID"
124 << " TrackNum " << track_num_;
125 return false;
128 if (text_track_kind != kTextSubtitles &&
129 text_track_kind != kTextCaptions) {
130 MEDIA_LOG(log_cb_) << "Wrong TrackEntry CodecID"
131 << " TrackNum " << track_num_;
132 return false;
134 } else if (track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
135 text_track_kind = CodecIdToTextKind(codec_id_);
136 if (text_track_kind == kTextNone) {
137 MEDIA_LOG(log_cb_) << "Missing TrackEntry CodecID"
138 << " TrackNum " << track_num_;
139 return false;
142 if (text_track_kind != kTextDescriptions &&
143 text_track_kind != kTextMetadata) {
144 MEDIA_LOG(log_cb_) << "Wrong TrackEntry CodecID"
145 << " TrackNum " << track_num_;
146 return false;
150 std::string encryption_key_id;
151 if (track_content_encodings_client_) {
152 DCHECK(!track_content_encodings_client_->content_encodings().empty());
153 // If we have multiple ContentEncoding in one track. Always choose the
154 // key id in the first ContentEncoding as the key id of the track.
155 encryption_key_id = track_content_encodings_client_->
156 content_encodings()[0]->encryption_key_id();
159 if (track_type_ == kWebMTrackTypeAudio) {
160 if (audio_track_num_ == -1) {
161 audio_track_num_ = track_num_;
162 audio_encryption_key_id_ = encryption_key_id;
164 DCHECK(!audio_decoder_config_.IsValidConfig());
165 if (!audio_client_.InitializeConfig(
166 codec_id_, codec_private_, seek_preroll_, codec_delay_,
167 !audio_encryption_key_id_.empty(), &audio_decoder_config_)) {
168 return false;
170 } else {
171 MEDIA_LOG(log_cb_) << "Ignoring audio track " << track_num_;
172 ignored_tracks_.insert(track_num_);
174 } else if (track_type_ == kWebMTrackTypeVideo) {
175 if (video_track_num_ == -1) {
176 video_track_num_ = track_num_;
177 video_encryption_key_id_ = encryption_key_id;
179 DCHECK(!video_decoder_config_.IsValidConfig());
180 if (!video_client_.InitializeConfig(
181 codec_id_, codec_private_, !video_encryption_key_id_.empty(),
182 &video_decoder_config_)) {
183 return false;
185 } else {
186 MEDIA_LOG(log_cb_) << "Ignoring video track " << track_num_;
187 ignored_tracks_.insert(track_num_);
189 } else if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions ||
190 track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
191 if (ignore_text_tracks_) {
192 MEDIA_LOG(log_cb_) << "Ignoring text track " << track_num_;
193 ignored_tracks_.insert(track_num_);
194 } else {
195 TextTrackInfo& text_track_info = text_tracks_[track_num_];
196 text_track_info.kind = text_track_kind;
197 text_track_info.name = track_name_;
198 text_track_info.language = track_language_;
200 } else {
201 MEDIA_LOG(log_cb_) << "Unexpected TrackType " << track_type_;
202 return false;
205 track_type_ = -1;
206 track_num_ = -1;
207 track_name_.clear();
208 track_language_.clear();
209 codec_id_ = "";
210 codec_private_.clear();
211 track_content_encodings_client_.reset();
213 audio_client_.Reset();
214 video_client_.Reset();
215 return true;
218 return true;
221 bool WebMTracksParser::OnUInt(int id, int64 val) {
222 int64* dst = NULL;
224 switch (id) {
225 case kWebMIdTrackNumber:
226 dst = &track_num_;
227 break;
228 case kWebMIdTrackType:
229 dst = &track_type_;
230 break;
231 case kWebMIdSeekPreRoll:
232 dst = &seek_preroll_;
233 break;
234 case kWebMIdCodecDelay:
235 dst = &codec_delay_;
236 break;
237 default:
238 return true;
241 if (*dst != -1) {
242 MEDIA_LOG(log_cb_) << "Multiple values for id " << std::hex << id
243 << " specified";
244 return false;
247 *dst = val;
248 return true;
251 bool WebMTracksParser::OnFloat(int id, double val) {
252 return true;
255 bool WebMTracksParser::OnBinary(int id, const uint8* data, int size) {
256 if (id == kWebMIdCodecPrivate) {
257 if (!codec_private_.empty()) {
258 MEDIA_LOG(log_cb_) << "Multiple CodecPrivate fields in a track.";
259 return false;
262 codec_private_.assign(data, data + size);
263 return true;
265 return true;
268 bool WebMTracksParser::OnString(int id, const std::string& str) {
269 if (id == kWebMIdCodecID) {
270 if (!codec_id_.empty()) {
271 MEDIA_LOG(log_cb_) << "Multiple CodecID fields in a track";
272 return false;
275 codec_id_ = str;
276 return true;
279 if (id == kWebMIdName) {
280 track_name_ = str;
281 return true;
284 if (id == kWebMIdLanguage) {
285 track_language_ = str;
286 return true;
289 return true;
292 } // namespace media