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 #include "media/base/timestamp_constants.h" | 9 #include "media/base/timestamp_constants.h" |
10 | 10 |
11 namespace media { | 11 namespace media { |
12 | 12 |
13 // Comparison operators for std::upper_bound() and std::lower_bound(). | 13 // Comparison operators for std::upper_bound() and std::lower_bound(). |
14 static bool CompareTimeDeltaToStreamParserBuffer( | 14 static bool CompareTimeDeltaToStreamParserBuffer( |
15 const DecodeTimestamp& decode_timestamp, | 15 const DecodeTimestamp& decode_timestamp, |
16 const scoped_refptr<StreamParserBuffer>& buffer) { | 16 const scoped_refptr<StreamParserBuffer>& buffer) { |
17 return decode_timestamp < buffer->GetDecodeTimestamp(); | 17 return decode_timestamp < buffer->GetDecodeTimestamp(); |
18 } | 18 } |
19 static bool CompareStreamParserBufferToTimeDelta( | 19 static bool CompareStreamParserBufferToTimeDelta( |
20 const scoped_refptr<StreamParserBuffer>& buffer, | 20 const scoped_refptr<StreamParserBuffer>& buffer, |
21 const DecodeTimestamp& decode_timestamp) { | 21 const DecodeTimestamp& decode_timestamp) { |
22 return buffer->GetDecodeTimestamp() < decode_timestamp; | 22 return buffer->GetDecodeTimestamp() < decode_timestamp; |
23 } | 23 } |
24 | 24 |
25 bool SourceBufferRange::AllowSameTimestamp( | 25 bool SourceBufferRange::IsUncommonSameTimestampSequence( |
26 bool prev_is_keyframe, bool current_is_keyframe) { | 26 bool prev_is_keyframe, |
27 return prev_is_keyframe || !current_is_keyframe; | 27 bool current_is_keyframe) { |
28 return current_is_keyframe && !prev_is_keyframe; | |
28 } | 29 } |
29 | 30 |
30 SourceBufferRange::SourceBufferRange( | 31 SourceBufferRange::SourceBufferRange( |
31 GapPolicy gap_policy, const BufferQueue& new_buffers, | 32 GapPolicy gap_policy, |
32 DecodeTimestamp media_segment_start_time, | 33 const BufferQueue& new_buffers, |
34 DecodeTimestamp range_start_time, | |
33 const InterbufferDistanceCB& interbuffer_distance_cb) | 35 const InterbufferDistanceCB& interbuffer_distance_cb) |
34 : gap_policy_(gap_policy), | 36 : gap_policy_(gap_policy), |
35 keyframe_map_index_base_(0), | 37 keyframe_map_index_base_(0), |
36 next_buffer_index_(-1), | 38 next_buffer_index_(-1), |
37 media_segment_start_time_(media_segment_start_time), | 39 range_start_time_(range_start_time), |
38 interbuffer_distance_cb_(interbuffer_distance_cb), | 40 interbuffer_distance_cb_(interbuffer_distance_cb), |
39 size_in_bytes_(0) { | 41 size_in_bytes_(0) { |
40 CHECK(!new_buffers.empty()); | 42 CHECK(!new_buffers.empty()); |
41 DCHECK(new_buffers.front()->is_key_frame()); | 43 DCHECK(new_buffers.front()->is_key_frame()); |
42 DCHECK(!interbuffer_distance_cb.is_null()); | 44 DCHECK(!interbuffer_distance_cb.is_null()); |
43 AppendBuffersToEnd(new_buffers); | 45 AppendBuffersToEnd(new_buffers, range_start_time_); |
44 } | 46 } |
45 | 47 |
46 SourceBufferRange::~SourceBufferRange() {} | 48 SourceBufferRange::~SourceBufferRange() {} |
47 | 49 |
48 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) { | 50 void SourceBufferRange::AppendBuffersToEnd( |
49 DCHECK(buffers_.empty() || CanAppendBuffersToEnd(new_buffers)); | 51 const BufferQueue& new_buffers, |
50 DCHECK(media_segment_start_time_ == kNoDecodeTimestamp() || | 52 DecodeTimestamp new_buffers_group_start_timestamp) { |
51 media_segment_start_time_ <= | 53 DCHECK(buffers_.empty() || |
chcunningham
2016/02/12 22:46:40
DCHECK -> CHECK?
wolenetz
2016/02/24 00:34:46
Done.
| |
52 new_buffers.front()->GetDecodeTimestamp()); | 54 CanAppendBuffersToEnd(new_buffers, new_buffers_group_start_timestamp)); |
55 DCHECK(range_start_time_ == kNoDecodeTimestamp() || | |
chcunningham
2016/02/12 22:46:40
Can range start time really be kNoDecodeTimestamp?
wolenetz
2016/02/24 00:34:46
Yes. See the comment for |range_start_time_| in th
chcunningham
2016/02/24 19:06:26
Acknowledged.
| |
56 range_start_time_ <= new_buffers.front()->GetDecodeTimestamp()); | |
53 | 57 |
54 AdjustEstimatedDurationForNewAppend(new_buffers); | 58 AdjustEstimatedDurationForNewAppend(new_buffers); |
55 | 59 |
56 for (BufferQueue::const_iterator itr = new_buffers.begin(); | 60 for (BufferQueue::const_iterator itr = new_buffers.begin(); |
57 itr != new_buffers.end(); | 61 itr != new_buffers.end(); |
58 ++itr) { | 62 ++itr) { |
59 DCHECK((*itr)->GetDecodeTimestamp() != kNoDecodeTimestamp()); | 63 DCHECK((*itr)->GetDecodeTimestamp() != kNoDecodeTimestamp()); |
60 buffers_.push_back(*itr); | 64 buffers_.push_back(*itr); |
61 size_in_bytes_ += (*itr)->data_size(); | 65 size_in_bytes_ += (*itr)->data_size(); |
62 | 66 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
147 // into |removed_buffers|. | 151 // into |removed_buffers|. |
148 int keyframe_index = | 152 int keyframe_index = |
149 new_beginning_keyframe->second - keyframe_map_index_base_; | 153 new_beginning_keyframe->second - keyframe_map_index_base_; |
150 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); | 154 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); |
151 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index; | 155 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index; |
152 BufferQueue removed_buffers(starting_point, buffers_.end()); | 156 BufferQueue removed_buffers(starting_point, buffers_.end()); |
153 | 157 |
154 DecodeTimestamp new_range_start_timestamp = kNoDecodeTimestamp(); | 158 DecodeTimestamp new_range_start_timestamp = kNoDecodeTimestamp(); |
155 if (GetStartTimestamp() < buffers_.front()->GetDecodeTimestamp() && | 159 if (GetStartTimestamp() < buffers_.front()->GetDecodeTimestamp() && |
156 timestamp < removed_buffers.front()->GetDecodeTimestamp()) { | 160 timestamp < removed_buffers.front()->GetDecodeTimestamp()) { |
157 // The split is in the gap between |media_segment_start_time_| and | 161 // The split is in the gap between |range_start_time_| and the first buffer |
158 // the first buffer of the new range so we should set the start | 162 // of the new range so we should set the start time of the new range to |
159 // time of the new range to |timestamp| so we preserve part of the | 163 // |timestamp| so we preserve part of the gap in the new range. |
160 // gap in the new range. | |
161 new_range_start_timestamp = timestamp; | 164 new_range_start_timestamp = timestamp; |
162 } | 165 } |
163 | 166 |
164 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end()); | 167 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end()); |
165 FreeBufferRange(starting_point, buffers_.end()); | 168 FreeBufferRange(starting_point, buffers_.end()); |
166 | 169 |
167 // Create a new range with |removed_buffers|. | 170 // Create a new range with |removed_buffers|. |
168 SourceBufferRange* split_range = | 171 SourceBufferRange* split_range = |
169 new SourceBufferRange( | 172 new SourceBufferRange( |
170 gap_policy_, removed_buffers, new_range_start_timestamp, | 173 gap_policy_, removed_buffers, new_range_start_timestamp, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
263 | 266 |
264 // Update |keyframe_map_index_base_| to account for the deleted buffers. | 267 // Update |keyframe_map_index_base_| to account for the deleted buffers. |
265 keyframe_map_index_base_ += buffers_deleted; | 268 keyframe_map_index_base_ += buffers_deleted; |
266 | 269 |
267 if (next_buffer_index_ > -1) { | 270 if (next_buffer_index_ > -1) { |
268 next_buffer_index_ -= buffers_deleted; | 271 next_buffer_index_ -= buffers_deleted; |
269 CHECK_GE(next_buffer_index_, 0) << next_buffer_index_ << ", deleted " | 272 CHECK_GE(next_buffer_index_, 0) << next_buffer_index_ << ", deleted " |
270 << buffers_deleted; | 273 << buffers_deleted; |
271 } | 274 } |
272 | 275 |
273 // Invalidate media segment start time if we've deleted the first buffer of | 276 // Invalidate range start time if we've deleted the first buffer of the range. |
274 // the range. | |
275 if (buffers_deleted > 0) | 277 if (buffers_deleted > 0) |
276 media_segment_start_time_ = kNoDecodeTimestamp(); | 278 range_start_time_ = kNoDecodeTimestamp(); |
277 | 279 |
278 return total_bytes_deleted; | 280 return total_bytes_deleted; |
279 } | 281 } |
280 | 282 |
281 size_t SourceBufferRange::DeleteGOPFromBack(BufferQueue* deleted_buffers) { | 283 size_t SourceBufferRange::DeleteGOPFromBack(BufferQueue* deleted_buffers) { |
282 DCHECK(!LastGOPContainsNextBufferPosition()); | 284 DCHECK(!LastGOPContainsNextBufferPosition()); |
283 DCHECK(deleted_buffers); | 285 DCHECK(deleted_buffers); |
284 | 286 |
285 // Remove the last GOP's keyframe from the |keyframe_map_|. | 287 // Remove the last GOP's keyframe from the |keyframe_map_|. |
286 KeyframeMap::iterator back = keyframe_map_.end(); | 288 KeyframeMap::iterator back = keyframe_map_.end(); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
474 } | 476 } |
475 | 477 |
476 void SourceBufferRange::AppendRangeToEnd(const SourceBufferRange& range, | 478 void SourceBufferRange::AppendRangeToEnd(const SourceBufferRange& range, |
477 bool transfer_current_position) { | 479 bool transfer_current_position) { |
478 DCHECK(CanAppendRangeToEnd(range)); | 480 DCHECK(CanAppendRangeToEnd(range)); |
479 DCHECK(!buffers_.empty()); | 481 DCHECK(!buffers_.empty()); |
480 | 482 |
481 if (transfer_current_position && range.next_buffer_index_ >= 0) | 483 if (transfer_current_position && range.next_buffer_index_ >= 0) |
482 next_buffer_index_ = range.next_buffer_index_ + buffers_.size(); | 484 next_buffer_index_ = range.next_buffer_index_ + buffers_.size(); |
483 | 485 |
484 AppendBuffersToEnd(range.buffers_); | 486 AppendBuffersToEnd(range.buffers_, kNoDecodeTimestamp()); |
485 } | 487 } |
486 | 488 |
487 bool SourceBufferRange::CanAppendRangeToEnd( | 489 bool SourceBufferRange::CanAppendRangeToEnd( |
488 const SourceBufferRange& range) const { | 490 const SourceBufferRange& range) const { |
489 return CanAppendBuffersToEnd(range.buffers_); | 491 return CanAppendBuffersToEnd(range.buffers_, kNoDecodeTimestamp()); |
490 } | 492 } |
491 | 493 |
492 bool SourceBufferRange::CanAppendBuffersToEnd( | 494 bool SourceBufferRange::CanAppendBuffersToEnd( |
493 const BufferQueue& buffers) const { | 495 const BufferQueue& buffers, |
496 DecodeTimestamp new_buffers_group_start_timestamp) const { | |
494 DCHECK(!buffers_.empty()); | 497 DCHECK(!buffers_.empty()); |
495 return IsNextInSequence(buffers.front()->GetDecodeTimestamp(), | 498 if (new_buffers_group_start_timestamp == kNoDecodeTimestamp()) { |
496 buffers.front()->is_key_frame()); | 499 return IsNextInSequence(buffers.front()->GetDecodeTimestamp()); |
500 } | |
501 DCHECK(new_buffers_group_start_timestamp >= GetEndTimestamp()); | |
502 DCHECK(buffers.front()->GetDecodeTimestamp() >= | |
503 new_buffers_group_start_timestamp); | |
504 return IsNextInSequence(new_buffers_group_start_timestamp); | |
497 } | 505 } |
498 | 506 |
499 bool SourceBufferRange::BelongsToRange(DecodeTimestamp timestamp) const { | 507 bool SourceBufferRange::BelongsToRange(DecodeTimestamp timestamp) const { |
500 DCHECK(!buffers_.empty()); | 508 DCHECK(!buffers_.empty()); |
501 | 509 |
502 return (IsNextInSequence(timestamp, false) || | 510 return (IsNextInSequence(timestamp) || |
503 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp())); | 511 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp())); |
504 } | 512 } |
505 | 513 |
506 bool SourceBufferRange::CanSeekTo(DecodeTimestamp timestamp) const { | 514 bool SourceBufferRange::CanSeekTo(DecodeTimestamp timestamp) const { |
507 DecodeTimestamp start_timestamp = | 515 DecodeTimestamp start_timestamp = |
508 std::max(DecodeTimestamp(), GetStartTimestamp() - GetFudgeRoom()); | 516 std::max(DecodeTimestamp(), GetStartTimestamp() - GetFudgeRoom()); |
509 return !keyframe_map_.empty() && start_timestamp <= timestamp && | 517 return !keyframe_map_.empty() && start_timestamp <= timestamp && |
510 timestamp < GetBufferedEndTimestamp(); | 518 timestamp < GetBufferedEndTimestamp(); |
511 } | 519 } |
512 | 520 |
513 bool SourceBufferRange::CompletelyOverlaps( | 521 bool SourceBufferRange::CompletelyOverlaps( |
514 const SourceBufferRange& range) const { | 522 const SourceBufferRange& range) const { |
515 return GetStartTimestamp() <= range.GetStartTimestamp() && | 523 return GetStartTimestamp() <= range.GetStartTimestamp() && |
516 GetEndTimestamp() >= range.GetEndTimestamp(); | 524 GetEndTimestamp() >= range.GetEndTimestamp(); |
517 } | 525 } |
518 | 526 |
519 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const { | 527 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const { |
520 return range.GetStartTimestamp() <= GetEndTimestamp() && | 528 return range.GetStartTimestamp() <= GetEndTimestamp() && |
521 GetEndTimestamp() < range.GetEndTimestamp(); | 529 GetEndTimestamp() < range.GetEndTimestamp(); |
522 } | 530 } |
523 | 531 |
524 DecodeTimestamp SourceBufferRange::GetStartTimestamp() const { | 532 DecodeTimestamp SourceBufferRange::GetStartTimestamp() const { |
525 DCHECK(!buffers_.empty()); | 533 DCHECK(!buffers_.empty()); |
526 DecodeTimestamp start_timestamp = media_segment_start_time_; | 534 DecodeTimestamp start_timestamp = range_start_time_; |
527 if (start_timestamp == kNoDecodeTimestamp()) | 535 if (start_timestamp == kNoDecodeTimestamp()) |
528 start_timestamp = buffers_.front()->GetDecodeTimestamp(); | 536 start_timestamp = buffers_.front()->GetDecodeTimestamp(); |
529 return start_timestamp; | 537 return start_timestamp; |
530 } | 538 } |
531 | 539 |
532 DecodeTimestamp SourceBufferRange::GetEndTimestamp() const { | 540 DecodeTimestamp SourceBufferRange::GetEndTimestamp() const { |
533 DCHECK(!buffers_.empty()); | 541 DCHECK(!buffers_.empty()); |
534 return buffers_.back()->GetDecodeTimestamp(); | 542 return buffers_.back()->GetDecodeTimestamp(); |
535 } | 543 } |
536 | 544 |
537 DecodeTimestamp SourceBufferRange::GetBufferedEndTimestamp() const { | 545 DecodeTimestamp SourceBufferRange::GetBufferedEndTimestamp() const { |
538 DCHECK(!buffers_.empty()); | 546 DCHECK(!buffers_.empty()); |
539 base::TimeDelta duration = buffers_.back()->duration(); | 547 base::TimeDelta duration = buffers_.back()->duration(); |
540 if (duration == kNoTimestamp() || duration == base::TimeDelta()) | 548 if (duration == kNoTimestamp() || duration == base::TimeDelta()) |
541 duration = GetApproximateDuration(); | 549 duration = GetApproximateDuration(); |
542 return GetEndTimestamp() + duration; | 550 return GetEndTimestamp() + duration; |
543 } | 551 } |
544 | 552 |
545 DecodeTimestamp SourceBufferRange::NextKeyframeTimestamp( | 553 DecodeTimestamp SourceBufferRange::NextKeyframeTimestamp( |
546 DecodeTimestamp timestamp) { | 554 DecodeTimestamp timestamp) { |
547 DCHECK(!keyframe_map_.empty()); | 555 DCHECK(!keyframe_map_.empty()); |
548 | 556 |
549 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) | 557 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) |
550 return kNoDecodeTimestamp(); | 558 return kNoDecodeTimestamp(); |
551 | 559 |
552 KeyframeMap::iterator itr = GetFirstKeyframeAt(timestamp, false); | 560 KeyframeMap::iterator itr = GetFirstKeyframeAt(timestamp, false); |
553 if (itr == keyframe_map_.end()) | 561 if (itr == keyframe_map_.end()) |
554 return kNoDecodeTimestamp(); | 562 return kNoDecodeTimestamp(); |
555 | 563 |
556 // If the timestamp is inside the gap between the start of the media | 564 // If the timestamp is inside the gap between the start of the coded frame |
557 // segment and the first buffer, then just pretend there is a | 565 // group and the first buffer, then just pretend there is a keyframe at the |
chcunningham
2016/02/12 22:46:40
Why do we pretend? Why not return the actual times
wolenetz
2016/02/24 00:34:46
I think it simplifies seeking by SBS. (See FindNew
chcunningham
2016/02/24 19:06:26
Ack. SBR and SBS seem annoyingly aware/reliant of/
| |
558 // keyframe at the specified timestamp. | 566 // specified timestamp. |
559 if (itr == keyframe_map_.begin() && | 567 if (itr == keyframe_map_.begin() && timestamp > range_start_time_ && |
560 timestamp > media_segment_start_time_ && | |
561 timestamp < itr->first) { | 568 timestamp < itr->first) { |
562 return timestamp; | 569 return timestamp; |
563 } | 570 } |
564 | 571 |
565 return itr->first; | 572 return itr->first; |
566 } | 573 } |
567 | 574 |
568 DecodeTimestamp SourceBufferRange::KeyframeBeforeTimestamp( | 575 DecodeTimestamp SourceBufferRange::KeyframeBeforeTimestamp( |
569 DecodeTimestamp timestamp) { | 576 DecodeTimestamp timestamp) { |
570 DCHECK(!keyframe_map_.empty()); | 577 DCHECK(!keyframe_map_.empty()); |
571 | 578 |
572 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) | 579 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) |
573 return kNoDecodeTimestamp(); | 580 return kNoDecodeTimestamp(); |
574 | 581 |
575 return GetFirstKeyframeAtOrBefore(timestamp)->first; | 582 return GetFirstKeyframeAtOrBefore(timestamp)->first; |
576 } | 583 } |
577 | 584 |
578 bool SourceBufferRange::IsNextInSequence( | 585 bool SourceBufferRange::IsNextInSequence(DecodeTimestamp timestamp) const { |
579 DecodeTimestamp timestamp, bool is_key_frame) const { | |
580 DecodeTimestamp end = buffers_.back()->GetDecodeTimestamp(); | 586 DecodeTimestamp end = buffers_.back()->GetDecodeTimestamp(); |
581 if (end < timestamp && | 587 return (end == timestamp || |
582 (gap_policy_ == ALLOW_GAPS || | 588 (end < timestamp && |
583 timestamp <= end + GetFudgeRoom())) { | 589 (gap_policy_ == ALLOW_GAPS || timestamp <= end + GetFudgeRoom()))); |
584 return true; | |
585 } | |
586 | |
587 return timestamp == end && AllowSameTimestamp( | |
588 buffers_.back()->is_key_frame(), is_key_frame); | |
589 } | 590 } |
590 | 591 |
591 base::TimeDelta SourceBufferRange::GetFudgeRoom() const { | 592 base::TimeDelta SourceBufferRange::GetFudgeRoom() const { |
592 // Because we do not know exactly when is the next timestamp, any buffer | 593 // Because we do not know exactly when is the next timestamp, any buffer |
593 // that starts within 2x the approximate duration of a buffer is considered | 594 // that starts within 2x the approximate duration of a buffer is considered |
594 // within this range. | 595 // within this range. |
595 return 2 * GetApproximateDuration(); | 596 return 2 * GetApproximateDuration(); |
596 } | 597 } |
597 | 598 |
598 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { | 599 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { |
(...skipping 27 matching lines...) Expand all Loading... | |
626 } | 627 } |
627 | 628 |
628 if (buffer->timestamp() + buffer->duration() <= start.ToPresentationTime()) | 629 if (buffer->timestamp() + buffer->duration() <= start.ToPresentationTime()) |
629 continue; | 630 continue; |
630 buffers->push_back(buffer); | 631 buffers->push_back(buffer); |
631 } | 632 } |
632 return previous_size < buffers->size(); | 633 return previous_size < buffers->size(); |
633 } | 634 } |
634 | 635 |
635 } // namespace media | 636 } // namespace media |
OLD | NEW |