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/timestamp.h"
13 #include "packager/media/formats/webm/webm_cluster_parser.h"
14 #include "packager/media/formats/webm/webm_constants.h"
15 #include "packager/media/formats/webm/webm_content_encodings.h"
16 #include "packager/media/formats/webm/webm_info_parser.h"
17 #include "packager/media/formats/webm/webm_tracks_parser.h"
19 namespace edash_packager {
22 WebMMediaParser::WebMMediaParser()
23 : state_(kWaitingForInit), unknown_segment_size_(false) {}
25 WebMMediaParser::~WebMMediaParser() {}
30 DCHECK_EQ(state_, kWaitingForInit);
31 DCHECK(init_cb_.is_null());
32 DCHECK(!init_cb.is_null());
33 DCHECK(!new_sample_cb.is_null());
35 ChangeState(kParsingHeaders);
37 new_sample_cb_ = new_sample_cb;
38 decryption_key_source_ = decryption_key_source;
39 ignore_text_tracks_ =
true;
43 DCHECK_NE(state_, kWaitingForInit);
47 cluster_parser_->Reset();
48 if (state_ == kParsingClusters) {
49 ChangeState(kParsingHeaders);
54 DCHECK_NE(state_, kWaitingForInit);
59 byte_queue_.
Push(buf, size);
63 const uint8_t* cur = NULL;
66 byte_queue_.
Peek(&cur, &cur_size);
67 while (cur_size > 0) {
68 State oldState = state_;
71 result = ParseInfoAndTracks(cur, cur_size);
74 case kParsingClusters:
75 result = ParseCluster(cur, cur_size);
88 if (state_ == oldState && result == 0)
94 bytes_parsed += result;
97 byte_queue_.
Pop(bytes_parsed);
101 void WebMMediaParser::ChangeState(State new_state) {
102 DVLOG(1) <<
"ChangeState() : " << state_ <<
" -> " << new_state;
106 int WebMMediaParser::ParseInfoAndTracks(
const uint8_t* data,
int size) {
107 DVLOG(2) <<
"ParseInfoAndTracks()";
111 const uint8_t* cur = data;
113 int bytes_parsed = 0;
116 int64_t element_size;
117 int result = WebMParseElementHeader(cur, cur_size, &
id, &element_size);
123 case kWebMIdEBMLHeader:
124 case kWebMIdSeekHead:
128 case kWebMIdChapters:
130 case kWebMIdAttachments:
132 if (cur_size < (result + element_size)) {
137 return result + element_size;
140 if (!cluster_parser_) {
141 LOG(ERROR) <<
"Found Cluster element before Info.";
144 ChangeState(kParsingClusters);
149 if (element_size == kWebMUnknownSize)
150 unknown_segment_size_ =
true;
158 LOG(ERROR) <<
"Unexpected element ID 0x" << std::hex << id;
163 WebMInfoParser info_parser;
164 result = info_parser.Parse(cur, cur_size);
171 bytes_parsed += result;
173 WebMTracksParser tracks_parser(ignore_text_tracks_);
174 result = tracks_parser.Parse(cur, cur_size);
179 bytes_parsed += result;
181 double timecode_scale_in_us = info_parser.timecode_scale() / 1000.0;
182 int64_t duration_in_us = info_parser.duration() * timecode_scale_in_us;
184 std::vector<scoped_refptr<StreamInfo>> streams;
185 AudioCodec audio_codec = kCodecOpus;
186 if (tracks_parser.audio_stream_info()) {
187 streams.push_back(tracks_parser.audio_stream_info());
188 streams.back()->set_duration(duration_in_us);
189 if (streams.back()->is_encrypted())
190 OnEncryptedMediaInitData(tracks_parser.audio_encryption_key_id());
191 audio_codec = tracks_parser.audio_stream_info()->codec();
193 VLOG(1) <<
"No audio track info found.";
196 if (tracks_parser.video_stream_info()) {
197 streams.push_back(tracks_parser.video_stream_info());
198 streams.back()->set_duration(duration_in_us);
199 if (streams.back()->is_encrypted())
200 OnEncryptedMediaInitData(tracks_parser.video_encryption_key_id());
202 VLOG(1) <<
"No video track info found.";
205 init_cb_.Run(streams);
207 cluster_parser_.reset(
new WebMClusterParser(
208 info_parser.timecode_scale(), tracks_parser.audio_track_num(),
209 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us),
210 tracks_parser.video_track_num(),
211 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
212 tracks_parser.text_tracks(), tracks_parser.ignored_tracks(),
213 tracks_parser.audio_encryption_key_id(),
214 tracks_parser.video_encryption_key_id(), audio_codec, new_sample_cb_));
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 void WebMMediaParser::OnEncryptedMediaInitData(
const std::string& key_id) {
236 NOTIMPLEMENTED() <<
"WebM decryption is not implemented yet.";