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_->Flush();
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 scoped_refptr<AudioStreamInfo> audio_stream_info =
185 tracks_parser.audio_stream_info();
186 if (audio_stream_info) {
187 audio_stream_info->set_duration(duration_in_us);
188 if (audio_stream_info->is_encrypted())
189 OnEncryptedMediaInitData(tracks_parser.audio_encryption_key_id());
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);
198 if (video_stream_info->is_encrypted())
199 OnEncryptedMediaInitData(tracks_parser.video_encryption_key_id());
201 VLOG(1) <<
"No video track info found.";
204 cluster_parser_.reset(
new WebMClusterParser(
205 info_parser.timecode_scale(), audio_stream_info, video_stream_info,
206 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us),
207 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
208 tracks_parser.text_tracks(), tracks_parser.ignored_tracks(),
209 tracks_parser.audio_encryption_key_id(),
210 tracks_parser.video_encryption_key_id(), new_sample_cb_, init_cb_));
215 int WebMMediaParser::ParseCluster(
const uint8_t* data,
int size) {
216 if (!cluster_parser_)
219 int bytes_parsed = cluster_parser_->Parse(data, size);
220 if (bytes_parsed < 0)
223 bool cluster_ended = cluster_parser_->cluster_ended();
225 ChangeState(kParsingHeaders);
231 void WebMMediaParser::OnEncryptedMediaInitData(
const std::string& key_id) {
232 NOTIMPLEMENTED() <<
"WebM decryption is not implemented yet.";