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() {}
28 void WebMMediaParser::Init(
const InitCB& init_cb,
32 DCHECK_EQ(state_, kWaitingForInit);
33 DCHECK(init_cb_.is_null());
34 DCHECK(!init_cb.is_null());
35 DCHECK(!new_media_sample_cb.is_null());
37 ChangeState(kParsingHeaders);
39 new_sample_cb_ = new_media_sample_cb;
40 decryption_key_source_ = decryption_key_source;
41 ignore_text_tracks_ =
true;
44 bool WebMMediaParser::Flush() {
45 DCHECK_NE(state_, kWaitingForInit);
50 result = cluster_parser_->Flush();
51 if (state_ == kParsingClusters) {
52 ChangeState(kParsingHeaders);
57 bool WebMMediaParser::Parse(
const uint8_t* buf,
int size) {
58 DCHECK_NE(state_, kWaitingForInit);
63 byte_queue_.Push(buf, size);
67 const uint8_t* cur = NULL;
70 byte_queue_.Peek(&cur, &cur_size);
71 while (cur_size > 0) {
72 State oldState = state_;
75 result = ParseInfoAndTracks(cur, cur_size);
78 case kParsingClusters:
79 result = ParseCluster(cur, cur_size);
92 if (state_ == oldState && result == 0)
98 bytes_parsed += result;
101 byte_queue_.Pop(bytes_parsed);
105 void WebMMediaParser::ChangeState(State new_state) {
106 DVLOG(1) <<
"ChangeState() : " << state_ <<
" -> " << new_state;
110 int WebMMediaParser::ParseInfoAndTracks(
const uint8_t* data,
int size) {
111 DVLOG(2) <<
"ParseInfoAndTracks()";
115 const uint8_t* cur = data;
117 int bytes_parsed = 0;
120 int64_t element_size;
121 int result = WebMParseElementHeader(cur, cur_size, &
id, &element_size);
127 case kWebMIdEBMLHeader:
128 case kWebMIdSeekHead:
132 case kWebMIdChapters:
134 case kWebMIdAttachments:
136 if (cur_size < (result + element_size)) {
141 return result + element_size;
144 if (!cluster_parser_) {
145 LOG(ERROR) <<
"Found Cluster element before Info.";
148 ChangeState(kParsingClusters);
153 if (element_size == kWebMUnknownSize)
154 unknown_segment_size_ =
true;
162 LOG(ERROR) <<
"Unexpected element ID 0x" << std::hex << id;
167 WebMInfoParser info_parser;
168 result = info_parser.Parse(cur, cur_size);
175 bytes_parsed += result;
177 WebMTracksParser tracks_parser(ignore_text_tracks_);
178 result = tracks_parser.Parse(cur, cur_size);
183 bytes_parsed += result;
185 double timecode_scale_in_us = info_parser.timecode_scale() / 1000.0;
186 int64_t duration_in_us = info_parser.duration() * timecode_scale_in_us;
188 std::shared_ptr<AudioStreamInfo> audio_stream_info =
189 tracks_parser.audio_stream_info();
190 if (audio_stream_info) {
191 audio_stream_info->set_duration(duration_in_us);
193 VLOG(1) <<
"No audio track info found.";
196 std::shared_ptr<VideoStreamInfo> video_stream_info =
197 tracks_parser.video_stream_info();
198 if (video_stream_info) {
199 video_stream_info->set_duration(duration_in_us);
201 VLOG(1) <<
"No video track info found.";
204 if (!FetchKeysIfNecessary(tracks_parser.audio_encryption_key_id(),
205 tracks_parser.video_encryption_key_id())) {
209 cluster_parser_.reset(
new WebMClusterParser(
210 info_parser.timecode_scale(), audio_stream_info, video_stream_info,
211 tracks_parser.vp_config(),
212 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us),
213 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
214 tracks_parser.text_tracks(), tracks_parser.ignored_tracks(),
215 tracks_parser.audio_encryption_key_id(),
216 tracks_parser.video_encryption_key_id(), new_sample_cb_, init_cb_,
217 decryption_key_source_));
222 int WebMMediaParser::ParseCluster(
const uint8_t* data,
int size) {
223 if (!cluster_parser_)
226 int bytes_parsed = cluster_parser_->Parse(data, size);
227 if (bytes_parsed < 0)
230 bool cluster_ended = cluster_parser_->cluster_ended();
232 ChangeState(kParsingHeaders);
238 bool WebMMediaParser::FetchKeysIfNecessary(
239 const std::string& audio_encryption_key_id,
240 const std::string& video_encryption_key_id) {
241 if (audio_encryption_key_id.empty() && video_encryption_key_id.empty())
244 if (!decryption_key_source_)
248 if (!audio_encryption_key_id.empty()) {
249 status.Update(decryption_key_source_->FetchKeys(
250 EmeInitDataType::WEBM,
251 std::vector<uint8_t>(audio_encryption_key_id.begin(),
252 audio_encryption_key_id.end())));
254 if (!video_encryption_key_id.empty()) {
255 status.Update(decryption_key_source_->FetchKeys(
256 EmeInitDataType::WEBM,
257 std::vector<uint8_t>(video_encryption_key_id.begin(),
258 video_encryption_key_id.end())));
261 LOG(ERROR) <<
"Error fetching decryption keys: " << status;
All the methods that are virtual are virtual for mocking.