5 #include "packager/media/formats/webm/webm_tracks_parser.h"
7 #include "packager/base/logging.h"
8 #include "packager/base/strings/string_number_conversions.h"
9 #include "packager/base/strings/string_util.h"
10 #include "packager/media/base/timestamp.h"
11 #include "packager/media/formats/webm/webm_constants.h"
12 #include "packager/media/formats/webm/webm_content_encodings.h"
17 static TextKind CodecIdToTextKind(
const std::string& codec_id) {
18 if (codec_id == kWebMCodecSubtitles)
19 return kTextSubtitles;
21 if (codec_id == kWebMCodecCaptions)
24 if (codec_id == kWebMCodecDescriptions)
25 return kTextDescriptions;
27 if (codec_id == kWebMCodecMetadata)
33 static int64_t PrecisionCappedDefaultDuration(
34 const double timecode_scale_in_us,
35 const int64_t duration_in_ns) {
36 if (duration_in_ns <= 0)
39 int64_t mult = duration_in_ns / 1000;
40 mult /= timecode_scale_in_us;
44 mult =
static_cast<double>(mult) * timecode_scale_in_us;
48 WebMTracksParser::WebMTracksParser(
bool ignore_text_tracks)
53 default_duration_(-1),
55 audio_default_duration_(-1),
57 video_default_duration_(-1),
58 ignore_text_tracks_(ignore_text_tracks),
63 WebMTracksParser::~WebMTracksParser() {}
68 default_duration_ = -1;
70 track_language_.clear();
71 audio_track_num_ = -1;
72 audio_default_duration_ = -1;
73 audio_stream_info_ =
nullptr;
74 video_track_num_ = -1;
75 video_default_duration_ = -1;
76 video_stream_info_ =
nullptr;
78 ignored_tracks_.clear();
81 int result = parser.
Parse(buf, size);
91 const double timecode_scale_in_us)
const {
92 return PrecisionCappedDefaultDuration(timecode_scale_in_us,
93 audio_default_duration_);
96 int64_t WebMTracksParser::GetVideoDefaultDuration(
97 const double timecode_scale_in_us)
const {
98 return PrecisionCappedDefaultDuration(timecode_scale_in_us,
99 video_default_duration_);
102 WebMParserClient* WebMTracksParser::OnListStart(
int id) {
103 if (
id == kWebMIdContentEncodings) {
104 DCHECK(!track_content_encodings_client_.get());
105 track_content_encodings_client_.reset(
new WebMContentEncodingsClient());
106 return track_content_encodings_client_->OnListStart(
id);
109 if (
id == kWebMIdTrackEntry) {
112 default_duration_ = -1;
114 track_language_.clear();
116 codec_private_.clear();
117 audio_client_.
Reset();
118 video_client_.
Reset();
122 if (
id == kWebMIdAudio)
123 return &audio_client_;
125 if (
id == kWebMIdVideo)
126 return &video_client_;
131 bool WebMTracksParser::OnListEnd(
int id) {
132 if (
id == kWebMIdContentEncodings) {
133 DCHECK(track_content_encodings_client_.get());
134 return track_content_encodings_client_->OnListEnd(
id);
137 if (
id == kWebMIdTrackEntry) {
138 if (track_type_ == -1 || track_num_ == -1) {
139 LOG(ERROR) <<
"Missing TrackEntry data for "
140 <<
" TrackType " << track_type_ <<
" TrackNum " << track_num_;
144 if (track_type_ != kWebMTrackTypeAudio &&
145 track_type_ != kWebMTrackTypeVideo &&
146 track_type_ != kWebMTrackTypeSubtitlesOrCaptions &&
147 track_type_ != kWebMTrackTypeDescriptionsOrMetadata) {
148 LOG(ERROR) <<
"Unexpected TrackType " << track_type_;
152 TextKind text_track_kind = kTextNone;
153 if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions) {
154 text_track_kind = CodecIdToTextKind(codec_id_);
155 if (text_track_kind == kTextNone) {
156 LOG(ERROR) <<
"Missing TrackEntry CodecID"
157 <<
" TrackNum " << track_num_;
161 if (text_track_kind != kTextSubtitles &&
162 text_track_kind != kTextCaptions) {
163 LOG(ERROR) <<
"Wrong TrackEntry CodecID"
164 <<
" TrackNum " << track_num_;
167 }
else if (track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
168 text_track_kind = CodecIdToTextKind(codec_id_);
169 if (text_track_kind == kTextNone) {
170 LOG(ERROR) <<
"Missing TrackEntry CodecID"
171 <<
" TrackNum " << track_num_;
175 if (text_track_kind != kTextDescriptions &&
176 text_track_kind != kTextMetadata) {
177 LOG(ERROR) <<
"Wrong TrackEntry CodecID"
178 <<
" TrackNum " << track_num_;
183 std::string encryption_key_id;
184 if (track_content_encodings_client_) {
185 DCHECK(!track_content_encodings_client_->content_encodings().empty());
188 encryption_key_id = track_content_encodings_client_->
189 content_encodings()[0]->encryption_key_id();
192 if (track_type_ == kWebMTrackTypeAudio) {
193 if (audio_track_num_ == -1) {
194 audio_track_num_ = track_num_;
195 audio_encryption_key_id_ = encryption_key_id;
197 if (default_duration_ == 0) {
198 LOG(ERROR) <<
"Illegal 0ns audio TrackEntry "
202 audio_default_duration_ = default_duration_;
204 DCHECK(!audio_stream_info_);
206 audio_track_num_, codec_id_, codec_private_, seek_preroll_,
207 codec_delay_, track_language_, !audio_encryption_key_id_.empty());
208 if (!audio_stream_info_)
211 DLOG(INFO) <<
"Ignoring audio track " << track_num_;
212 ignored_tracks_.insert(track_num_);
214 }
else if (track_type_ == kWebMTrackTypeVideo) {
215 if (video_track_num_ == -1) {
216 video_track_num_ = track_num_;
217 video_encryption_key_id_ = encryption_key_id;
219 if (default_duration_ == 0) {
220 LOG(ERROR) <<
"Illegal 0ns video TrackEntry "
224 video_default_duration_ = default_duration_;
226 DCHECK(!video_stream_info_);
229 video_track_num_, codec_id_, !video_encryption_key_id_.empty());
230 if (!video_stream_info_)
233 DLOG(INFO) <<
"Ignoring video track " << track_num_;
234 ignored_tracks_.insert(track_num_);
236 }
else if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions ||
237 track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
238 if (ignore_text_tracks_) {
239 DLOG(INFO) <<
"Ignoring text track " << track_num_;
240 ignored_tracks_.insert(track_num_);
242 std::string track_num = base::Int64ToString(track_num_);
243 text_tracks_[track_num_] = TextTrackConfig(
244 text_track_kind, track_name_, track_language_, track_num);
247 LOG(ERROR) <<
"Unexpected TrackType " << track_type_;
253 default_duration_ = -1;
255 track_language_.clear();
257 codec_private_.clear();
258 track_content_encodings_client_.reset();
260 audio_client_.
Reset();
261 video_client_.
Reset();
268 bool WebMTracksParser::OnUInt(
int id, int64_t val) {
272 case kWebMIdTrackNumber:
275 case kWebMIdTrackType:
278 case kWebMIdSeekPreRoll:
279 dst = &seek_preroll_;
281 case kWebMIdCodecDelay:
284 case kWebMIdDefaultDuration:
285 dst = &default_duration_;
292 LOG(ERROR) <<
"Multiple values for id " << std::hex <<
id <<
" specified";
300 bool WebMTracksParser::OnFloat(
int id,
double val) {
304 bool WebMTracksParser::OnBinary(
int id,
const uint8_t* data,
int size) {
305 if (
id == kWebMIdCodecPrivate) {
306 if (!codec_private_.empty()) {
307 LOG(ERROR) <<
"Multiple CodecPrivate fields in a track.";
310 codec_private_.assign(data, data + size);
316 bool WebMTracksParser::OnString(
int id,
const std::string& str) {
317 if (
id == kWebMIdCodecID) {
318 if (!codec_id_.empty()) {
319 LOG(ERROR) <<
"Multiple CodecID fields in a track";
327 if (
id == kWebMIdName) {
332 if (
id == kWebMIdLanguage) {
333 track_language_ = str;