Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: media/formats/webm/webm_stream_parser.cc

Issue 346613003: Fix WebMStreamParser to handle Cues between Clusters correctly. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/formats/webm/webm_stream_parser.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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; 61 if (cluster_parser_)
63 62 cluster_parser_->Reset();
64 if (state_ != kParsingClusters) 63 if (state_ == kParsingClusters) {
65 return; 64 ChangeState(kParsingHeaders);
66 65 end_of_segment_cb_.Run();
67 cluster_parser_->Reset(); 66 }
68 } 67 }
69 68
70 bool WebMStreamParser::Parse(const uint8* buf, int size) { 69 bool WebMStreamParser::Parse(const uint8* buf, int size) {
71 DCHECK_NE(state_, kWaitingForInit); 70 DCHECK_NE(state_, kWaitingForInit);
72 71
73 if (state_ == kError) 72 if (state_ == kError)
74 return false; 73 return false;
75 74
76 byte_queue_.Push(buf, size); 75 byte_queue_.Push(buf, size);
77 76
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 case kWebMIdCues: 143 case kWebMIdCues:
145 case kWebMIdChapters: 144 case kWebMIdChapters:
146 // TODO(matthewjheaney): Implement support for chapters. 145 // TODO(matthewjheaney): Implement support for chapters.
147 if (cur_size < (result + element_size)) { 146 if (cur_size < (result + element_size)) {
148 // We don't have the whole element yet. Signal we need more data. 147 // We don't have the whole element yet. Signal we need more data.
149 return 0; 148 return 0;
150 } 149 }
151 // Skip the element. 150 // Skip the element.
152 return result + element_size; 151 return result + element_size;
153 break; 152 break;
153 case kWebMIdCluster:
154 if (!cluster_parser_) {
155 MEDIA_LOG(log_cb_) << "Found Cluster element before Info.";
156 return -1;
157 }
158 ChangeState(kParsingClusters);
159 new_segment_cb_.Run();
160 return 0;
161 break;
154 case kWebMIdSegment: 162 case kWebMIdSegment:
155 // Segment of unknown size indicates live stream. 163 // Segment of unknown size indicates live stream.
156 if (element_size == kWebMUnknownSize) 164 if (element_size == kWebMUnknownSize)
157 unknown_segment_size_ = true; 165 unknown_segment_size_ = true;
158 // Just consume the segment header. 166 // Just consume the segment header.
159 return result; 167 return result;
160 break; 168 break;
161 case kWebMIdInfo: 169 case kWebMIdInfo:
162 // We've found the element we are looking for. 170 // We've found the element we are looking for.
163 break; 171 break;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 tracks_parser.audio_track_num(), 232 tracks_parser.audio_track_num(),
225 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us), 233 tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us),
226 tracks_parser.video_track_num(), 234 tracks_parser.video_track_num(),
227 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us), 235 tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
228 tracks_parser.text_tracks(), 236 tracks_parser.text_tracks(),
229 tracks_parser.ignored_tracks(), 237 tracks_parser.ignored_tracks(),
230 tracks_parser.audio_encryption_key_id(), 238 tracks_parser.audio_encryption_key_id(),
231 tracks_parser.video_encryption_key_id(), 239 tracks_parser.video_encryption_key_id(),
232 log_cb_)); 240 log_cb_));
233 241
234 ChangeState(kParsingClusters);
235
236 if (!init_cb_.is_null()) 242 if (!init_cb_.is_null())
237 base::ResetAndReturn(&init_cb_).Run(true, params); 243 base::ResetAndReturn(&init_cb_).Run(true, params);
238 244
239 return bytes_parsed; 245 return bytes_parsed;
240 } 246 }
241 247
242 int WebMStreamParser::ParseCluster(const uint8* data, int size) { 248 int WebMStreamParser::ParseCluster(const uint8* data, int size) {
243 if (!cluster_parser_) 249 if (!cluster_parser_)
244 return -1; 250 return -1;
245 251
246 int result = 0; 252 int bytes_parsed = cluster_parser_->Parse(data, size);
247 int bytes_parsed; 253 if (bytes_parsed < 0)
248 bool cluster_ended; 254 return bytes_parsed;
249 do {
250 cluster_ended = false;
251 255
252 // If we are not parsing a cluster then handle the case when the next 256 const BufferQueue& audio_buffers = cluster_parser_->GetAudioBuffers();
253 // element is not a cluster. 257 const BufferQueue& video_buffers = cluster_parser_->GetVideoBuffers();
254 if (!parsing_cluster_) { 258 const TextBufferQueueMap& text_map = cluster_parser_->GetTextBuffers();
255 int id;
256 int64 element_size;
257 bytes_parsed = WebMParseElementHeader(data, size, &id, &element_size);
258 259
259 if (bytes_parsed < 0) 260 bool cluster_ended = cluster_parser_->cluster_ended();
260 return bytes_parsed;
261 261
262 if (bytes_parsed == 0) 262 if ((!audio_buffers.empty() || !video_buffers.empty() ||
263 return result; 263 !text_map.empty()) &&
264 !new_buffers_cb_.Run(audio_buffers, video_buffers, text_map)) {
265 return -1;
266 }
264 267
265 if (id != kWebMIdCluster) { 268 if (cluster_ended) {
266 ChangeState(kParsingHeaders); 269 ChangeState(kParsingHeaders);
267 return result; 270 end_of_segment_cb_.Run();
268 } 271 }
269 }
270 272
271 bytes_parsed = cluster_parser_->Parse(data, size); 273 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 } 274 }
311 275
312 void WebMStreamParser::FireNeedKey(const std::string& key_id) { 276 void WebMStreamParser::FireNeedKey(const std::string& key_id) {
313 std::vector<uint8> key_id_vector(key_id.begin(), key_id.end()); 277 std::vector<uint8> key_id_vector(key_id.begin(), key_id.end());
314 need_key_cb_.Run(kWebMEncryptInitDataType, key_id_vector); 278 need_key_cb_.Run(kWebMEncryptInitDataType, key_id_vector);
315 } 279 }
316 280
317 } // namespace media 281 } // namespace media
OLDNEW
« no previous file with comments | « media/formats/webm/webm_stream_parser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698