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/base/widevine_pssh_data.pb.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"
21 namespace edash_packager {
24 WebMMediaParser::WebMMediaParser()
25 : state_(kWaitingForInit), unknown_segment_size_(false) {}
27 WebMMediaParser::~WebMMediaParser() {}
32 DCHECK_EQ(state_, kWaitingForInit);
33 DCHECK(init_cb_.is_null());
34 DCHECK(!init_cb.is_null());
35 DCHECK(!new_sample_cb.is_null());
37 ChangeState(kParsingHeaders);
39 new_sample_cb_ = new_sample_cb;
40 decryption_key_source_ = decryption_key_source;
41 ignore_text_tracks_ =
true;
45 DCHECK_NE(state_, kWaitingForInit);
49 cluster_parser_->Flush();
50 if (state_ == kParsingClusters) {
51 ChangeState(kParsingHeaders);
56 DCHECK_NE(state_, kWaitingForInit);
61 byte_queue_.
Push(buf, size);
65 const uint8_t* cur = NULL;
68 byte_queue_.
Peek(&cur, &cur_size);
69 while (cur_size > 0) {
70 State oldState = state_;
73 result = ParseInfoAndTracks(cur, cur_size);
76 case kParsingClusters:
77 result = ParseCluster(cur, cur_size);
90 if (state_ == oldState && result == 0)
96 bytes_parsed += result;
99 byte_queue_.
Pop(bytes_parsed);
103 void WebMMediaParser::ChangeState(State new_state) {
104 DVLOG(1) <<
"ChangeState() : " << state_ <<
" -> " << new_state;
108 int WebMMediaParser::ParseInfoAndTracks(
const uint8_t* data,
int size) {
109 DVLOG(2) <<
"ParseInfoAndTracks()";
113 const uint8_t* cur = data;
115 int bytes_parsed = 0;
118 int64_t element_size;
119 int result = WebMParseElementHeader(cur, cur_size, &
id, &element_size);
125 case kWebMIdEBMLHeader:
126 case kWebMIdSeekHead:
130 case kWebMIdChapters:
132 case kWebMIdAttachments:
134 if (cur_size < (result + element_size)) {
139 return result + element_size;
142 if (!cluster_parser_) {
143 LOG(ERROR) <<
"Found Cluster element before Info.";
146 ChangeState(kParsingClusters);
151 if (element_size == kWebMUnknownSize)
152 unknown_segment_size_ =
true;
160 LOG(ERROR) <<
"Unexpected element ID 0x" << std::hex << id;
165 WebMInfoParser info_parser;
166 result = info_parser.Parse(cur, cur_size);
173 bytes_parsed += result;
175 WebMTracksParser tracks_parser(ignore_text_tracks_);
176 result = tracks_parser.Parse(cur, cur_size);
181 bytes_parsed += result;
183 double timecode_scale_in_us = info_parser.timecode_scale() / 1000.0;
184 int64_t duration_in_us = info_parser.duration() * timecode_scale_in_us;
186 scoped_refptr<AudioStreamInfo> audio_stream_info =
187 tracks_parser.audio_stream_info();
188 if (audio_stream_info) {
189 audio_stream_info->set_duration(duration_in_us);
191 VLOG(1) <<
"No audio track info found.";
194 scoped_refptr<VideoStreamInfo> video_stream_info =
195 tracks_parser.video_stream_info();
196 if (video_stream_info) {
197 video_stream_info->set_duration(duration_in_us);
199 VLOG(1) <<
"No video track info found.";
202 if (!FetchKeysIfNecessary(tracks_parser.audio_encryption_key_id(),
203 tracks_parser.video_encryption_key_id())) {
207 cluster_parser_.reset(
new WebMClusterParser(
208 info_parser.timecode_scale(), audio_stream_info, video_stream_info,
209 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us),
210 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
211 tracks_parser.text_tracks(), tracks_parser.ignored_tracks(),
212 tracks_parser.audio_encryption_key_id(),
213 tracks_parser.video_encryption_key_id(), new_sample_cb_, init_cb_,
214 decryption_key_source_));
219 int WebMMediaParser::ParseCluster(
const uint8_t* data,
int size) {
220 if (!cluster_parser_)
223 int bytes_parsed = cluster_parser_->Parse(data, size);
224 if (bytes_parsed < 0)
227 bool cluster_ended = cluster_parser_->cluster_ended();
229 ChangeState(kParsingHeaders);
235 bool WebMMediaParser::FetchKeysIfNecessary(
236 const std::string& audio_encryption_key_id,
237 const std::string& video_encryption_key_id) {
238 if (audio_encryption_key_id.empty() && video_encryption_key_id.empty())
241 if (!decryption_key_source_)
245 WidevinePsshData widevine_pssh_data;
246 if (!audio_encryption_key_id.empty())
247 widevine_pssh_data.add_key_id(audio_encryption_key_id);
248 if (!video_encryption_key_id.empty())
249 widevine_pssh_data.add_key_id(video_encryption_key_id);
251 const std::string serialized_string = widevine_pssh_data.SerializeAsString();
252 Status status = decryption_key_source_->
FetchKeys(
253 std::vector<uint8_t>(serialized_string.begin(), serialized_string.end()));
255 LOG(ERROR) <<
"Error fetching decryption keys: " << status;