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_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" |
(...skipping 24 matching lines...) Expand all Loading... |
35 int64 timecode_scale, | 35 int64 timecode_scale, |
36 int audio_track_num, | 36 int audio_track_num, |
37 base::TimeDelta audio_default_duration, | 37 base::TimeDelta audio_default_duration, |
38 int video_track_num, | 38 int video_track_num, |
39 base::TimeDelta video_default_duration, | 39 base::TimeDelta video_default_duration, |
40 const WebMTracksParser::TextTracks& text_tracks, | 40 const WebMTracksParser::TextTracks& text_tracks, |
41 const std::set<int64>& ignored_tracks, | 41 const std::set<int64>& ignored_tracks, |
42 const std::string& audio_encryption_key_id, | 42 const std::string& audio_encryption_key_id, |
43 const std::string& video_encryption_key_id, | 43 const std::string& video_encryption_key_id, |
44 const AudioCodec audio_codec, | 44 const AudioCodec audio_codec, |
45 const LogCB& log_cb) | 45 const scoped_refptr<MediaLog>& media_log) |
46 : num_duration_errors_(0), | 46 : num_duration_errors_(0), |
47 timecode_multiplier_(timecode_scale / 1000.0), | 47 timecode_multiplier_(timecode_scale / 1000.0), |
48 ignored_tracks_(ignored_tracks), | 48 ignored_tracks_(ignored_tracks), |
49 audio_encryption_key_id_(audio_encryption_key_id), | 49 audio_encryption_key_id_(audio_encryption_key_id), |
50 video_encryption_key_id_(video_encryption_key_id), | 50 video_encryption_key_id_(video_encryption_key_id), |
51 audio_codec_(audio_codec), | 51 audio_codec_(audio_codec), |
52 parser_(kWebMIdCluster, this), | 52 parser_(kWebMIdCluster, this), |
53 last_block_timecode_(-1), | 53 last_block_timecode_(-1), |
54 block_data_size_(-1), | 54 block_data_size_(-1), |
55 block_duration_(-1), | 55 block_duration_(-1), |
56 block_add_id_(-1), | 56 block_add_id_(-1), |
57 block_additional_data_size_(0), | 57 block_additional_data_size_(0), |
58 discard_padding_(-1), | 58 discard_padding_(-1), |
59 cluster_timecode_(-1), | 59 cluster_timecode_(-1), |
60 cluster_start_time_(kNoTimestamp()), | 60 cluster_start_time_(kNoTimestamp()), |
61 cluster_ended_(false), | 61 cluster_ended_(false), |
62 audio_(audio_track_num, false, audio_default_duration, log_cb), | 62 audio_(audio_track_num, false, audio_default_duration, media_log), |
63 video_(video_track_num, true, video_default_duration, log_cb), | 63 video_(video_track_num, true, video_default_duration, media_log), |
64 ready_buffer_upper_bound_(kNoDecodeTimestamp()), | 64 ready_buffer_upper_bound_(kNoDecodeTimestamp()), |
65 log_cb_(log_cb) { | 65 media_log_(media_log) { |
66 for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin(); | 66 for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin(); |
67 it != text_tracks.end(); | 67 it != text_tracks.end(); |
68 ++it) { | 68 ++it) { |
69 text_track_map_.insert(std::make_pair( | 69 text_track_map_.insert(std::make_pair( |
70 it->first, Track(it->first, false, kNoTimestamp(), log_cb_))); | 70 it->first, Track(it->first, false, kNoTimestamp(), media_log_))); |
71 } | 71 } |
72 } | 72 } |
73 | 73 |
74 WebMClusterParser::~WebMClusterParser() {} | 74 WebMClusterParser::~WebMClusterParser() {} |
75 | 75 |
76 void WebMClusterParser::Reset() { | 76 void WebMClusterParser::Reset() { |
77 last_block_timecode_ = -1; | 77 last_block_timecode_ = -1; |
78 cluster_timecode_ = -1; | 78 cluster_timecode_ = -1; |
79 cluster_start_time_ = kNoTimestamp(); | 79 cluster_start_time_ = kNoTimestamp(); |
80 cluster_ended_ = false; | 80 cluster_ended_ = false; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 int size) { | 181 int size) { |
182 // Masks and constants for Opus packets. See | 182 // Masks and constants for Opus packets. See |
183 // https://tools.ietf.org/html/rfc6716#page-14 | 183 // https://tools.ietf.org/html/rfc6716#page-14 |
184 static const uint8_t kTocConfigMask = 0xf8; | 184 static const uint8_t kTocConfigMask = 0xf8; |
185 static const uint8_t kTocFrameCountCodeMask = 0x03; | 185 static const uint8_t kTocFrameCountCodeMask = 0x03; |
186 static const uint8_t kFrameCountMask = 0x3f; | 186 static const uint8_t kFrameCountMask = 0x3f; |
187 static const base::TimeDelta kPacketDurationMax = | 187 static const base::TimeDelta kPacketDurationMax = |
188 base::TimeDelta::FromMilliseconds(120); | 188 base::TimeDelta::FromMilliseconds(120); |
189 | 189 |
190 if (size < 1) { | 190 if (size < 1) { |
191 LIMITED_MEDIA_LOG(DEBUG, log_cb_, num_duration_errors_, | 191 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
192 kMaxDurationErrorLogs) | 192 kMaxDurationErrorLogs) |
193 << "Invalid zero-byte Opus packet; demuxed block duration may be " | 193 << "Invalid zero-byte Opus packet; demuxed block duration may be " |
194 "imprecise."; | 194 "imprecise."; |
195 return kNoTimestamp(); | 195 return kNoTimestamp(); |
196 } | 196 } |
197 | 197 |
198 // Frame count type described by last 2 bits of Opus TOC byte. | 198 // Frame count type described by last 2 bits of Opus TOC byte. |
199 int frame_count_type = data[0] & kTocFrameCountCodeMask; | 199 int frame_count_type = data[0] & kTocFrameCountCodeMask; |
200 | 200 |
201 int frame_count = 0; | 201 int frame_count = 0; |
202 switch (frame_count_type) { | 202 switch (frame_count_type) { |
203 case 0: | 203 case 0: |
204 frame_count = 1; | 204 frame_count = 1; |
205 break; | 205 break; |
206 case 1: | 206 case 1: |
207 case 2: | 207 case 2: |
208 frame_count = 2; | 208 frame_count = 2; |
209 break; | 209 break; |
210 case 3: | 210 case 3: |
211 // Type 3 indicates an arbitrary frame count described in the next byte. | 211 // Type 3 indicates an arbitrary frame count described in the next byte. |
212 if (size < 2) { | 212 if (size < 2) { |
213 LIMITED_MEDIA_LOG(DEBUG, log_cb_, num_duration_errors_, | 213 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
214 kMaxDurationErrorLogs) | 214 kMaxDurationErrorLogs) |
215 << "Second byte missing from 'Code 3' Opus packet; demuxed block " | 215 << "Second byte missing from 'Code 3' Opus packet; demuxed block " |
216 "duration may be imprecise."; | 216 "duration may be imprecise."; |
217 return kNoTimestamp(); | 217 return kNoTimestamp(); |
218 } | 218 } |
219 | 219 |
220 frame_count = data[1] & kFrameCountMask; | 220 frame_count = data[1] & kFrameCountMask; |
221 | 221 |
222 if (frame_count == 0) { | 222 if (frame_count == 0) { |
223 LIMITED_MEDIA_LOG(DEBUG, log_cb_, num_duration_errors_, | 223 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
224 kMaxDurationErrorLogs) | 224 kMaxDurationErrorLogs) |
225 << "Illegal 'Code 3' Opus packet with frame count zero; demuxed " | 225 << "Illegal 'Code 3' Opus packet with frame count zero; demuxed " |
226 "block duration may be imprecise."; | 226 "block duration may be imprecise."; |
227 return kNoTimestamp(); | 227 return kNoTimestamp(); |
228 } | 228 } |
229 | 229 |
230 break; | 230 break; |
231 default: | 231 default: |
232 LIMITED_MEDIA_LOG(DEBUG, log_cb_, num_duration_errors_, | 232 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
233 kMaxDurationErrorLogs) | 233 kMaxDurationErrorLogs) |
234 << "Unexpected Opus frame count type: " << frame_count_type << "; " | 234 << "Unexpected Opus frame count type: " << frame_count_type << "; " |
235 << "demuxed block duration may be imprecise."; | 235 << "demuxed block duration may be imprecise."; |
236 return kNoTimestamp(); | 236 return kNoTimestamp(); |
237 } | 237 } |
238 | 238 |
239 int opusConfig = (data[0] & kTocConfigMask) >> 3; | 239 int opusConfig = (data[0] & kTocConfigMask) >> 3; |
240 CHECK_GE(opusConfig, 0); | 240 CHECK_GE(opusConfig, 0); |
241 CHECK_LT(opusConfig, static_cast<int>(arraysize(kOpusFrameDurationsMu))); | 241 CHECK_LT(opusConfig, static_cast<int>(arraysize(kOpusFrameDurationsMu))); |
242 | 242 |
243 DCHECK_GT(frame_count, 0); | 243 DCHECK_GT(frame_count, 0); |
244 base::TimeDelta duration = base::TimeDelta::FromMicroseconds( | 244 base::TimeDelta duration = base::TimeDelta::FromMicroseconds( |
245 kOpusFrameDurationsMu[opusConfig] * frame_count); | 245 kOpusFrameDurationsMu[opusConfig] * frame_count); |
246 | 246 |
247 if (duration > kPacketDurationMax) { | 247 if (duration > kPacketDurationMax) { |
248 // Intentionally allowing packet to pass through for now. Decoder should | 248 // Intentionally allowing packet to pass through for now. Decoder should |
249 // either handle or fail gracefully. MEDIA_LOG as breadcrumbs in case | 249 // either handle or fail gracefully. MEDIA_LOG as breadcrumbs in case |
250 // things go sideways. | 250 // things go sideways. |
251 LIMITED_MEDIA_LOG(DEBUG, log_cb_, num_duration_errors_, | 251 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
252 kMaxDurationErrorLogs) | 252 kMaxDurationErrorLogs) |
253 << "Warning, demuxed Opus packet with encoded duration: " << duration | 253 << "Warning, demuxed Opus packet with encoded duration: " << duration |
254 << ". Should be no greater than " << kPacketDurationMax; | 254 << ". Should be no greater than " << kPacketDurationMax; |
255 } | 255 } |
256 | 256 |
257 return duration; | 257 return duration; |
258 } | 258 } |
259 | 259 |
260 WebMParserClient* WebMClusterParser::OnListStart(int id) { | 260 WebMParserClient* WebMClusterParser::OnListStart(int id) { |
261 if (id == kWebMIdCluster) { | 261 if (id == kWebMIdCluster) { |
(...skipping 13 matching lines...) Expand all Loading... |
275 | 275 |
276 return this; | 276 return this; |
277 } | 277 } |
278 | 278 |
279 bool WebMClusterParser::OnListEnd(int id) { | 279 bool WebMClusterParser::OnListEnd(int id) { |
280 if (id != kWebMIdBlockGroup) | 280 if (id != kWebMIdBlockGroup) |
281 return true; | 281 return true; |
282 | 282 |
283 // Make sure the BlockGroup actually had a Block. | 283 // Make sure the BlockGroup actually had a Block. |
284 if (block_data_size_ == -1) { | 284 if (block_data_size_ == -1) { |
285 MEDIA_LOG(ERROR, log_cb_) << "Block missing from BlockGroup."; | 285 MEDIA_LOG(ERROR, media_log_) << "Block missing from BlockGroup."; |
286 return false; | 286 return false; |
287 } | 287 } |
288 | 288 |
289 bool result = ParseBlock(false, block_data_.get(), block_data_size_, | 289 bool result = ParseBlock(false, block_data_.get(), block_data_size_, |
290 block_additional_data_.get(), | 290 block_additional_data_.get(), |
291 block_additional_data_size_, block_duration_, | 291 block_additional_data_size_, block_duration_, |
292 discard_padding_set_ ? discard_padding_ : 0); | 292 discard_padding_set_ ? discard_padding_ : 0); |
293 block_data_.reset(); | 293 block_data_.reset(); |
294 block_data_size_ = -1; | 294 block_data_size_ = -1; |
295 block_duration_ = -1; | 295 block_duration_ = -1; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 const uint8_t* additional, | 328 const uint8_t* additional, |
329 int additional_size, | 329 int additional_size, |
330 int duration, | 330 int duration, |
331 int64 discard_padding) { | 331 int64 discard_padding) { |
332 if (size < 4) | 332 if (size < 4) |
333 return false; | 333 return false; |
334 | 334 |
335 // Return an error if the trackNum > 127. We just aren't | 335 // Return an error if the trackNum > 127. We just aren't |
336 // going to support large track numbers right now. | 336 // going to support large track numbers right now. |
337 if (!(buf[0] & 0x80)) { | 337 if (!(buf[0] & 0x80)) { |
338 MEDIA_LOG(ERROR, log_cb_) << "TrackNumber over 127 not supported"; | 338 MEDIA_LOG(ERROR, media_log_) << "TrackNumber over 127 not supported"; |
339 return false; | 339 return false; |
340 } | 340 } |
341 | 341 |
342 int track_num = buf[0] & 0x7f; | 342 int track_num = buf[0] & 0x7f; |
343 int timecode = buf[1] << 8 | buf[2]; | 343 int timecode = buf[1] << 8 | buf[2]; |
344 int flags = buf[3] & 0xff; | 344 int flags = buf[3] & 0xff; |
345 int lacing = (flags >> 1) & 0x3; | 345 int lacing = (flags >> 1) & 0x3; |
346 | 346 |
347 if (lacing) { | 347 if (lacing) { |
348 MEDIA_LOG(ERROR, log_cb_) << "Lacing " << lacing | 348 MEDIA_LOG(ERROR, media_log_) << "Lacing " << lacing |
349 << " is not supported yet."; | 349 << " is not supported yet."; |
350 return false; | 350 return false; |
351 } | 351 } |
352 | 352 |
353 // Sign extend negative timecode offsets. | 353 // Sign extend negative timecode offsets. |
354 if (timecode & 0x8000) | 354 if (timecode & 0x8000) |
355 timecode |= ~0xffff; | 355 timecode |= ~0xffff; |
356 | 356 |
357 const uint8_t* frame_data = buf + 4; | 357 const uint8_t* frame_data = buf + 4; |
358 int frame_size = size - (frame_data - buf); | 358 int frame_size = size - (frame_data - buf); |
359 return OnBlock(is_simple_block, track_num, timecode, duration, flags, | 359 return OnBlock(is_simple_block, track_num, timecode, duration, flags, |
360 frame_data, frame_size, additional, additional_size, | 360 frame_data, frame_size, additional, additional_size, |
361 discard_padding); | 361 discard_padding); |
362 } | 362 } |
363 | 363 |
364 bool WebMClusterParser::OnBinary(int id, const uint8_t* data, int size) { | 364 bool WebMClusterParser::OnBinary(int id, const uint8_t* data, int size) { |
365 switch (id) { | 365 switch (id) { |
366 case kWebMIdSimpleBlock: | 366 case kWebMIdSimpleBlock: |
367 return ParseBlock(true, data, size, NULL, 0, -1, 0); | 367 return ParseBlock(true, data, size, NULL, 0, -1, 0); |
368 | 368 |
369 case kWebMIdBlock: | 369 case kWebMIdBlock: |
370 if (block_data_) { | 370 if (block_data_) { |
371 MEDIA_LOG(ERROR, log_cb_) << "More than 1 Block in a BlockGroup is not " | 371 MEDIA_LOG(ERROR, media_log_) |
372 "supported."; | 372 << "More than 1 Block in a BlockGroup is not " |
| 373 "supported."; |
373 return false; | 374 return false; |
374 } | 375 } |
375 block_data_.reset(new uint8_t[size]); | 376 block_data_.reset(new uint8_t[size]); |
376 memcpy(block_data_.get(), data, size); | 377 memcpy(block_data_.get(), data, size); |
377 block_data_size_ = size; | 378 block_data_size_ = size; |
378 return true; | 379 return true; |
379 | 380 |
380 case kWebMIdBlockAdditional: { | 381 case kWebMIdBlockAdditional: { |
381 uint64 block_add_id = base::HostToNet64(block_add_id_); | 382 uint64 block_add_id = base::HostToNet64(block_add_id_); |
382 if (block_additional_data_) { | 383 if (block_additional_data_) { |
383 // TODO(vigneshv): Technically, more than 1 BlockAdditional is allowed | 384 // TODO(vigneshv): Technically, more than 1 BlockAdditional is allowed |
384 // as per matroska spec. But for now we don't have a use case to | 385 // as per matroska spec. But for now we don't have a use case to |
385 // support parsing of such files. Take a look at this again when such a | 386 // support parsing of such files. Take a look at this again when such a |
386 // case arises. | 387 // case arises. |
387 MEDIA_LOG(ERROR, log_cb_) << "More than 1 BlockAdditional in a " | 388 MEDIA_LOG(ERROR, media_log_) << "More than 1 BlockAdditional in a " |
388 "BlockGroup is not supported."; | 389 "BlockGroup is not supported."; |
389 return false; | 390 return false; |
390 } | 391 } |
391 // First 8 bytes of side_data in DecoderBuffer is the BlockAddID | 392 // First 8 bytes of side_data in DecoderBuffer is the BlockAddID |
392 // element's value in Big Endian format. This is done to mimic ffmpeg | 393 // element's value in Big Endian format. This is done to mimic ffmpeg |
393 // demuxer's behavior. | 394 // demuxer's behavior. |
394 block_additional_data_size_ = size + sizeof(block_add_id); | 395 block_additional_data_size_ = size + sizeof(block_add_id); |
395 block_additional_data_.reset(new uint8_t[block_additional_data_size_]); | 396 block_additional_data_.reset(new uint8_t[block_additional_data_size_]); |
396 memcpy(block_additional_data_.get(), &block_add_id, | 397 memcpy(block_additional_data_.get(), &block_add_id, |
397 sizeof(block_add_id)); | 398 sizeof(block_add_id)); |
398 memcpy(block_additional_data_.get() + 8, data, size); | 399 memcpy(block_additional_data_.get() + 8, data, size); |
(...skipping 21 matching lines...) Expand all Loading... |
420 int timecode, | 421 int timecode, |
421 int block_duration, | 422 int block_duration, |
422 int flags, | 423 int flags, |
423 const uint8_t* data, | 424 const uint8_t* data, |
424 int size, | 425 int size, |
425 const uint8_t* additional, | 426 const uint8_t* additional, |
426 int additional_size, | 427 int additional_size, |
427 int64 discard_padding) { | 428 int64 discard_padding) { |
428 DCHECK_GE(size, 0); | 429 DCHECK_GE(size, 0); |
429 if (cluster_timecode_ == -1) { | 430 if (cluster_timecode_ == -1) { |
430 MEDIA_LOG(ERROR, log_cb_) << "Got a block before cluster timecode."; | 431 MEDIA_LOG(ERROR, media_log_) << "Got a block before cluster timecode."; |
431 return false; | 432 return false; |
432 } | 433 } |
433 | 434 |
434 // TODO(acolwell): Should relative negative timecode offsets be rejected? Or | 435 // TODO(acolwell): Should relative negative timecode offsets be rejected? Or |
435 // only when the absolute timecode is negative? See http://crbug.com/271794 | 436 // only when the absolute timecode is negative? See http://crbug.com/271794 |
436 if (timecode < 0) { | 437 if (timecode < 0) { |
437 MEDIA_LOG(ERROR, log_cb_) << "Got a block with negative timecode offset " | 438 MEDIA_LOG(ERROR, media_log_) << "Got a block with negative timecode offset " |
438 << timecode; | 439 << timecode; |
439 return false; | 440 return false; |
440 } | 441 } |
441 | 442 |
442 if (last_block_timecode_ != -1 && timecode < last_block_timecode_) { | 443 if (last_block_timecode_ != -1 && timecode < last_block_timecode_) { |
443 MEDIA_LOG(ERROR, log_cb_) | 444 MEDIA_LOG(ERROR, media_log_) |
444 << "Got a block with a timecode before the previous block."; | 445 << "Got a block with a timecode before the previous block."; |
445 return false; | 446 return false; |
446 } | 447 } |
447 | 448 |
448 Track* track = NULL; | 449 Track* track = NULL; |
449 StreamParserBuffer::Type buffer_type = DemuxerStream::AUDIO; | 450 StreamParserBuffer::Type buffer_type = DemuxerStream::AUDIO; |
450 std::string encryption_key_id; | 451 std::string encryption_key_id; |
451 base::TimeDelta encoded_duration = kNoTimestamp(); | 452 base::TimeDelta encoded_duration = kNoTimestamp(); |
452 if (track_num == audio_.track_num()) { | 453 if (track_num == audio_.track_num()) { |
453 track = &audio_; | 454 track = &audio_; |
454 encryption_key_id = audio_encryption_key_id_; | 455 encryption_key_id = audio_encryption_key_id_; |
455 if (encryption_key_id.empty()) { | 456 if (encryption_key_id.empty()) { |
456 encoded_duration = TryGetEncodedAudioDuration(data, size); | 457 encoded_duration = TryGetEncodedAudioDuration(data, size); |
457 } | 458 } |
458 } else if (track_num == video_.track_num()) { | 459 } else if (track_num == video_.track_num()) { |
459 track = &video_; | 460 track = &video_; |
460 encryption_key_id = video_encryption_key_id_; | 461 encryption_key_id = video_encryption_key_id_; |
461 buffer_type = DemuxerStream::VIDEO; | 462 buffer_type = DemuxerStream::VIDEO; |
462 } else if (ignored_tracks_.find(track_num) != ignored_tracks_.end()) { | 463 } else if (ignored_tracks_.find(track_num) != ignored_tracks_.end()) { |
463 return true; | 464 return true; |
464 } else if (Track* const text_track = FindTextTrack(track_num)) { | 465 } else if (Track* const text_track = FindTextTrack(track_num)) { |
465 if (is_simple_block) // BlockGroup is required for WebVTT cues | 466 if (is_simple_block) // BlockGroup is required for WebVTT cues |
466 return false; | 467 return false; |
467 if (block_duration < 0) // not specified | 468 if (block_duration < 0) // not specified |
468 return false; | 469 return false; |
469 track = text_track; | 470 track = text_track; |
470 buffer_type = DemuxerStream::TEXT; | 471 buffer_type = DemuxerStream::TEXT; |
471 } else { | 472 } else { |
472 MEDIA_LOG(ERROR, log_cb_) << "Unexpected track number " << track_num; | 473 MEDIA_LOG(ERROR, media_log_) << "Unexpected track number " << track_num; |
473 return false; | 474 return false; |
474 } | 475 } |
475 | 476 |
476 last_block_timecode_ = timecode; | 477 last_block_timecode_ = timecode; |
477 | 478 |
478 base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( | 479 base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( |
479 (cluster_timecode_ + timecode) * timecode_multiplier_); | 480 (cluster_timecode_ + timecode) * timecode_multiplier_); |
480 | 481 |
481 scoped_refptr<StreamParserBuffer> buffer; | 482 scoped_refptr<StreamParserBuffer> buffer; |
482 if (buffer_type != DemuxerStream::TEXT) { | 483 if (buffer_type != DemuxerStream::TEXT) { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 DVLOG(3) << __FUNCTION__ << " : " | 561 DVLOG(3) << __FUNCTION__ << " : " |
561 << "Using encoded duration " << encoded_duration.InSecondsF(); | 562 << "Using encoded duration " << encoded_duration.InSecondsF(); |
562 | 563 |
563 if (block_duration_time_delta != kNoTimestamp()) { | 564 if (block_duration_time_delta != kNoTimestamp()) { |
564 base::TimeDelta duration_difference = | 565 base::TimeDelta duration_difference = |
565 block_duration_time_delta - encoded_duration; | 566 block_duration_time_delta - encoded_duration; |
566 | 567 |
567 const auto kWarnDurationDiff = | 568 const auto kWarnDurationDiff = |
568 base::TimeDelta::FromMicroseconds(timecode_multiplier_ * 2); | 569 base::TimeDelta::FromMicroseconds(timecode_multiplier_ * 2); |
569 if (duration_difference.magnitude() > kWarnDurationDiff) { | 570 if (duration_difference.magnitude() > kWarnDurationDiff) { |
570 LIMITED_MEDIA_LOG(DEBUG, log_cb_, num_duration_errors_, | 571 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
571 kMaxDurationErrorLogs) | 572 kMaxDurationErrorLogs) |
572 << "BlockDuration " | 573 << "BlockDuration " |
573 << "(" << block_duration_time_delta << ") " | 574 << "(" << block_duration_time_delta << ") " |
574 << "differs significantly from encoded duration " | 575 << "differs significantly from encoded duration " |
575 << "(" << encoded_duration << ")."; | 576 << "(" << encoded_duration << ")."; |
576 } | 577 } |
577 } | 578 } |
578 } else if (block_duration_time_delta != kNoTimestamp()) { | 579 } else if (block_duration_time_delta != kNoTimestamp()) { |
579 buffer->set_duration(block_duration_time_delta); | 580 buffer->set_duration(block_duration_time_delta); |
580 } else { | 581 } else { |
581 DCHECK_NE(buffer_type, DemuxerStream::TEXT); | 582 DCHECK_NE(buffer_type, DemuxerStream::TEXT); |
582 buffer->set_duration(track->default_duration()); | 583 buffer->set_duration(track->default_duration()); |
583 } | 584 } |
584 | 585 |
585 if (discard_padding != 0) { | 586 if (discard_padding != 0) { |
586 buffer->set_discard_padding(std::make_pair( | 587 buffer->set_discard_padding(std::make_pair( |
587 base::TimeDelta(), | 588 base::TimeDelta(), |
588 base::TimeDelta::FromMicroseconds(discard_padding / 1000))); | 589 base::TimeDelta::FromMicroseconds(discard_padding / 1000))); |
589 } | 590 } |
590 | 591 |
591 return track->AddBuffer(buffer); | 592 return track->AddBuffer(buffer); |
592 } | 593 } |
593 | 594 |
594 WebMClusterParser::Track::Track(int track_num, | 595 WebMClusterParser::Track::Track(int track_num, |
595 bool is_video, | 596 bool is_video, |
596 base::TimeDelta default_duration, | 597 base::TimeDelta default_duration, |
597 const LogCB& log_cb) | 598 const scoped_refptr<MediaLog>& media_log) |
598 : num_duration_estimates_(0), | 599 : num_duration_estimates_(0), |
599 track_num_(track_num), | 600 track_num_(track_num), |
600 is_video_(is_video), | 601 is_video_(is_video), |
601 default_duration_(default_duration), | 602 default_duration_(default_duration), |
602 estimated_next_frame_duration_(kNoTimestamp()), | 603 estimated_next_frame_duration_(kNoTimestamp()), |
603 log_cb_(log_cb) { | 604 media_log_(media_log) { |
604 DCHECK(default_duration_ == kNoTimestamp() || | 605 DCHECK(default_duration_ == kNoTimestamp() || |
605 default_duration_ > base::TimeDelta()); | 606 default_duration_ > base::TimeDelta()); |
606 } | 607 } |
607 | 608 |
608 WebMClusterParser::Track::~Track() {} | 609 WebMClusterParser::Track::~Track() {} |
609 | 610 |
610 DecodeTimestamp WebMClusterParser::Track::GetReadyUpperBound() { | 611 DecodeTimestamp WebMClusterParser::Track::GetReadyUpperBound() { |
611 DCHECK(ready_buffers_.empty()); | 612 DCHECK(ready_buffers_.empty()); |
612 if (last_added_buffer_missing_duration_.get()) | 613 if (last_added_buffer_missing_duration_.get()) |
613 return last_added_buffer_missing_duration_->GetDecodeTimestamp(); | 614 return last_added_buffer_missing_duration_->GetDecodeTimestamp(); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 last_added_buffer_missing_duration_->set_duration(estimated_duration); | 694 last_added_buffer_missing_duration_->set_duration(estimated_duration); |
694 | 695 |
695 if (is_video_) { | 696 if (is_video_) { |
696 // Exposing estimation so splicing/overlap frame processing can make | 697 // Exposing estimation so splicing/overlap frame processing can make |
697 // informed decisions downstream. | 698 // informed decisions downstream. |
698 // TODO(chcunningham): Set this for audio as well in later change where | 699 // TODO(chcunningham): Set this for audio as well in later change where |
699 // audio is switched to max estimation and splicing is disabled. | 700 // audio is switched to max estimation and splicing is disabled. |
700 last_added_buffer_missing_duration_->set_is_duration_estimated(true); | 701 last_added_buffer_missing_duration_->set_is_duration_estimated(true); |
701 } | 702 } |
702 | 703 |
703 LIMITED_MEDIA_LOG(INFO, log_cb_, num_duration_estimates_, | 704 LIMITED_MEDIA_LOG(INFO, media_log_, num_duration_estimates_, |
704 kMaxDurationEstimateLogs) | 705 kMaxDurationEstimateLogs) |
705 << "Estimating WebM block duration to be " << estimated_duration << " " | 706 << "Estimating WebM block duration to be " << estimated_duration << " " |
706 << "for the last (Simple)Block in the Cluster for this Track. Use " | 707 << "for the last (Simple)Block in the Cluster for this Track. Use " |
707 << "BlockGroups with BlockDurations at the end of each Track in a " | 708 << "BlockGroups with BlockDurations at the end of each Track in a " |
708 << "Cluster to avoid estimation."; | 709 << "Cluster to avoid estimation."; |
709 | 710 |
710 DVLOG(2) << __FUNCTION__ << " new dur : ts " | 711 DVLOG(2) << __FUNCTION__ << " new dur : ts " |
711 << last_added_buffer_missing_duration_->timestamp().InSecondsF() | 712 << last_added_buffer_missing_duration_->timestamp().InSecondsF() |
712 << " dur " | 713 << " dur " |
713 << last_added_buffer_missing_duration_->duration().InSecondsF() | 714 << last_added_buffer_missing_duration_->duration().InSecondsF() |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 | 762 |
762 // WebMClusterParser::OnBlock() gives MEDIA_LOG and parse error on decreasing | 763 // WebMClusterParser::OnBlock() gives MEDIA_LOG and parse error on decreasing |
763 // block timecode detection within a cluster. Therefore, we should not see | 764 // block timecode detection within a cluster. Therefore, we should not see |
764 // those here. | 765 // those here. |
765 DecodeTimestamp previous_buffers_timestamp = buffers_.empty() ? | 766 DecodeTimestamp previous_buffers_timestamp = buffers_.empty() ? |
766 DecodeTimestamp() : buffers_.back()->GetDecodeTimestamp(); | 767 DecodeTimestamp() : buffers_.back()->GetDecodeTimestamp(); |
767 CHECK(previous_buffers_timestamp <= buffer->GetDecodeTimestamp()); | 768 CHECK(previous_buffers_timestamp <= buffer->GetDecodeTimestamp()); |
768 | 769 |
769 base::TimeDelta duration = buffer->duration(); | 770 base::TimeDelta duration = buffer->duration(); |
770 if (duration < base::TimeDelta() || duration == kNoTimestamp()) { | 771 if (duration < base::TimeDelta() || duration == kNoTimestamp()) { |
771 MEDIA_LOG(ERROR, log_cb_) | 772 MEDIA_LOG(ERROR, media_log_) |
772 << "Invalid buffer duration: " << duration.InSecondsF(); | 773 << "Invalid buffer duration: " << duration.InSecondsF(); |
773 return false; | 774 return false; |
774 } | 775 } |
775 | 776 |
776 // The estimated frame duration is the minimum (for audio) or the maximum | 777 // The estimated frame duration is the minimum (for audio) or the maximum |
777 // (for video) non-zero duration since the last initialization segment. The | 778 // (for video) non-zero duration since the last initialization segment. The |
778 // minimum is used for audio to ensure frame durations aren't overestimated, | 779 // minimum is used for audio to ensure frame durations aren't overestimated, |
779 // triggering unnecessary frame splicing. For video, splicing does not apply, | 780 // triggering unnecessary frame splicing. For video, splicing does not apply, |
780 // so maximum is used and overlap is simply resolved by showing the | 781 // so maximum is used and overlap is simply resolved by showing the |
781 // later of the overlapping frames at its given PTS, effectively trimming down | 782 // later of the overlapping frames at its given PTS, effectively trimming down |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
881 WebMClusterParser::FindTextTrack(int track_num) { | 882 WebMClusterParser::FindTextTrack(int track_num) { |
882 const TextTrackMap::iterator it = text_track_map_.find(track_num); | 883 const TextTrackMap::iterator it = text_track_map_.find(track_num); |
883 | 884 |
884 if (it == text_track_map_.end()) | 885 if (it == text_track_map_.end()) |
885 return NULL; | 886 return NULL; |
886 | 887 |
887 return &it->second; | 888 return &it->second; |
888 } | 889 } |
889 | 890 |
890 } // namespace media | 891 } // namespace media |
OLD | NEW |