| 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 |