This source file includes following definitions.
- SetMemoryLimit
- SetStreamInfo
- SetTextStream
- SetAudioStream
- NewSegmentAppend
- NewSegmentAppend
- NewSegmentAppend_OffsetFirstBuffer
- NewSegmentAppend_ExpectFailure
- AppendBuffers
- AppendBuffers
- NewSegmentAppend
- NewSegmentAppend
- AppendBuffers
- NewSegmentAppendOneByOne
- AppendBuffersOneByOne
- NewSegmentAppend_ExpectFailure
- AppendBuffers_ExpectFailure
- Seek
- SeekToTimestamp
- RemoveInMs
- Remove
- GetRemovalRangeInMs
- CheckExpectedRanges
- CheckExpectedRangesByTimestamp
- CheckExpectedBuffers
- CheckExpectedBuffers
- CheckExpectedBuffers
- CheckExpectedBuffers
- CheckExpectedBuffers
- CheckExpectedBuffers
- CheckNoNextBuffer
- CheckVideoConfig
- log_cb
- frame_duration
- ConvertToFrameDuration
- AppendBuffers
- StringToBufferQueue
- AppendBuffers
- DebugMediaLog
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "media/filters/source_buffer_stream.h"
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "media/base/data_buffer.h"
#include "media/base/media_log.h"
#include "media/base/test_helpers.h"
#include "media/base/text_track_config.h"
#include "media/filters/webvtt_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
typedef StreamParser::BufferQueue BufferQueue;
static const int kDefaultFramesPerSecond = 30;
static const int kDefaultKeyframesPerSecond = 6;
static const uint8 kDataA = 0x11;
static const uint8 kDataB = 0x33;
static const int kDataSize = 1;
class SourceBufferStreamTest : public testing::Test {
protected:
SourceBufferStreamTest()
: accurate_durations_(false) {
video_config_ = TestVideoConfig::Normal();
SetStreamInfo(kDefaultFramesPerSecond, kDefaultKeyframesPerSecond);
stream_.reset(new SourceBufferStream(video_config_, log_cb(), true));
}
void SetMemoryLimit(int buffers_of_data) {
stream_->set_memory_limit_for_testing(buffers_of_data * kDataSize);
}
void SetStreamInfo(int frames_per_second, int keyframes_per_second) {
frames_per_second_ = frames_per_second;
keyframes_per_second_ = keyframes_per_second;
frame_duration_ = ConvertToFrameDuration(frames_per_second);
}
void SetTextStream() {
video_config_ = TestVideoConfig::Invalid();
TextTrackConfig config(kTextSubtitles, "", "", "");
stream_.reset(new SourceBufferStream(config, LogCB(), true));
SetStreamInfo(2, 2);
}
void SetAudioStream() {
video_config_ = TestVideoConfig::Invalid();
accurate_durations_ = true;
AudioDecoderConfig config(kCodecVorbis,
kSampleFormatPlanarF32,
CHANNEL_LAYOUT_STEREO,
1000,
NULL,
0,
false);
stream_.reset(new SourceBufferStream(config, LogCB(), true));
SetStreamInfo(500, 500);
}
void NewSegmentAppend(int starting_position, int number_of_buffers) {
AppendBuffers(starting_position, number_of_buffers, true,
base::TimeDelta(), true, &kDataA, kDataSize);
}
void NewSegmentAppend(int starting_position, int number_of_buffers,
const uint8* data) {
AppendBuffers(starting_position, number_of_buffers, true,
base::TimeDelta(), true, data, kDataSize);
}
void NewSegmentAppend_OffsetFirstBuffer(
int starting_position, int number_of_buffers,
base::TimeDelta first_buffer_offset) {
AppendBuffers(starting_position, number_of_buffers, true,
first_buffer_offset, true, &kDataA, kDataSize);
}
void NewSegmentAppend_ExpectFailure(
int starting_position, int number_of_buffers) {
AppendBuffers(starting_position, number_of_buffers, true,
base::TimeDelta(), false, &kDataA, kDataSize);
}
void AppendBuffers(int starting_position, int number_of_buffers) {
AppendBuffers(starting_position, number_of_buffers, false,
base::TimeDelta(), true, &kDataA, kDataSize);
}
void AppendBuffers(int starting_position, int number_of_buffers,
const uint8* data) {
AppendBuffers(starting_position, number_of_buffers, false,
base::TimeDelta(), true, data, kDataSize);
}
void NewSegmentAppend(const std::string& buffers_to_append) {
AppendBuffers(buffers_to_append, true, kNoTimestamp(), false, true);
}
void NewSegmentAppend(base::TimeDelta start_timestamp,
const std::string& buffers_to_append) {
AppendBuffers(buffers_to_append, true, start_timestamp, false, true);
}
void AppendBuffers(const std::string& buffers_to_append) {
AppendBuffers(buffers_to_append, false, kNoTimestamp(), false, true);
}
void NewSegmentAppendOneByOne(const std::string& buffers_to_append) {
AppendBuffers(buffers_to_append, true, kNoTimestamp(), true, true);
}
void AppendBuffersOneByOne(const std::string& buffers_to_append) {
AppendBuffers(buffers_to_append, false, kNoTimestamp(), true, true);
}
void NewSegmentAppend_ExpectFailure(const std::string& buffers_to_append) {
AppendBuffers(buffers_to_append, true, kNoTimestamp(), false, false);
}
void AppendBuffers_ExpectFailure(const std::string& buffers_to_append) {
AppendBuffers(buffers_to_append, false, kNoTimestamp(), false, false);
}
void Seek(int position) {
stream_->Seek(position * frame_duration_);
}
void SeekToTimestamp(base::TimeDelta timestamp) {
stream_->Seek(timestamp);
}
void RemoveInMs(int start, int end, int duration) {
Remove(base::TimeDelta::FromMilliseconds(start),
base::TimeDelta::FromMilliseconds(end),
base::TimeDelta::FromMilliseconds(duration));
}
void Remove(base::TimeDelta start, base::TimeDelta end,
base::TimeDelta duration) {
stream_->Remove(start, end, duration);
}
int GetRemovalRangeInMs(int start, int end, int bytes_to_free,
int* removal_end) {
base::TimeDelta removal_end_timestamp =
base::TimeDelta::FromMilliseconds(*removal_end);
int bytes_removed = stream_->GetRemovalRange(
base::TimeDelta::FromMilliseconds(start),
base::TimeDelta::FromMilliseconds(end), bytes_to_free,
&removal_end_timestamp);
*removal_end = removal_end_timestamp.InMilliseconds();
return bytes_removed;
}
void CheckExpectedRanges(const std::string& expected) {
Ranges<base::TimeDelta> r = stream_->GetBufferedTime();
std::stringstream ss;
ss << "{ ";
for (size_t i = 0; i < r.size(); ++i) {
int64 start = (r.start(i) / frame_duration_);
int64 end = (r.end(i) / frame_duration_) - 1;
ss << "[" << start << "," << end << ") ";
}
ss << "}";
EXPECT_EQ(expected, ss.str());
}
void CheckExpectedRangesByTimestamp(const std::string& expected) {
Ranges<base::TimeDelta> r = stream_->GetBufferedTime();
std::stringstream ss;
ss << "{ ";
for (size_t i = 0; i < r.size(); ++i) {
int64 start = r.start(i).InMilliseconds();
int64 end = r.end(i).InMilliseconds();
ss << "[" << start << "," << end << ") ";
}
ss << "}";
EXPECT_EQ(expected, ss.str());
}
void CheckExpectedBuffers(
int starting_position, int ending_position) {
CheckExpectedBuffers(starting_position, ending_position, false, NULL, 0);
}
void CheckExpectedBuffers(
int starting_position, int ending_position, bool expect_keyframe) {
CheckExpectedBuffers(starting_position, ending_position, expect_keyframe,
NULL, 0);
}
void CheckExpectedBuffers(
int starting_position, int ending_position, const uint8* data) {
CheckExpectedBuffers(starting_position, ending_position, false, data,
kDataSize);
}
void CheckExpectedBuffers(
int starting_position, int ending_position, const uint8* data,
bool expect_keyframe) {
CheckExpectedBuffers(starting_position, ending_position, expect_keyframe,
data, kDataSize);
}
void CheckExpectedBuffers(
int starting_position, int ending_position, bool expect_keyframe,
const uint8* expected_data, int expected_size) {
int current_position = starting_position;
for (; current_position <= ending_position; current_position++) {
scoped_refptr<StreamParserBuffer> buffer;
SourceBufferStream::Status status = stream_->GetNextBuffer(&buffer);
EXPECT_NE(status, SourceBufferStream::kConfigChange);
if (status != SourceBufferStream::kSuccess)
break;
if (expect_keyframe && current_position == starting_position)
EXPECT_TRUE(buffer->IsKeyframe());
if (expected_data) {
const uint8* actual_data = buffer->data();
const int actual_size = buffer->data_size();
EXPECT_EQ(expected_size, actual_size);
for (int i = 0; i < std::min(actual_size, expected_size); i++) {
EXPECT_EQ(expected_data[i], actual_data[i]);
}
}
EXPECT_EQ(buffer->GetDecodeTimestamp() / frame_duration_,
current_position);
}
EXPECT_EQ(ending_position + 1, current_position);
}
void CheckExpectedBuffers(const std::string& expected) {
std::vector<std::string> timestamps;
base::SplitString(expected, ' ', ×tamps);
std::stringstream ss;
const SourceBufferStream::Type type = stream_->GetType();
for (size_t i = 0; i < timestamps.size(); i++) {
scoped_refptr<StreamParserBuffer> buffer;
SourceBufferStream::Status status = stream_->GetNextBuffer(&buffer);
if (i > 0)
ss << " ";
if (status == SourceBufferStream::kConfigChange) {
switch (type) {
case SourceBufferStream::kVideo:
stream_->GetCurrentVideoDecoderConfig();
break;
case SourceBufferStream::kAudio:
stream_->GetCurrentAudioDecoderConfig();
break;
case SourceBufferStream::kText:
stream_->GetCurrentTextTrackConfig();
break;
}
if (timestamps[i] == "C")
EXPECT_EQ(SourceBufferStream::kConfigChange, status);
ss << "C";
continue;
}
EXPECT_EQ(SourceBufferStream::kSuccess, status);
if (status != SourceBufferStream::kSuccess)
break;
ss << buffer->GetDecodeTimestamp().InMilliseconds();
if (buffer->IsKeyframe())
ss << "K";
}
EXPECT_EQ(expected, ss.str());
}
void CheckNoNextBuffer() {
scoped_refptr<StreamParserBuffer> buffer;
EXPECT_EQ(SourceBufferStream::kNeedBuffer, stream_->GetNextBuffer(&buffer));
}
void CheckVideoConfig(const VideoDecoderConfig& config) {
const VideoDecoderConfig& actual = stream_->GetCurrentVideoDecoderConfig();
EXPECT_TRUE(actual.Matches(config))
<< "Expected: " << config.AsHumanReadableString()
<< "\nActual: " << actual.AsHumanReadableString();
}
const LogCB log_cb() {
return base::Bind(&SourceBufferStreamTest::DebugMediaLog,
base::Unretained(this));
}
base::TimeDelta frame_duration() const { return frame_duration_; }
scoped_ptr<SourceBufferStream> stream_;
VideoDecoderConfig video_config_;
private:
base::TimeDelta ConvertToFrameDuration(int frames_per_second) {
return base::TimeDelta::FromMicroseconds(
base::Time::kMicrosecondsPerSecond / frames_per_second);
}
void AppendBuffers(int starting_position,
int number_of_buffers,
bool begin_media_segment,
base::TimeDelta first_buffer_offset,
bool expect_success,
const uint8* data,
int size) {
if (begin_media_segment)
stream_->OnNewMediaSegment(starting_position * frame_duration_);
int keyframe_interval = frames_per_second_ / keyframes_per_second_;
BufferQueue queue;
for (int i = 0; i < number_of_buffers; i++) {
int position = starting_position + i;
bool is_keyframe = position % keyframe_interval == 0;
scoped_refptr<StreamParserBuffer> buffer =
StreamParserBuffer::CopyFrom(data, size, is_keyframe,
DemuxerStream::AUDIO, 0);
base::TimeDelta timestamp = frame_duration_ * position;
if (i == 0)
timestamp += first_buffer_offset;
buffer->SetDecodeTimestamp(timestamp);
base::TimeDelta presentation_timestamp;
if (is_keyframe) {
presentation_timestamp = timestamp;
} else if ((position - 1) % keyframe_interval == 0) {
presentation_timestamp =
(timestamp + frame_duration_ * (keyframe_interval - 2));
} else {
presentation_timestamp = timestamp - frame_duration_;
}
buffer->set_timestamp(presentation_timestamp);
if (accurate_durations_)
buffer->set_duration(frame_duration_);
queue.push_back(buffer);
}
if (!queue.empty())
EXPECT_EQ(expect_success, stream_->Append(queue));
}
BufferQueue StringToBufferQueue(const std::string& buffers_to_append) {
std::vector<std::string> timestamps;
base::SplitString(buffers_to_append, ' ', ×tamps);
CHECK_GT(timestamps.size(), 0u);
bool splice_frame = false;
size_t splice_config_id = stream_->append_config_index_;
BufferQueue pre_splice_buffers;
BufferQueue buffers;
for (size_t i = 0; i < timestamps.size(); i++) {
bool is_keyframe = false;
bool last_splice_frame = false;
if (StartsWithASCII(timestamps[i], "S(", true)) {
CHECK(!splice_frame);
splice_frame = true;
timestamps[i] = timestamps[i].substr(2, timestamps[i].length());
}
if (splice_frame && EndsWith(timestamps[i], ")", true)) {
splice_frame = false;
last_splice_frame = true;
timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1);
}
if (splice_frame && EndsWith(timestamps[i], "C", true)) {
splice_config_id++;
CHECK(splice_config_id < stream_->audio_configs_.size() ||
splice_config_id < stream_->video_configs_.size());
timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1);
}
if (EndsWith(timestamps[i], "K", true)) {
is_keyframe = true;
timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1);
}
int time_in_ms;
CHECK(base::StringToInt(timestamps[i], &time_in_ms));
scoped_refptr<StreamParserBuffer> buffer =
StreamParserBuffer::CopyFrom(&kDataA, kDataSize, is_keyframe,
DemuxerStream::AUDIO, 0);
base::TimeDelta timestamp =
base::TimeDelta::FromMilliseconds(time_in_ms);
buffer->set_timestamp(timestamp);
if (accurate_durations_)
buffer->set_duration(frame_duration_);
buffer->SetDecodeTimestamp(timestamp);
if (splice_frame) {
if (!pre_splice_buffers.empty()) {
CHECK_GT(
timestamp.InMicroseconds(),
pre_splice_buffers.back()->GetDecodeTimestamp().InMicroseconds());
}
buffer->SetConfigId(splice_config_id);
pre_splice_buffers.push_back(buffer);
continue;
}
if (last_splice_frame) {
CHECK(!pre_splice_buffers.empty());
buffer->ConvertToSpliceBuffer(pre_splice_buffers);
pre_splice_buffers.clear();
}
buffers.push_back(buffer);
}
return buffers;
}
void AppendBuffers(const std::string& buffers_to_append,
bool start_new_segment,
base::TimeDelta segment_start_timestamp,
bool one_by_one,
bool expect_success) {
BufferQueue buffers = StringToBufferQueue(buffers_to_append);
if (start_new_segment) {
base::TimeDelta start_timestamp = segment_start_timestamp;
if (start_timestamp == kNoTimestamp())
start_timestamp = buffers[0]->GetDecodeTimestamp();
ASSERT_TRUE(start_timestamp <= buffers[0]->GetDecodeTimestamp());
stream_->OnNewMediaSegment(start_timestamp);
}
if (!one_by_one) {
EXPECT_EQ(expect_success, stream_->Append(buffers));
return;
}
for (size_t i = 0; i < buffers.size(); i++) {
BufferQueue wrapper;
wrapper.push_back(buffers[i]);
EXPECT_TRUE(stream_->Append(wrapper));
}
}
void DebugMediaLog(const std::string& log) {
DVLOG(1) << log;
}
int frames_per_second_;
int keyframes_per_second_;
base::TimeDelta frame_duration_;
bool accurate_durations_;
DISALLOW_COPY_AND_ASSIGN(SourceBufferStreamTest);
};
TEST_F(SourceBufferStreamTest, Append_SingleRange) {
NewSegmentAppend(0, 15);
CheckExpectedRanges("{ [0,14) }");
Seek(0);
CheckExpectedBuffers(0, 14);
}
TEST_F(SourceBufferStreamTest, Append_SingleRange_OneBufferAtATime) {
NewSegmentAppend(0, 1);
for (int i = 1; i < 15; i++)
AppendBuffers(i, 1);
CheckExpectedRanges("{ [0,14) }");
Seek(0);
CheckExpectedBuffers(0, 14);
}
TEST_F(SourceBufferStreamTest, Append_DisjointRanges) {
NewSegmentAppend(0, 5);
NewSegmentAppend(15, 10);
CheckExpectedRanges("{ [0,4) [15,24) }");
Seek(0);
CheckExpectedBuffers(0, 4);
Seek(15);
CheckExpectedBuffers(15, 24);
}
TEST_F(SourceBufferStreamTest, Append_AdjacentRanges) {
NewSegmentAppend(0, 10);
NewSegmentAppend(15, 11);
NewSegmentAppend(10, 5);
CheckExpectedRanges("{ [0,25) }");
Seek(0);
CheckExpectedBuffers(0, 25);
}
TEST_F(SourceBufferStreamTest, Append_DoesNotBeginWithKeyframe) {
NewSegmentAppend_ExpectFailure(3, 2);
NewSegmentAppend(5, 10);
CheckExpectedRanges("{ [5,14) }");
Seek(5);
CheckExpectedBuffers(5, 14);
NewSegmentAppend_ExpectFailure(17, 3);
CheckExpectedRanges("{ [5,14) }");
Seek(5);
CheckExpectedBuffers(5, 14);
}
TEST_F(SourceBufferStreamTest, Append_DoesNotBeginWithKeyframe_Adjacent) {
NewSegmentAppend(0, 8);
NewSegmentAppend_ExpectFailure(8, 2);
CheckExpectedRanges("{ [0,7) }");
Seek(0);
CheckExpectedBuffers(0, 7);
}
TEST_F(SourceBufferStreamTest, Complete_Overlap) {
NewSegmentAppend(5, 5);
NewSegmentAppend(0, 15);
CheckExpectedRanges("{ [0,14) }");
Seek(0);
CheckExpectedBuffers(0, 14);
}
TEST_F(SourceBufferStreamTest,
Complete_Overlap_AfterSegmentTimestampAndBeforeFirstBufferTimestamp) {
NewSegmentAppend(base::TimeDelta::FromMilliseconds(0), "30K 60K 90K 120K");
CheckExpectedRangesByTimestamp("{ [0,150) }");
NewSegmentAppend("20K 50K 80K 110K");
CheckExpectedRangesByTimestamp("{ [20,150) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(20));
CheckExpectedBuffers("20K 50K 80K 110K 120K");
}
TEST_F(SourceBufferStreamTest, Complete_Overlap_EdgeCase) {
SetStreamInfo(30, 30);
NewSegmentAppend(6, 6);
NewSegmentAppend(5, 8);
CheckExpectedRanges("{ [5,12) }");
Seek(5);
CheckExpectedBuffers(5, 12);
}
TEST_F(SourceBufferStreamTest, Start_Overlap) {
NewSegmentAppend(5, 5);
NewSegmentAppend(10, 6);
CheckExpectedRanges("{ [5,15) }");
Seek(5);
CheckExpectedBuffers(5, 15);
}
TEST_F(SourceBufferStreamTest, End_Overlap) {
NewSegmentAppend(10, 10);
NewSegmentAppend(5, 10);
CheckExpectedRanges("{ [5,19) }");
Seek(5);
CheckExpectedBuffers(5, 19);
}
TEST_F(SourceBufferStreamTest, End_Overlap_Several) {
NewSegmentAppend(10, 10);
NewSegmentAppend(5, 8);
CheckExpectedRanges("{ [5,12) [15,19) }");
Seek(5);
CheckExpectedBuffers(5, 12);
CheckNoNextBuffer();
Seek(19);
CheckExpectedBuffers(15, 19);
}
TEST_F(SourceBufferStreamTest, End_Overlap_SingleBuffer) {
SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
NewSegmentAppend("0K 30 60 90 120K 150");
CheckExpectedRangesByTimestamp("{ [0,180) }");
NewSegmentAppend("0K");
CheckExpectedRangesByTimestamp("{ [0,30) [120,180) }");
CheckExpectedBuffers("0K");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Complete_Overlap_Several) {
NewSegmentAppend(5, 2);
NewSegmentAppend(10, 2);
NewSegmentAppend(15, 2);
CheckExpectedRanges("{ [5,6) [10,11) [15,16) }");
NewSegmentAppend(0, 20);
CheckExpectedRanges("{ [0,19) }");
Seek(0);
CheckExpectedBuffers(0, 19);
}
TEST_F(SourceBufferStreamTest, Complete_Overlap_Several_Then_Merge) {
NewSegmentAppend(5, 2);
NewSegmentAppend(10, 2);
NewSegmentAppend(15, 2);
NewSegmentAppend(20, 2);
NewSegmentAppend(0, 20);
CheckExpectedRanges("{ [0,21) }");
Seek(0);
CheckExpectedBuffers(0, 21);
}
TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected) {
NewSegmentAppend(5, 10, &kDataA);
Seek(5);
NewSegmentAppend(5, 10, &kDataB);
CheckExpectedRanges("{ [5,14) }");
CheckExpectedBuffers(5, 14, &kDataB);
}
TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected_TrackBuffer) {
NewSegmentAppend(5, 10, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 5, &kDataA);
NewSegmentAppend(0, 20, &kDataB);
CheckExpectedRanges("{ [0,19) }");
CheckExpectedBuffers(6, 9, &kDataA);
CheckExpectedBuffers(10, 10, &kDataB, true);
CheckExpectedBuffers(11, 19, &kDataB);
Seek(0);
CheckExpectedBuffers(0, 19, &kDataB);
CheckExpectedRanges("{ [0,19) }");
}
TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected_EdgeCase) {
NewSegmentAppend(5, 10, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 5, &kDataA);
NewSegmentAppend(5, 10, &kDataB);
CheckExpectedRanges("{ [5,14) }");
CheckExpectedBuffers(6, 9, &kDataA);
CheckExpectedBuffers(10, 10, &kDataB, true);
CheckExpectedBuffers(11, 14, &kDataB);
Seek(5);
CheckExpectedBuffers(5, 14, &kDataB);
CheckExpectedRanges("{ [5,14) }");
}
TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected_Multiple) {
static const uint8 kDataC = 0x55;
static const uint8 kDataD = 0x77;
NewSegmentAppend(5, 5, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 5, &kDataA);
NewSegmentAppend(5, 5, &kDataB);
NewSegmentAppend(5, 5, &kDataC);
NewSegmentAppend(10, 5, &kDataC);
NewSegmentAppend(5, 10, &kDataD);
CheckExpectedBuffers(6, 9, &kDataA);
CheckExpectedBuffers(10, 14, &kDataD);
CheckNoNextBuffer();
Seek(5);
CheckExpectedBuffers(5, 14, &kDataD);
}
TEST_F(SourceBufferStreamTest, Start_Overlap_Selected) {
NewSegmentAppend(0, 10, &kDataA);
Seek(5);
NewSegmentAppend(5, 10, &kDataB);
CheckExpectedRanges("{ [0,14) }");
CheckExpectedBuffers(5, 14, &kDataB);
Seek(0);
CheckExpectedBuffers(0, 4, &kDataA);
CheckExpectedBuffers(5, 14, &kDataB);
}
TEST_F(SourceBufferStreamTest, Start_Overlap_Selected_TrackBuffer) {
NewSegmentAppend(0, 15, &kDataA);
Seek(10);
CheckExpectedBuffers(10, 10, &kDataA);
NewSegmentAppend(10, 10, &kDataB);
CheckExpectedRanges("{ [0,19) }");
CheckExpectedBuffers(11, 14, &kDataA);
CheckExpectedBuffers(15, 15, &kDataB, true);
CheckExpectedBuffers(16, 19, &kDataB);
Seek(0);
CheckExpectedBuffers(0, 9, &kDataA);
CheckExpectedBuffers(10, 19, &kDataB);
CheckExpectedRanges("{ [0,19) }");
}
TEST_F(SourceBufferStreamTest, Start_Overlap_Selected_EdgeCase) {
NewSegmentAppend(5, 10, &kDataA);
Seek(10);
CheckExpectedBuffers(10, 10, &kDataA);
NewSegmentAppend(10, 5, &kDataB);
CheckExpectedBuffers(11, 14, &kDataA);
CheckNoNextBuffer();
NewSegmentAppend(15, 5, &kDataB);
CheckExpectedBuffers(15, 19, &kDataB);
Seek(5);
CheckExpectedBuffers(5, 9, &kDataA);
CheckExpectedBuffers(10, 19, &kDataB);
CheckExpectedRanges("{ [5,19) }");
}
TEST_F(SourceBufferStreamTest, End_Overlap_Selected) {
NewSegmentAppend(5, 10, &kDataA);
Seek(5);
NewSegmentAppend(0, 10, &kDataB);
CheckExpectedRanges("{ [0,14) }");
CheckExpectedBuffers(5, 9, &kDataB);
Seek(0);
CheckExpectedBuffers(0, 9, &kDataB);
CheckExpectedBuffers(10, 14, &kDataA);
}
TEST_F(SourceBufferStreamTest, End_Overlap_Selected_AfterEndOfNew_1) {
NewSegmentAppend(5, 10, &kDataA);
Seek(10);
CheckExpectedBuffers(10, 12, &kDataA);
NewSegmentAppend(0, 10, &kDataB);
CheckExpectedRanges("{ [0,14) }");
CheckExpectedBuffers(13, 14, &kDataA);
Seek(0);
CheckExpectedBuffers(0, 9, &kDataB);
CheckExpectedBuffers(10, 14, &kDataA);
}
TEST_F(SourceBufferStreamTest, End_Overlap_Selected_AfterEndOfNew_2) {
NewSegmentAppend(5, 10, &kDataA);
Seek(10);
CheckExpectedBuffers(10, 12, &kDataA);
NewSegmentAppend(0, 8, &kDataB);
CheckExpectedRanges("{ [0,7) [10,14) }");
CheckExpectedBuffers(13, 14, &kDataA);
Seek(0);
CheckExpectedBuffers(0, 7, &kDataB);
CheckNoNextBuffer();
Seek(10);
CheckExpectedBuffers(10, 14, &kDataA);
}
TEST_F(SourceBufferStreamTest, End_Overlap_Selected_AfterEndOfNew_3) {
NewSegmentAppend(5, 10, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 7, &kDataA);
NewSegmentAppend(0, 8, &kDataB);
CheckExpectedRanges("{ [0,7) [10,14) }");
CheckExpectedBuffers(8, 9, &kDataA);
CheckExpectedBuffers(10, 10, &kDataA, true);
Seek(0);
CheckExpectedBuffers(0, 7, &kDataB);
Seek(10);
CheckExpectedBuffers(10, 14, &kDataA);
}
TEST_F(SourceBufferStreamTest, End_Overlap_Selected_OverlappedByNew_1) {
NewSegmentAppend(5, 10, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 7, &kDataA);
NewSegmentAppend(0, 10, &kDataB);
CheckExpectedRanges("{ [0,14) }");
CheckExpectedBuffers(8, 9, &kDataA);
CheckExpectedBuffers(10, 10, &kDataA, true);
Seek(0);
CheckExpectedBuffers(0, 9, &kDataB);
CheckExpectedBuffers(10, 14, &kDataA);
}
TEST_F(SourceBufferStreamTest, End_Overlap_Selected_OverlappedByNew_2) {
NewSegmentAppend(5, 10, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 5, &kDataA);
NewSegmentAppend(0, 7, &kDataB);
CheckExpectedRanges("{ [0,6) [10,14) }");
CheckExpectedBuffers(6, 9, &kDataA);
CheckExpectedBuffers(10, 10, &kDataA, true);
Seek(0);
CheckExpectedBuffers(0, 6, &kDataB);
CheckNoNextBuffer();
Seek(10);
CheckExpectedBuffers(10, 14, &kDataA);
}
TEST_F(SourceBufferStreamTest, End_Overlap_Selected_OverlappedByNew_3) {
NewSegmentAppend(5, 15, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 5, &kDataA);
NewSegmentAppend(0, 13, &kDataB);
CheckExpectedRanges("{ [0,12) [15,19) }");
CheckExpectedBuffers(6, 9, &kDataA);
CheckExpectedBuffers(10, 10, &kDataB, true);
Seek(0);
CheckExpectedBuffers(0, 12, &kDataB);
CheckNoNextBuffer();
Seek(15);
CheckExpectedBuffers(15, 19, &kDataA);
}
TEST_F(SourceBufferStreamTest, End_Overlap_Selected_NoKeyframeAfterNew) {
NewSegmentAppend(5, 5, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 5, &kDataA);
NewSegmentAppend(0, 6, &kDataB);
CheckExpectedRanges("{ [0,5) }");
CheckExpectedBuffers(6, 9, &kDataA);
CheckNoNextBuffer();
AppendBuffers(6, 5, &kDataB);
CheckExpectedBuffers(10, 10, &kDataB);
}
TEST_F(SourceBufferStreamTest, End_Overlap_Selected_NoKeyframeAfterNew2) {
NewSegmentAppend(10, 7, &kDataA);
Seek(15);
CheckExpectedBuffers(15, 15, &kDataA);
NewSegmentAppend(5, 11, &kDataB);
CheckExpectedRanges("{ [5,15) }");
NewSegmentAppend(0, 6, &kDataA);
CheckExpectedRanges("{ [0,5) [10,15) }");
CheckExpectedBuffers(16, 16, &kDataA);
CheckNoNextBuffer();
NewSegmentAppend(15, 1, &kDataB);
CheckNoNextBuffer();
for (int i = 16; i <= 19; i++) {
AppendBuffers(i, 1, &kDataB);
CheckNoNextBuffer();
}
AppendBuffers(20, 1, &kDataB);
CheckExpectedBuffers(20, 20, &kDataB, true);
}
TEST_F(SourceBufferStreamTest, End_Overlap_Selected_NoKeyframeAfterNew3) {
NewSegmentAppend(5, 5, &kDataA);
NewSegmentAppend(15, 5, &kDataA);
CheckExpectedRanges("{ [5,9) [15,19) }");
Seek(5);
CheckExpectedBuffers(5, 5, &kDataA);
NewSegmentAppend(0, 6, &kDataB);
CheckExpectedRanges("{ [0,5) [15,19) }");
CheckExpectedBuffers(6, 9, &kDataA);
CheckNoNextBuffer();
AppendBuffers(6, 9, &kDataB);
CheckExpectedRanges("{ [0,19) }");
CheckExpectedBuffers(10, 14, &kDataB);
CheckExpectedBuffers(15, 19, &kDataA);
}
TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_1) {
NewSegmentAppend(0, 15, &kDataA);
Seek(5);
NewSegmentAppend(5, 5, &kDataB);
CheckExpectedRanges("{ [0,14) }");
CheckExpectedBuffers(5, 9, &kDataB);
Seek(0);
CheckExpectedBuffers(0, 4, &kDataA);
CheckExpectedBuffers(5, 9, &kDataB);
CheckExpectedBuffers(10, 14, &kDataA);
}
TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_2) {
NewSegmentAppend(0, 15, &kDataA);
Seek(10);
CheckExpectedBuffers(10, 10, &kDataA);
NewSegmentAppend(5, 5, &kDataB);
CheckExpectedRanges("{ [0,14) }");
CheckExpectedBuffers(11, 14, &kDataA);
Seek(0);
CheckExpectedBuffers(0, 4, &kDataA);
CheckExpectedBuffers(5, 9, &kDataB);
CheckExpectedBuffers(10, 14, &kDataA);
}
TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_3) {
NewSegmentAppend(0, 15, &kDataA);
Seek(0);
CheckExpectedBuffers(0, 1, &kDataA);
NewSegmentAppend(5, 3, &kDataB);
CheckExpectedRanges("{ [0,7) [10,14) }");
CheckExpectedBuffers(2, 4, &kDataA);
CheckExpectedBuffers(5, 7, &kDataB);
Seek(10);
CheckExpectedBuffers(10, 14, &kDataA);
}
TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_4) {
NewSegmentAppend(0, 15, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 7, &kDataA);
NewSegmentAppend(5, 3, &kDataB);
CheckExpectedRanges("{ [0,7) [10,14) }");
CheckExpectedBuffers(8, 9, &kDataA);
CheckExpectedBuffers(10, 10, &kDataA, true);
Seek(0);
CheckExpectedBuffers(0, 4, &kDataA);
CheckExpectedBuffers(5, 7, &kDataB);
Seek(10);
CheckExpectedBuffers(10, 14, &kDataA);
}
TEST_F(SourceBufferStreamTest, Overlap_OneByOne) {
NewSegmentAppendOneByOne("10K 40 70 100 130");
CheckExpectedRangesByTimestamp("{ [10,160) }");
NewSegmentAppend(0, 1, &kDataB);
for (int i = 1; i < 10; i++)
AppendBuffers(i, 1, &kDataB);
Seek(0);
CheckExpectedRanges("{ [0,9) }");
CheckExpectedBuffers(0, 9, &kDataB);
}
TEST_F(SourceBufferStreamTest, Overlap_OneByOne_DeleteGroup) {
NewSegmentAppendOneByOne("10K 40 70 100 130K");
CheckExpectedRangesByTimestamp("{ [10,160) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(130));
NewSegmentAppendOneByOne("0K 120");
CheckExpectedBuffers("130K");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
CheckExpectedBuffers("0K 120 130K");
}
TEST_F(SourceBufferStreamTest, Overlap_OneByOne_BetweenMediaSegments) {
NewSegmentAppendOneByOne("110K 140 170 200 230");
CheckExpectedRangesByTimestamp("{ [110,260) }");
NewSegmentAppendOneByOne("0K 30 60 90");
NewSegmentAppendOneByOne("120K 150 180 210");
CheckExpectedRangesByTimestamp("{ [0,240) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
CheckExpectedBuffers("0K 30 60 90 120K 150 180 210");
}
TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer) {
NewSegmentAppendOneByOne("10K 40 70 100K 125 130K");
CheckExpectedRangesByTimestamp("{ [10,160) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(70));
CheckExpectedBuffers("10K 40");
NewSegmentAppendOneByOne("0K 30 60 90 120K");
CheckExpectedRangesByTimestamp("{ [0,160) }");
CheckExpectedBuffers("70 100K 120K 130K");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
CheckExpectedBuffers("0K 30 60 90 120K 130K");
}
TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer2) {
NewSegmentAppendOneByOne("10K 40 70 100K 125 130K");
CheckExpectedRangesByTimestamp("{ [10,160) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(70));
CheckExpectedBuffers("10K 40");
NewSegmentAppendOneByOne("0K 30 60 90 120K");
CheckExpectedRangesByTimestamp("{ [0,160) }");
NewSegmentAppendOneByOne("110K 130");
CheckExpectedBuffers("70 100K 110K 130");
}
TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer3) {
NewSegmentAppendOneByOne("10K 40 70 100K 125 130K");
CheckExpectedRangesByTimestamp("{ [10,160) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(70));
CheckExpectedBuffers("10K 40");
NewSegmentAppendOneByOne("0K 30 60 90 120K");
CheckExpectedRangesByTimestamp("{ [0,160) }");
NewSegmentAppendOneByOne("50K 80 110 140");
CheckExpectedBuffers("70 100K 120K 130K");
CheckNoNextBuffer();
AppendBuffersOneByOne("150K");
CheckExpectedBuffers("150K");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer4) {
NewSegmentAppendOneByOne("10K 40 70 100K 125 130K");
CheckExpectedRangesByTimestamp("{ [10,160) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(70));
CheckExpectedBuffers("10K 40");
NewSegmentAppendOneByOne("0K 30 60 90 120K");
CheckExpectedRangesByTimestamp("{ [0,160) }");
NewSegmentAppendOneByOne("80K 110 140");
CheckExpectedBuffers("70 80K 110 140");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer5) {
NewSegmentAppendOneByOne("10K 40 70 100K");
CheckExpectedRangesByTimestamp("{ [10,130) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(70));
CheckExpectedBuffers("10K 40");
NewSegmentAppendOneByOne("0K 30 60 90 120");
CheckExpectedRangesByTimestamp("{ [0,150) }");
NewSegmentAppendOneByOne("80K 110 140");
CheckExpectedBuffers("70 80K 110 140");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer6) {
NewSegmentAppendOneByOne("10K 40 70 100K 125 130K");
NewSegmentAppendOneByOne("200K 230");
CheckExpectedRangesByTimestamp("{ [10,160) [200,260) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(70));
CheckExpectedBuffers("10K 40");
NewSegmentAppendOneByOne("0K 30 60 90 120K");
CheckExpectedRangesByTimestamp("{ [0,160) [200,260) }");
CheckExpectedBuffers("70");
NewSegmentAppendOneByOne("260K 290");
CheckExpectedRangesByTimestamp("{ [0,160) [200,320) }");
CheckExpectedBuffers("100K 120K 130K");
CheckNoNextBuffer();
SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
CheckExpectedBuffers("0K 30 60 90 120K 130K");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Seek_Keyframe) {
NewSegmentAppend(0, 6);
Seek(0);
CheckExpectedBuffers(0, 5, true);
}
TEST_F(SourceBufferStreamTest, Seek_NonKeyframe) {
NewSegmentAppend(0, 15);
Seek(13);
CheckExpectedBuffers(10, 14, true);
Seek(3);
CheckExpectedBuffers(0, 3, true);
}
TEST_F(SourceBufferStreamTest, Seek_NotBuffered) {
Seek(0);
CheckNoNextBuffer();
NewSegmentAppend(0, 2);
Seek(0);
CheckExpectedBuffers(0, 1);
Seek(2);
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Seek_InBetweenTimestamps) {
NewSegmentAppend(0, 10);
base::TimeDelta bump = frame_duration() / 4;
CHECK(bump > base::TimeDelta());
stream_->Seek(5 * frame_duration() + bump);
CheckExpectedBuffers(5, 5, true);
stream_->Seek(5 * frame_duration() - bump);
CheckExpectedBuffers(0, 0, true);
}
TEST_F(SourceBufferStreamTest, Seek_After_TrackBuffer_Filled) {
NewSegmentAppend(5, 10, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 5, &kDataA);
NewSegmentAppend(0, 20, &kDataB);
CheckExpectedRanges("{ [0,19) }");
Seek(0);
CheckExpectedBuffers(0, 19, &kDataB);
CheckExpectedRanges("{ [0,19) }");
}
TEST_F(SourceBufferStreamTest, Seek_StartOfSegment) {
base::TimeDelta bump = frame_duration() / 4;
CHECK(bump > base::TimeDelta());
Seek(5);
NewSegmentAppend_OffsetFirstBuffer(5, 5, bump);
scoped_refptr<StreamParserBuffer> buffer;
EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kSuccess);
EXPECT_EQ(buffer->GetDecodeTimestamp(), 5 * frame_duration() + bump);
CheckExpectedBuffers(6, 9);
Seek(15);
NewSegmentAppend_OffsetFirstBuffer(15, 5, bump);
EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kSuccess);
EXPECT_EQ(buffer->GetDecodeTimestamp(), 15 * frame_duration() + bump);
CheckExpectedBuffers(16, 19);
}
TEST_F(SourceBufferStreamTest, Seek_BeforeStartOfSegment) {
NewSegmentAppend(5, 10);
Seek(0);
CheckExpectedBuffers(5, 14);
}
TEST_F(SourceBufferStreamTest, OldSeekPoint_CompleteOverlap) {
NewSegmentAppend(0, 4);
NewSegmentAppend(10, 5);
Seek(10);
Seek(0);
NewSegmentAppend(5, 15);
CheckExpectedBuffers(0, 0);
}
TEST_F(SourceBufferStreamTest, OldSeekPoint_CompleteOverlap_Pending) {
NewSegmentAppend(0, 2);
NewSegmentAppend(15, 5);
Seek(15);
Seek(5);
NewSegmentAppend(10, 15);
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, OldSeekPoint_MiddleOverlap) {
NewSegmentAppend(0, 2);
NewSegmentAppend(5, 15);
Seek(15);
Seek(0);
NewSegmentAppend(10, 3);
CheckExpectedRanges("{ [0,1) [5,12) [15,19) }");
CheckExpectedBuffers(0, 0);
}
TEST_F(SourceBufferStreamTest, OldSeekPoint_MiddleOverlap_Pending) {
NewSegmentAppend(0, 2);
NewSegmentAppend(10, 15);
Seek(20);
Seek(5);
NewSegmentAppend(15, 3);
CheckExpectedRanges("{ [0,1) [10,17) [20,24) }");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, OldSeekPoint_StartOverlap) {
NewSegmentAppend(0, 2);
NewSegmentAppend(5, 15);
Seek(15);
Seek(0);
NewSegmentAppend(10, 10);
CheckExpectedBuffers(0, 0);
}
TEST_F(SourceBufferStreamTest, OldSeekPoint_StartOverlap_Pending) {
NewSegmentAppend(0, 2);
NewSegmentAppend(10, 15);
Seek(20);
Seek(5);
NewSegmentAppend(15, 10);
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, OldSeekPoint_EndOverlap) {
NewSegmentAppend(0, 4);
NewSegmentAppend(10, 15);
Seek(10);
Seek(0);
NewSegmentAppend(5, 10);
CheckExpectedBuffers(0, 0);
}
TEST_F(SourceBufferStreamTest, OldSeekPoint_EndOverlap_Pending) {
NewSegmentAppend(0, 2);
NewSegmentAppend(15, 15);
Seek(15);
Seek(5);
NewSegmentAppend(10, 10);
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, GetNextBuffer_AfterMerges) {
NewSegmentAppend(10, 5);
Seek(12);
NewSegmentAppend(5, 5);
CheckExpectedRanges("{ [5,14) }");
CheckExpectedBuffers(10, 10);
NewSegmentAppend(15, 5);
CheckExpectedRanges("{ [5,19) }");
CheckExpectedBuffers(11, 14);
}
TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenAppend) {
NewSegmentAppend(0, 4);
Seek(0);
CheckExpectedBuffers(0, 3);
CheckNoNextBuffer();
AppendBuffers(4, 2);
CheckExpectedBuffers(4, 5);
}
TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenStartOverlap) {
NewSegmentAppend(0, 10, &kDataA);
Seek(0);
CheckExpectedBuffers(0, 9, &kDataA);
CheckNoNextBuffer();
NewSegmentAppend(5, 6, &kDataB);
CheckExpectedBuffers(10, 10, &kDataB);
AppendBuffers(11, 5, &kDataB);
CheckExpectedBuffers(11, 14, &kDataB);
NewSegmentAppend(15, 2, &kDataA);
CheckExpectedBuffers(15, 16, &kDataA);
}
TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenStartOverlap2) {
NewSegmentAppend("0K 30 60 90 120");
Seek(0);
CheckExpectedBuffers("0K 30 60 90 120");
CheckNoNextBuffer();
NewSegmentAppend("120K");
CheckNoNextBuffer();
AppendBuffers("150 180 210K 240");
CheckExpectedBuffers("210K 240");
Seek(0);
CheckExpectedBuffers("0K 30 60 90 120K 150 180 210K 240");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenCompleteOverlap) {
NewSegmentAppend(10, 5, &kDataA);
Seek(10);
CheckExpectedBuffers(10, 14, &kDataA);
CheckNoNextBuffer();
NewSegmentAppend(5, 11, &kDataB);
CheckExpectedBuffers(15, 15, &kDataB);
AppendBuffers(16, 5, &kDataB);
CheckExpectedBuffers(16, 19, &kDataB);
NewSegmentAppend(0, 21, &kDataA);
CheckExpectedBuffers(20, 20, &kDataA);
}
TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenEndOverlap) {
NewSegmentAppend(10, 5, &kDataA);
Seek(10);
CheckExpectedBuffers(10, 14, &kDataA);
CheckExpectedRanges("{ [10,14) }");
CheckNoNextBuffer();
NewSegmentAppend(5, 6, &kDataB);
CheckNoNextBuffer();
CheckExpectedRanges("{ [5,10) }");
for (int i = 11; i <= 14; i++) {
AppendBuffers(i, 1, &kDataB);
CheckNoNextBuffer();
}
AppendBuffers(15, 1);
CheckExpectedBuffers(15, 15);
CheckExpectedRanges("{ [5,15) }");
}
TEST_F(SourceBufferStreamTest, GetNextBuffer_Overlap_Selected_Complete) {
NewSegmentAppend(5, 5, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 5, &kDataA);
NewSegmentAppend(5, 5, &kDataB);
CheckExpectedBuffers(6, 9, &kDataA);
CheckNoNextBuffer();
AppendBuffers(10, 5, &kDataB);
CheckExpectedBuffers(10, 14, &kDataB);
}
TEST_F(SourceBufferStreamTest, PresentationTimestampIndependence) {
NewSegmentAppend(0, 20);
Seek(0);
int last_keyframe_idx = -1;
base::TimeDelta last_keyframe_presentation_timestamp;
base::TimeDelta last_p_frame_presentation_timestamp;
for (int i = 0; i < 20; i++) {
scoped_refptr<StreamParserBuffer> buffer;
ASSERT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kSuccess);
if (buffer->IsKeyframe()) {
EXPECT_EQ(buffer->timestamp(), buffer->GetDecodeTimestamp());
last_keyframe_idx = i;
last_keyframe_presentation_timestamp = buffer->timestamp();
} else if (i == last_keyframe_idx + 1) {
ASSERT_NE(last_keyframe_idx, -1);
last_p_frame_presentation_timestamp = buffer->timestamp();
EXPECT_LT(last_keyframe_presentation_timestamp,
last_p_frame_presentation_timestamp);
} else {
EXPECT_GT(buffer->timestamp(), last_keyframe_presentation_timestamp);
EXPECT_LT(buffer->timestamp(), last_p_frame_presentation_timestamp);
EXPECT_LT(buffer->timestamp(), buffer->GetDecodeTimestamp());
}
}
}
TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFront) {
SetMemoryLimit(20);
NewSegmentAppend(0, 1, &kDataA);
for (int i = 1; i < 20; i++)
AppendBuffers(i, 1, &kDataA);
CheckExpectedRanges("{ [0,19) }");
Seek(0);
CheckExpectedBuffers(0, 19, &kDataA);
Seek(10);
AppendBuffers(20, 5, &kDataA);
CheckExpectedRanges("{ [5,24) }");
CheckExpectedBuffers(10, 24, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 9, &kDataA);
}
TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFrontGOPsAtATime) {
SetMemoryLimit(20);
NewSegmentAppend(0, 20, &kDataA);
Seek(10);
AppendBuffers(20, 1, &kDataA);
CheckExpectedRanges("{ [5,20) }");
CheckExpectedBuffers(10, 20, &kDataA);
Seek(5);
CheckExpectedBuffers(5, 9, &kDataA);
}
TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteBack) {
SetMemoryLimit(5);
Seek(0);
NewSegmentAppend(0, 20, &kDataA);
CheckExpectedRanges("{ [0,4) [15,19) }");
CheckExpectedBuffers(0, 4, &kDataA);
}
TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFrontAndBack) {
SetMemoryLimit(3);
Seek(15);
NewSegmentAppend(0, 40, &kDataA);
CheckExpectedRanges("{ [15,19) [35,39) }");
CheckExpectedBuffers(15, 19, &kDataA);
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteSeveralRanges) {
NewSegmentAppend(0, 5);
NewSegmentAppend(10, 5);
NewSegmentAppend(20, 5);
NewSegmentAppend(30, 5);
CheckExpectedRanges("{ [0,4) [10,14) [20,24) [30,34) }");
Seek(20);
CheckExpectedBuffers(20, 20);
SetMemoryLimit(1);
NewSegmentAppend(40, 5);
CheckExpectedRanges("{ [20,24) [40,44) }");
CheckExpectedBuffers(21, 24);
CheckNoNextBuffer();
AppendBuffers(45, 10);
CheckExpectedRanges("{ [20,24) [50,54) }");
SetMemoryLimit(100);
NewSegmentAppend(0, 10);
CheckExpectedRanges("{ [0,9) [20,24) [50,54) }");
Seek(0);
CheckExpectedBuffers(0, 9);
NewSegmentAppend(90, 10);
CheckExpectedRanges("{ [0,9) [20,24) [50,54) [90,99) }");
Seek(50);
CheckExpectedBuffers(50, 54);
CheckNoNextBuffer();
Seek(90);
CheckExpectedBuffers(90, 99);
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteAfterLastAppend) {
SetMemoryLimit(10);
NewSegmentAppend("310K 340 370");
NewSegmentAppend("490K 520 550 580K 610 640");
CheckExpectedRangesByTimestamp("{ [310,400) [490,670) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(580));
NewSegmentAppend("100K 130 160 190K 220 250K");
CheckExpectedRangesByTimestamp("{ [100,280) [580,670) }");
}
TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteAfterLastAppendMerged) {
SetMemoryLimit(10);
NewSegmentAppend("400K 430 460 490K 520 550 580K 610 640");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(580));
NewSegmentAppend("220K 250 280 310K 340 370");
CheckExpectedRangesByTimestamp("{ [220,400) [580,670) }");
}
TEST_F(SourceBufferStreamTest, GarbageCollection_NoSeek) {
SetMemoryLimit(20);
NewSegmentAppend(0, 25, &kDataA);
CheckExpectedRanges("{ [5,24) }");
CheckNoNextBuffer();
Seek(5);
CheckExpectedBuffers(5, 24, &kDataA);
}
TEST_F(SourceBufferStreamTest, GarbageCollection_PendingSeek) {
NewSegmentAppend(0, 10, &kDataA);
NewSegmentAppend(25, 5, &kDataA);
Seek(15);
CheckNoNextBuffer();
CheckExpectedRanges("{ [0,9) [25,29) }");
SetMemoryLimit(5);
AppendBuffers(30, 5, &kDataA);
CheckExpectedRanges("{ [30,34) }");
SetMemoryLimit(100);
NewSegmentAppend(15, 5, &kDataA);
CheckExpectedRanges("{ [15,19) [30,34) }");
CheckExpectedBuffers(15, 19, &kDataA);
Seek(30);
CheckExpectedBuffers(30, 34, &kDataA);
}
TEST_F(SourceBufferStreamTest, GarbageCollection_NeedsMoreData) {
SetMemoryLimit(15);
NewSegmentAppend(0, 10, &kDataA);
Seek(0);
CheckExpectedBuffers(0, 9, &kDataA);
CheckNoNextBuffer();
NewSegmentAppend(15, 20, &kDataA);
CheckExpectedRanges("{ [5,9) [15,19) [30,34) }");
NewSegmentAppend(10, 5, &kDataA);
CheckExpectedRanges("{ [10,19) [30,34) }");
CheckExpectedBuffers(10, 19, &kDataA);
}
TEST_F(SourceBufferStreamTest, GarbageCollection_TrackBuffer) {
SetMemoryLimit(3);
Seek(15);
NewSegmentAppend(0, 18, &kDataA);
CheckExpectedRanges("{ [15,17) }");
CheckExpectedBuffers(15, 15, &kDataA);
NewSegmentAppend(0, 20, &kDataB);
CheckExpectedRanges("{ [15,19) }");
CheckExpectedBuffers(16, 17, &kDataA);
CheckNoNextBuffer();
AppendBuffers(20, 5, &kDataB);
CheckExpectedRanges("{ [20,24) }");
CheckExpectedBuffers(20, 24, &kDataB);
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP) {
SetMemoryLimit(3);
NewSegmentAppend("0K 30 60 90");
CheckExpectedRangesByTimestamp("{ [0,120) }");
AppendBuffers("120");
CheckExpectedRangesByTimestamp("{ [0,150) }");
SetMemoryLimit(100);
NewSegmentAppend("200K 230 260 290K 320 350");
CheckExpectedRangesByTimestamp("{ [0,150) [200,380) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(290));
SetMemoryLimit(3);
NewSegmentAppend("500K 530 560 590");
CheckExpectedRangesByTimestamp("{ [290,380) [500,620) }");
AppendBuffers("620");
CheckExpectedRangesByTimestamp("{ [290,380) [500,650) }");
}
TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Middle) {
NewSegmentAppend("0K 30 60 90K 120 150 180K 210 240");
CheckExpectedRangesByTimestamp("{ [0,270) }");
SetMemoryLimit(1);
NewSegmentAppend("80K 110 140");
CheckExpectedRangesByTimestamp("{ [80,170) }");
AppendBuffers("170");
CheckExpectedRangesByTimestamp("{ [80,200) }");
SetMemoryLimit(100);
NewSegmentAppend("400K 430 460 490K 520 550 580K 610 640");
CheckExpectedRangesByTimestamp("{ [80,200) [400,670) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(80));
SetMemoryLimit(3);
NewSegmentAppend("500K 530 560 590");
CheckExpectedRangesByTimestamp("{ [80,200) [500,620) }");
AppendBuffers("620");
CheckExpectedRangesByTimestamp("{ [80,200) [500,650) }");
}
TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Selected1) {
NewSegmentAppend("0K 30 60 90K 120 150 180K 210 240");
CheckExpectedRangesByTimestamp("{ [0,270) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(90));
SetMemoryLimit(1);
NewSegmentAppend("0K 30 60");
CheckExpectedRangesByTimestamp("{ [0,180) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
CheckExpectedBuffers("0K 30 60 90K 120 150");
CheckNoNextBuffer();
SeekToTimestamp(base::TimeDelta::FromMilliseconds(90));
NewSegmentAppend("180K 210 240");
CheckExpectedRangesByTimestamp("{ [90,270) }");
CheckExpectedBuffers("90K 120 150 180K 210 240");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Selected2) {
NewSegmentAppend("0K 30 60 90K 120 150 180K 210 240 270K 300 330");
CheckExpectedRangesByTimestamp("{ [0,360) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(270));
SetMemoryLimit(1);
NewSegmentAppend("90K 120 150");
CheckExpectedRangesByTimestamp("{ [90,180) [270,360) }");
SetMemoryLimit(100);
NewSegmentAppend("360K 390 420 450K 480 510 540K 570 600");
CheckExpectedRangesByTimestamp("{ [90,180) [270,630) }");
SetMemoryLimit(1);
NewSegmentAppend("450K 480 510");
CheckExpectedRangesByTimestamp("{ [270,360) [450,540) }");
}
TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Selected3) {
SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
NewSegmentAppend("0K 30 60 90K 120 150 180K 210 240");
CheckExpectedRangesByTimestamp("{ [0,270) }");
SetMemoryLimit(1);
NewSegmentAppend("0K 30");
CheckExpectedRangesByTimestamp("{ [0,60) }");
CheckExpectedBuffers("0K 30");
CheckNoNextBuffer();
AppendBuffers("60 90");
CheckExpectedRangesByTimestamp("{ [0,120) }");
CheckExpectedBuffers("60 90");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, DISABLED_GarbageCollection_WaitingForKeyframe) {
SetMemoryLimit(10);
NewSegmentAppend(10, 5, &kDataA);
Seek(10);
CheckExpectedBuffers(10, 14, &kDataA);
CheckExpectedRanges("{ [10,14) }");
CheckNoNextBuffer();
NewSegmentAppend(5, 6, &kDataA);
CheckNoNextBuffer();
CheckExpectedRanges("{ [5,10) }");
NewSegmentAppend(20, 10, &kDataA);
CheckNoNextBuffer();
CheckExpectedRanges("{ [10,10) [20,28) }");
NewSegmentAppend(15, 1, &kDataA);
CheckExpectedBuffers(15, 15, &kDataA);
CheckExpectedRanges("{ [15,15) [20,28) }");
}
TEST_F(SourceBufferStreamTest, GarbageCollection_Performance) {
SetStreamInfo(kDefaultFramesPerSecond, kDefaultFramesPerSecond);
const int kBuffersToKeep = 1000;
SetMemoryLimit(kBuffersToKeep);
int buffers_appended = 0;
NewSegmentAppend(0, kBuffersToKeep);
buffers_appended += kBuffersToKeep;
const int kBuffersToAppend = 1000;
const int kGarbageCollections = 3;
for (int i = 0; i < kGarbageCollections; ++i) {
AppendBuffers(buffers_appended, kBuffersToAppend);
buffers_appended += kBuffersToAppend;
}
}
TEST_F(SourceBufferStreamTest, GetRemovalRange_BytesToFree) {
NewSegmentAppend("300K 330 360 390K 420 450");
NewSegmentAppend("600K 630 660 690K 720 750");
NewSegmentAppend("900K 930 960 990K 1020 1050");
CheckExpectedRangesByTimestamp("{ [300,480) [600,780) [900,1080) }");
int remove_range_end = -1;
int bytes_removed = -1;
bytes_removed = GetRemovalRangeInMs(300, 1080, 0, &remove_range_end);
EXPECT_EQ(-1, remove_range_end);
EXPECT_EQ(0, bytes_removed);
bytes_removed = GetRemovalRangeInMs(300, 1080, 1, &remove_range_end);
EXPECT_EQ(390, remove_range_end);
EXPECT_EQ(3, bytes_removed);
bytes_removed = GetRemovalRangeInMs(300, 1080, 3, &remove_range_end);
EXPECT_EQ(390, remove_range_end);
EXPECT_EQ(3, bytes_removed);
bytes_removed = GetRemovalRangeInMs(300, 1080, 6, &remove_range_end);
EXPECT_EQ(480, remove_range_end);
EXPECT_EQ(6, bytes_removed);
bytes_removed = GetRemovalRangeInMs(300, 1080, 7, &remove_range_end);
EXPECT_EQ(690, remove_range_end);
EXPECT_EQ(9, bytes_removed);
bytes_removed = GetRemovalRangeInMs(300, 1080, 12, &remove_range_end);
EXPECT_EQ(780, remove_range_end);
EXPECT_EQ(12, bytes_removed);
bytes_removed = GetRemovalRangeInMs(300, 1080, 14, &remove_range_end);
EXPECT_EQ(990, remove_range_end);
EXPECT_EQ(15, bytes_removed);
bytes_removed = GetRemovalRangeInMs(300, 1080, 18, &remove_range_end);
EXPECT_EQ(1080, remove_range_end);
EXPECT_EQ(18, bytes_removed);
bytes_removed = GetRemovalRangeInMs(300, 1080, 20, &remove_range_end);
EXPECT_EQ(1080, remove_range_end);
EXPECT_EQ(18, bytes_removed);
}
TEST_F(SourceBufferStreamTest, GetRemovalRange_Range) {
NewSegmentAppend("300K 330 360 390K 420 450");
NewSegmentAppend("600K 630 660 690K 720 750");
NewSegmentAppend("900K 930 960 990K 1020 1050");
CheckExpectedRangesByTimestamp("{ [300,480) [600,780) [900,1080) }");
int remove_range_end = -1;
int bytes_removed = -1;
bytes_removed = GetRemovalRangeInMs(630, 660, 20, &remove_range_end);
EXPECT_EQ(-1, remove_range_end);
EXPECT_EQ(0, bytes_removed);
bytes_removed = GetRemovalRangeInMs(630, 750, 20, &remove_range_end);
EXPECT_EQ(-1, remove_range_end);
EXPECT_EQ(0, bytes_removed);
bytes_removed = GetRemovalRangeInMs(600, 780, 20, &remove_range_end);
EXPECT_EQ(780, remove_range_end);
EXPECT_EQ(6, bytes_removed);
bytes_removed = GetRemovalRangeInMs(570, 810, 20, &remove_range_end);
EXPECT_EQ(780, remove_range_end);
EXPECT_EQ(6, bytes_removed);
bytes_removed = GetRemovalRangeInMs(480, 900, 20, &remove_range_end);
EXPECT_EQ(780, remove_range_end);
EXPECT_EQ(6, bytes_removed);
bytes_removed = GetRemovalRangeInMs(420, 960, 20, &remove_range_end);
EXPECT_EQ(780, remove_range_end);
EXPECT_EQ(6, bytes_removed);
bytes_removed = GetRemovalRangeInMs(390, 990, 20, &remove_range_end);
EXPECT_EQ(990, remove_range_end);
EXPECT_EQ(12, bytes_removed);
bytes_removed = GetRemovalRangeInMs(330, 1050, 20, &remove_range_end);
EXPECT_EQ(990, remove_range_end);
EXPECT_EQ(12, bytes_removed);
bytes_removed = GetRemovalRangeInMs(300, 1080, 20, &remove_range_end);
EXPECT_EQ(1080, remove_range_end);
EXPECT_EQ(18, bytes_removed);
bytes_removed = GetRemovalRangeInMs(270, 1110, 20, &remove_range_end);
EXPECT_EQ(1080, remove_range_end);
EXPECT_EQ(18, bytes_removed);
}
TEST_F(SourceBufferStreamTest, ConfigChange_Basic) {
VideoDecoderConfig new_config = TestVideoConfig::Large();
ASSERT_FALSE(new_config.Matches(video_config_));
Seek(0);
CheckVideoConfig(video_config_);
NewSegmentAppend(0, 5, &kDataA);
CheckVideoConfig(video_config_);
stream_->UpdateVideoConfig(new_config);
CheckVideoConfig(video_config_);
NewSegmentAppend(5, 5, &kDataB);
scoped_refptr<StreamParserBuffer> buffer;
for (int i = 0; i < 5; i++) {
EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kSuccess);
CheckVideoConfig(video_config_);
}
EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kConfigChange);
CheckVideoConfig(new_config);
for (int i = 0; i < 5; i++) {
CheckVideoConfig(new_config);
EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kSuccess);
}
}
TEST_F(SourceBufferStreamTest, ConfigChange_Seek) {
scoped_refptr<StreamParserBuffer> buffer;
VideoDecoderConfig new_config = TestVideoConfig::Large();
Seek(0);
NewSegmentAppend(0, 5, &kDataA);
stream_->UpdateVideoConfig(new_config);
NewSegmentAppend(5, 5, &kDataB);
CheckVideoConfig(video_config_);
Seek(5);
CheckVideoConfig(video_config_);
EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kConfigChange);
CheckVideoConfig(new_config);
CheckExpectedBuffers(5, 9, &kDataB);
CheckVideoConfig(new_config);
Seek(0);
Seek(7);
CheckExpectedBuffers(5, 9, &kDataB);
CheckVideoConfig(new_config);
Seek(0);
CheckVideoConfig(new_config);
EXPECT_EQ(stream_->GetNextBuffer(&buffer), SourceBufferStream::kConfigChange);
CheckVideoConfig(video_config_);
CheckExpectedBuffers(0, 4, &kDataA);
}
TEST_F(SourceBufferStreamTest, SetExplicitDuration) {
NewSegmentAppend(5, 2);
NewSegmentAppend(10, 2);
NewSegmentAppend(15, 2);
CheckExpectedRanges("{ [5,6) [10,11) [15,16) }");
stream_->OnSetDuration(frame_duration() * 8);
CheckExpectedRanges("{ [5,6) }");
NewSegmentAppend(0, 20);
CheckExpectedRanges("{ [0,19) }");
}
TEST_F(SourceBufferStreamTest, SetExplicitDuration_EdgeCase) {
NewSegmentAppend(10, 10);
NewSegmentAppend(25, 5);
CheckExpectedRanges("{ [10,19) [25,29) }");
stream_->OnSetDuration(frame_duration() * 25);
CheckExpectedRanges("{ [10,19) }");
}
TEST_F(SourceBufferStreamTest, SetExplicitDuration_DeletePartialRange) {
NewSegmentAppend(0, 5);
NewSegmentAppend(10, 10);
NewSegmentAppend(25, 5);
CheckExpectedRanges("{ [0,4) [10,19) [25,29) }");
stream_->OnSetDuration(frame_duration() * 14);
CheckExpectedRanges("{ [0,4) [10,13) }");
}
TEST_F(SourceBufferStreamTest, SetExplicitDuration_DeleteSelectedRange) {
NewSegmentAppend(5, 2);
NewSegmentAppend(10, 2);
NewSegmentAppend(15, 2);
CheckExpectedRanges("{ [5,6) [10,11) [15,16) }");
Seek(10);
stream_->OnSetDuration(frame_duration() * 4);
CheckNoNextBuffer();
CheckExpectedRanges("{ }");
NewSegmentAppend(0, 15);
CheckNoNextBuffer();
CheckExpectedRanges("{ [0,14) }");
}
TEST_F(SourceBufferStreamTest, SetExplicitDuration_DeletePartialSelectedRange) {
NewSegmentAppend(0, 5);
NewSegmentAppend(10, 20);
CheckExpectedRanges("{ [0,4) [10,29) }");
Seek(10);
stream_->OnSetDuration(frame_duration() * 25);
CheckExpectedRanges("{ [0,4) [10,24) }");
CheckExpectedBuffers(10, 10);
stream_->OnSetDuration(frame_duration() * 11);
CheckNoNextBuffer();
CheckExpectedRanges("{ [0,4) [10,10) }");
}
TEST_F(SourceBufferStreamTest, SetExplicitDuration_UpdateSelectedRange) {
SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
NewSegmentAppend("0K 30 60 90");
CheckExpectedBuffers("0K 30");
stream_->OnSetDuration(base::TimeDelta::FromMilliseconds(60));
CheckNoNextBuffer();
NewSegmentAppend("120K 150");
CheckExpectedRangesByTimestamp("{ [0,60) [120,180) }");
}
TEST_F(SourceBufferStreamTest,
SetExplicitDuration_AfterSegmentTimestampAndBeforeFirstBufferTimestamp) {
NewSegmentAppend("0K 30K 60K");
NewSegmentAppend(base::TimeDelta::FromMilliseconds(200),
"230K 260K 290K 320K");
NewSegmentAppend("400K 430K 460K");
CheckExpectedRangesByTimestamp("{ [0,90) [200,350) [400,490) }");
stream_->OnSetDuration(base::TimeDelta::FromMilliseconds(120));
CheckExpectedRangesByTimestamp("{ [0,90) }");
}
TEST_F(SourceBufferStreamTest, OverlapSplitAndMergeWhileWaitingForMoreData) {
SeekToTimestamp(base::TimeDelta::FromMilliseconds(0));
NewSegmentAppend("0K 30 60 90 120K 150");
CheckExpectedRangesByTimestamp("{ [0,180) }");
CheckExpectedBuffers("0K 30 60 90 120K 150");
CheckNoNextBuffer();
NewSegmentAppend("120K 150");
CheckExpectedRangesByTimestamp("{ [0,180) }");
NewSegmentAppend("0K 30");
CheckExpectedRangesByTimestamp("{ [0,60) [120,180) }");
AppendBuffers("60 90");
CheckExpectedRangesByTimestamp("{ [0,180) }");
CheckNoNextBuffer();
NewSegmentAppend("180K 210");
CheckExpectedRangesByTimestamp("{ [0,240) }");
CheckExpectedBuffers("180K 210");
}
TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend) {
Seek(0);
NewSegmentAppend("0K 30 30 60 90 120K 150");
CheckExpectedBuffers("0K 30 30 60 90 120K 150");
}
TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends) {
Seek(0);
NewSegmentAppend("0K 30");
AppendBuffers("30 60 90 120K 150");
CheckExpectedBuffers("0K 30 30 60 90 120K 150");
}
TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Invalid_1) {
Seek(0);
NewSegmentAppend("0K 30");
AppendBuffers_ExpectFailure("30K 60");
}
TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Invalid_2) {
Seek(0);
NewSegmentAppend_ExpectFailure("0K 30 30K 60");
}
TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_TwoAppends) {
Seek(0);
NewSegmentAppend("0K 30K");
AppendBuffers("30 60");
CheckExpectedBuffers("0K 30K 30 60");
}
TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_SingleAppend) {
Seek(0);
NewSegmentAppend("0K 30K 30 60");
CheckExpectedBuffers("0K 30K 30 60");
}
TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_1) {
Seek(0);
NewSegmentAppend("0K 30 60 60 90 120K 150");
NewSegmentAppend("60K 91 121K 151");
CheckExpectedBuffers("0K 30 60K 91 121K 151");
}
TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_2) {
Seek(0);
NewSegmentAppend("0K 30 60 60 90 120K 150");
NewSegmentAppend("0K 30 61");
CheckExpectedBuffers("0K 30 61 120K 150");
}
TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_3) {
Seek(0);
NewSegmentAppend("0K 20 40 60 80 100K 101 102 103K");
NewSegmentAppend("0K 20 40 60 80 90");
CheckExpectedBuffers("0K 20 40 60 80 90 100K 101 102 103K");
AppendBuffers("90 110K 150");
Seek(0);
CheckExpectedBuffers("0K 20 40 60 80 90 90 110K 150");
CheckNoNextBuffer();
CheckExpectedRangesByTimestamp("{ [0,190) }");
}
TEST_F(SourceBufferStreamTest, SameTimestamp_Audio) {
AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO,
44100, NULL, 0, false);
stream_.reset(new SourceBufferStream(config, log_cb(), true));
Seek(0);
NewSegmentAppend("0K 0K 30K 30 60 60");
CheckExpectedBuffers("0K 0K 30K 30 60 60");
}
TEST_F(SourceBufferStreamTest, SameTimestamp_Audio_Invalid_1) {
AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO,
44100, NULL, 0, false);
stream_.reset(new SourceBufferStream(config, log_cb(), true));
Seek(0);
NewSegmentAppend_ExpectFailure("0K 30 30K 60");
}
TEST_F(SourceBufferStreamTest, EndSelected_During_PendingSeek) {
NewSegmentAppend(0, 15);
Seek(20);
EXPECT_TRUE(stream_->IsSeekPending());
stream_->MarkEndOfStream();
EXPECT_FALSE(stream_->IsSeekPending());
}
TEST_F(SourceBufferStreamTest, EndNotSelected_During_PendingSeek) {
NewSegmentAppend(0, 10);
NewSegmentAppend(30, 10);
Seek(20);
EXPECT_TRUE(stream_->IsSeekPending());
stream_->MarkEndOfStream();
EXPECT_TRUE(stream_->IsSeekPending());
}
TEST_F(SourceBufferStreamTest, Remove_WholeRange1) {
Seek(0);
NewSegmentAppend("10K 40 70K 100 130K");
CheckExpectedRangesByTimestamp("{ [10,160) }");
RemoveInMs(10, 160, 160);
CheckExpectedRangesByTimestamp("{ }");
}
TEST_F(SourceBufferStreamTest, Remove_WholeRange2) {
Seek(0);
NewSegmentAppend("10K 40 70K 100 130K");
CheckExpectedRangesByTimestamp("{ [10,160) }");
RemoveInMs(0, 160, 160);
CheckExpectedRangesByTimestamp("{ }");
}
TEST_F(SourceBufferStreamTest, Remove_WholeRange3) {
Seek(0);
NewSegmentAppend("10K 40 70K 100 130K");
CheckExpectedRangesByTimestamp("{ [10,160) }");
RemoveInMs(10, 200, 200);
CheckExpectedRangesByTimestamp("{ }");
}
TEST_F(SourceBufferStreamTest, Remove_WholeRange4) {
Seek(0);
NewSegmentAppend("10K 40 70K 100 130K");
CheckExpectedRangesByTimestamp("{ [10,160) }");
RemoveInMs(0, 200, 200);
CheckExpectedRangesByTimestamp("{ }");
}
TEST_F(SourceBufferStreamTest, Remove_WholeRange5) {
Seek(0);
NewSegmentAppend("10K 40 70K 100 130K");
NewSegmentAppend("1000K 1030 1060K 1090 1120K");
NewSegmentAppend("2000K 2030 2060K 2090 2120K");
CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) [2000,2150) }");
RemoveInMs(10, 3000, 3000);
CheckExpectedRangesByTimestamp("{ }");
}
TEST_F(SourceBufferStreamTest, Remove_ZeroToInfinity) {
Seek(0);
NewSegmentAppend("10K 40 70K 100 130K");
NewSegmentAppend("1000K 1030 1060K 1090 1120K");
NewSegmentAppend("2000K 2030 2060K 2090 2120K");
CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) [2000,2150) }");
Remove(base::TimeDelta(), kInfiniteDuration(), kInfiniteDuration());
CheckExpectedRangesByTimestamp("{ }");
}
TEST_F(SourceBufferStreamTest, Remove_Partial1) {
Seek(0);
NewSegmentAppend("10K 40 70K 100 130K");
NewSegmentAppend("1000K 1030 1060K 1090 1120K");
CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) }");
RemoveInMs(0, 80, 2200);
CheckExpectedRangesByTimestamp("{ [130,160) [1000,1150) }");
}
TEST_F(SourceBufferStreamTest, Remove_Partial2) {
Seek(0);
NewSegmentAppend("10K 40 70K 100 130K");
NewSegmentAppend("1000K 1030 1060K 1090 1120K");
CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) }");
RemoveInMs(40, 160, 2200);
CheckExpectedRangesByTimestamp("{ [10,40) [1000,1150) }");
}
TEST_F(SourceBufferStreamTest, Remove_Partial3) {
Seek(0);
NewSegmentAppend("10K 40 70K 100 130K");
NewSegmentAppend("1000K 1030 1060K 1090 1120K");
CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) }");
RemoveInMs(40, 120, 2200);
CheckExpectedRangesByTimestamp("{ [10,40) [130,160) [1000,1150) }");
}
TEST_F(SourceBufferStreamTest, Remove_Partial4) {
Seek(0);
NewSegmentAppend("10K 40 70K 100 130K");
NewSegmentAppend("1000K 1030 1060K 1090 1120K");
NewSegmentAppend("2000K 2030 2060K 2090 2120K");
CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) [2000,2150) }");
RemoveInMs(40, 2030, 2200);
CheckExpectedRangesByTimestamp("{ [10,40) [2060,2150) }");
}
TEST_F(SourceBufferStreamTest, Remove_CurrentPosition) {
Seek(0);
NewSegmentAppend("0K 30 60 90K 120 150 180K 210 240 270K 300 330");
CheckExpectedRangesByTimestamp("{ [0,360) }");
CheckExpectedBuffers("0K 30 60 90K 120");
RemoveInMs(150, 210, 360);
CheckExpectedRangesByTimestamp("{ [0,150) [270,360) }");
CheckNoNextBuffer();
NewSegmentAppend("120K 150 180 210K 240");
CheckExpectedRangesByTimestamp("{ [0,360) }");
CheckExpectedBuffers("210K 240 270K 300 330");
}
TEST_F(SourceBufferStreamTest, Remove_BeforeCurrentPosition) {
Seek(0);
NewSegmentAppend("0K 30 60 90K 120 150 180K 210 240 270K 300 330");
CheckExpectedRangesByTimestamp("{ [0,360) }");
CheckExpectedBuffers("0K 30 60 90K 120");
RemoveInMs(0, 90, 360);
CheckExpectedRangesByTimestamp("{ [90,360) }");
CheckExpectedBuffers("150 180K 210 240 270K 300 330");
}
TEST_F(SourceBufferStreamTest, Remove_MidSegment) {
Seek(0);
NewSegmentAppend("0K 30 60 90 120K 150 180 210");
CheckExpectedRangesByTimestamp("{ [0,240) }");
NewSegmentAppend("0K 30");
CheckExpectedBuffers("0K");
CheckExpectedRangesByTimestamp("{ [0,60) [120,240) }");
RemoveInMs(0, 60, 240);
CheckNoNextBuffer();
CheckExpectedRangesByTimestamp("{ [120,240) }");
AppendBuffers("60 90");
CheckExpectedRangesByTimestamp("{ [120,240) }");
AppendBuffers("120 150K 180");
CheckExpectedRangesByTimestamp("{ [150,210) }");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(150));
CheckExpectedBuffers("150K 180");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Remove_GOPBeingAppended) {
Seek(0);
NewSegmentAppend("0K 30 60 90 120K 150 180");
CheckExpectedRangesByTimestamp("{ [0,210) }");
RemoveInMs(120, 150, 240);
CheckExpectedRangesByTimestamp("{ [0,120) }");
AppendBuffers("210 240K 270 300");
CheckExpectedRangesByTimestamp("{ [0,120) [240,330) }");
CheckExpectedBuffers("0K 30 60 90");
CheckNoNextBuffer();
SeekToTimestamp(base::TimeDelta::FromMilliseconds(240));
CheckExpectedBuffers("240K 270 300");
}
TEST_F(SourceBufferStreamTest,
Remove_PreviousAppendDestroyedAndOverwriteExistingRange) {
SeekToTimestamp(base::TimeDelta::FromMilliseconds(90));
NewSegmentAppend("90K 120 150");
CheckExpectedRangesByTimestamp("{ [90,180) }");
NewSegmentAppend("0K 30 60");
CheckExpectedRangesByTimestamp("{ [0,180) }");
RemoveInMs(0, 90, 360);
CheckExpectedRangesByTimestamp("{ [90,180) }");
NewSegmentAppend("90K 121 151");
CheckExpectedBuffers("90K 121 151");
}
TEST_F(SourceBufferStreamTest, Text_Append_SingleRange) {
SetTextStream();
NewSegmentAppend("0K 500K 1000K");
CheckExpectedRangesByTimestamp("{ [0,1500) }");
Seek(0);
CheckExpectedBuffers("0K 500K 1000K");
}
TEST_F(SourceBufferStreamTest, Text_Append_DisjointAfter) {
SetTextStream();
NewSegmentAppend("0K 500K 1000K");
CheckExpectedRangesByTimestamp("{ [0,1500) }");
NewSegmentAppend("3000K 3500K 4000K");
CheckExpectedRangesByTimestamp("{ [0,4500) }");
Seek(0);
CheckExpectedBuffers("0K 500K 1000K 3000K 3500K 4000K");
}
TEST_F(SourceBufferStreamTest, Text_Append_DisjointBefore) {
SetTextStream();
NewSegmentAppend("3000K 3500K 4000K");
CheckExpectedRangesByTimestamp("{ [3000,4500) }");
NewSegmentAppend("0K 500K 1000K");
CheckExpectedRangesByTimestamp("{ [0,4500) }");
Seek(0);
CheckExpectedBuffers("0K 500K 1000K 3000K 3500K 4000K");
}
TEST_F(SourceBufferStreamTest, Text_CompleteOverlap) {
SetTextStream();
NewSegmentAppend("3000K 3500K 4000K");
CheckExpectedRangesByTimestamp("{ [3000,4500) }");
NewSegmentAppend("0K 501K 1001K 1501K 2001K 2501K "
"3001K 3501K 4001K 4501K 5001K");
CheckExpectedRangesByTimestamp("{ [0,5502) }");
Seek(0);
CheckExpectedBuffers("0K 501K 1001K 1501K 2001K 2501K "
"3001K 3501K 4001K 4501K 5001K");
}
TEST_F(SourceBufferStreamTest, Text_OverlapAfter) {
SetTextStream();
NewSegmentAppend("0K 500K 1000K 1500K 2000K");
CheckExpectedRangesByTimestamp("{ [0,2500) }");
NewSegmentAppend("1499K 2001K 2501K 3001K");
CheckExpectedRangesByTimestamp("{ [0,3503) }");
Seek(0);
CheckExpectedBuffers("0K 500K 1000K 1499K 2001K 2501K 3001K");
}
TEST_F(SourceBufferStreamTest, Text_OverlapBefore) {
SetTextStream();
NewSegmentAppend("1500K 2000K 2500K 3000K 3500K");
CheckExpectedRangesByTimestamp("{ [1500,4000) }");
NewSegmentAppend("0K 501K 1001K 1501K 2001K");
CheckExpectedRangesByTimestamp("{ [0,4001) }");
Seek(0);
CheckExpectedBuffers("0K 501K 1001K 1501K 2001K 2500K 3000K 3500K");
}
TEST_F(SourceBufferStreamTest, SpliceFrame_Basic) {
Seek(0);
NewSegmentAppend("0K S(3K 6 9 10) 15 20 S(25K 30 35) 40");
CheckExpectedBuffers("0K 3K 6 9 C 10 15 20 25K 30 C 35 40");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, SpliceFrame_SeekClearsSplice) {
Seek(0);
NewSegmentAppend("0K S(3K 6 9 10) 15K 20");
CheckExpectedBuffers("0K 3K 6");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(15));
CheckExpectedBuffers("15K 20");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, SpliceFrame_SeekClearsSpliceFromTrackBuffer) {
Seek(0);
NewSegmentAppend("0K 2K S(3K 6 9 10) 15K 20");
CheckExpectedBuffers("0K 2K");
NewSegmentAppend("5K 15K 20");
CheckExpectedBuffers("3K 6");
SeekToTimestamp(base::TimeDelta::FromMilliseconds(15));
CheckExpectedBuffers("15K 20");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, SpliceFrame_ConfigChangeWithinSplice) {
VideoDecoderConfig new_config = TestVideoConfig::Large();
ASSERT_FALSE(new_config.Matches(video_config_));
stream_->UpdateVideoConfig(new_config);
stream_->UpdateVideoConfig(video_config_);
Seek(0);
CheckVideoConfig(video_config_);
NewSegmentAppend("0K S(3K 6C 9 10) 15");
CheckExpectedBuffers("0K 3K C");
CheckVideoConfig(new_config);
CheckExpectedBuffers("6 9 C");
CheckVideoConfig(video_config_);
CheckExpectedBuffers("10 15");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, SpliceFrame_BasicFromTrackBuffer) {
Seek(0);
NewSegmentAppend("0K 5K S(8K 9 10) 20");
CheckExpectedBuffers("0K 5K");
NewSegmentAppend("5K 20");
CheckExpectedBuffers("8K 9 C 10 20");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest,
SpliceFrame_ConfigChangeWithinSpliceFromTrackBuffer) {
VideoDecoderConfig new_config = TestVideoConfig::Large();
ASSERT_FALSE(new_config.Matches(video_config_));
stream_->UpdateVideoConfig(new_config);
stream_->UpdateVideoConfig(video_config_);
Seek(0);
CheckVideoConfig(video_config_);
NewSegmentAppend("0K 5K S(7K 8C 9 10) 20");
CheckExpectedBuffers("0K 5K");
NewSegmentAppend("5K 20");
CheckExpectedBuffers("7K C");
CheckVideoConfig(new_config);
CheckExpectedBuffers("8 9 C");
CheckVideoConfig(video_config_);
CheckExpectedBuffers("10 20");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_Basic) {
SetAudioStream();
Seek(0);
NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
NewSegmentAppend("11K 13K 15K 17K");
CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K C 11K 13K 15K 17K");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoExactSplices) {
SetAudioStream();
Seek(0);
NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
NewSegmentAppend("10K 14K");
CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 14K");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_DoubleSpliceEarlierOverlap) {
SetAudioStream();
Seek(0);
NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
NewSegmentAppend("11K 13K 15K 17K");
NewSegmentAppend("9K");
CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 11K 13K C 9K");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_DoubleSpliceLaterOverlap) {
SetAudioStream();
Seek(0);
NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
NewSegmentAppend("10K 13K 15K 17K");
NewSegmentAppend("11K");
CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 13K 15K C 11K");
CheckNoNextBuffer();
}
TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoSplice) {
SetAudioStream();
Seek(0);
NewSegmentAppend("0K 2K 4K 6K 8K 10K");
NewSegmentAppend("12K 14K 16K 18K");
CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K 14K 16K 18K");
CheckNoNextBuffer();
}
}