| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/formats/webm/webm_tracks_parser.h" | 5 #include "media/formats/webm/webm_tracks_parser.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "media/base/buffers.h" | 10 #include "media/base/buffers.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 | 36 |
| 37 int64 mult = duration_in_ns / 1000; | 37 int64 mult = duration_in_ns / 1000; |
| 38 mult /= timecode_scale_in_us; | 38 mult /= timecode_scale_in_us; |
| 39 if (mult == 0) | 39 if (mult == 0) |
| 40 return kNoTimestamp(); | 40 return kNoTimestamp(); |
| 41 | 41 |
| 42 mult = static_cast<double>(mult) * timecode_scale_in_us; | 42 mult = static_cast<double>(mult) * timecode_scale_in_us; |
| 43 return base::TimeDelta::FromMicroseconds(mult); | 43 return base::TimeDelta::FromMicroseconds(mult); |
| 44 } | 44 } |
| 45 | 45 |
| 46 WebMTracksParser::WebMTracksParser(const LogCB& log_cb, bool ignore_text_tracks) | 46 WebMTracksParser::WebMTracksParser(const scoped_refptr<MediaLog>& media_log, |
| 47 bool ignore_text_tracks) |
| 47 : track_type_(-1), | 48 : track_type_(-1), |
| 48 track_num_(-1), | 49 track_num_(-1), |
| 49 seek_preroll_(-1), | 50 seek_preroll_(-1), |
| 50 codec_delay_(-1), | 51 codec_delay_(-1), |
| 51 default_duration_(-1), | 52 default_duration_(-1), |
| 52 audio_track_num_(-1), | 53 audio_track_num_(-1), |
| 53 audio_default_duration_(-1), | 54 audio_default_duration_(-1), |
| 54 video_track_num_(-1), | 55 video_track_num_(-1), |
| 55 video_default_duration_(-1), | 56 video_default_duration_(-1), |
| 56 ignore_text_tracks_(ignore_text_tracks), | 57 ignore_text_tracks_(ignore_text_tracks), |
| 57 log_cb_(log_cb), | 58 media_log_(media_log), |
| 58 audio_client_(log_cb), | 59 audio_client_(media_log), |
| 59 video_client_(log_cb) { | 60 video_client_(media_log) { |
| 60 } | 61 } |
| 61 | 62 |
| 62 WebMTracksParser::~WebMTracksParser() {} | 63 WebMTracksParser::~WebMTracksParser() {} |
| 63 | 64 |
| 64 int WebMTracksParser::Parse(const uint8* buf, int size) { | 65 int WebMTracksParser::Parse(const uint8* buf, int size) { |
| 65 track_type_ =-1; | 66 track_type_ =-1; |
| 66 track_num_ = -1; | 67 track_num_ = -1; |
| 67 default_duration_ = -1; | 68 default_duration_ = -1; |
| 68 track_name_.clear(); | 69 track_name_.clear(); |
| 69 track_language_.clear(); | 70 track_language_.clear(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 95 base::TimeDelta WebMTracksParser::GetVideoDefaultDuration( | 96 base::TimeDelta WebMTracksParser::GetVideoDefaultDuration( |
| 96 const double timecode_scale_in_us) const { | 97 const double timecode_scale_in_us) const { |
| 97 return PrecisionCappedDefaultDuration(timecode_scale_in_us, | 98 return PrecisionCappedDefaultDuration(timecode_scale_in_us, |
| 98 video_default_duration_); | 99 video_default_duration_); |
| 99 } | 100 } |
| 100 | 101 |
| 101 WebMParserClient* WebMTracksParser::OnListStart(int id) { | 102 WebMParserClient* WebMTracksParser::OnListStart(int id) { |
| 102 if (id == kWebMIdContentEncodings) { | 103 if (id == kWebMIdContentEncodings) { |
| 103 DCHECK(!track_content_encodings_client_.get()); | 104 DCHECK(!track_content_encodings_client_.get()); |
| 104 track_content_encodings_client_.reset( | 105 track_content_encodings_client_.reset( |
| 105 new WebMContentEncodingsClient(log_cb_)); | 106 new WebMContentEncodingsClient(media_log_)); |
| 106 return track_content_encodings_client_->OnListStart(id); | 107 return track_content_encodings_client_->OnListStart(id); |
| 107 } | 108 } |
| 108 | 109 |
| 109 if (id == kWebMIdTrackEntry) { | 110 if (id == kWebMIdTrackEntry) { |
| 110 track_type_ = -1; | 111 track_type_ = -1; |
| 111 track_num_ = -1; | 112 track_num_ = -1; |
| 112 default_duration_ = -1; | 113 default_duration_ = -1; |
| 113 track_name_.clear(); | 114 track_name_.clear(); |
| 114 track_language_.clear(); | 115 track_language_.clear(); |
| 115 codec_id_ = ""; | 116 codec_id_ = ""; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 129 } | 130 } |
| 130 | 131 |
| 131 bool WebMTracksParser::OnListEnd(int id) { | 132 bool WebMTracksParser::OnListEnd(int id) { |
| 132 if (id == kWebMIdContentEncodings) { | 133 if (id == kWebMIdContentEncodings) { |
| 133 DCHECK(track_content_encodings_client_.get()); | 134 DCHECK(track_content_encodings_client_.get()); |
| 134 return track_content_encodings_client_->OnListEnd(id); | 135 return track_content_encodings_client_->OnListEnd(id); |
| 135 } | 136 } |
| 136 | 137 |
| 137 if (id == kWebMIdTrackEntry) { | 138 if (id == kWebMIdTrackEntry) { |
| 138 if (track_type_ == -1 || track_num_ == -1) { | 139 if (track_type_ == -1 || track_num_ == -1) { |
| 139 MEDIA_LOG(ERROR, log_cb_) << "Missing TrackEntry data for " | 140 MEDIA_LOG(ERROR, media_log_) << "Missing TrackEntry data for " |
| 140 << " TrackType " << track_type_ << " TrackNum " | 141 << " TrackType " << track_type_ |
| 141 << track_num_; | 142 << " TrackNum " << track_num_; |
| 142 return false; | 143 return false; |
| 143 } | 144 } |
| 144 | 145 |
| 145 if (track_type_ != kWebMTrackTypeAudio && | 146 if (track_type_ != kWebMTrackTypeAudio && |
| 146 track_type_ != kWebMTrackTypeVideo && | 147 track_type_ != kWebMTrackTypeVideo && |
| 147 track_type_ != kWebMTrackTypeSubtitlesOrCaptions && | 148 track_type_ != kWebMTrackTypeSubtitlesOrCaptions && |
| 148 track_type_ != kWebMTrackTypeDescriptionsOrMetadata) { | 149 track_type_ != kWebMTrackTypeDescriptionsOrMetadata) { |
| 149 MEDIA_LOG(ERROR, log_cb_) << "Unexpected TrackType " << track_type_; | 150 MEDIA_LOG(ERROR, media_log_) << "Unexpected TrackType " << track_type_; |
| 150 return false; | 151 return false; |
| 151 } | 152 } |
| 152 | 153 |
| 153 TextKind text_track_kind = kTextNone; | 154 TextKind text_track_kind = kTextNone; |
| 154 if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions) { | 155 if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions) { |
| 155 text_track_kind = CodecIdToTextKind(codec_id_); | 156 text_track_kind = CodecIdToTextKind(codec_id_); |
| 156 if (text_track_kind == kTextNone) { | 157 if (text_track_kind == kTextNone) { |
| 157 MEDIA_LOG(ERROR, log_cb_) << "Missing TrackEntry CodecID" | 158 MEDIA_LOG(ERROR, media_log_) << "Missing TrackEntry CodecID" |
| 158 << " TrackNum " << track_num_; | 159 << " TrackNum " << track_num_; |
| 159 return false; | 160 return false; |
| 160 } | 161 } |
| 161 | 162 |
| 162 if (text_track_kind != kTextSubtitles && | 163 if (text_track_kind != kTextSubtitles && |
| 163 text_track_kind != kTextCaptions) { | 164 text_track_kind != kTextCaptions) { |
| 164 MEDIA_LOG(ERROR, log_cb_) << "Wrong TrackEntry CodecID" | 165 MEDIA_LOG(ERROR, media_log_) << "Wrong TrackEntry CodecID" |
| 165 << " TrackNum " << track_num_; | 166 << " TrackNum " << track_num_; |
| 166 return false; | 167 return false; |
| 167 } | 168 } |
| 168 } else if (track_type_ == kWebMTrackTypeDescriptionsOrMetadata) { | 169 } else if (track_type_ == kWebMTrackTypeDescriptionsOrMetadata) { |
| 169 text_track_kind = CodecIdToTextKind(codec_id_); | 170 text_track_kind = CodecIdToTextKind(codec_id_); |
| 170 if (text_track_kind == kTextNone) { | 171 if (text_track_kind == kTextNone) { |
| 171 MEDIA_LOG(ERROR, log_cb_) << "Missing TrackEntry CodecID" | 172 MEDIA_LOG(ERROR, media_log_) << "Missing TrackEntry CodecID" |
| 172 << " TrackNum " << track_num_; | 173 << " TrackNum " << track_num_; |
| 173 return false; | 174 return false; |
| 174 } | 175 } |
| 175 | 176 |
| 176 if (text_track_kind != kTextDescriptions && | 177 if (text_track_kind != kTextDescriptions && |
| 177 text_track_kind != kTextMetadata) { | 178 text_track_kind != kTextMetadata) { |
| 178 MEDIA_LOG(ERROR, log_cb_) << "Wrong TrackEntry CodecID" | 179 MEDIA_LOG(ERROR, media_log_) << "Wrong TrackEntry CodecID" |
| 179 << " TrackNum " << track_num_; | 180 << " TrackNum " << track_num_; |
| 180 return false; | 181 return false; |
| 181 } | 182 } |
| 182 } | 183 } |
| 183 | 184 |
| 184 std::string encryption_key_id; | 185 std::string encryption_key_id; |
| 185 if (track_content_encodings_client_) { | 186 if (track_content_encodings_client_) { |
| 186 DCHECK(!track_content_encodings_client_->content_encodings().empty()); | 187 DCHECK(!track_content_encodings_client_->content_encodings().empty()); |
| 187 // If we have multiple ContentEncoding in one track. Always choose the | 188 // If we have multiple ContentEncoding in one track. Always choose the |
| 188 // key id in the first ContentEncoding as the key id of the track. | 189 // key id in the first ContentEncoding as the key id of the track. |
| 189 encryption_key_id = track_content_encodings_client_-> | 190 encryption_key_id = track_content_encodings_client_-> |
| 190 content_encodings()[0]->encryption_key_id(); | 191 content_encodings()[0]->encryption_key_id(); |
| 191 } | 192 } |
| 192 | 193 |
| 193 if (track_type_ == kWebMTrackTypeAudio) { | 194 if (track_type_ == kWebMTrackTypeAudio) { |
| 194 if (audio_track_num_ == -1) { | 195 if (audio_track_num_ == -1) { |
| 195 audio_track_num_ = track_num_; | 196 audio_track_num_ = track_num_; |
| 196 audio_encryption_key_id_ = encryption_key_id; | 197 audio_encryption_key_id_ = encryption_key_id; |
| 197 | 198 |
| 198 if (default_duration_ == 0) { | 199 if (default_duration_ == 0) { |
| 199 MEDIA_LOG(ERROR, log_cb_) << "Illegal 0ns audio TrackEntry " | 200 MEDIA_LOG(ERROR, media_log_) << "Illegal 0ns audio TrackEntry " |
| 200 "DefaultDuration"; | 201 "DefaultDuration"; |
| 201 return false; | 202 return false; |
| 202 } | 203 } |
| 203 audio_default_duration_ = default_duration_; | 204 audio_default_duration_ = default_duration_; |
| 204 | 205 |
| 205 DCHECK(!audio_decoder_config_.IsValidConfig()); | 206 DCHECK(!audio_decoder_config_.IsValidConfig()); |
| 206 if (!audio_client_.InitializeConfig( | 207 if (!audio_client_.InitializeConfig( |
| 207 codec_id_, codec_private_, seek_preroll_, codec_delay_, | 208 codec_id_, codec_private_, seek_preroll_, codec_delay_, |
| 208 !audio_encryption_key_id_.empty(), &audio_decoder_config_)) { | 209 !audio_encryption_key_id_.empty(), &audio_decoder_config_)) { |
| 209 return false; | 210 return false; |
| 210 } | 211 } |
| 211 } else { | 212 } else { |
| 212 MEDIA_LOG(DEBUG, log_cb_) << "Ignoring audio track " << track_num_; | 213 MEDIA_LOG(DEBUG, media_log_) << "Ignoring audio track " << track_num_; |
| 213 ignored_tracks_.insert(track_num_); | 214 ignored_tracks_.insert(track_num_); |
| 214 } | 215 } |
| 215 } else if (track_type_ == kWebMTrackTypeVideo) { | 216 } else if (track_type_ == kWebMTrackTypeVideo) { |
| 216 if (video_track_num_ == -1) { | 217 if (video_track_num_ == -1) { |
| 217 video_track_num_ = track_num_; | 218 video_track_num_ = track_num_; |
| 218 video_encryption_key_id_ = encryption_key_id; | 219 video_encryption_key_id_ = encryption_key_id; |
| 219 | 220 |
| 220 if (default_duration_ == 0) { | 221 if (default_duration_ == 0) { |
| 221 MEDIA_LOG(ERROR, log_cb_) << "Illegal 0ns video TrackEntry " | 222 MEDIA_LOG(ERROR, media_log_) << "Illegal 0ns video TrackEntry " |
| 222 "DefaultDuration"; | 223 "DefaultDuration"; |
| 223 return false; | 224 return false; |
| 224 } | 225 } |
| 225 video_default_duration_ = default_duration_; | 226 video_default_duration_ = default_duration_; |
| 226 | 227 |
| 227 DCHECK(!video_decoder_config_.IsValidConfig()); | 228 DCHECK(!video_decoder_config_.IsValidConfig()); |
| 228 if (!video_client_.InitializeConfig( | 229 if (!video_client_.InitializeConfig( |
| 229 codec_id_, codec_private_, !video_encryption_key_id_.empty(), | 230 codec_id_, codec_private_, !video_encryption_key_id_.empty(), |
| 230 &video_decoder_config_)) { | 231 &video_decoder_config_)) { |
| 231 return false; | 232 return false; |
| 232 } | 233 } |
| 233 } else { | 234 } else { |
| 234 MEDIA_LOG(DEBUG, log_cb_) << "Ignoring video track " << track_num_; | 235 MEDIA_LOG(DEBUG, media_log_) << "Ignoring video track " << track_num_; |
| 235 ignored_tracks_.insert(track_num_); | 236 ignored_tracks_.insert(track_num_); |
| 236 } | 237 } |
| 237 } else if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions || | 238 } else if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions || |
| 238 track_type_ == kWebMTrackTypeDescriptionsOrMetadata) { | 239 track_type_ == kWebMTrackTypeDescriptionsOrMetadata) { |
| 239 if (ignore_text_tracks_) { | 240 if (ignore_text_tracks_) { |
| 240 MEDIA_LOG(DEBUG, log_cb_) << "Ignoring text track " << track_num_; | 241 MEDIA_LOG(DEBUG, media_log_) << "Ignoring text track " << track_num_; |
| 241 ignored_tracks_.insert(track_num_); | 242 ignored_tracks_.insert(track_num_); |
| 242 } else { | 243 } else { |
| 243 std::string track_num = base::Int64ToString(track_num_); | 244 std::string track_num = base::Int64ToString(track_num_); |
| 244 text_tracks_[track_num_] = TextTrackConfig( | 245 text_tracks_[track_num_] = TextTrackConfig( |
| 245 text_track_kind, track_name_, track_language_, track_num); | 246 text_track_kind, track_name_, track_language_, track_num); |
| 246 } | 247 } |
| 247 } else { | 248 } else { |
| 248 MEDIA_LOG(ERROR, log_cb_) << "Unexpected TrackType " << track_type_; | 249 MEDIA_LOG(ERROR, media_log_) << "Unexpected TrackType " << track_type_; |
| 249 return false; | 250 return false; |
| 250 } | 251 } |
| 251 | 252 |
| 252 track_type_ = -1; | 253 track_type_ = -1; |
| 253 track_num_ = -1; | 254 track_num_ = -1; |
| 254 default_duration_ = -1; | 255 default_duration_ = -1; |
| 255 track_name_.clear(); | 256 track_name_.clear(); |
| 256 track_language_.clear(); | 257 track_language_.clear(); |
| 257 codec_id_ = ""; | 258 codec_id_ = ""; |
| 258 codec_private_.clear(); | 259 codec_private_.clear(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 283 dst = &codec_delay_; | 284 dst = &codec_delay_; |
| 284 break; | 285 break; |
| 285 case kWebMIdDefaultDuration: | 286 case kWebMIdDefaultDuration: |
| 286 dst = &default_duration_; | 287 dst = &default_duration_; |
| 287 break; | 288 break; |
| 288 default: | 289 default: |
| 289 return true; | 290 return true; |
| 290 } | 291 } |
| 291 | 292 |
| 292 if (*dst != -1) { | 293 if (*dst != -1) { |
| 293 MEDIA_LOG(ERROR, log_cb_) << "Multiple values for id " << std::hex << id | 294 MEDIA_LOG(ERROR, media_log_) << "Multiple values for id " << std::hex << id |
| 294 << " specified"; | 295 << " specified"; |
| 295 return false; | 296 return false; |
| 296 } | 297 } |
| 297 | 298 |
| 298 *dst = val; | 299 *dst = val; |
| 299 return true; | 300 return true; |
| 300 } | 301 } |
| 301 | 302 |
| 302 bool WebMTracksParser::OnFloat(int id, double val) { | 303 bool WebMTracksParser::OnFloat(int id, double val) { |
| 303 return true; | 304 return true; |
| 304 } | 305 } |
| 305 | 306 |
| 306 bool WebMTracksParser::OnBinary(int id, const uint8* data, int size) { | 307 bool WebMTracksParser::OnBinary(int id, const uint8* data, int size) { |
| 307 if (id == kWebMIdCodecPrivate) { | 308 if (id == kWebMIdCodecPrivate) { |
| 308 if (!codec_private_.empty()) { | 309 if (!codec_private_.empty()) { |
| 309 MEDIA_LOG(ERROR, log_cb_) << "Multiple CodecPrivate fields in a track."; | 310 MEDIA_LOG(ERROR, media_log_) |
| 311 << "Multiple CodecPrivate fields in a track."; |
| 310 return false; | 312 return false; |
| 311 } | 313 } |
| 312 codec_private_.assign(data, data + size); | 314 codec_private_.assign(data, data + size); |
| 313 return true; | 315 return true; |
| 314 } | 316 } |
| 315 return true; | 317 return true; |
| 316 } | 318 } |
| 317 | 319 |
| 318 bool WebMTracksParser::OnString(int id, const std::string& str) { | 320 bool WebMTracksParser::OnString(int id, const std::string& str) { |
| 319 if (id == kWebMIdCodecID) { | 321 if (id == kWebMIdCodecID) { |
| 320 if (!codec_id_.empty()) { | 322 if (!codec_id_.empty()) { |
| 321 MEDIA_LOG(ERROR, log_cb_) << "Multiple CodecID fields in a track"; | 323 MEDIA_LOG(ERROR, media_log_) << "Multiple CodecID fields in a track"; |
| 322 return false; | 324 return false; |
| 323 } | 325 } |
| 324 | 326 |
| 325 codec_id_ = str; | 327 codec_id_ = str; |
| 326 return true; | 328 return true; |
| 327 } | 329 } |
| 328 | 330 |
| 329 if (id == kWebMIdName) { | 331 if (id == kWebMIdName) { |
| 330 track_name_ = str; | 332 track_name_ = str; |
| 331 return true; | 333 return true; |
| 332 } | 334 } |
| 333 | 335 |
| 334 if (id == kWebMIdLanguage) { | 336 if (id == kWebMIdLanguage) { |
| 335 track_language_ = str; | 337 track_language_ = str; |
| 336 return true; | 338 return true; |
| 337 } | 339 } |
| 338 | 340 |
| 339 return true; | 341 return true; |
| 340 } | 342 } |
| 341 | 343 |
| 342 } // namespace media | 344 } // namespace media |
| OLD | NEW |