5#include <packager/media/formats/webm/webm_media_parser.h>
14#include <absl/log/check.h>
15#include <absl/log/log.h>
17#include <packager/media/base/audio_stream_info.h>
18#include <packager/media/base/key_source.h>
19#include <packager/media/base/video_stream_info.h>
20#include <packager/media/formats/webm/webm_cluster_parser.h>
21#include <packager/media/formats/webm/webm_constants.h>
22#include <packager/media/formats/webm/webm_info_parser.h>
23#include <packager/media/formats/webm/webm_parser.h>
24#include <packager/media/formats/webm/webm_tracks_parser.h>
25#include <packager/status.h>
30WebMMediaParser::WebMMediaParser()
31 : state_(kWaitingForInit), unknown_segment_size_(false) {}
33WebMMediaParser::~WebMMediaParser() {}
35void WebMMediaParser::Init(
const InitCB& init_cb,
39 DCHECK_EQ(state_, kWaitingForInit);
42 DCHECK(new_media_sample_cb);
44 ChangeState(kParsingHeaders);
46 new_sample_cb_ = new_media_sample_cb;
47 decryption_key_source_ = decryption_key_source;
48 ignore_text_tracks_ =
true;
51bool WebMMediaParser::Flush() {
52 DCHECK_NE(state_, kWaitingForInit);
57 result = cluster_parser_->Flush();
58 if (state_ == kParsingClusters) {
59 ChangeState(kParsingHeaders);
64bool WebMMediaParser::Parse(
const uint8_t* buf,
int size) {
65 DCHECK_NE(state_, kWaitingForInit);
70 byte_queue_.Push(buf, size);
74 const uint8_t* cur = NULL;
77 byte_queue_.Peek(&cur, &cur_size);
78 while (cur_size > 0) {
79 State oldState = state_;
82 result = ParseInfoAndTracks(cur, cur_size);
85 case kParsingClusters:
86 result = ParseCluster(cur, cur_size);
99 if (state_ == oldState && result == 0)
102 DCHECK_GE(result, 0);
105 bytes_parsed += result;
108 byte_queue_.Pop(bytes_parsed);
112void WebMMediaParser::ChangeState(State new_state) {
113 DVLOG(1) <<
"ChangeState() : " << state_ <<
" -> " << new_state;
117int WebMMediaParser::ParseInfoAndTracks(
const uint8_t* data,
int size) {
118 DVLOG(2) <<
"ParseInfoAndTracks()";
122 const uint8_t* cur = data;
124 int bytes_parsed = 0;
127 int64_t element_size;
128 int result = WebMParseElementHeader(cur, cur_size, &
id, &element_size);
134 case kWebMIdEBMLHeader:
135 case kWebMIdSeekHead:
139 case kWebMIdChapters:
141 case kWebMIdAttachments:
143 if (cur_size < (result + element_size)) {
148 return result + element_size;
151 if (!cluster_parser_) {
152 LOG(ERROR) <<
"Found Cluster element before Info.";
155 ChangeState(kParsingClusters);
160 if (element_size == kWebMUnknownSize)
161 unknown_segment_size_ =
true;
169 LOG(ERROR) <<
"Unexpected element ID 0x" << std::hex << id;
174 WebMInfoParser info_parser;
175 result = info_parser.Parse(cur, cur_size);
182 bytes_parsed += result;
184 WebMTracksParser tracks_parser(ignore_text_tracks_);
185 result = tracks_parser.Parse(cur, cur_size);
190 bytes_parsed += result;
192 double timecode_scale_in_us = info_parser.timecode_scale() / 1000.0;
193 int64_t duration_in_us = info_parser.duration() * timecode_scale_in_us;
195 std::shared_ptr<AudioStreamInfo> audio_stream_info =
196 tracks_parser.audio_stream_info();
197 if (audio_stream_info) {
198 audio_stream_info->set_duration(duration_in_us);
200 VLOG(1) <<
"No audio track info found.";
203 std::shared_ptr<VideoStreamInfo> video_stream_info =
204 tracks_parser.video_stream_info();
205 if (video_stream_info) {
206 video_stream_info->set_duration(duration_in_us);
208 VLOG(1) <<
"No video track info found.";
211 if (!FetchKeysIfNecessary(tracks_parser.audio_encryption_key_id(),
212 tracks_parser.video_encryption_key_id())) {
216 cluster_parser_.reset(
new WebMClusterParser(
217 info_parser.timecode_scale(), audio_stream_info, video_stream_info,
218 tracks_parser.vp_config(),
219 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us),
220 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
221 tracks_parser.text_tracks(), tracks_parser.ignored_tracks(),
222 tracks_parser.audio_encryption_key_id(),
223 tracks_parser.video_encryption_key_id(), new_sample_cb_, init_cb_,
224 decryption_key_source_));
229int WebMMediaParser::ParseCluster(
const uint8_t* data,
int size) {
230 if (!cluster_parser_)
233 int bytes_parsed = cluster_parser_->Parse(data, size);
234 if (bytes_parsed < 0)
237 bool cluster_ended = cluster_parser_->cluster_ended();
239 ChangeState(kParsingHeaders);
245bool WebMMediaParser::FetchKeysIfNecessary(
246 const std::string& audio_encryption_key_id,
247 const std::string& video_encryption_key_id) {
248 if (audio_encryption_key_id.empty() && video_encryption_key_id.empty())
251 if (!decryption_key_source_)
255 if (!audio_encryption_key_id.empty()) {
256 status.Update(decryption_key_source_->FetchKeys(
257 EmeInitDataType::WEBM,
258 std::vector<uint8_t>(audio_encryption_key_id.begin(),
259 audio_encryption_key_id.end())));
261 if (!video_encryption_key_id.empty()) {
262 status.Update(decryption_key_source_->FetchKeys(
263 EmeInitDataType::WEBM,
264 std::vector<uint8_t>(video_encryption_key_id.begin(),
265 video_encryption_key_id.end())));
268 LOG(ERROR) <<
"Error fetching decryption keys: " << status;
All the methods that are virtual are virtual for mocking.