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 <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 const std::string& audio_encryption_key_id, | 45 const std::string& audio_encryption_key_id, |
46 const std::string& video_encryption_key_id, | 46 const std::string& video_encryption_key_id, |
47 const AudioCodec audio_codec, | 47 const AudioCodec audio_codec, |
48 const scoped_refptr<MediaLog>& media_log) | 48 const scoped_refptr<MediaLog>& media_log) |
49 : timecode_multiplier_(timecode_scale / 1000.0), | 49 : timecode_multiplier_(timecode_scale / 1000.0), |
50 ignored_tracks_(ignored_tracks), | 50 ignored_tracks_(ignored_tracks), |
51 audio_encryption_key_id_(audio_encryption_key_id), | 51 audio_encryption_key_id_(audio_encryption_key_id), |
52 video_encryption_key_id_(video_encryption_key_id), | 52 video_encryption_key_id_(video_encryption_key_id), |
53 audio_codec_(audio_codec), | 53 audio_codec_(audio_codec), |
54 parser_(kWebMIdCluster, this), | 54 parser_(kWebMIdCluster, this), |
55 cluster_start_time_(kNoTimestamp()), | 55 cluster_start_time_(kNoTimestamp), |
56 audio_(audio_track_num, false, audio_default_duration, media_log), | 56 audio_(audio_track_num, false, audio_default_duration, media_log), |
57 video_(video_track_num, true, video_default_duration, media_log), | 57 video_(video_track_num, true, video_default_duration, media_log), |
58 ready_buffer_upper_bound_(kNoDecodeTimestamp()), | 58 ready_buffer_upper_bound_(kNoDecodeTimestamp()), |
59 media_log_(media_log) { | 59 media_log_(media_log) { |
60 for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin(); | 60 for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin(); |
61 it != text_tracks.end(); | 61 it != text_tracks.end(); |
62 ++it) { | 62 ++it) { |
63 text_track_map_.insert(std::make_pair( | 63 text_track_map_.insert(std::make_pair( |
64 it->first, Track(it->first, false, kNoTimestamp(), media_log_))); | 64 it->first, Track(it->first, false, kNoTimestamp, media_log_))); |
65 } | 65 } |
66 } | 66 } |
67 | 67 |
68 WebMClusterParser::~WebMClusterParser() {} | 68 WebMClusterParser::~WebMClusterParser() {} |
69 | 69 |
70 void WebMClusterParser::Reset() { | 70 void WebMClusterParser::Reset() { |
71 last_block_timecode_ = -1; | 71 last_block_timecode_ = -1; |
72 cluster_timecode_ = -1; | 72 cluster_timecode_ = -1; |
73 cluster_start_time_ = kNoTimestamp(); | 73 cluster_start_time_ = kNoTimestamp; |
74 cluster_ended_ = false; | 74 cluster_ended_ = false; |
75 parser_.Reset(); | 75 parser_.Reset(); |
76 audio_.Reset(); | 76 audio_.Reset(); |
77 video_.Reset(); | 77 video_.Reset(); |
78 ResetTextTracks(); | 78 ResetTextTracks(); |
79 ready_buffer_upper_bound_ = kNoDecodeTimestamp(); | 79 ready_buffer_upper_bound_ = kNoDecodeTimestamp(); |
80 } | 80 } |
81 | 81 |
82 int WebMClusterParser::Parse(const uint8_t* buf, int size) { | 82 int WebMClusterParser::Parse(const uint8_t* buf, int size) { |
83 audio_.ClearReadyBuffers(); | 83 audio_.ClearReadyBuffers(); |
84 video_.ClearReadyBuffers(); | 84 video_.ClearReadyBuffers(); |
85 ClearTextTrackReadyBuffers(); | 85 ClearTextTrackReadyBuffers(); |
86 ready_buffer_upper_bound_ = kNoDecodeTimestamp(); | 86 ready_buffer_upper_bound_ = kNoDecodeTimestamp(); |
87 | 87 |
88 int result = parser_.Parse(buf, size); | 88 int result = parser_.Parse(buf, size); |
89 | 89 |
90 if (result < 0) { | 90 if (result < 0) { |
91 cluster_ended_ = false; | 91 cluster_ended_ = false; |
92 return result; | 92 return result; |
93 } | 93 } |
94 | 94 |
95 cluster_ended_ = parser_.IsParsingComplete(); | 95 cluster_ended_ = parser_.IsParsingComplete(); |
96 if (cluster_ended_) { | 96 if (cluster_ended_) { |
97 // If there were no buffers in this cluster, set the cluster start time to | 97 // If there were no buffers in this cluster, set the cluster start time to |
98 // be the |cluster_timecode_|. | 98 // be the |cluster_timecode_|. |
99 if (cluster_start_time_ == kNoTimestamp()) { | 99 if (cluster_start_time_ == kNoTimestamp) { |
100 // If the cluster did not even have a |cluster_timecode_|, signal parse | 100 // If the cluster did not even have a |cluster_timecode_|, signal parse |
101 // error. | 101 // error. |
102 if (cluster_timecode_ < 0) | 102 if (cluster_timecode_ < 0) |
103 return -1; | 103 return -1; |
104 | 104 |
105 cluster_start_time_ = base::TimeDelta::FromMicroseconds( | 105 cluster_start_time_ = base::TimeDelta::FromMicroseconds( |
106 cluster_timecode_ * timecode_multiplier_); | 106 cluster_timecode_ * timecode_multiplier_); |
107 } | 107 } |
108 | 108 |
109 // Reset the parser if we're done parsing so that | 109 // Reset the parser if we're done parsing so that |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 // TODO(chcunningham): Consider parsing "Signal Byte" for encrypted streams | 161 // TODO(chcunningham): Consider parsing "Signal Byte" for encrypted streams |
162 // to return duration for any unencrypted blocks. | 162 // to return duration for any unencrypted blocks. |
163 | 163 |
164 if (audio_codec_ == kCodecOpus) { | 164 if (audio_codec_ == kCodecOpus) { |
165 return ReadOpusDuration(data, size); | 165 return ReadOpusDuration(data, size); |
166 } | 166 } |
167 | 167 |
168 // TODO(wolenetz/chcunningham): Implement duration reading for Vorbis. See | 168 // TODO(wolenetz/chcunningham): Implement duration reading for Vorbis. See |
169 // motivations in http://crbug.com/396634. | 169 // motivations in http://crbug.com/396634. |
170 | 170 |
171 return kNoTimestamp(); | 171 return kNoTimestamp; |
172 } | 172 } |
173 | 173 |
174 base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data, | 174 base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data, |
175 int size) { | 175 int size) { |
176 // Masks and constants for Opus packets. See | 176 // Masks and constants for Opus packets. See |
177 // https://tools.ietf.org/html/rfc6716#page-14 | 177 // https://tools.ietf.org/html/rfc6716#page-14 |
178 static const uint8_t kTocConfigMask = 0xf8; | 178 static const uint8_t kTocConfigMask = 0xf8; |
179 static const uint8_t kTocFrameCountCodeMask = 0x03; | 179 static const uint8_t kTocFrameCountCodeMask = 0x03; |
180 static const uint8_t kFrameCountMask = 0x3f; | 180 static const uint8_t kFrameCountMask = 0x3f; |
181 static const base::TimeDelta kPacketDurationMax = | 181 static const base::TimeDelta kPacketDurationMax = |
182 base::TimeDelta::FromMilliseconds(120); | 182 base::TimeDelta::FromMilliseconds(120); |
183 | 183 |
184 if (size < 1) { | 184 if (size < 1) { |
185 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, | 185 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
186 kMaxDurationErrorLogs) | 186 kMaxDurationErrorLogs) |
187 << "Invalid zero-byte Opus packet; demuxed block duration may be " | 187 << "Invalid zero-byte Opus packet; demuxed block duration may be " |
188 "imprecise."; | 188 "imprecise."; |
189 return kNoTimestamp(); | 189 return kNoTimestamp; |
190 } | 190 } |
191 | 191 |
192 // Frame count type described by last 2 bits of Opus TOC byte. | 192 // Frame count type described by last 2 bits of Opus TOC byte. |
193 int frame_count_type = data[0] & kTocFrameCountCodeMask; | 193 int frame_count_type = data[0] & kTocFrameCountCodeMask; |
194 | 194 |
195 int frame_count = 0; | 195 int frame_count = 0; |
196 switch (frame_count_type) { | 196 switch (frame_count_type) { |
197 case 0: | 197 case 0: |
198 frame_count = 1; | 198 frame_count = 1; |
199 break; | 199 break; |
200 case 1: | 200 case 1: |
201 case 2: | 201 case 2: |
202 frame_count = 2; | 202 frame_count = 2; |
203 break; | 203 break; |
204 case 3: | 204 case 3: |
205 // Type 3 indicates an arbitrary frame count described in the next byte. | 205 // Type 3 indicates an arbitrary frame count described in the next byte. |
206 if (size < 2) { | 206 if (size < 2) { |
207 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, | 207 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
208 kMaxDurationErrorLogs) | 208 kMaxDurationErrorLogs) |
209 << "Second byte missing from 'Code 3' Opus packet; demuxed block " | 209 << "Second byte missing from 'Code 3' Opus packet; demuxed block " |
210 "duration may be imprecise."; | 210 "duration may be imprecise."; |
211 return kNoTimestamp(); | 211 return kNoTimestamp; |
212 } | 212 } |
213 | 213 |
214 frame_count = data[1] & kFrameCountMask; | 214 frame_count = data[1] & kFrameCountMask; |
215 | 215 |
216 if (frame_count == 0) { | 216 if (frame_count == 0) { |
217 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, | 217 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
218 kMaxDurationErrorLogs) | 218 kMaxDurationErrorLogs) |
219 << "Illegal 'Code 3' Opus packet with frame count zero; demuxed " | 219 << "Illegal 'Code 3' Opus packet with frame count zero; demuxed " |
220 "block duration may be imprecise."; | 220 "block duration may be imprecise."; |
221 return kNoTimestamp(); | 221 return kNoTimestamp; |
222 } | 222 } |
223 | 223 |
224 break; | 224 break; |
225 default: | 225 default: |
226 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, | 226 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
227 kMaxDurationErrorLogs) | 227 kMaxDurationErrorLogs) |
228 << "Unexpected Opus frame count type: " << frame_count_type << "; " | 228 << "Unexpected Opus frame count type: " << frame_count_type << "; " |
229 << "demuxed block duration may be imprecise."; | 229 << "demuxed block duration may be imprecise."; |
230 return kNoTimestamp(); | 230 return kNoTimestamp; |
231 } | 231 } |
232 | 232 |
233 int opusConfig = (data[0] & kTocConfigMask) >> 3; | 233 int opusConfig = (data[0] & kTocConfigMask) >> 3; |
234 CHECK_GE(opusConfig, 0); | 234 CHECK_GE(opusConfig, 0); |
235 CHECK_LT(opusConfig, static_cast<int>(arraysize(kOpusFrameDurationsMu))); | 235 CHECK_LT(opusConfig, static_cast<int>(arraysize(kOpusFrameDurationsMu))); |
236 | 236 |
237 DCHECK_GT(frame_count, 0); | 237 DCHECK_GT(frame_count, 0); |
238 base::TimeDelta duration = base::TimeDelta::FromMicroseconds( | 238 base::TimeDelta duration = base::TimeDelta::FromMicroseconds( |
239 kOpusFrameDurationsMu[opusConfig] * frame_count); | 239 kOpusFrameDurationsMu[opusConfig] * frame_count); |
240 | 240 |
241 if (duration > kPacketDurationMax) { | 241 if (duration > kPacketDurationMax) { |
242 // Intentionally allowing packet to pass through for now. Decoder should | 242 // Intentionally allowing packet to pass through for now. Decoder should |
243 // either handle or fail gracefully. MEDIA_LOG as breadcrumbs in case | 243 // either handle or fail gracefully. MEDIA_LOG as breadcrumbs in case |
244 // things go sideways. | 244 // things go sideways. |
245 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, | 245 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
246 kMaxDurationErrorLogs) | 246 kMaxDurationErrorLogs) |
247 << "Warning, demuxed Opus packet with encoded duration: " | 247 << "Warning, demuxed Opus packet with encoded duration: " |
248 << duration.InMilliseconds() << "ms. Should be no greater than " | 248 << duration.InMilliseconds() << "ms. Should be no greater than " |
249 << kPacketDurationMax.InMilliseconds() << "ms."; | 249 << kPacketDurationMax.InMilliseconds() << "ms."; |
250 } | 250 } |
251 | 251 |
252 return duration; | 252 return duration; |
253 } | 253 } |
254 | 254 |
255 WebMParserClient* WebMClusterParser::OnListStart(int id) { | 255 WebMParserClient* WebMClusterParser::OnListStart(int id) { |
256 if (id == kWebMIdCluster) { | 256 if (id == kWebMIdCluster) { |
257 cluster_timecode_ = -1; | 257 cluster_timecode_ = -1; |
258 cluster_start_time_ = kNoTimestamp(); | 258 cluster_start_time_ = kNoTimestamp; |
259 } else if (id == kWebMIdBlockGroup) { | 259 } else if (id == kWebMIdBlockGroup) { |
260 block_data_.reset(); | 260 block_data_.reset(); |
261 block_data_size_ = -1; | 261 block_data_size_ = -1; |
262 block_duration_ = -1; | 262 block_duration_ = -1; |
263 discard_padding_ = -1; | 263 discard_padding_ = -1; |
264 discard_padding_set_ = false; | 264 discard_padding_set_ = false; |
265 reference_block_set_ = false; | 265 reference_block_set_ = false; |
266 } else if (id == kWebMIdBlockAdditions) { | 266 } else if (id == kWebMIdBlockAdditions) { |
267 block_add_id_ = -1; | 267 block_add_id_ = -1; |
268 block_additional_data_.reset(); | 268 block_additional_data_.reset(); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 | 454 |
455 if (last_block_timecode_ != -1 && timecode < last_block_timecode_) { | 455 if (last_block_timecode_ != -1 && timecode < last_block_timecode_) { |
456 MEDIA_LOG(ERROR, media_log_) | 456 MEDIA_LOG(ERROR, media_log_) |
457 << "Got a block with a timecode before the previous block."; | 457 << "Got a block with a timecode before the previous block."; |
458 return false; | 458 return false; |
459 } | 459 } |
460 | 460 |
461 Track* track = NULL; | 461 Track* track = NULL; |
462 StreamParserBuffer::Type buffer_type = DemuxerStream::AUDIO; | 462 StreamParserBuffer::Type buffer_type = DemuxerStream::AUDIO; |
463 std::string encryption_key_id; | 463 std::string encryption_key_id; |
464 base::TimeDelta encoded_duration = kNoTimestamp(); | 464 base::TimeDelta encoded_duration = kNoTimestamp; |
465 if (track_num == audio_.track_num()) { | 465 if (track_num == audio_.track_num()) { |
466 track = &audio_; | 466 track = &audio_; |
467 encryption_key_id = audio_encryption_key_id_; | 467 encryption_key_id = audio_encryption_key_id_; |
468 if (encryption_key_id.empty()) { | 468 if (encryption_key_id.empty()) { |
469 encoded_duration = TryGetEncodedAudioDuration(data, size); | 469 encoded_duration = TryGetEncodedAudioDuration(data, size); |
470 } | 470 } |
471 } else if (track_num == video_.track_num()) { | 471 } else if (track_num == video_.track_num()) { |
472 track = &video_; | 472 track = &video_; |
473 encryption_key_id = video_encryption_key_id_; | 473 encryption_key_id = video_encryption_key_id_; |
474 buffer_type = DemuxerStream::VIDEO; | 474 buffer_type = DemuxerStream::VIDEO; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 // applicable. See https://crbug.com/341581. | 531 // applicable. See https://crbug.com/341581. |
532 buffer = StreamParserBuffer::CopyFrom( | 532 buffer = StreamParserBuffer::CopyFrom( |
533 reinterpret_cast<const uint8_t*>(content.data()), | 533 reinterpret_cast<const uint8_t*>(content.data()), |
534 content.length(), | 534 content.length(), |
535 &side_data[0], | 535 &side_data[0], |
536 side_data.size(), | 536 side_data.size(), |
537 true, buffer_type, track_num); | 537 true, buffer_type, track_num); |
538 } | 538 } |
539 | 539 |
540 buffer->set_timestamp(timestamp); | 540 buffer->set_timestamp(timestamp); |
541 if (cluster_start_time_ == kNoTimestamp()) | 541 if (cluster_start_time_ == kNoTimestamp) |
542 cluster_start_time_ = timestamp; | 542 cluster_start_time_ = timestamp; |
543 | 543 |
544 base::TimeDelta block_duration_time_delta = kNoTimestamp(); | 544 base::TimeDelta block_duration_time_delta = kNoTimestamp; |
545 if (block_duration >= 0) { | 545 if (block_duration >= 0) { |
546 block_duration_time_delta = base::TimeDelta::FromMicroseconds( | 546 block_duration_time_delta = base::TimeDelta::FromMicroseconds( |
547 block_duration * timecode_multiplier_); | 547 block_duration * timecode_multiplier_); |
548 } | 548 } |
549 | 549 |
550 // Prefer encoded duration over BlockGroup->BlockDuration or | 550 // Prefer encoded duration over BlockGroup->BlockDuration or |
551 // TrackEntry->DefaultDuration when available. This layering violation is a | 551 // TrackEntry->DefaultDuration when available. This layering violation is a |
552 // workaround for http://crbug.com/396634, decreasing the likelihood of | 552 // workaround for http://crbug.com/396634, decreasing the likelihood of |
553 // fall-back to rough estimation techniques for Blocks that lack a | 553 // fall-back to rough estimation techniques for Blocks that lack a |
554 // BlockDuration at the end of a cluster. Cross cluster durations are not | 554 // BlockDuration at the end of a cluster. Cross cluster durations are not |
555 // feasible given flexibility of cluster ordering and MSE APIs. Duration | 555 // feasible given flexibility of cluster ordering and MSE APIs. Duration |
556 // estimation may still apply in cases of encryption and codecs for which | 556 // estimation may still apply in cases of encryption and codecs for which |
557 // we do not extract encoded duration. Within a cluster, estimates are applied | 557 // we do not extract encoded duration. Within a cluster, estimates are applied |
558 // as Block Timecode deltas, or once the whole cluster is parsed in the case | 558 // as Block Timecode deltas, or once the whole cluster is parsed in the case |
559 // of the last Block in the cluster. See Track::AddBuffer and | 559 // of the last Block in the cluster. See Track::AddBuffer and |
560 // ApplyDurationEstimateIfNeeded(). | 560 // ApplyDurationEstimateIfNeeded(). |
561 if (encoded_duration != kNoTimestamp()) { | 561 if (encoded_duration != kNoTimestamp) { |
562 DCHECK(encoded_duration != kInfiniteDuration()); | 562 DCHECK(encoded_duration != kInfiniteDuration); |
563 DCHECK(encoded_duration > base::TimeDelta()); | 563 DCHECK(encoded_duration > base::TimeDelta()); |
564 buffer->set_duration(encoded_duration); | 564 buffer->set_duration(encoded_duration); |
565 | 565 |
566 DVLOG(3) << __FUNCTION__ << " : " | 566 DVLOG(3) << __FUNCTION__ << " : " |
567 << "Using encoded duration " << encoded_duration.InSecondsF(); | 567 << "Using encoded duration " << encoded_duration.InSecondsF(); |
568 | 568 |
569 if (block_duration_time_delta != kNoTimestamp()) { | 569 if (block_duration_time_delta != kNoTimestamp) { |
570 base::TimeDelta duration_difference = | 570 base::TimeDelta duration_difference = |
571 block_duration_time_delta - encoded_duration; | 571 block_duration_time_delta - encoded_duration; |
572 | 572 |
573 const auto kWarnDurationDiff = | 573 const auto kWarnDurationDiff = |
574 base::TimeDelta::FromMicroseconds(timecode_multiplier_ * 2); | 574 base::TimeDelta::FromMicroseconds(timecode_multiplier_ * 2); |
575 if (duration_difference.magnitude() > kWarnDurationDiff) { | 575 if (duration_difference.magnitude() > kWarnDurationDiff) { |
576 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, | 576 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_duration_errors_, |
577 kMaxDurationErrorLogs) | 577 kMaxDurationErrorLogs) |
578 << "BlockDuration (" << block_duration_time_delta.InMilliseconds() | 578 << "BlockDuration (" << block_duration_time_delta.InMilliseconds() |
579 << "ms) differs significantly from encoded duration (" | 579 << "ms) differs significantly from encoded duration (" |
580 << encoded_duration.InMilliseconds() << "ms)."; | 580 << encoded_duration.InMilliseconds() << "ms)."; |
581 } | 581 } |
582 } | 582 } |
583 } else if (block_duration_time_delta != kNoTimestamp()) { | 583 } else if (block_duration_time_delta != kNoTimestamp) { |
584 buffer->set_duration(block_duration_time_delta); | 584 buffer->set_duration(block_duration_time_delta); |
585 } else { | 585 } else { |
586 DCHECK_NE(buffer_type, DemuxerStream::TEXT); | 586 DCHECK_NE(buffer_type, DemuxerStream::TEXT); |
587 buffer->set_duration(track->default_duration()); | 587 buffer->set_duration(track->default_duration()); |
588 } | 588 } |
589 | 589 |
590 if (discard_padding != 0) { | 590 if (discard_padding != 0) { |
591 buffer->set_discard_padding(std::make_pair( | 591 buffer->set_discard_padding(std::make_pair( |
592 base::TimeDelta(), | 592 base::TimeDelta(), |
593 base::TimeDelta::FromMicroseconds(discard_padding / 1000))); | 593 base::TimeDelta::FromMicroseconds(discard_padding / 1000))); |
594 } | 594 } |
595 | 595 |
596 return track->AddBuffer(buffer); | 596 return track->AddBuffer(buffer); |
597 } | 597 } |
598 | 598 |
599 WebMClusterParser::Track::Track(int track_num, | 599 WebMClusterParser::Track::Track(int track_num, |
600 bool is_video, | 600 bool is_video, |
601 base::TimeDelta default_duration, | 601 base::TimeDelta default_duration, |
602 const scoped_refptr<MediaLog>& media_log) | 602 const scoped_refptr<MediaLog>& media_log) |
603 : track_num_(track_num), | 603 : track_num_(track_num), |
604 is_video_(is_video), | 604 is_video_(is_video), |
605 default_duration_(default_duration), | 605 default_duration_(default_duration), |
606 estimated_next_frame_duration_(kNoTimestamp()), | 606 estimated_next_frame_duration_(kNoTimestamp), |
607 media_log_(media_log) { | 607 media_log_(media_log) { |
608 DCHECK(default_duration_ == kNoTimestamp() || | 608 DCHECK(default_duration_ == kNoTimestamp || |
609 default_duration_ > base::TimeDelta()); | 609 default_duration_ > base::TimeDelta()); |
610 } | 610 } |
611 | 611 |
612 WebMClusterParser::Track::Track(const Track& other) = default; | 612 WebMClusterParser::Track::Track(const Track& other) = default; |
613 | 613 |
614 WebMClusterParser::Track::~Track() {} | 614 WebMClusterParser::Track::~Track() {} |
615 | 615 |
616 DecodeTimestamp WebMClusterParser::Track::GetReadyUpperBound() { | 616 DecodeTimestamp WebMClusterParser::Track::GetReadyUpperBound() { |
617 DCHECK(ready_buffers_.empty()); | 617 DCHECK(ready_buffers_.empty()); |
618 if (last_added_buffer_missing_duration_.get()) | 618 if (last_added_buffer_missing_duration_.get()) |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 << last_added_buffer_missing_duration_->duration().InSecondsF() | 675 << last_added_buffer_missing_duration_->duration().InSecondsF() |
676 << " kf " << last_added_buffer_missing_duration_->is_key_frame() | 676 << " kf " << last_added_buffer_missing_duration_->is_key_frame() |
677 << " size " << last_added_buffer_missing_duration_->data_size(); | 677 << " size " << last_added_buffer_missing_duration_->data_size(); |
678 scoped_refptr<StreamParserBuffer> updated_buffer = | 678 scoped_refptr<StreamParserBuffer> updated_buffer = |
679 last_added_buffer_missing_duration_; | 679 last_added_buffer_missing_duration_; |
680 last_added_buffer_missing_duration_ = NULL; | 680 last_added_buffer_missing_duration_ = NULL; |
681 if (!QueueBuffer(updated_buffer)) | 681 if (!QueueBuffer(updated_buffer)) |
682 return false; | 682 return false; |
683 } | 683 } |
684 | 684 |
685 if (buffer->duration() == kNoTimestamp()) { | 685 if (buffer->duration() == kNoTimestamp) { |
686 last_added_buffer_missing_duration_ = buffer; | 686 last_added_buffer_missing_duration_ = buffer; |
687 DVLOG(2) << "AddBuffer() : holding back buffer that is missing duration"; | 687 DVLOG(2) << "AddBuffer() : holding back buffer that is missing duration"; |
688 return true; | 688 return true; |
689 } | 689 } |
690 | 690 |
691 return QueueBuffer(buffer); | 691 return QueueBuffer(buffer); |
692 } | 692 } |
693 | 693 |
694 void WebMClusterParser::Track::ApplyDurationEstimateIfNeeded() { | 694 void WebMClusterParser::Track::ApplyDurationEstimateIfNeeded() { |
695 if (!last_added_buffer_missing_duration_.get()) | 695 if (!last_added_buffer_missing_duration_.get()) |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
744 DCHECK(!last_added_buffer_missing_duration_.get()); | 744 DCHECK(!last_added_buffer_missing_duration_.get()); |
745 | 745 |
746 // WebMClusterParser::OnBlock() gives MEDIA_LOG and parse error on decreasing | 746 // WebMClusterParser::OnBlock() gives MEDIA_LOG and parse error on decreasing |
747 // block timecode detection within a cluster. Therefore, we should not see | 747 // block timecode detection within a cluster. Therefore, we should not see |
748 // those here. | 748 // those here. |
749 DecodeTimestamp previous_buffers_timestamp = buffers_.empty() ? | 749 DecodeTimestamp previous_buffers_timestamp = buffers_.empty() ? |
750 DecodeTimestamp() : buffers_.back()->GetDecodeTimestamp(); | 750 DecodeTimestamp() : buffers_.back()->GetDecodeTimestamp(); |
751 CHECK(previous_buffers_timestamp <= buffer->GetDecodeTimestamp()); | 751 CHECK(previous_buffers_timestamp <= buffer->GetDecodeTimestamp()); |
752 | 752 |
753 base::TimeDelta duration = buffer->duration(); | 753 base::TimeDelta duration = buffer->duration(); |
754 if (duration < base::TimeDelta() || duration == kNoTimestamp()) { | 754 if (duration < base::TimeDelta() || duration == kNoTimestamp) { |
755 MEDIA_LOG(ERROR, media_log_) | 755 MEDIA_LOG(ERROR, media_log_) |
756 << "Invalid buffer duration: " << duration.InSecondsF(); | 756 << "Invalid buffer duration: " << duration.InSecondsF(); |
757 return false; | 757 return false; |
758 } | 758 } |
759 | 759 |
760 // The estimated frame duration is the minimum (for audio) or the maximum | 760 // The estimated frame duration is the minimum (for audio) or the maximum |
761 // (for video) non-zero duration since the last initialization segment. The | 761 // (for video) non-zero duration since the last initialization segment. The |
762 // minimum is used for audio to ensure frame durations aren't overestimated, | 762 // minimum is used for audio to ensure frame durations aren't overestimated, |
763 // triggering unnecessary frame splicing. For video, splicing does not apply, | 763 // triggering unnecessary frame splicing. For video, splicing does not apply, |
764 // so maximum is used and overlap is simply resolved by showing the | 764 // so maximum is used and overlap is simply resolved by showing the |
765 // later of the overlapping frames at its given PTS, effectively trimming down | 765 // later of the overlapping frames at its given PTS, effectively trimming down |
766 // the over-estimated duration of the previous frame. | 766 // the over-estimated duration of the previous frame. |
767 // TODO(chcunningham): Use max for audio and disable splicing whenever | 767 // TODO(chcunningham): Use max for audio and disable splicing whenever |
768 // estimated buffers are encountered. | 768 // estimated buffers are encountered. |
769 if (duration > base::TimeDelta()) { | 769 if (duration > base::TimeDelta()) { |
770 base::TimeDelta orig_duration_estimate = estimated_next_frame_duration_; | 770 base::TimeDelta orig_duration_estimate = estimated_next_frame_duration_; |
771 if (estimated_next_frame_duration_ == kNoTimestamp()) { | 771 if (estimated_next_frame_duration_ == kNoTimestamp) { |
772 estimated_next_frame_duration_ = duration; | 772 estimated_next_frame_duration_ = duration; |
773 } else if (is_video_) { | 773 } else if (is_video_) { |
774 estimated_next_frame_duration_ = | 774 estimated_next_frame_duration_ = |
775 std::max(duration, estimated_next_frame_duration_); | 775 std::max(duration, estimated_next_frame_duration_); |
776 } else { | 776 } else { |
777 estimated_next_frame_duration_ = | 777 estimated_next_frame_duration_ = |
778 std::min(duration, estimated_next_frame_duration_); | 778 std::min(duration, estimated_next_frame_duration_); |
779 } | 779 } |
780 | 780 |
781 if (orig_duration_estimate != estimated_next_frame_duration_) { | 781 if (orig_duration_estimate != estimated_next_frame_duration_) { |
782 DVLOG(3) << "Updated duration estimate:" | 782 DVLOG(3) << "Updated duration estimate:" |
783 << orig_duration_estimate | 783 << orig_duration_estimate |
784 << " -> " | 784 << " -> " |
785 << estimated_next_frame_duration_ | 785 << estimated_next_frame_duration_ |
786 << " at timestamp: " | 786 << " at timestamp: " |
787 << buffer->GetDecodeTimestamp().InSecondsF(); | 787 << buffer->GetDecodeTimestamp().InSecondsF(); |
788 } | 788 } |
789 } | 789 } |
790 | 790 |
791 buffers_.push_back(buffer); | 791 buffers_.push_back(buffer); |
792 return true; | 792 return true; |
793 } | 793 } |
794 | 794 |
795 base::TimeDelta WebMClusterParser::Track::GetDurationEstimate() { | 795 base::TimeDelta WebMClusterParser::Track::GetDurationEstimate() { |
796 base::TimeDelta duration = estimated_next_frame_duration_; | 796 base::TimeDelta duration = estimated_next_frame_duration_; |
797 if (duration != kNoTimestamp()) { | 797 if (duration != kNoTimestamp) { |
798 DVLOG(3) << __FUNCTION__ << " : using estimated duration"; | 798 DVLOG(3) << __FUNCTION__ << " : using estimated duration"; |
799 } else { | 799 } else { |
800 DVLOG(3) << __FUNCTION__ << " : using hardcoded default duration"; | 800 DVLOG(3) << __FUNCTION__ << " : using hardcoded default duration"; |
801 if (is_video_) { | 801 if (is_video_) { |
802 duration = base::TimeDelta::FromMilliseconds( | 802 duration = base::TimeDelta::FromMilliseconds( |
803 kDefaultVideoBufferDurationInMs); | 803 kDefaultVideoBufferDurationInMs); |
804 } else { | 804 } else { |
805 duration = base::TimeDelta::FromMilliseconds( | 805 duration = base::TimeDelta::FromMilliseconds( |
806 kDefaultAudioBufferDurationInMs); | 806 kDefaultAudioBufferDurationInMs); |
807 } | 807 } |
808 } | 808 } |
809 | 809 |
810 DCHECK(duration > base::TimeDelta()); | 810 DCHECK(duration > base::TimeDelta()); |
811 DCHECK(duration != kNoTimestamp()); | 811 DCHECK(duration != kNoTimestamp); |
812 return duration; | 812 return duration; |
813 } | 813 } |
814 | 814 |
815 void WebMClusterParser::ClearTextTrackReadyBuffers() { | 815 void WebMClusterParser::ClearTextTrackReadyBuffers() { |
816 text_buffers_map_.clear(); | 816 text_buffers_map_.clear(); |
817 for (TextTrackMap::iterator it = text_track_map_.begin(); | 817 for (TextTrackMap::iterator it = text_track_map_.begin(); |
818 it != text_track_map_.end(); | 818 it != text_track_map_.end(); |
819 ++it) { | 819 ++it) { |
820 it->second.ClearReadyBuffers(); | 820 it->second.ClearReadyBuffers(); |
821 } | 821 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
865 WebMClusterParser::FindTextTrack(int track_num) { | 865 WebMClusterParser::FindTextTrack(int track_num) { |
866 const TextTrackMap::iterator it = text_track_map_.find(track_num); | 866 const TextTrackMap::iterator it = text_track_map_.find(track_num); |
867 | 867 |
868 if (it == text_track_map_.end()) | 868 if (it == text_track_map_.end()) |
869 return NULL; | 869 return NULL; |
870 | 870 |
871 return &it->second; | 871 return &it->second; |
872 } | 872 } |
873 | 873 |
874 } // namespace media | 874 } // namespace media |
OLD | NEW |