5 #include "packager/media/formats/webm/webm_media_parser.h"
9 #include "packager/base/callback.h"
10 #include "packager/base/callback_helpers.h"
11 #include "packager/base/logging.h"
12 #include "packager/media/base/buffer_writer.h"
13 #include "packager/media/base/timestamp.h"
14 #include "packager/media/formats/webm/webm_cluster_parser.h"
15 #include "packager/media/formats/webm/webm_constants.h"
16 #include "packager/media/formats/webm/webm_content_encodings.h"
17 #include "packager/media/formats/webm/webm_info_parser.h"
18 #include "packager/media/formats/webm/webm_tracks_parser.h"
23 WebMMediaParser::WebMMediaParser()
24 : state_(kWaitingForInit), unknown_segment_size_(false) {}
26 WebMMediaParser::~WebMMediaParser() {}
31 DCHECK_EQ(state_, kWaitingForInit);
32 DCHECK(init_cb_.is_null());
33 DCHECK(!init_cb.is_null());
34 DCHECK(!new_sample_cb.is_null());
36 ChangeState(kParsingHeaders);
38 new_sample_cb_ = new_sample_cb;
39 decryption_key_source_ = decryption_key_source;
40 ignore_text_tracks_ =
true;
44 DCHECK_NE(state_, kWaitingForInit);
49 result = cluster_parser_->Flush();
50 if (state_ == kParsingClusters) {
51 ChangeState(kParsingHeaders);
57 DCHECK_NE(state_, kWaitingForInit);
62 byte_queue_.
Push(buf, size);
66 const uint8_t* cur = NULL;
69 byte_queue_.
Peek(&cur, &cur_size);
70 while (cur_size > 0) {
71 State oldState = state_;
74 result = ParseInfoAndTracks(cur, cur_size);
77 case kParsingClusters:
78 result = ParseCluster(cur, cur_size);
91 if (state_ == oldState && result == 0)
97 bytes_parsed += result;
100 byte_queue_.
Pop(bytes_parsed);
104 void WebMMediaParser::ChangeState(State new_state) {
105 DVLOG(1) <<
"ChangeState() : " << state_ <<
" -> " << new_state;
109 int WebMMediaParser::ParseInfoAndTracks(
const uint8_t* data,
int size) {
110 DVLOG(2) <<
"ParseInfoAndTracks()";
114 const uint8_t* cur = data;
116 int bytes_parsed = 0;
119 int64_t element_size;
120 int result = WebMParseElementHeader(cur, cur_size, &
id, &element_size);
126 case kWebMIdEBMLHeader:
127 case kWebMIdSeekHead:
131 case kWebMIdChapters:
133 case kWebMIdAttachments:
135 if (cur_size < (result + element_size)) {
140 return result + element_size;
143 if (!cluster_parser_) {
144 LOG(ERROR) <<
"Found Cluster element before Info.";
147 ChangeState(kParsingClusters);
152 if (element_size == kWebMUnknownSize)
153 unknown_segment_size_ =
true;
161 LOG(ERROR) <<
"Unexpected element ID 0x" << std::hex << id;
166 WebMInfoParser info_parser;
167 result = info_parser.Parse(cur, cur_size);
174 bytes_parsed += result;
176 WebMTracksParser tracks_parser(ignore_text_tracks_);
177 result = tracks_parser.Parse(cur, cur_size);
182 bytes_parsed += result;
184 double timecode_scale_in_us = info_parser.timecode_scale() / 1000.0;
185 int64_t duration_in_us = info_parser.duration() * timecode_scale_in_us;
187 std::shared_ptr<AudioStreamInfo> audio_stream_info =
188 tracks_parser.audio_stream_info();
189 if (audio_stream_info) {
190 audio_stream_info->set_duration(duration_in_us);
192 VLOG(1) <<
"No audio track info found.";
195 std::shared_ptr<VideoStreamInfo> video_stream_info =
196 tracks_parser.video_stream_info();
197 if (video_stream_info) {
198 video_stream_info->set_duration(duration_in_us);
200 VLOG(1) <<
"No video track info found.";
203 if (!FetchKeysIfNecessary(tracks_parser.audio_encryption_key_id(),
204 tracks_parser.video_encryption_key_id())) {
208 cluster_parser_.reset(
new WebMClusterParser(
209 info_parser.timecode_scale(), audio_stream_info, video_stream_info,
210 tracks_parser.vp_config(),
211 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us),
212 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
213 tracks_parser.text_tracks(), tracks_parser.ignored_tracks(),
214 tracks_parser.audio_encryption_key_id(),
215 tracks_parser.video_encryption_key_id(), new_sample_cb_, init_cb_,
216 decryption_key_source_));
221 int WebMMediaParser::ParseCluster(
const uint8_t* data,
int size) {
222 if (!cluster_parser_)
225 int bytes_parsed = cluster_parser_->Parse(data, size);
226 if (bytes_parsed < 0)
229 bool cluster_ended = cluster_parser_->cluster_ended();
231 ChangeState(kParsingHeaders);
237 bool WebMMediaParser::FetchKeysIfNecessary(
238 const std::string& audio_encryption_key_id,
239 const std::string& video_encryption_key_id) {
240 if (audio_encryption_key_id.empty() && video_encryption_key_id.empty())
243 if (!decryption_key_source_)
247 if (!audio_encryption_key_id.empty()) {
248 status.Update(decryption_key_source_->
FetchKeys(
249 EmeInitDataType::WEBM,
250 std::vector<uint8_t>(audio_encryption_key_id.begin(),
251 audio_encryption_key_id.end())));
253 if (!video_encryption_key_id.empty()) {
254 status.Update(decryption_key_source_->
FetchKeys(
255 EmeInitDataType::WEBM,
256 std::vector<uint8_t>(video_encryption_key_id.begin(),
257 video_encryption_key_id.end())));
260 LOG(ERROR) <<
"Error fetching decryption keys: " << status;