Chromium Code Reviews| 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/filters/source_buffer_range.h" | 5 #include "media/filters/source_buffer_range.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 namespace media { | 9 namespace media { |
| 10 | 10 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 AppendBuffersToEnd(new_buffers); | 41 AppendBuffersToEnd(new_buffers); |
| 42 } | 42 } |
| 43 | 43 |
| 44 SourceBufferRange::~SourceBufferRange() {} | 44 SourceBufferRange::~SourceBufferRange() {} |
| 45 | 45 |
| 46 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) { | 46 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) { |
| 47 DCHECK(buffers_.empty() || CanAppendBuffersToEnd(new_buffers)); | 47 DCHECK(buffers_.empty() || CanAppendBuffersToEnd(new_buffers)); |
| 48 DCHECK(media_segment_start_time_ == kNoDecodeTimestamp() || | 48 DCHECK(media_segment_start_time_ == kNoDecodeTimestamp() || |
| 49 media_segment_start_time_ <= | 49 media_segment_start_time_ <= |
| 50 new_buffers.front()->GetDecodeTimestamp()); | 50 new_buffers.front()->GetDecodeTimestamp()); |
| 51 | |
| 52 AdjustEstimatedDurationForNewAppend(new_buffers); | |
| 53 | |
| 51 for (BufferQueue::const_iterator itr = new_buffers.begin(); | 54 for (BufferQueue::const_iterator itr = new_buffers.begin(); |
| 52 itr != new_buffers.end(); | 55 itr != new_buffers.end(); |
| 53 ++itr) { | 56 ++itr) { |
| 54 DCHECK((*itr)->GetDecodeTimestamp() != kNoDecodeTimestamp()); | 57 DCHECK((*itr)->GetDecodeTimestamp() != kNoDecodeTimestamp()); |
| 55 buffers_.push_back(*itr); | 58 buffers_.push_back(*itr); |
| 56 size_in_bytes_ += (*itr)->data_size(); | 59 size_in_bytes_ += (*itr)->data_size(); |
| 57 | 60 |
| 58 if ((*itr)->is_key_frame()) { | 61 if ((*itr)->is_key_frame()) { |
| 59 keyframe_map_.insert( | 62 keyframe_map_.insert( |
| 60 std::make_pair((*itr)->GetDecodeTimestamp(), | 63 std::make_pair((*itr)->GetDecodeTimestamp(), |
| 61 buffers_.size() - 1 + keyframe_map_index_base_)); | 64 buffers_.size() - 1 + keyframe_map_index_base_)); |
| 62 } | 65 } |
| 63 } | 66 } |
| 64 } | 67 } |
| 65 | 68 |
| 69 void SourceBufferRange::AdjustEstimatedDurationForNewAppend( | |
| 70 const BufferQueue& new_buffers) { | |
| 71 if (buffers_.empty() || new_buffers.empty()) { | |
|
DaleCurtis
2015/04/15 22:51:46
Typically no {} for one line if statements, but up
chcunningham
2015/04/16 18:04:16
I'm a believer! I think no brackets is asking for
| |
| 72 return; | |
| 73 } | |
| 74 | |
| 75 // If the last of the previously appended buffers contains estimated duration, | |
| 76 // we now refine that estimate by taking the PTS delta from the first new | |
| 77 // buffer being appended. | |
| 78 const auto& last_appended_buffer = buffers_.back(); | |
| 79 if (last_appended_buffer->is_duration_estimated()) { | |
| 80 base::TimeDelta timestamp_delta = | |
| 81 new_buffers.front()->timestamp() - last_appended_buffer->timestamp(); | |
|
DaleCurtis
2015/04/15 22:51:46
Always positive? What happens in an overlap case?
chcunningham
2015/04/16 18:04:16
This should be always positive, but I think this i
| |
| 82 if (last_appended_buffer->duration() != timestamp_delta) { | |
| 83 DVLOG(1) << "Replacing estimated duration (" | |
| 84 << last_appended_buffer->duration() | |
| 85 << ") from previous range end with derived duration (" | |
| 86 << timestamp_delta << ")."; | |
| 87 last_appended_buffer->set_duration(timestamp_delta); | |
| 88 } | |
| 89 } | |
| 90 } | |
| 91 | |
| 66 void SourceBufferRange::Seek(DecodeTimestamp timestamp) { | 92 void SourceBufferRange::Seek(DecodeTimestamp timestamp) { |
| 67 DCHECK(CanSeekTo(timestamp)); | 93 DCHECK(CanSeekTo(timestamp)); |
| 68 DCHECK(!keyframe_map_.empty()); | 94 DCHECK(!keyframe_map_.empty()); |
| 69 | 95 |
| 70 KeyframeMap::iterator result = GetFirstKeyframeBefore(timestamp); | 96 KeyframeMap::iterator result = GetFirstKeyframeAtOrBefore(timestamp); |
| 71 next_buffer_index_ = result->second - keyframe_map_index_base_; | 97 next_buffer_index_ = result->second - keyframe_map_index_base_; |
| 72 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); | 98 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); |
| 73 } | 99 } |
| 74 | 100 |
| 75 void SourceBufferRange::SeekAheadTo(DecodeTimestamp timestamp) { | 101 void SourceBufferRange::SeekAheadTo(DecodeTimestamp timestamp) { |
| 76 SeekAhead(timestamp, false); | 102 SeekAhead(timestamp, false); |
| 77 } | 103 } |
| 78 | 104 |
| 79 void SourceBufferRange::SeekAheadPast(DecodeTimestamp timestamp) { | 105 void SourceBufferRange::SeekAheadPast(DecodeTimestamp timestamp) { |
| 80 SeekAhead(timestamp, true); | 106 SeekAhead(timestamp, true); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 | 192 |
| 167 SourceBufferRange::KeyframeMap::iterator | 193 SourceBufferRange::KeyframeMap::iterator |
| 168 SourceBufferRange::GetFirstKeyframeAt(DecodeTimestamp timestamp, | 194 SourceBufferRange::GetFirstKeyframeAt(DecodeTimestamp timestamp, |
| 169 bool skip_given_timestamp) { | 195 bool skip_given_timestamp) { |
| 170 return skip_given_timestamp ? | 196 return skip_given_timestamp ? |
| 171 keyframe_map_.upper_bound(timestamp) : | 197 keyframe_map_.upper_bound(timestamp) : |
| 172 keyframe_map_.lower_bound(timestamp); | 198 keyframe_map_.lower_bound(timestamp); |
| 173 } | 199 } |
| 174 | 200 |
| 175 SourceBufferRange::KeyframeMap::iterator | 201 SourceBufferRange::KeyframeMap::iterator |
| 176 SourceBufferRange::GetFirstKeyframeBefore(DecodeTimestamp timestamp) { | 202 SourceBufferRange::GetFirstKeyframeAtOrBefore(DecodeTimestamp timestamp) { |
| 177 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); | 203 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); |
| 178 // lower_bound() returns the first element >= |timestamp|, so we want the | 204 // lower_bound() returns the first element >= |timestamp|, so we want the |
| 179 // previous element if it did not return the element exactly equal to | 205 // previous element if it did not return the element exactly equal to |
| 180 // |timestamp|. | 206 // |timestamp|. |
| 181 if (result != keyframe_map_.begin() && | 207 if (result != keyframe_map_.begin() && |
| 182 (result == keyframe_map_.end() || result->first != timestamp)) { | 208 (result == keyframe_map_.end() || result->first != timestamp)) { |
| 183 --result; | 209 --result; |
| 184 } | 210 } |
| 185 return result; | 211 return result; |
| 186 } | 212 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 int bytes_to_free = total_bytes_to_free; | 305 int bytes_to_free = total_bytes_to_free; |
| 280 int bytes_removed = 0; | 306 int bytes_removed = 0; |
| 281 | 307 |
| 282 KeyframeMap::iterator gop_itr = GetFirstKeyframeAt(start_timestamp, false); | 308 KeyframeMap::iterator gop_itr = GetFirstKeyframeAt(start_timestamp, false); |
| 283 if (gop_itr == keyframe_map_.end()) | 309 if (gop_itr == keyframe_map_.end()) |
| 284 return 0; | 310 return 0; |
| 285 int keyframe_index = gop_itr->second - keyframe_map_index_base_; | 311 int keyframe_index = gop_itr->second - keyframe_map_index_base_; |
| 286 BufferQueue::iterator buffer_itr = buffers_.begin() + keyframe_index; | 312 BufferQueue::iterator buffer_itr = buffers_.begin() + keyframe_index; |
| 287 KeyframeMap::iterator gop_end = keyframe_map_.end(); | 313 KeyframeMap::iterator gop_end = keyframe_map_.end(); |
| 288 if (end_timestamp < GetBufferedEndTimestamp()) | 314 if (end_timestamp < GetBufferedEndTimestamp()) |
| 289 gop_end = GetFirstKeyframeBefore(end_timestamp); | 315 gop_end = GetFirstKeyframeAtOrBefore(end_timestamp); |
| 290 | 316 |
| 291 // Check if the removal range is within a GOP and skip the loop if so. | 317 // Check if the removal range is within a GOP and skip the loop if so. |
| 292 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe] | 318 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe] |
| 293 KeyframeMap::iterator gop_itr_prev = gop_itr; | 319 KeyframeMap::iterator gop_itr_prev = gop_itr; |
| 294 if (gop_itr_prev != keyframe_map_.begin() && --gop_itr_prev == gop_end) | 320 if (gop_itr_prev != keyframe_map_.begin() && --gop_itr_prev == gop_end) |
| 295 gop_end = gop_itr; | 321 gop_end = gop_itr; |
| 296 | 322 |
| 297 while (gop_itr != gop_end && bytes_to_free > 0) { | 323 while (gop_itr != gop_end && bytes_to_free > 0) { |
| 298 ++gop_itr; | 324 ++gop_itr; |
| 299 | 325 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 519 return itr->first; | 545 return itr->first; |
| 520 } | 546 } |
| 521 | 547 |
| 522 DecodeTimestamp SourceBufferRange::KeyframeBeforeTimestamp( | 548 DecodeTimestamp SourceBufferRange::KeyframeBeforeTimestamp( |
| 523 DecodeTimestamp timestamp) { | 549 DecodeTimestamp timestamp) { |
| 524 DCHECK(!keyframe_map_.empty()); | 550 DCHECK(!keyframe_map_.empty()); |
| 525 | 551 |
| 526 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) | 552 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) |
| 527 return kNoDecodeTimestamp(); | 553 return kNoDecodeTimestamp(); |
| 528 | 554 |
| 529 return GetFirstKeyframeBefore(timestamp)->first; | 555 return GetFirstKeyframeAtOrBefore(timestamp)->first; |
| 530 } | 556 } |
| 531 | 557 |
| 532 bool SourceBufferRange::IsNextInSequence( | 558 bool SourceBufferRange::IsNextInSequence( |
| 533 DecodeTimestamp timestamp, bool is_key_frame) const { | 559 DecodeTimestamp timestamp, bool is_key_frame) const { |
| 534 DecodeTimestamp end = buffers_.back()->GetDecodeTimestamp(); | 560 DecodeTimestamp end = buffers_.back()->GetDecodeTimestamp(); |
| 535 if (end < timestamp && | 561 if (end < timestamp && |
| 536 (gap_policy_ == ALLOW_GAPS || | 562 (gap_policy_ == ALLOW_GAPS || |
| 537 timestamp <= end + GetFudgeRoom())) { | 563 timestamp <= end + GetFudgeRoom())) { |
| 538 return true; | 564 return true; |
| 539 } | 565 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 580 } | 606 } |
| 581 | 607 |
| 582 if (buffer->timestamp() + buffer->duration() <= start.ToPresentationTime()) | 608 if (buffer->timestamp() + buffer->duration() <= start.ToPresentationTime()) |
| 583 continue; | 609 continue; |
| 584 buffers->push_back(buffer); | 610 buffers->push_back(buffer); |
| 585 } | 611 } |
| 586 return previous_size < buffers->size(); | 612 return previous_size < buffers->size(); |
| 587 } | 613 } |
| 588 | 614 |
| 589 } // namespace media | 615 } // namespace media |
| OLD | NEW |