5 #include <packager/media/formats/webm/webm_media_parser.h>
9 #include <absl/log/check.h>
10 #include <absl/log/log.h>
12 #include <packager/macros/logging.h>
13 #include <packager/media/base/buffer_writer.h>
14 #include <packager/media/base/timestamp.h>
15 #include <packager/media/formats/webm/webm_cluster_parser.h>
16 #include <packager/media/formats/webm/webm_constants.h>
17 #include <packager/media/formats/webm/webm_content_encodings.h>
18 #include <packager/media/formats/webm/webm_info_parser.h>
19 #include <packager/media/formats/webm/webm_tracks_parser.h>
24 WebMMediaParser::WebMMediaParser()
25 : state_(kWaitingForInit), unknown_segment_size_(false) {}
27 WebMMediaParser::~WebMMediaParser() {}
29 void WebMMediaParser::Init(
const InitCB& init_cb,
33 DCHECK_EQ(state_, kWaitingForInit);
36 DCHECK(new_media_sample_cb);
38 ChangeState(kParsingHeaders);
40 new_sample_cb_ = new_media_sample_cb;
41 decryption_key_source_ = decryption_key_source;
42 ignore_text_tracks_ =
true;
45 bool WebMMediaParser::Flush() {
46 DCHECK_NE(state_, kWaitingForInit);
51 result = cluster_parser_->Flush();
52 if (state_ == kParsingClusters) {
53 ChangeState(kParsingHeaders);
58 bool WebMMediaParser::Parse(
const uint8_t* buf,
int size) {
59 DCHECK_NE(state_, kWaitingForInit);
64 byte_queue_.Push(buf, size);
68 const uint8_t* cur = NULL;
71 byte_queue_.Peek(&cur, &cur_size);
72 while (cur_size > 0) {
73 State oldState = state_;
76 result = ParseInfoAndTracks(cur, cur_size);
79 case kParsingClusters:
80 result = ParseCluster(cur, cur_size);
93 if (state_ == oldState && result == 0)
99 bytes_parsed += result;
102 byte_queue_.Pop(bytes_parsed);
106 void WebMMediaParser::ChangeState(State new_state) {
107 DVLOG(1) <<
"ChangeState() : " << state_ <<
" -> " << new_state;
111 int WebMMediaParser::ParseInfoAndTracks(
const uint8_t* data,
int size) {
112 DVLOG(2) <<
"ParseInfoAndTracks()";
116 const uint8_t* cur = data;
118 int bytes_parsed = 0;
121 int64_t element_size;
122 int result = WebMParseElementHeader(cur, cur_size, &
id, &element_size);
128 case kWebMIdEBMLHeader:
129 case kWebMIdSeekHead:
133 case kWebMIdChapters:
135 case kWebMIdAttachments:
137 if (cur_size < (result + element_size)) {
142 return result + element_size;
145 if (!cluster_parser_) {
146 LOG(ERROR) <<
"Found Cluster element before Info.";
149 ChangeState(kParsingClusters);
154 if (element_size == kWebMUnknownSize)
155 unknown_segment_size_ =
true;
163 LOG(ERROR) <<
"Unexpected element ID 0x" << std::hex << id;
168 WebMInfoParser info_parser;
169 result = info_parser.Parse(cur, cur_size);
176 bytes_parsed += result;
178 WebMTracksParser tracks_parser(ignore_text_tracks_);
179 result = tracks_parser.Parse(cur, cur_size);
184 bytes_parsed += result;
186 double timecode_scale_in_us = info_parser.timecode_scale() / 1000.0;
187 int64_t duration_in_us = info_parser.duration() * timecode_scale_in_us;
189 std::shared_ptr<AudioStreamInfo> audio_stream_info =
190 tracks_parser.audio_stream_info();
191 if (audio_stream_info) {
192 audio_stream_info->set_duration(duration_in_us);
194 VLOG(1) <<
"No audio track info found.";
197 std::shared_ptr<VideoStreamInfo> video_stream_info =
198 tracks_parser.video_stream_info();
199 if (video_stream_info) {
200 video_stream_info->set_duration(duration_in_us);
202 VLOG(1) <<
"No video track info found.";
205 if (!FetchKeysIfNecessary(tracks_parser.audio_encryption_key_id(),
206 tracks_parser.video_encryption_key_id())) {
210 cluster_parser_.reset(
new WebMClusterParser(
211 info_parser.timecode_scale(), audio_stream_info, video_stream_info,
212 tracks_parser.vp_config(),
213 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us),
214 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
215 tracks_parser.text_tracks(), tracks_parser.ignored_tracks(),
216 tracks_parser.audio_encryption_key_id(),
217 tracks_parser.video_encryption_key_id(), new_sample_cb_, init_cb_,
218 decryption_key_source_));
223 int WebMMediaParser::ParseCluster(
const uint8_t* data,
int size) {
224 if (!cluster_parser_)
227 int bytes_parsed = cluster_parser_->Parse(data, size);
228 if (bytes_parsed < 0)
231 bool cluster_ended = cluster_parser_->cluster_ended();
233 ChangeState(kParsingHeaders);
239 bool WebMMediaParser::FetchKeysIfNecessary(
240 const std::string& audio_encryption_key_id,
241 const std::string& video_encryption_key_id) {
242 if (audio_encryption_key_id.empty() && video_encryption_key_id.empty())
245 if (!decryption_key_source_)
249 if (!audio_encryption_key_id.empty()) {
250 status.Update(decryption_key_source_->FetchKeys(
251 EmeInitDataType::WEBM,
252 std::vector<uint8_t>(audio_encryption_key_id.begin(),
253 audio_encryption_key_id.end())));
255 if (!video_encryption_key_id.empty()) {
256 status.Update(decryption_key_source_->FetchKeys(
257 EmeInitDataType::WEBM,
258 std::vector<uint8_t>(video_encryption_key_id.begin(),
259 video_encryption_key_id.end())));
262 LOG(ERROR) <<
"Error fetching decryption keys: " << status;
All the methods that are virtual are virtual for mocking.