5 #include <packager/media/formats/webm/webm_tracks_parser.h>
7 #include <absl/log/check.h>
8 #include <absl/log/log.h>
9 #include <absl/strings/str_format.h>
11 #include <packager/media/base/timestamp.h>
12 #include <packager/media/formats/webm/webm_constants.h>
13 #include <packager/media/formats/webm/webm_content_encodings.h>
18 static TextKind CodecIdToTextKind(
const std::string& codec_id) {
19 if (codec_id == kWebMCodecSubtitles)
20 return kTextSubtitles;
22 if (codec_id == kWebMCodecCaptions)
25 if (codec_id == kWebMCodecDescriptions)
26 return kTextDescriptions;
28 if (codec_id == kWebMCodecMetadata)
34 static int64_t PrecisionCappedDefaultDuration(
35 const double timecode_scale_in_us,
36 const int64_t duration_in_ns) {
37 if (duration_in_ns <= 0)
40 int64_t mult = duration_in_ns / 1000;
41 mult /= timecode_scale_in_us;
45 mult =
static_cast<double>(mult) * timecode_scale_in_us;
49 WebMTracksParser::WebMTracksParser(
bool ignore_text_tracks)
54 default_duration_(-1),
56 audio_default_duration_(-1),
58 video_default_duration_(-1),
59 ignore_text_tracks_(ignore_text_tracks),
64 WebMTracksParser::~WebMTracksParser() {}
66 int WebMTracksParser::Parse(
const uint8_t* buf,
int size) {
69 default_duration_ = -1;
71 track_language_.clear();
72 audio_track_num_ = -1;
73 audio_default_duration_ = -1;
74 audio_stream_info_ =
nullptr;
75 video_track_num_ = -1;
76 video_default_duration_ = -1;
77 video_stream_info_ =
nullptr;
79 ignored_tracks_.clear();
82 int result = parser.
Parse(buf, size);
91 int64_t WebMTracksParser::GetAudioDefaultDuration(
92 const double timecode_scale_in_us)
const {
93 return PrecisionCappedDefaultDuration(timecode_scale_in_us,
94 audio_default_duration_);
97 int64_t WebMTracksParser::GetVideoDefaultDuration(
98 const double timecode_scale_in_us)
const {
99 return PrecisionCappedDefaultDuration(timecode_scale_in_us,
100 video_default_duration_);
103 WebMParserClient* WebMTracksParser::OnListStart(
int id) {
104 if (
id == kWebMIdContentEncodings) {
105 DCHECK(!track_content_encodings_client_.get());
106 track_content_encodings_client_.reset(
new WebMContentEncodingsClient());
107 return track_content_encodings_client_->OnListStart(
id);
110 if (
id == kWebMIdTrackEntry) {
113 default_duration_ = -1;
115 track_language_.clear();
117 codec_private_.clear();
118 audio_client_.Reset();
119 video_client_.Reset();
123 if (
id == kWebMIdAudio)
124 return &audio_client_;
126 if (
id == kWebMIdVideo)
127 return &video_client_;
132 bool WebMTracksParser::OnListEnd(
int id) {
133 if (
id == kWebMIdContentEncodings) {
134 DCHECK(track_content_encodings_client_.get());
135 return track_content_encodings_client_->OnListEnd(
id);
138 if (
id == kWebMIdTrackEntry) {
139 if (track_type_ == -1 || track_num_ == -1) {
140 LOG(ERROR) <<
"Missing TrackEntry data for "
141 <<
" TrackType " << track_type_ <<
" TrackNum " << track_num_;
145 if (track_type_ != kWebMTrackTypeAudio &&
146 track_type_ != kWebMTrackTypeVideo &&
147 track_type_ != kWebMTrackTypeSubtitlesOrCaptions &&
148 track_type_ != kWebMTrackTypeDescriptionsOrMetadata) {
149 LOG(ERROR) <<
"Unexpected TrackType " << track_type_;
153 TextKind text_track_kind = kTextNone;
154 if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions) {
155 text_track_kind = CodecIdToTextKind(codec_id_);
156 if (text_track_kind == kTextNone) {
157 LOG(ERROR) <<
"Missing TrackEntry CodecID"
158 <<
" TrackNum " << track_num_;
162 if (text_track_kind != kTextSubtitles &&
163 text_track_kind != kTextCaptions) {
164 LOG(ERROR) <<
"Wrong TrackEntry CodecID"
165 <<
" TrackNum " << track_num_;
168 }
else if (track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
169 text_track_kind = CodecIdToTextKind(codec_id_);
170 if (text_track_kind == kTextNone) {
171 LOG(ERROR) <<
"Missing TrackEntry CodecID"
172 <<
" TrackNum " << track_num_;
176 if (text_track_kind != kTextDescriptions &&
177 text_track_kind != kTextMetadata) {
178 LOG(ERROR) <<
"Wrong TrackEntry CodecID"
179 <<
" TrackNum " << track_num_;
184 std::string encryption_key_id;
185 if (track_content_encodings_client_) {
186 DCHECK(!track_content_encodings_client_->content_encodings().empty());
189 encryption_key_id = track_content_encodings_client_->
190 content_encodings()[0]->encryption_key_id();
193 if (track_type_ == kWebMTrackTypeAudio) {
194 if (audio_track_num_ == -1) {
195 audio_track_num_ = track_num_;
196 audio_encryption_key_id_ = encryption_key_id;
198 if (default_duration_ == 0) {
199 LOG(ERROR) <<
"Illegal 0ns audio TrackEntry "
203 audio_default_duration_ = default_duration_;
205 DCHECK(!audio_stream_info_);
206 audio_stream_info_ = audio_client_.GetAudioStreamInfo(
207 audio_track_num_, codec_id_, codec_private_, seek_preroll_,
208 codec_delay_, track_language_, !audio_encryption_key_id_.empty());
209 if (!audio_stream_info_)
212 DLOG(INFO) <<
"Ignoring audio track " << track_num_;
213 ignored_tracks_.insert(track_num_);
215 }
else if (track_type_ == kWebMTrackTypeVideo) {
216 if (video_track_num_ == -1) {
217 video_track_num_ = track_num_;
218 video_encryption_key_id_ = encryption_key_id;
220 if (default_duration_ == 0) {
221 LOG(ERROR) <<
"Illegal 0ns video TrackEntry "
225 video_default_duration_ = default_duration_;
227 DCHECK(!video_stream_info_);
228 video_stream_info_ = video_client_.GetVideoStreamInfo(
229 video_track_num_, codec_id_, codec_private_,
230 !video_encryption_key_id_.empty());
231 if (!video_stream_info_)
234 if (codec_id_ ==
"V_VP8" || codec_id_ ==
"V_VP9") {
235 vp_config_ = video_client_.GetVpCodecConfig(codec_private_);
236 const double kNanosecondsPerSecond = 1000000000.0;
237 if (codec_id_ ==
"V_VP9" &&
238 (!vp_config_.is_level_set() || vp_config_.level() == 0)) {
239 vp_config_.SetVP9Level(
240 video_stream_info_->width(), video_stream_info_->height(),
241 video_default_duration_ / kNanosecondsPerSecond);
246 DLOG(INFO) <<
"Ignoring video track " << track_num_;
247 ignored_tracks_.insert(track_num_);
249 }
else if (track_type_ == kWebMTrackTypeSubtitlesOrCaptions ||
250 track_type_ == kWebMTrackTypeDescriptionsOrMetadata) {
251 if (ignore_text_tracks_) {
252 DLOG(INFO) <<
"Ignoring text track " << track_num_;
253 ignored_tracks_.insert(track_num_);
255 std::string track_num = absl::StrFormat(
"%d", track_num_);
256 text_tracks_[track_num_] = TextTrackConfig(
257 text_track_kind, track_name_, track_language_, track_num);
260 LOG(ERROR) <<
"Unexpected TrackType " << track_type_;
266 default_duration_ = -1;
268 track_language_.clear();
270 codec_private_.clear();
271 track_content_encodings_client_.reset();
273 audio_client_.Reset();
274 video_client_.Reset();
281 bool WebMTracksParser::OnUInt(
int id, int64_t val) {
285 case kWebMIdTrackNumber:
288 case kWebMIdTrackType:
291 case kWebMIdSeekPreRoll:
292 dst = &seek_preroll_;
294 case kWebMIdCodecDelay:
297 case kWebMIdDefaultDuration:
298 dst = &default_duration_;
305 LOG(ERROR) <<
"Multiple values for id " << std::hex <<
id <<
" specified";
313 bool WebMTracksParser::OnFloat(
int ,
double ) {
317 bool WebMTracksParser::OnBinary(
int id,
const uint8_t* data,
int size) {
318 if (
id == kWebMIdCodecPrivate) {
319 if (!codec_private_.empty()) {
320 LOG(ERROR) <<
"Multiple CodecPrivate fields in a track.";
323 codec_private_.assign(data, data + size);
329 bool WebMTracksParser::OnString(
int id,
const std::string& str) {
330 if (
id == kWebMIdCodecID) {
331 if (!codec_id_.empty()) {
332 LOG(ERROR) <<
"Multiple CodecID fields in a track";
340 if (
id == kWebMIdName) {
345 if (
id == kWebMIdLanguage) {
346 track_language_ = str;
All the methods that are virtual are virtual for mocking.