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( | |
|
wolenetz
2015/03/28 00:26:06
Does adjustment to duration correctly include when
chcunningham
2015/04/13 23:25:17
This is a great question and I've given it a lot o
wolenetz
2015/04/15 02:55:23
I agree.
| |
| 70 const BufferQueue& new_buffers) { | |
| 71 if (buffers_.empty() || new_buffers.empty()) { | |
|
wolenetz
2015/03/28 00:26:06
nit: Change call to only occur when buffers_ is no
chcunningham
2015/04/13 23:25:18
Let me push back a little here (or at least argue
wolenetz
2015/04/15 02:55:23
That's fine. If this method really needed to requi
| |
| 72 return; | |
| 73 } | |
| 74 | |
| 75 // Only adjust the last of the previously appended buffers. The last buffer | |
|
wolenetz
2015/03/28 00:26:05
nit: s/buffers./buffers if its duration was previo
chcunningham
2015/04/13 23:25:17
Done.
| |
| 76 // in a given append is an edge case where the parsers (upstream) cannot know | |
| 77 // the implicit PTS-delta duration because the do not know the PTS of the | |
|
wolenetz
2015/03/28 00:26:05
nit: s/because the/because they/.. Actually, is th
chcunningham
2015/04/13 23:25:17
Done. Changed a little from what you wrote, but di
| |
| 78 // frame that may follow the last for that append. The PTS of this new append | |
| 79 // supplies the missing information for a better duration estimate. | |
| 80 scoped_refptr<StreamParserBuffer> last_appended_buffer = buffers_.back(); | |
|
wolenetz
2015/03/28 00:26:05
nit: const& the smart pointer to reduce unnecessar
chcunningham
2015/04/13 23:25:18
Done. Made auto too.
| |
| 81 if (last_appended_buffer->is_duration_estimated()) { | |
| 82 base::TimeDelta timestamp_delta = | |
| 83 new_buffers.front()->timestamp() - last_appended_buffer->timestamp(); | |
| 84 if (last_appended_buffer->duration() != timestamp_delta) { | |
| 85 DVLOG(1) << "Replacing estimated duration (" | |
| 86 << last_appended_buffer->duration() | |
| 87 << ") from last append with derived duration (" | |
|
wolenetz
2015/03/28 00:26:06
nit: may not have been from "last" append.
chcunningham
2015/04/13 23:25:17
Done. Now reads "Replacing estimated duration (X)
| |
| 88 << timestamp_delta << ")."; | |
| 89 last_appended_buffer->set_duration(timestamp_delta); | |
| 90 } | |
| 91 } | |
| 92 } | |
| 93 | |
| 66 void SourceBufferRange::Seek(DecodeTimestamp timestamp) { | 94 void SourceBufferRange::Seek(DecodeTimestamp timestamp) { |
| 67 DCHECK(CanSeekTo(timestamp)); | 95 DCHECK(CanSeekTo(timestamp)); |
| 68 DCHECK(!keyframe_map_.empty()); | 96 DCHECK(!keyframe_map_.empty()); |
| 69 | 97 |
| 70 KeyframeMap::iterator result = GetFirstKeyframeBefore(timestamp); | 98 KeyframeMap::iterator result = GetFirstKeyframeAtOrBefore(timestamp); |
| 71 next_buffer_index_ = result->second - keyframe_map_index_base_; | 99 next_buffer_index_ = result->second - keyframe_map_index_base_; |
| 72 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); | 100 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); |
| 73 } | 101 } |
| 74 | 102 |
| 75 void SourceBufferRange::SeekAheadTo(DecodeTimestamp timestamp) { | 103 void SourceBufferRange::SeekAheadTo(DecodeTimestamp timestamp) { |
| 76 SeekAhead(timestamp, false); | 104 SeekAhead(timestamp, false); |
| 77 } | 105 } |
| 78 | 106 |
| 79 void SourceBufferRange::SeekAheadPast(DecodeTimestamp timestamp) { | 107 void SourceBufferRange::SeekAheadPast(DecodeTimestamp timestamp) { |
| 80 SeekAhead(timestamp, true); | 108 SeekAhead(timestamp, true); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 | 196 |
| 169 SourceBufferRange::KeyframeMap::iterator | 197 SourceBufferRange::KeyframeMap::iterator |
| 170 SourceBufferRange::GetFirstKeyframeAt(DecodeTimestamp timestamp, | 198 SourceBufferRange::GetFirstKeyframeAt(DecodeTimestamp timestamp, |
| 171 bool skip_given_timestamp) { | 199 bool skip_given_timestamp) { |
| 172 return skip_given_timestamp ? | 200 return skip_given_timestamp ? |
| 173 keyframe_map_.upper_bound(timestamp) : | 201 keyframe_map_.upper_bound(timestamp) : |
| 174 keyframe_map_.lower_bound(timestamp); | 202 keyframe_map_.lower_bound(timestamp); |
| 175 } | 203 } |
| 176 | 204 |
| 177 SourceBufferRange::KeyframeMap::iterator | 205 SourceBufferRange::KeyframeMap::iterator |
| 178 SourceBufferRange::GetFirstKeyframeBefore(DecodeTimestamp timestamp) { | 206 SourceBufferRange::GetFirstKeyframeAtOrBefore(DecodeTimestamp timestamp) { |
| 179 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); | 207 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); |
| 180 // lower_bound() returns the first element >= |timestamp|, so we want the | 208 // lower_bound() returns the first element >= |timestamp|, so we want the |
| 181 // previous element if it did not return the element exactly equal to | 209 // previous element if it did not return the element exactly equal to |
| 182 // |timestamp|. | 210 // |timestamp|. |
| 183 if (result != keyframe_map_.begin() && | 211 if (result != keyframe_map_.begin() && |
| 184 (result == keyframe_map_.end() || result->first != timestamp)) { | 212 (result == keyframe_map_.end() || result->first != timestamp)) { |
| 185 --result; | 213 --result; |
| 186 } | 214 } |
| 187 return result; | 215 return result; |
| 188 } | 216 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 281 int bytes_to_free = total_bytes_to_free; | 309 int bytes_to_free = total_bytes_to_free; |
| 282 int bytes_removed = 0; | 310 int bytes_removed = 0; |
| 283 | 311 |
| 284 KeyframeMap::iterator gop_itr = GetFirstKeyframeAt(start_timestamp, false); | 312 KeyframeMap::iterator gop_itr = GetFirstKeyframeAt(start_timestamp, false); |
| 285 if (gop_itr == keyframe_map_.end()) | 313 if (gop_itr == keyframe_map_.end()) |
| 286 return 0; | 314 return 0; |
| 287 int keyframe_index = gop_itr->second - keyframe_map_index_base_; | 315 int keyframe_index = gop_itr->second - keyframe_map_index_base_; |
| 288 BufferQueue::iterator buffer_itr = buffers_.begin() + keyframe_index; | 316 BufferQueue::iterator buffer_itr = buffers_.begin() + keyframe_index; |
| 289 KeyframeMap::iterator gop_end = keyframe_map_.end(); | 317 KeyframeMap::iterator gop_end = keyframe_map_.end(); |
| 290 if (end_timestamp < GetBufferedEndTimestamp()) | 318 if (end_timestamp < GetBufferedEndTimestamp()) |
| 291 gop_end = GetFirstKeyframeBefore(end_timestamp); | 319 gop_end = GetFirstKeyframeAtOrBefore(end_timestamp); |
| 292 | 320 |
| 293 // Check if the removal range is within a GOP and skip the loop if so. | 321 // Check if the removal range is within a GOP and skip the loop if so. |
| 294 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe] | 322 // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe] |
| 295 KeyframeMap::iterator gop_itr_prev = gop_itr; | 323 KeyframeMap::iterator gop_itr_prev = gop_itr; |
| 296 if (gop_itr_prev != keyframe_map_.begin() && --gop_itr_prev == gop_end) | 324 if (gop_itr_prev != keyframe_map_.begin() && --gop_itr_prev == gop_end) |
| 297 gop_end = gop_itr; | 325 gop_end = gop_itr; |
| 298 | 326 |
| 299 while (gop_itr != gop_end && bytes_to_free > 0) { | 327 while (gop_itr != gop_end && bytes_to_free > 0) { |
| 300 ++gop_itr; | 328 ++gop_itr; |
| 301 | 329 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 521 return itr->first; | 549 return itr->first; |
| 522 } | 550 } |
| 523 | 551 |
| 524 DecodeTimestamp SourceBufferRange::KeyframeBeforeTimestamp( | 552 DecodeTimestamp SourceBufferRange::KeyframeBeforeTimestamp( |
| 525 DecodeTimestamp timestamp) { | 553 DecodeTimestamp timestamp) { |
| 526 DCHECK(!keyframe_map_.empty()); | 554 DCHECK(!keyframe_map_.empty()); |
| 527 | 555 |
| 528 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) | 556 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) |
| 529 return kNoDecodeTimestamp(); | 557 return kNoDecodeTimestamp(); |
| 530 | 558 |
| 531 return GetFirstKeyframeBefore(timestamp)->first; | 559 return GetFirstKeyframeAtOrBefore(timestamp)->first; |
| 532 } | 560 } |
| 533 | 561 |
| 534 bool SourceBufferRange::IsNextInSequence( | 562 bool SourceBufferRange::IsNextInSequence( |
| 535 DecodeTimestamp timestamp, bool is_key_frame) const { | 563 DecodeTimestamp timestamp, bool is_key_frame) const { |
| 536 DecodeTimestamp end = buffers_.back()->GetDecodeTimestamp(); | 564 DecodeTimestamp end = buffers_.back()->GetDecodeTimestamp(); |
| 537 if (end < timestamp && | 565 if (end < timestamp && |
| 538 (gap_policy_ == ALLOW_GAPS || | 566 (gap_policy_ == ALLOW_GAPS || |
| 539 timestamp <= end + GetFudgeRoom())) { | 567 timestamp <= end + GetFudgeRoom())) { |
| 540 return true; | 568 return true; |
| 541 } | 569 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 582 } | 610 } |
| 583 | 611 |
| 584 if (buffer->timestamp() + buffer->duration() <= start.ToPresentationTime()) | 612 if (buffer->timestamp() + buffer->duration() <= start.ToPresentationTime()) |
| 585 continue; | 613 continue; |
| 586 buffers->push_back(buffer); | 614 buffers->push_back(buffer); |
| 587 } | 615 } |
| 588 return previous_size < buffers->size(); | 616 return previous_size < buffers->size(); |
| 589 } | 617 } |
| 590 | 618 |
| 591 } // namespace media | 619 } // namespace media |
| OLD | NEW |