Commit 345657b7 authored by wolenetz's avatar wolenetz Committed by Commit bot

MSE: More cleanly handle stall resolution edge cases

Refactors SourceBufferStream::FindNewSelectedRangeSeekTimestamp() to be more
readable and to handle a few edge cases when the last read position has been
removed and new buffers are appended. Includes new tests for the edge cases.

BUG=140875

Review URL: https://codereview.chromium.org/1898373002

Cr-Commit-Position: refs/heads/master@{#388582}
parent 0fde1fd3
......@@ -1600,68 +1600,33 @@ DecodeTimestamp SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
RangeList::iterator itr = ranges_.begin();
// When checking a range to see if it has or begins soon enough after
// |start_timestamp|, use the fudge room to determine "soon enough".
DecodeTimestamp start_timestamp_plus_fudge =
start_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
// Multiple ranges could be within the fudge room, because the fudge room is
// dynamic based on max inter-buffer distance seen so far. Optimistically
// check the earliest ones first.
for (; itr != ranges_.end(); ++itr) {
if ((*itr)->GetEndTimestamp() >= start_timestamp) {
DecodeTimestamp range_start = (*itr)->GetStartTimestamp();
if (range_start >= start_timestamp_plus_fudge)
break;
if ((*itr)->GetEndTimestamp() < start_timestamp)
continue;
DecodeTimestamp search_timestamp = start_timestamp;
if (start_timestamp < range_start &&
start_timestamp_plus_fudge >= range_start) {
search_timestamp = range_start;
}
DecodeTimestamp keyframe_timestamp =
(*itr)->NextKeyframeTimestamp(search_timestamp);
if (keyframe_timestamp != kNoDecodeTimestamp())
return keyframe_timestamp;
}
if (itr == ranges_.end()) {
DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
<< " no buffered data for dts=" << start_timestamp.InSecondsF();
return kNoDecodeTimestamp();
}
// First check for a keyframe timestamp >= |start_timestamp|
// in the current range.
DecodeTimestamp keyframe_timestamp =
(*itr)->NextKeyframeTimestamp(start_timestamp);
if (keyframe_timestamp != kNoDecodeTimestamp())
return keyframe_timestamp;
// If a keyframe was not found then look for a keyframe that is
// "close enough" in the current or next range.
DecodeTimestamp end_timestamp =
start_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
DCHECK(start_timestamp < end_timestamp);
// Make sure the current range doesn't start beyond |end_timestamp|.
if ((*itr)->GetStartTimestamp() >= end_timestamp)
return kNoDecodeTimestamp();
keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
// Check to see if the keyframe is within the acceptable range
// (|start_timestamp|, |end_timestamp|].
if (keyframe_timestamp != kNoDecodeTimestamp() &&
start_timestamp < keyframe_timestamp &&
keyframe_timestamp <= end_timestamp) {
return keyframe_timestamp;
}
// If |end_timestamp| is within this range, then no other checks are
// necessary.
if (end_timestamp <= (*itr)->GetEndTimestamp())
return kNoDecodeTimestamp();
// Move on to the next range.
++itr;
// Return early if the next range does not contain |end_timestamp|.
if (itr == ranges_.end() || (*itr)->GetStartTimestamp() >= end_timestamp)
return kNoDecodeTimestamp();
keyframe_timestamp = (*itr)->KeyframeBeforeTimestamp(end_timestamp);
// Check to see if the keyframe is within the acceptable range
// (|start_timestamp|, |end_timestamp|].
if (keyframe_timestamp != kNoDecodeTimestamp() &&
start_timestamp < keyframe_timestamp &&
keyframe_timestamp <= end_timestamp) {
return keyframe_timestamp;
}
DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName()
<< " no buffered data for dts=" << start_timestamp.InSecondsF();
return kNoDecodeTimestamp();
}
......
......@@ -3534,6 +3534,76 @@ TEST_F(SourceBufferStreamTest, OverlapSplitAndMergeWhileWaitingForMoreData) {
CheckExpectedBuffers("180K 210");
}
// Verify that a single coded frame at the current read position unblocks the
// read even if the frame is buffered after the previously read position is
// removed.
TEST_F(SourceBufferStreamTest, AfterRemove_SingleFrameRange_Unblocks_Read) {
Seek(0);
NewCodedFrameGroupAppend("0K 30 60 90D30");
CheckExpectedRangesByTimestamp("{ [0,120) }");
CheckExpectedBuffers("0K 30 60 90");
CheckNoNextBuffer();
RemoveInMs(0, 120, 120);
CheckExpectedRangesByTimestamp("{ }");
NewCodedFrameGroupAppend("120D30K");
CheckExpectedRangesByTimestamp("{ [120,150) }");
CheckExpectedBuffers("120K");
CheckNoNextBuffer();
}
// Verify that multiple short (relative to max-inter-buffer-distance * 2) coded
// frames at the current read position unblock the read even if the frames are
// buffered after the previously read position is removed.
TEST_F(SourceBufferStreamTest, AfterRemove_TinyFrames_Unblock_Read_1) {
Seek(0);
NewCodedFrameGroupAppend("0K 30 60 90D30");
CheckExpectedRangesByTimestamp("{ [0,120) }");
CheckExpectedBuffers("0K 30 60 90");
CheckNoNextBuffer();
RemoveInMs(0, 120, 120);
CheckExpectedRangesByTimestamp("{ }");
NewCodedFrameGroupAppend("120D1K 121D1");
CheckExpectedRangesByTimestamp("{ [120,122) }");
CheckExpectedBuffers("120K 121");
CheckNoNextBuffer();
}
// Verify that multiple short (relative to max-inter-buffer-distance * 2) coded
// frames starting at the fudge room boundary unblock the read even if the
// frames are buffered after the previously read position is removed.
TEST_F(SourceBufferStreamTest, AfterRemove_TinyFrames_Unblock_Read_2) {
Seek(0);
NewCodedFrameGroupAppend("0K 30 60 90D30");
CheckExpectedRangesByTimestamp("{ [0,120) }");
CheckExpectedBuffers("0K 30 60 90");
CheckNoNextBuffer();
RemoveInMs(0, 120, 120);
CheckExpectedRangesByTimestamp("{ }");
NewCodedFrameGroupAppend("150D1K 151D1");
CheckExpectedRangesByTimestamp("{ [150,152) }");
CheckExpectedBuffers("150K 151");
CheckNoNextBuffer();
}
// Verify that coded frames starting after the fudge room boundary do not
// unblock the read when buffered after the previously read position is removed.
TEST_F(SourceBufferStreamTest, AfterRemove_BeyondFudge_Stalled) {
Seek(0);
NewCodedFrameGroupAppend("0K 30 60 90D30");
CheckExpectedRangesByTimestamp("{ [0,120) }");
CheckExpectedBuffers("0K 30 60 90");
CheckNoNextBuffer();
RemoveInMs(0, 120, 120);
CheckExpectedRangesByTimestamp("{ }");
NewCodedFrameGroupAppend("151D1K 152D1");
CheckExpectedRangesByTimestamp("{ [151,153) }");
CheckNoNextBuffer();
}
// Verify that non-keyframes with the same timestamp in the same
// append are handled correctly.
TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment