OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/formats/webm/webm_stream_parser.h" | 5 #include "media/formats/webm/webm_stream_parser.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "media/formats/webm/webm_cluster_parser.h" | 12 #include "media/formats/webm/webm_cluster_parser.h" |
13 #include "media/formats/webm/webm_constants.h" | 13 #include "media/formats/webm/webm_constants.h" |
14 #include "media/formats/webm/webm_content_encodings.h" | 14 #include "media/formats/webm/webm_content_encodings.h" |
15 #include "media/formats/webm/webm_crypto_helpers.h" | 15 #include "media/formats/webm/webm_crypto_helpers.h" |
16 #include "media/formats/webm/webm_info_parser.h" | 16 #include "media/formats/webm/webm_info_parser.h" |
17 #include "media/formats/webm/webm_tracks_parser.h" | 17 #include "media/formats/webm/webm_tracks_parser.h" |
18 | 18 |
19 namespace media { | 19 namespace media { |
20 | 20 |
21 WebMStreamParser::WebMStreamParser() | 21 WebMStreamParser::WebMStreamParser() |
22 : state_(kWaitingForInit), | 22 : state_(kWaitingForInit), |
23 unknown_segment_size_(false), | 23 unknown_segment_size_(false) { |
24 parsing_cluster_(false) { | |
25 } | 24 } |
26 | 25 |
27 WebMStreamParser::~WebMStreamParser() { | 26 WebMStreamParser::~WebMStreamParser() { |
28 } | 27 } |
29 | 28 |
30 void WebMStreamParser::Init(const InitCB& init_cb, | 29 void WebMStreamParser::Init(const InitCB& init_cb, |
31 const NewConfigCB& config_cb, | 30 const NewConfigCB& config_cb, |
32 const NewBuffersCB& new_buffers_cb, | 31 const NewBuffersCB& new_buffers_cb, |
33 bool ignore_text_tracks, | 32 bool ignore_text_tracks, |
34 const NeedKeyCB& need_key_cb, | 33 const NeedKeyCB& need_key_cb, |
(...skipping 17 matching lines...) Expand all Loading... | |
52 need_key_cb_ = need_key_cb; | 51 need_key_cb_ = need_key_cb; |
53 new_segment_cb_ = new_segment_cb; | 52 new_segment_cb_ = new_segment_cb; |
54 end_of_segment_cb_ = end_of_segment_cb; | 53 end_of_segment_cb_ = end_of_segment_cb; |
55 log_cb_ = log_cb; | 54 log_cb_ = log_cb; |
56 } | 55 } |
57 | 56 |
58 void WebMStreamParser::Flush() { | 57 void WebMStreamParser::Flush() { |
59 DCHECK_NE(state_, kWaitingForInit); | 58 DCHECK_NE(state_, kWaitingForInit); |
60 | 59 |
61 byte_queue_.Reset(); | 60 byte_queue_.Reset(); |
62 parsing_cluster_ = false; | |
63 | |
64 if (state_ != kParsingClusters) | |
65 return; | |
66 | |
67 cluster_parser_->Reset(); | 61 cluster_parser_->Reset(); |
wolenetz
2014/06/18 22:47:53
cluster_parser_ may still be null prior to complet
Sergey Ulanov
2014/06/18 23:26:50
Done.
| |
62 if (state_ == kParsingClusters) { | |
63 ChangeState(kParsingHeaders); | |
64 end_of_segment_cb_.Run(); | |
65 } | |
68 } | 66 } |
69 | 67 |
70 bool WebMStreamParser::Parse(const uint8* buf, int size) { | 68 bool WebMStreamParser::Parse(const uint8* buf, int size) { |
71 DCHECK_NE(state_, kWaitingForInit); | 69 DCHECK_NE(state_, kWaitingForInit); |
72 | 70 |
73 if (state_ == kError) | 71 if (state_ == kError) |
74 return false; | 72 return false; |
75 | 73 |
76 byte_queue_.Push(buf, size); | 74 byte_queue_.Push(buf, size); |
77 | 75 |
(...skipping 17 matching lines...) Expand all Loading... | |
95 case kWaitingForInit: | 93 case kWaitingForInit: |
96 case kError: | 94 case kError: |
97 return false; | 95 return false; |
98 } | 96 } |
99 | 97 |
100 if (result < 0) { | 98 if (result < 0) { |
101 ChangeState(kError); | 99 ChangeState(kError); |
102 return false; | 100 return false; |
103 } | 101 } |
104 | 102 |
105 if (state_ == oldState && result == 0) | 103 if (state_ == oldState && result == 0) |
wolenetz
2014/06/18 22:47:53
aside: This state_ == oldState is key to the simpl
Sergey Ulanov
2014/06/18 23:26:49
Yes
| |
106 break; | 104 break; |
107 | 105 |
108 DCHECK_GE(result, 0); | 106 DCHECK_GE(result, 0); |
109 cur += result; | 107 cur += result; |
110 cur_size -= result; | 108 cur_size -= result; |
111 bytes_parsed += result; | 109 bytes_parsed += result; |
112 } | 110 } |
113 | 111 |
114 byte_queue_.Pop(bytes_parsed); | 112 byte_queue_.Pop(bytes_parsed); |
115 return true; | 113 return true; |
(...skipping 28 matching lines...) Expand all Loading... | |
144 case kWebMIdCues: | 142 case kWebMIdCues: |
145 case kWebMIdChapters: | 143 case kWebMIdChapters: |
146 // TODO(matthewjheaney): Implement support for chapters. | 144 // TODO(matthewjheaney): Implement support for chapters. |
147 if (cur_size < (result + element_size)) { | 145 if (cur_size < (result + element_size)) { |
148 // We don't have the whole element yet. Signal we need more data. | 146 // We don't have the whole element yet. Signal we need more data. |
149 return 0; | 147 return 0; |
150 } | 148 } |
151 // Skip the element. | 149 // Skip the element. |
152 return result + element_size; | 150 return result + element_size; |
153 break; | 151 break; |
152 case kWebMIdCluster: | |
153 if (!cluster_parser_) { | |
154 MEDIA_LOG(log_cb_) << "Found Cluster element before Info."; | |
155 return -1; | |
156 } | |
157 ChangeState(kParsingClusters); | |
158 new_segment_cb_.Run(); | |
159 return 0; | |
160 break; | |
154 case kWebMIdSegment: | 161 case kWebMIdSegment: |
155 // Segment of unknown size indicates live stream. | 162 // Segment of unknown size indicates live stream. |
156 if (element_size == kWebMUnknownSize) | 163 if (element_size == kWebMUnknownSize) |
157 unknown_segment_size_ = true; | 164 unknown_segment_size_ = true; |
158 // Just consume the segment header. | 165 // Just consume the segment header. |
159 return result; | 166 return result; |
160 break; | 167 break; |
161 case kWebMIdInfo: | 168 case kWebMIdInfo: |
162 // We've found the element we are looking for. | 169 // We've found the element we are looking for. |
163 break; | 170 break; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
224 tracks_parser.audio_track_num(), | 231 tracks_parser.audio_track_num(), |
225 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us), | 232 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us), |
226 tracks_parser.video_track_num(), | 233 tracks_parser.video_track_num(), |
227 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us), | 234 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us), |
228 tracks_parser.text_tracks(), | 235 tracks_parser.text_tracks(), |
229 tracks_parser.ignored_tracks(), | 236 tracks_parser.ignored_tracks(), |
230 tracks_parser.audio_encryption_key_id(), | 237 tracks_parser.audio_encryption_key_id(), |
231 tracks_parser.video_encryption_key_id(), | 238 tracks_parser.video_encryption_key_id(), |
232 log_cb_)); | 239 log_cb_)); |
233 | 240 |
234 ChangeState(kParsingClusters); | |
235 | |
236 if (!init_cb_.is_null()) | 241 if (!init_cb_.is_null()) |
237 base::ResetAndReturn(&init_cb_).Run(true, params); | 242 base::ResetAndReturn(&init_cb_).Run(true, params); |
238 | 243 |
239 return bytes_parsed; | 244 return bytes_parsed; |
240 } | 245 } |
241 | 246 |
242 int WebMStreamParser::ParseCluster(const uint8* data, int size) { | 247 int WebMStreamParser::ParseCluster(const uint8* data, int size) { |
243 if (!cluster_parser_) | 248 if (!cluster_parser_) |
244 return -1; | 249 return -1; |
245 | 250 |
246 int result = 0; | 251 int bytes_parsed = cluster_parser_->Parse(data, size); |
247 int bytes_parsed; | 252 if (bytes_parsed < 0) |
248 bool cluster_ended; | 253 return bytes_parsed; |
249 do { | |
250 cluster_ended = false; | |
251 | 254 |
252 // If we are not parsing a cluster then handle the case when the next | 255 const BufferQueue& audio_buffers = cluster_parser_->GetAudioBuffers(); |
253 // element is not a cluster. | 256 const BufferQueue& video_buffers = cluster_parser_->GetVideoBuffers(); |
254 if (!parsing_cluster_) { | 257 const TextBufferQueueMap& text_map = cluster_parser_->GetTextBuffers(); |
255 int id; | |
256 int64 element_size; | |
257 bytes_parsed = WebMParseElementHeader(data, size, &id, &element_size); | |
258 | 258 |
259 if (bytes_parsed < 0) | 259 bool cluster_ended = cluster_parser_->cluster_ended(); |
260 return bytes_parsed; | |
261 | 260 |
262 if (bytes_parsed == 0) | 261 if ((!audio_buffers.empty() || !video_buffers.empty() || |
263 return result; | 262 !text_map.empty()) && |
263 !new_buffers_cb_.Run(audio_buffers, video_buffers, text_map)) { | |
264 return -1; | |
265 } | |
264 | 266 |
265 if (id != kWebMIdCluster) { | 267 if (cluster_ended) { |
266 ChangeState(kParsingHeaders); | 268 ChangeState(kParsingHeaders); |
267 return result; | 269 end_of_segment_cb_.Run(); |
268 } | 270 } |
269 } | |
270 | 271 |
271 bytes_parsed = cluster_parser_->Parse(data, size); | 272 return bytes_parsed; |
272 | |
273 if (bytes_parsed < 0) | |
274 return bytes_parsed; | |
275 | |
276 // If cluster detected, immediately notify new segment if we have not | |
277 // already done this. | |
278 if (!parsing_cluster_ && bytes_parsed > 0) { | |
279 parsing_cluster_ = true; | |
280 new_segment_cb_.Run(); | |
281 } | |
282 | |
283 const BufferQueue& audio_buffers = cluster_parser_->GetAudioBuffers(); | |
284 const BufferQueue& video_buffers = cluster_parser_->GetVideoBuffers(); | |
285 const TextBufferQueueMap& text_map = cluster_parser_->GetTextBuffers(); | |
286 | |
287 cluster_ended = cluster_parser_->cluster_ended(); | |
288 | |
289 if ((!audio_buffers.empty() || !video_buffers.empty() || | |
290 !text_map.empty()) && | |
291 !new_buffers_cb_.Run(audio_buffers, video_buffers, text_map)) { | |
292 return -1; | |
293 } | |
294 | |
295 if (cluster_ended) { | |
296 parsing_cluster_ = false; | |
297 end_of_segment_cb_.Run(); | |
298 } | |
299 | |
300 result += bytes_parsed; | |
301 data += bytes_parsed; | |
302 size -= bytes_parsed; | |
303 | |
304 // WebMClusterParser returns 0 and |cluster_ended| is true if previously | |
305 // parsing an unknown-size cluster and |data| does not continue that | |
306 // cluster. Try parsing again in that case. | |
307 } while (size > 0 && (bytes_parsed > 0 || cluster_ended)); | |
308 | |
309 return result; | |
310 } | 273 } |
311 | 274 |
312 void WebMStreamParser::FireNeedKey(const std::string& key_id) { | 275 void WebMStreamParser::FireNeedKey(const std::string& key_id) { |
313 std::vector<uint8> key_id_vector(key_id.begin(), key_id.end()); | 276 std::vector<uint8> key_id_vector(key_id.begin(), key_id.end()); |
314 need_key_cb_.Run(kWebMEncryptInitDataType, key_id_vector); | 277 need_key_cb_.Run(kWebMEncryptInitDataType, key_id_vector); |
315 } | 278 } |
316 | 279 |
317 } // namespace media | 280 } // namespace media |
OLD | NEW |