Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(644)

Side by Side Diff: media/filters/source_buffer_range.cc

Issue 1670033002: Reland: MSE: Relax the 'media segment must begin with keyframe' requirement (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase plus handling item #7 from CL description Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698