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

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
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;
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
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
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
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
OLDNEW
« media/filters/chunk_demuxer_unittest.cc ('K') | « 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