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

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

Issue 883403002: Parsing of encoded duration for unencrypted opus streams. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Responding to final feedback Created 5 years, 10 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
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_cluster_parser.h" 5 #include "media/formats/webm/webm_cluster_parser.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/sys_byteorder.h" 10 #include "base/sys_byteorder.h"
11 #include "media/base/buffers.h" 11 #include "media/base/buffers.h"
12 #include "media/base/decrypt_config.h" 12 #include "media/base/decrypt_config.h"
13 #include "media/filters/webvtt_util.h" 13 #include "media/filters/webvtt_util.h"
14 #include "media/formats/webm/webm_constants.h" 14 #include "media/formats/webm/webm_constants.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_webvtt_parser.h" 16 #include "media/formats/webm/webm_webvtt_parser.h"
17 17
18 namespace media { 18 namespace media {
19 19
20 const uint16_t WebMClusterParser::kOpusFrameDurationsMu[] = {
21 10000, 20000, 40000, 60000, 10000, 20000, 40000, 60000, 10000, 20000, 40000,
22 60000, 10000, 20000, 10000, 20000, 2500, 5000, 10000, 20000, 2500, 5000,
23 10000, 20000, 2500, 5000, 10000, 20000, 2500, 5000, 10000, 20000};
24
25 enum {
26 // Limits the number of MEDIA_LOG() calls in the path of reading encoded
27 // duration to avoid spamming for corrupted data.
28 kMaxDurationLogs = 10,
29 };
30
20 WebMClusterParser::WebMClusterParser( 31 WebMClusterParser::WebMClusterParser(
21 int64 timecode_scale, 32 int64 timecode_scale,
22 int audio_track_num, 33 int audio_track_num,
23 base::TimeDelta audio_default_duration, 34 base::TimeDelta audio_default_duration,
24 int video_track_num, 35 int video_track_num,
25 base::TimeDelta video_default_duration, 36 base::TimeDelta video_default_duration,
26 const WebMTracksParser::TextTracks& text_tracks, 37 const WebMTracksParser::TextTracks& text_tracks,
27 const std::set<int64>& ignored_tracks, 38 const std::set<int64>& ignored_tracks,
28 const std::string& audio_encryption_key_id, 39 const std::string& audio_encryption_key_id,
29 const std::string& video_encryption_key_id, 40 const std::string& video_encryption_key_id,
41 const AudioCodec audio_codec,
30 const LogCB& log_cb) 42 const LogCB& log_cb)
31 : timecode_multiplier_(timecode_scale / 1000.0), 43 : num_duration_errors_(0),
44 timecode_multiplier_(timecode_scale / 1000.0),
32 ignored_tracks_(ignored_tracks), 45 ignored_tracks_(ignored_tracks),
33 audio_encryption_key_id_(audio_encryption_key_id), 46 audio_encryption_key_id_(audio_encryption_key_id),
34 video_encryption_key_id_(video_encryption_key_id), 47 video_encryption_key_id_(video_encryption_key_id),
48 audio_codec_(audio_codec),
35 parser_(kWebMIdCluster, this), 49 parser_(kWebMIdCluster, this),
36 last_block_timecode_(-1), 50 last_block_timecode_(-1),
37 block_data_size_(-1), 51 block_data_size_(-1),
38 block_duration_(-1), 52 block_duration_(-1),
39 block_add_id_(-1), 53 block_add_id_(-1),
40 block_additional_data_size_(0), 54 block_additional_data_size_(0),
41 discard_padding_(-1), 55 discard_padding_(-1),
42 cluster_timecode_(-1), 56 cluster_timecode_(-1),
43 cluster_start_time_(kNoTimestamp()), 57 cluster_start_time_(kNoTimestamp()),
44 cluster_ended_(false), 58 cluster_ended_(false),
(...skipping 16 matching lines...) Expand all
61 cluster_timecode_ = -1; 75 cluster_timecode_ = -1;
62 cluster_start_time_ = kNoTimestamp(); 76 cluster_start_time_ = kNoTimestamp();
63 cluster_ended_ = false; 77 cluster_ended_ = false;
64 parser_.Reset(); 78 parser_.Reset();
65 audio_.Reset(); 79 audio_.Reset();
66 video_.Reset(); 80 video_.Reset();
67 ResetTextTracks(); 81 ResetTextTracks();
68 ready_buffer_upper_bound_ = kNoDecodeTimestamp(); 82 ready_buffer_upper_bound_ = kNoDecodeTimestamp();
69 } 83 }
70 84
71 int WebMClusterParser::Parse(const uint8* buf, int size) { 85 int WebMClusterParser::Parse(const uint8_t* buf, int size) {
72 audio_.ClearReadyBuffers(); 86 audio_.ClearReadyBuffers();
73 video_.ClearReadyBuffers(); 87 video_.ClearReadyBuffers();
74 ClearTextTrackReadyBuffers(); 88 ClearTextTrackReadyBuffers();
75 ready_buffer_upper_bound_ = kNoDecodeTimestamp(); 89 ready_buffer_upper_bound_ = kNoDecodeTimestamp();
76 90
77 int result = parser_.Parse(buf, size); 91 int result = parser_.Parse(buf, size);
78 92
79 if (result < 0) { 93 if (result < 0) {
80 cluster_ended_ = false; 94 cluster_ended_ = false;
81 return result; 95 return result;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 itr != text_track_map_.end(); 147 itr != text_track_map_.end();
134 ++itr) { 148 ++itr) {
135 const BufferQueue& text_buffers = itr->second.ready_buffers(); 149 const BufferQueue& text_buffers = itr->second.ready_buffers();
136 if (!text_buffers.empty()) 150 if (!text_buffers.empty())
137 text_buffers_map_.insert(std::make_pair(itr->first, text_buffers)); 151 text_buffers_map_.insert(std::make_pair(itr->first, text_buffers));
138 } 152 }
139 153
140 return text_buffers_map_; 154 return text_buffers_map_;
141 } 155 }
142 156
157 base::TimeDelta WebMClusterParser::TryGetEncodedAudioDuration(
158 const uint8_t* data,
159 int size) {
160
161 // Duration is currently read assuming the *entire* stream is unencrypted.
162 // The special "Signal Byte" prepended to Blocks in encrypted streams is
163 // assumed to not be present.
164 // TODO(chcunningham): Consider parsing "Signal Byte" for encrypted streams
165 // to return duration for any unencrypted blocks.
166
167 if (audio_codec_ == kCodecOpus) {
168 return ReadOpusDuration(data, size);
169 }
170
171 // TODO(wolenetz/chcunningham): Implement duration reading for Vorbis. See
172 // motivations in http://crbug.com/396634.
173
174 return kNoTimestamp();
175 }
176
177 base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data,
178 int size) {
179 // Masks and constants for Opus packets. See
180 // https://tools.ietf.org/html/rfc6716#page-14
181 static const uint8_t kTocConfigMask = 0xf8;
182 static const uint8_t kTocFrameCountCodeMask = 0x03;
183 static const uint8_t kFrameCountMask = 0x3f;
184 static const base::TimeDelta kPacketDurationMax =
185 base::TimeDelta::FromMilliseconds(120);
186
187 if (size < 1) {
188 LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
189 << "Invalid zero-byte Opus packet; demuxed block duration may be "
190 "imprecise.";
191 return kNoTimestamp();
192 }
193
194 // Frame count type described by last 2 bits of Opus TOC byte.
195 int frame_count_type = data[0] & kTocFrameCountCodeMask;
196
197 int frame_count = 0;
198 switch (frame_count_type) {
199 case 0:
200 frame_count = 1;
201 break;
202 case 1:
203 case 2:
204 frame_count = 2;
205 break;
206 case 3:
207 // Type 3 indicates an arbitrary frame count described in the next byte.
208 if (size < 2) {
209 LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
210 << "Second byte missing from 'Code 3' Opus packet; demuxed block "
211 "duration may be imprecise.";
212 return kNoTimestamp();
213 }
214
215 frame_count = data[1] & kFrameCountMask;
216
217 if (frame_count == 0) {
218 LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
219 << "Illegal 'Code 3' pus packet with frame count zero; demuxed "
wolenetz 2015/02/07 00:23:55 Oh noes! s/pus/Opus/ please
chcunningham 2015/02/09 19:21:51 Done.
220 "block duration may be imprecise.";
221 return kNoTimestamp();
222 }
223
224 break;
225 default:
226 LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
227 << "Unexpected Opus frame count type: " << frame_count_type << "; "
228 << "demuxed block duration may be imprecise.";
229 return kNoTimestamp();
230 }
231
232 int opusConfig = (data[0] & kTocConfigMask) >> 3;
233 CHECK_GE(opusConfig, 0);
234 CHECK_LT(opusConfig, static_cast<int>(arraysize(kOpusFrameDurationsMu)));
235
236 DCHECK_GT(frame_count, 0);
237 base::TimeDelta duration = base::TimeDelta::FromMicroseconds(
238 kOpusFrameDurationsMu[opusConfig] * frame_count);
239
240 if (duration > kPacketDurationMax) {
241 // Intentionally allowing packet to pass through for now. Decoder should
242 // either handle or fail gracefully. MEDIA_LOG as breadcrumbs in case
243 // things go sideways.
244 LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
245 << "Warning, demuxed Opus packet with encoded duration: " << duration
246 << ". Should be no greater than " << kPacketDurationMax;
247 }
248
249 return duration;
250 }
251
143 WebMParserClient* WebMClusterParser::OnListStart(int id) { 252 WebMParserClient* WebMClusterParser::OnListStart(int id) {
144 if (id == kWebMIdCluster) { 253 if (id == kWebMIdCluster) {
145 cluster_timecode_ = -1; 254 cluster_timecode_ = -1;
146 cluster_start_time_ = kNoTimestamp(); 255 cluster_start_time_ = kNoTimestamp();
147 } else if (id == kWebMIdBlockGroup) { 256 } else if (id == kWebMIdBlockGroup) {
148 block_data_.reset(); 257 block_data_.reset();
149 block_data_size_ = -1; 258 block_data_size_ = -1;
150 block_duration_ = -1; 259 block_duration_ = -1;
151 discard_padding_ = -1; 260 discard_padding_ = -1;
152 discard_padding_set_ = false; 261 discard_padding_set_ = false;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 break; 307 break;
199 default: 308 default:
200 return true; 309 return true;
201 } 310 }
202 if (*dst != -1) 311 if (*dst != -1)
203 return false; 312 return false;
204 *dst = val; 313 *dst = val;
205 return true; 314 return true;
206 } 315 }
207 316
208 bool WebMClusterParser::ParseBlock(bool is_simple_block, const uint8* buf, 317 bool WebMClusterParser::ParseBlock(bool is_simple_block,
209 int size, const uint8* additional, 318 const uint8_t* buf,
210 int additional_size, int duration, 319 int size,
320 const uint8_t* additional,
321 int additional_size,
322 int duration,
211 int64 discard_padding) { 323 int64 discard_padding) {
212 if (size < 4) 324 if (size < 4)
213 return false; 325 return false;
214 326
215 // Return an error if the trackNum > 127. We just aren't 327 // Return an error if the trackNum > 127. We just aren't
216 // going to support large track numbers right now. 328 // going to support large track numbers right now.
217 if (!(buf[0] & 0x80)) { 329 if (!(buf[0] & 0x80)) {
218 MEDIA_LOG(log_cb_) << "TrackNumber over 127 not supported"; 330 MEDIA_LOG(log_cb_) << "TrackNumber over 127 not supported";
219 return false; 331 return false;
220 } 332 }
221 333
222 int track_num = buf[0] & 0x7f; 334 int track_num = buf[0] & 0x7f;
223 int timecode = buf[1] << 8 | buf[2]; 335 int timecode = buf[1] << 8 | buf[2];
224 int flags = buf[3] & 0xff; 336 int flags = buf[3] & 0xff;
225 int lacing = (flags >> 1) & 0x3; 337 int lacing = (flags >> 1) & 0x3;
226 338
227 if (lacing) { 339 if (lacing) {
228 MEDIA_LOG(log_cb_) << "Lacing " << lacing << " is not supported yet."; 340 MEDIA_LOG(log_cb_) << "Lacing " << lacing << " is not supported yet.";
229 return false; 341 return false;
230 } 342 }
231 343
232 // Sign extend negative timecode offsets. 344 // Sign extend negative timecode offsets.
233 if (timecode & 0x8000) 345 if (timecode & 0x8000)
234 timecode |= ~0xffff; 346 timecode |= ~0xffff;
235 347
236 const uint8* frame_data = buf + 4; 348 const uint8_t* frame_data = buf + 4;
237 int frame_size = size - (frame_data - buf); 349 int frame_size = size - (frame_data - buf);
238 return OnBlock(is_simple_block, track_num, timecode, duration, flags, 350 return OnBlock(is_simple_block, track_num, timecode, duration, flags,
239 frame_data, frame_size, additional, additional_size, 351 frame_data, frame_size, additional, additional_size,
240 discard_padding); 352 discard_padding);
241 } 353 }
242 354
243 bool WebMClusterParser::OnBinary(int id, const uint8* data, int size) { 355 bool WebMClusterParser::OnBinary(int id, const uint8_t* data, int size) {
244 switch (id) { 356 switch (id) {
245 case kWebMIdSimpleBlock: 357 case kWebMIdSimpleBlock:
246 return ParseBlock(true, data, size, NULL, 0, -1, 0); 358 return ParseBlock(true, data, size, NULL, 0, -1, 0);
247 359
248 case kWebMIdBlock: 360 case kWebMIdBlock:
249 if (block_data_) { 361 if (block_data_) {
250 MEDIA_LOG(log_cb_) << "More than 1 Block in a BlockGroup is not " 362 MEDIA_LOG(log_cb_) << "More than 1 Block in a BlockGroup is not "
251 "supported."; 363 "supported.";
252 return false; 364 return false;
253 } 365 }
254 block_data_.reset(new uint8[size]); 366 block_data_.reset(new uint8_t[size]);
255 memcpy(block_data_.get(), data, size); 367 memcpy(block_data_.get(), data, size);
256 block_data_size_ = size; 368 block_data_size_ = size;
257 return true; 369 return true;
258 370
259 case kWebMIdBlockAdditional: { 371 case kWebMIdBlockAdditional: {
260 uint64 block_add_id = base::HostToNet64(block_add_id_); 372 uint64 block_add_id = base::HostToNet64(block_add_id_);
261 if (block_additional_data_) { 373 if (block_additional_data_) {
262 // TODO(vigneshv): Technically, more than 1 BlockAdditional is allowed 374 // TODO(vigneshv): Technically, more than 1 BlockAdditional is allowed
263 // as per matroska spec. But for now we don't have a use case to 375 // as per matroska spec. But for now we don't have a use case to
264 // support parsing of such files. Take a look at this again when such a 376 // support parsing of such files. Take a look at this again when such a
265 // case arises. 377 // case arises.
266 MEDIA_LOG(log_cb_) << "More than 1 BlockAdditional in a BlockGroup is " 378 MEDIA_LOG(log_cb_) << "More than 1 BlockAdditional in a BlockGroup is "
267 "not supported."; 379 "not supported.";
268 return false; 380 return false;
269 } 381 }
270 // First 8 bytes of side_data in DecoderBuffer is the BlockAddID 382 // First 8 bytes of side_data in DecoderBuffer is the BlockAddID
271 // element's value in Big Endian format. This is done to mimic ffmpeg 383 // element's value in Big Endian format. This is done to mimic ffmpeg
272 // demuxer's behavior. 384 // demuxer's behavior.
273 block_additional_data_size_ = size + sizeof(block_add_id); 385 block_additional_data_size_ = size + sizeof(block_add_id);
274 block_additional_data_.reset(new uint8[block_additional_data_size_]); 386 block_additional_data_.reset(new uint8_t[block_additional_data_size_]);
275 memcpy(block_additional_data_.get(), &block_add_id, 387 memcpy(block_additional_data_.get(), &block_add_id,
276 sizeof(block_add_id)); 388 sizeof(block_add_id));
277 memcpy(block_additional_data_.get() + 8, data, size); 389 memcpy(block_additional_data_.get() + 8, data, size);
278 return true; 390 return true;
279 } 391 }
280 case kWebMIdDiscardPadding: { 392 case kWebMIdDiscardPadding: {
281 if (discard_padding_set_ || size <= 0 || size > 8) 393 if (discard_padding_set_ || size <= 0 || size > 8)
282 return false; 394 return false;
283 discard_padding_set_ = true; 395 discard_padding_set_ = true;
284 396
285 // Read in the big-endian integer. 397 // Read in the big-endian integer.
286 discard_padding_ = static_cast<int8>(data[0]); 398 discard_padding_ = static_cast<int8>(data[0]);
287 for (int i = 1; i < size; ++i) 399 for (int i = 1; i < size; ++i)
288 discard_padding_ = (discard_padding_ << 8) | data[i]; 400 discard_padding_ = (discard_padding_ << 8) | data[i];
289 401
290 return true; 402 return true;
291 } 403 }
292 default: 404 default:
293 return true; 405 return true;
294 } 406 }
295 } 407 }
296 408
297 bool WebMClusterParser::OnBlock(bool is_simple_block, int track_num, 409 bool WebMClusterParser::OnBlock(bool is_simple_block,
410 int track_num,
298 int timecode, 411 int timecode,
299 int block_duration, 412 int block_duration,
300 int flags, 413 int flags,
301 const uint8* data, int size, 414 const uint8_t* data,
302 const uint8* additional, int additional_size, 415 int size,
416 const uint8_t* additional,
417 int additional_size,
303 int64 discard_padding) { 418 int64 discard_padding) {
304 DCHECK_GE(size, 0); 419 DCHECK_GE(size, 0);
305 if (cluster_timecode_ == -1) { 420 if (cluster_timecode_ == -1) {
306 MEDIA_LOG(log_cb_) << "Got a block before cluster timecode."; 421 MEDIA_LOG(log_cb_) << "Got a block before cluster timecode.";
307 return false; 422 return false;
308 } 423 }
309 424
310 // TODO(acolwell): Should relative negative timecode offsets be rejected? Or 425 // TODO(acolwell): Should relative negative timecode offsets be rejected? Or
311 // only when the absolute timecode is negative? See http://crbug.com/271794 426 // only when the absolute timecode is negative? See http://crbug.com/271794
312 if (timecode < 0) { 427 if (timecode < 0) {
313 MEDIA_LOG(log_cb_) << "Got a block with negative timecode offset " 428 MEDIA_LOG(log_cb_) << "Got a block with negative timecode offset "
314 << timecode; 429 << timecode;
315 return false; 430 return false;
316 } 431 }
317 432
318 if (last_block_timecode_ != -1 && timecode < last_block_timecode_) { 433 if (last_block_timecode_ != -1 && timecode < last_block_timecode_) {
319 MEDIA_LOG(log_cb_) 434 MEDIA_LOG(log_cb_)
320 << "Got a block with a timecode before the previous block."; 435 << "Got a block with a timecode before the previous block.";
321 return false; 436 return false;
322 } 437 }
323 438
324 Track* track = NULL; 439 Track* track = NULL;
325 StreamParserBuffer::Type buffer_type = DemuxerStream::AUDIO; 440 StreamParserBuffer::Type buffer_type = DemuxerStream::AUDIO;
326 std::string encryption_key_id; 441 std::string encryption_key_id;
442 base::TimeDelta encoded_duration = kNoTimestamp();
327 if (track_num == audio_.track_num()) { 443 if (track_num == audio_.track_num()) {
328 track = &audio_; 444 track = &audio_;
329 encryption_key_id = audio_encryption_key_id_; 445 encryption_key_id = audio_encryption_key_id_;
446 if (encryption_key_id.empty()) {
447 encoded_duration = TryGetEncodedAudioDuration(data, size);
448 }
330 } else if (track_num == video_.track_num()) { 449 } else if (track_num == video_.track_num()) {
331 track = &video_; 450 track = &video_;
332 encryption_key_id = video_encryption_key_id_; 451 encryption_key_id = video_encryption_key_id_;
333 buffer_type = DemuxerStream::VIDEO; 452 buffer_type = DemuxerStream::VIDEO;
334 } else if (ignored_tracks_.find(track_num) != ignored_tracks_.end()) { 453 } else if (ignored_tracks_.find(track_num) != ignored_tracks_.end()) {
335 return true; 454 return true;
336 } else if (Track* const text_track = FindTextTrack(track_num)) { 455 } else if (Track* const text_track = FindTextTrack(track_num)) {
337 if (is_simple_block) // BlockGroup is required for WebVTT cues 456 if (is_simple_block) // BlockGroup is required for WebVTT cues
338 return false; 457 return false;
339 if (block_duration < 0) // not specified 458 if (block_duration < 0) // not specified
(...skipping 20 matching lines...) Expand all
360 is_simple_block ? (flags & 0x80) != 0 : track->IsKeyframe(data, size); 479 is_simple_block ? (flags & 0x80) != 0 : track->IsKeyframe(data, size);
361 480
362 // Every encrypted Block has a signal byte and IV prepended to it. Current 481 // Every encrypted Block has a signal byte and IV prepended to it. Current
363 // encrypted WebM request for comments specification is here 482 // encrypted WebM request for comments specification is here
364 // http://wiki.webmproject.org/encryption/webm-encryption-rfc 483 // http://wiki.webmproject.org/encryption/webm-encryption-rfc
365 scoped_ptr<DecryptConfig> decrypt_config; 484 scoped_ptr<DecryptConfig> decrypt_config;
366 int data_offset = 0; 485 int data_offset = 0;
367 if (!encryption_key_id.empty() && 486 if (!encryption_key_id.empty() &&
368 !WebMCreateDecryptConfig( 487 !WebMCreateDecryptConfig(
369 data, size, 488 data, size,
370 reinterpret_cast<const uint8*>(encryption_key_id.data()), 489 reinterpret_cast<const uint8_t*>(encryption_key_id.data()),
371 encryption_key_id.size(), 490 encryption_key_id.size(),
372 &decrypt_config, &data_offset)) { 491 &decrypt_config, &data_offset)) {
373 return false; 492 return false;
374 } 493 }
375 494
376 // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId 495 // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId
377 // type with remapped bytestream track numbers and allow multiple tracks as 496 // type with remapped bytestream track numbers and allow multiple tracks as
378 // applicable. See https://crbug.com/341581. 497 // applicable. See https://crbug.com/341581.
379 buffer = StreamParserBuffer::CopyFrom( 498 buffer = StreamParserBuffer::CopyFrom(
380 data + data_offset, size - data_offset, 499 data + data_offset, size - data_offset,
381 additional, additional_size, 500 additional, additional_size,
382 is_keyframe, buffer_type, track_num); 501 is_keyframe, buffer_type, track_num);
383 502
384 if (decrypt_config) 503 if (decrypt_config)
385 buffer->set_decrypt_config(decrypt_config.Pass()); 504 buffer->set_decrypt_config(decrypt_config.Pass());
386 } else { 505 } else {
387 std::string id, settings, content; 506 std::string id, settings, content;
388 WebMWebVTTParser::Parse(data, size, &id, &settings, &content); 507 WebMWebVTTParser::Parse(data, size, &id, &settings, &content);
389 508
390 std::vector<uint8> side_data; 509 std::vector<uint8_t> side_data;
391 MakeSideData(id.begin(), id.end(), 510 MakeSideData(id.begin(), id.end(),
392 settings.begin(), settings.end(), 511 settings.begin(), settings.end(),
393 &side_data); 512 &side_data);
394 513
395 // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId 514 // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId
396 // type with remapped bytestream track numbers and allow multiple tracks as 515 // type with remapped bytestream track numbers and allow multiple tracks as
397 // applicable. See https://crbug.com/341581. 516 // applicable. See https://crbug.com/341581.
398 buffer = StreamParserBuffer::CopyFrom( 517 buffer = StreamParserBuffer::CopyFrom(
399 reinterpret_cast<const uint8*>(content.data()), 518 reinterpret_cast<const uint8_t*>(content.data()),
400 content.length(), 519 content.length(),
401 &side_data[0], 520 &side_data[0],
402 side_data.size(), 521 side_data.size(),
403 true, buffer_type, track_num); 522 true, buffer_type, track_num);
404 } 523 }
405 524
406 buffer->set_timestamp(timestamp); 525 buffer->set_timestamp(timestamp);
407 if (cluster_start_time_ == kNoTimestamp()) 526 if (cluster_start_time_ == kNoTimestamp())
408 cluster_start_time_ = timestamp; 527 cluster_start_time_ = timestamp;
409 528
529 base::TimeDelta block_duration_time_delta = kNoTimestamp();
410 if (block_duration >= 0) { 530 if (block_duration >= 0) {
411 buffer->set_duration(base::TimeDelta::FromMicroseconds( 531 block_duration_time_delta = base::TimeDelta::FromMicroseconds(
412 block_duration * timecode_multiplier_)); 532 block_duration * timecode_multiplier_);
533 }
534
535 // Prefer encoded duration over BlockGroup->BlockDuration or
536 // TrackEntry->DefaultDuration when available. This layering violation is a
537 // workaround for http://crbug.com/396634, decreasing the likelihood of
538 // fall-back to rough estimation techniques for Blocks that lack a
539 // BlockDuration at the end of a cluster. Cross cluster durations are not
540 // feasible given flexibility of cluster ordering and MSE APIs. Duration
541 // estimation may still apply in cases of encryption and codecs for which
542 // we do not extract encoded duration. Within a cluster, estimates are applied
543 // as Block Timecode deltas, or once the whole cluster is parsed in the case
544 // of the last Block in the cluster. See Track::AddBuffer and
545 // ApplyDurationEstimateIfNeeded().
546 if (encoded_duration != kNoTimestamp()) {
547 DCHECK(encoded_duration != kInfiniteDuration());
548 DCHECK(encoded_duration > base::TimeDelta());
549 buffer->set_duration(encoded_duration);
550
551 DVLOG(3) << __FUNCTION__ << " : "
552 << "Using encoded duration " << encoded_duration.InSecondsF();
553
554 if (block_duration_time_delta != kNoTimestamp()) {
555 base::TimeDelta duration_difference =
556 block_duration_time_delta - encoded_duration;
557
558 const auto kWarnDurationDiff =
559 base::TimeDelta::FromMicroseconds(timecode_multiplier_ * 2);
560 if (duration_difference.magnitude() > kWarnDurationDiff) {
561 LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
562 << "BlockDuration "
563 << "(" << block_duration_time_delta << ") "
564 << "differs significantly from encoded duration "
565 << "(" << encoded_duration << ").";
566 }
567 }
568 } else if (block_duration_time_delta != kNoTimestamp()) {
569 buffer->set_duration(block_duration_time_delta);
413 } else { 570 } else {
414 DCHECK_NE(buffer_type, DemuxerStream::TEXT); 571 DCHECK_NE(buffer_type, DemuxerStream::TEXT);
415 buffer->set_duration(track->default_duration()); 572 buffer->set_duration(track->default_duration());
416 } 573 }
417 574
418 if (discard_padding != 0) { 575 if (discard_padding != 0) {
419 buffer->set_discard_padding(std::make_pair( 576 buffer->set_discard_padding(std::make_pair(
420 base::TimeDelta(), 577 base::TimeDelta(),
421 base::TimeDelta::FromMicroseconds(discard_padding / 1000))); 578 base::TimeDelta::FromMicroseconds(discard_padding / 1000)));
422 } 579 }
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 // reset here. 699 // reset here.
543 ready_buffers_.clear(); 700 ready_buffers_.clear();
544 } 701 }
545 702
546 void WebMClusterParser::Track::Reset() { 703 void WebMClusterParser::Track::Reset() {
547 ClearReadyBuffers(); 704 ClearReadyBuffers();
548 buffers_.clear(); 705 buffers_.clear();
549 last_added_buffer_missing_duration_ = NULL; 706 last_added_buffer_missing_duration_ = NULL;
550 } 707 }
551 708
552 bool WebMClusterParser::Track::IsKeyframe(const uint8* data, int size) const { 709 bool WebMClusterParser::Track::IsKeyframe(const uint8_t* data, int size) const {
553 // For now, assume that all blocks are keyframes for datatypes other than 710 // For now, assume that all blocks are keyframes for datatypes other than
554 // video. This is a valid assumption for Vorbis, WebVTT, & Opus. 711 // video. This is a valid assumption for Vorbis, WebVTT, & Opus.
555 if (!is_video_) 712 if (!is_video_)
556 return true; 713 return true;
557 714
558 // Make sure the block is big enough for the minimal keyframe header size. 715 // Make sure the block is big enough for the minimal keyframe header size.
559 if (size < 7) 716 if (size < 7)
560 return false; 717 return false;
561 718
562 // The LSb of the first byte must be a 0 for a keyframe. 719 // The LSb of the first byte must be a 0 for a keyframe.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 WebMClusterParser::FindTextTrack(int track_num) { 835 WebMClusterParser::FindTextTrack(int track_num) {
679 const TextTrackMap::iterator it = text_track_map_.find(track_num); 836 const TextTrackMap::iterator it = text_track_map_.find(track_num);
680 837
681 if (it == text_track_map_.end()) 838 if (it == text_track_map_.end())
682 return NULL; 839 return NULL;
683 840
684 return &it->second; 841 return &it->second;
685 } 842 }
686 843
687 } // namespace media 844 } // namespace media
OLDNEW
« no previous file with comments | « media/formats/webm/webm_cluster_parser.h ('k') | media/formats/webm/webm_cluster_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698