Use TrickPlay Test Structure As Common Test Structure

Took the test structure for trick play and made a common test
structure that can be used for new tests. The next tests to
use this structure will be the new WebVtt pipeline.

Change-Id: I5faca306b8a2bd16b9f945d1ff5c336aed82bc35
This commit is contained in:
Aaron Vaage 2017-09-26 09:00:33 -07:00
parent 9cb4018235
commit 6c0f2bebef
3 changed files with 155 additions and 65 deletions

View File

@ -206,6 +206,71 @@ std::unique_ptr<TextSample> MediaHandlerTestBase::GetTextSample(
return sample; return sample;
} }
Status MediaHandlerTestBase::SetUpAndInitializeGraph(
std::shared_ptr<MediaHandler> handler,
size_t input_count,
size_t output_count) {
DCHECK(handler);
DCHECK_EQ(nullptr, handler_);
DCHECK(inputs_.empty());
DCHECK(outputs_.empty());
handler_ = std::move(handler);
Status status;
// Add and connect all the requested inputs.
for (size_t i = 0; i < input_count; i++) {
inputs_.emplace_back(new FakeInputMediaHandler);
}
for (auto& input : inputs_) {
status.Update(input->AddHandler(handler_));
}
if (!status.ok()) {
return status;
}
// Add and connect all the requested outputs.
for (size_t i = 0; i < output_count; i++) {
outputs_.emplace_back(new MockOutputMediaHandler);
}
for (auto& output : outputs_) {
status.Update(handler_->AddHandler(output));
}
if (!status.ok()) {
return status;
}
// Initialize the graph.
for (auto& input : inputs_) {
status.Update(input->Initialize());
}
// In the case that there are no inputs, the start of the graph
// is at |handler_| so it needs to be initialized or else the graph
// won't be initialized.
if (inputs_.empty()) {
status.Update(handler_->Initialize());
}
return status;
}
FakeInputMediaHandler* MediaHandlerTestBase::Input(size_t index) {
DCHECK_LT(index, inputs_.size());
return inputs_[index].get();
}
MockOutputMediaHandler* MediaHandlerTestBase::Output(size_t index) {
DCHECK_LT(index, outputs_.size());
return outputs_[index].get();
}
MediaHandlerGraphTestBase::MediaHandlerGraphTestBase() MediaHandlerGraphTestBase::MediaHandlerGraphTestBase()
: next_handler_(new FakeMediaHandler), : next_handler_(new FakeMediaHandler),
some_handler_(new FakeMediaHandler) {} some_handler_(new FakeMediaHandler) {}

View File

@ -171,9 +171,27 @@ class MediaHandlerTestBase : public ::testing::Test {
uint64_t end, uint64_t end,
const std::string& payload) const; const std::string& payload) const;
// Connect and initialize all handlers.
Status SetUpAndInitializeGraph(std::shared_ptr<MediaHandler> handler,
size_t input_count,
size_t output_count);
// Get the input handler at |index|. The values of |index| will match the
// call to |AddInput|.
FakeInputMediaHandler* Input(size_t index);
// Get the output handler at |index|. The values of |index| will match the
// call to |AddOutput|.
MockOutputMediaHandler* Output(size_t index);
private: private:
MediaHandlerTestBase(const MediaHandlerTestBase&) = delete; MediaHandlerTestBase(const MediaHandlerTestBase&) = delete;
MediaHandlerTestBase& operator=(const MediaHandlerTestBase&) = delete; MediaHandlerTestBase& operator=(const MediaHandlerTestBase&) = delete;
std::shared_ptr<MediaHandler> handler_;
std::vector<std::shared_ptr<FakeInputMediaHandler>> inputs_;
std::vector<std::shared_ptr<MockOutputMediaHandler>> outputs_;
}; };
class MediaHandlerGraphTestBase : public MediaHandlerTestBase { class MediaHandlerGraphTestBase : public MediaHandlerTestBase {

View File

@ -17,6 +17,10 @@
namespace shaka { namespace shaka {
namespace media { namespace media {
namespace { namespace {
const size_t kInputCount = 1;
const size_t kOutputCount = 1;
const size_t kInputIndex = 0;
const size_t kOutputIndex = 0;
const size_t kStreamIndex = 0; const size_t kStreamIndex = 0;
// This value does not matter as trick play does not use it, but it is needed // This value does not matter as trick play does not use it, but it is needed
@ -46,24 +50,15 @@ MATCHER_P2(IsTrickPlaySample, timestamp, duration, "") {
arg->media_sample->is_key_frame(); arg->media_sample->is_key_frame();
} }
// Creates a structure of [input]->[trick play]->[output] where all
// interactions are with input and output.
class TrickPlayHandlerTest : public MediaHandlerTestBase { class TrickPlayHandlerTest : public MediaHandlerTestBase {
protected: protected:
void SetUpAndInitializeGraph(uint32_t factor) { void SetUpAndInitializeGraph(uint32_t factor) {
input_ = std::make_shared<FakeInputMediaHandler>(); ASSERT_OK(MediaHandlerTestBase::SetUpAndInitializeGraph(
trick_play_ = std::make_shared<TrickPlayHandler>(factor); std::make_shared<TrickPlayHandler>(factor),
output_ = std::make_shared<MockOutputMediaHandler>(); kInputCount,
kOutputCount));
ASSERT_OK(input_->AddHandler(trick_play_));
ASSERT_OK(trick_play_->AddHandler(output_));
ASSERT_OK(input_->Initialize());
} }
FakeInputMediaHandler* input() { return input_.get(); }
MockOutputMediaHandler* output() { return output_.get(); }
// Create a series of samples where each sample has the same duration and ever // Create a series of samples where each sample has the same duration and ever
// sample that is an even multiple of |key_frame_frequency| will be a key // sample that is an even multiple of |key_frame_frequency| will be a key
// frame. // frame.
@ -84,11 +79,6 @@ class TrickPlayHandlerTest : public MediaHandlerTestBase {
return samples; return samples;
} }
private:
std::shared_ptr<FakeInputMediaHandler> input_;
std::shared_ptr<MediaHandler> trick_play_;
std::shared_ptr<MockOutputMediaHandler> output_;
}; };
// This test makes sure that audio streams are rejected by trick play handlers. // This test makes sure that audio streams are rejected by trick play handlers.
@ -96,8 +86,9 @@ TEST_F(TrickPlayHandlerTest, RejectsAudio) {
const uint32_t kTrickPlayFactor = 1u; const uint32_t kTrickPlayFactor = 1u;
SetUpAndInitializeGraph(kTrickPlayFactor); SetUpAndInitializeGraph(kTrickPlayFactor);
Status status = input()->Dispatch( Status status = Input(kInputIndex)
StreamData::FromStreamInfo(kStreamIndex, GetAudioStreamInfo(kTimescale))); ->Dispatch(StreamData::FromStreamInfo(
kStreamIndex, GetAudioStreamInfo(kTimescale)));
EXPECT_EQ(error::TRICK_PLAY_ERROR, status.error_code()); EXPECT_EQ(error::TRICK_PLAY_ERROR, status.error_code());
} }
@ -114,14 +105,15 @@ TEST_F(TrickPlayHandlerTest, TrickTrackNoSamples) {
{ {
testing::InSequence s; testing::InSequence s;
EXPECT_CALL(*output(), EXPECT_CALL(*Output(kOutputIndex),
OnProcess(IsTrickPlayVideoStream(kTrickPlayFactor, kPlayRate))); OnProcess(IsTrickPlayVideoStream(kTrickPlayFactor, kPlayRate)));
EXPECT_CALL(*output(), OnFlush(kStreamIndex)); EXPECT_CALL(*Output(kOutputIndex), OnFlush(kStreamIndex));
} }
ASSERT_OK(input()->Dispatch(StreamData::FromStreamInfo( ASSERT_OK(Input(kInputIndex)
kStreamIndex, GetVideoStreamInfo(kTimescale)))); ->Dispatch(StreamData::FromStreamInfo(
ASSERT_OK(input()->FlushAllDownstreams()); kStreamIndex, GetVideoStreamInfo(kTimescale))));
ASSERT_OK(Input(kInputIndex)->FlushAllDownstreams());
} }
// This test makes sure that when the trick play handler is initialized using // This test makes sure that when the trick play handler is initialized using
@ -142,28 +134,31 @@ TEST_F(TrickPlayHandlerTest, TrickTrackWithSamplesOnlyGetsKeyFrames) {
// handler. // handler.
{ {
testing::InSequence s; testing::InSequence s;
EXPECT_CALL(*output(), EXPECT_CALL(*Output(kOutputIndex),
OnProcess(IsTrickPlayVideoStream(kTrickPlayFactor, kPlayRate))); OnProcess(IsTrickPlayVideoStream(kTrickPlayFactor, kPlayRate)));
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
EXPECT_CALL(*output(), OnProcess(IsTrickPlaySample( EXPECT_CALL(
kStartTime + i * kTrickPlaySampleDuration, *Output(kOutputIndex),
kTrickPlaySampleDuration))); OnProcess(IsTrickPlaySample(kStartTime + i * kTrickPlaySampleDuration,
kTrickPlaySampleDuration)));
} }
EXPECT_CALL(*output(), OnFlush(kStreamIndex)); EXPECT_CALL(*Output(kOutputIndex), OnFlush(kStreamIndex));
} }
std::vector<std::shared_ptr<MediaSample>> samples = std::vector<std::shared_ptr<MediaSample>> samples =
CreateSamples(9 /* sample count */, kStartTime, kDuration, kKeyFrameRate); CreateSamples(9 /* sample count */, kStartTime, kDuration, kKeyFrameRate);
ASSERT_OK(input()->Dispatch(StreamData::FromStreamInfo( ASSERT_OK(Input(kInputIndex)
kStreamIndex, GetVideoStreamInfo(kTimescale)))); ->Dispatch(StreamData::FromStreamInfo(
kStreamIndex, GetVideoStreamInfo(kTimescale))));
for (const auto& sample : samples) { for (const auto& sample : samples) {
ASSERT_OK( ASSERT_OK(
input()->Dispatch(StreamData::FromMediaSample(kStreamIndex, sample))); Input(kInputIndex)
->Dispatch(StreamData::FromMediaSample(kStreamIndex, sample)));
} }
ASSERT_OK(input()->FlushAllDownstreams()); ASSERT_OK(Input(kInputIndex)->FlushAllDownstreams());
} }
// This test makes sure that when the trick play handler is initialized using // This test makes sure that when the trick play handler is initialized using
@ -184,28 +179,31 @@ TEST_F(TrickPlayHandlerTest, TrickTrackWithSamples) {
// handler. // handler.
{ {
testing::InSequence s; testing::InSequence s;
EXPECT_CALL(*output(), EXPECT_CALL(*Output(kOutputIndex),
OnProcess(IsTrickPlayVideoStream(kTrickPlayFactor, kPlayRate))); OnProcess(IsTrickPlayVideoStream(kTrickPlayFactor, kPlayRate)));
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
EXPECT_CALL(*output(), OnProcess(IsTrickPlaySample( EXPECT_CALL(
kStartTime + i * kTrickPlaySampleDuration, *Output(kOutputIndex),
kTrickPlaySampleDuration))); OnProcess(IsTrickPlaySample(kStartTime + i * kTrickPlaySampleDuration,
kTrickPlaySampleDuration)));
} }
EXPECT_CALL(*output(), OnFlush(0u)); EXPECT_CALL(*Output(kOutputIndex), OnFlush(0u));
} }
std::vector<std::shared_ptr<MediaSample>> samples = std::vector<std::shared_ptr<MediaSample>> samples =
CreateSamples(8 /* sample count */, kStartTime, kDuration, kKeyFrameRate); CreateSamples(8 /* sample count */, kStartTime, kDuration, kKeyFrameRate);
ASSERT_OK(input()->Dispatch(StreamData::FromStreamInfo( ASSERT_OK(Input(kInputIndex)
kStreamIndex, GetVideoStreamInfo(kTimescale)))); ->Dispatch(StreamData::FromStreamInfo(
kStreamIndex, GetVideoStreamInfo(kTimescale))));
for (const auto& sample : samples) { for (const auto& sample : samples) {
ASSERT_OK( ASSERT_OK(
input()->Dispatch(StreamData::FromMediaSample(kStreamIndex, sample))); Input(kInputIndex)
->Dispatch(StreamData::FromMediaSample(kStreamIndex, sample)));
} }
ASSERT_OK(input()->FlushAllDownstreams()); ASSERT_OK(Input(kInputIndex)->FlushAllDownstreams());
} }
TEST_F(TrickPlayHandlerTest, TrickTrackWithSamplesAndSegments) { TEST_F(TrickPlayHandlerTest, TrickTrackWithSamplesAndSegments) {
@ -223,30 +221,33 @@ TEST_F(TrickPlayHandlerTest, TrickTrackWithSamplesAndSegments) {
// handler. // handler.
{ {
testing::InSequence s; testing::InSequence s;
EXPECT_CALL(*output(), EXPECT_CALL(*Output(kOutputIndex),
OnProcess(IsTrickPlayVideoStream(kTrickPlayFactor, kPlayRate))); OnProcess(IsTrickPlayVideoStream(kTrickPlayFactor, kPlayRate)));
// Segment One // Segment One
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
EXPECT_CALL(*output(), OnProcess(IsTrickPlaySample( EXPECT_CALL(
kStartTime + kTrickPlaySampleDuration * i, *Output(kOutputIndex),
kTrickPlaySampleDuration))); OnProcess(IsTrickPlaySample(kStartTime + kTrickPlaySampleDuration * i,
kTrickPlaySampleDuration)));
} }
EXPECT_CALL(*output(), EXPECT_CALL(*Output(kOutputIndex),
OnProcess(IsSegmentInfo(kStreamIndex, kStartTime, 4 * kDuration, OnProcess(IsSegmentInfo(kStreamIndex, kStartTime, 4 * kDuration,
!kSubSegment, !kEncrypted))); !kSubSegment, !kEncrypted)));
// Segment Two // Segment Two
for (int i = 2; i < 4; i++) { for (int i = 2; i < 4; i++) {
EXPECT_CALL(*output(), OnProcess(IsTrickPlaySample( EXPECT_CALL(
kStartTime + kTrickPlaySampleDuration * i, *Output(kOutputIndex),
kTrickPlaySampleDuration))); OnProcess(IsTrickPlaySample(kStartTime + kTrickPlaySampleDuration * i,
kTrickPlaySampleDuration)));
} }
EXPECT_CALL(*output(), OnProcess(IsSegmentInfo( EXPECT_CALL(
kStreamIndex, kStartTime + 4 * kDuration, *Output(kOutputIndex),
4 * kDuration, !kSubSegment, !kEncrypted))); OnProcess(IsSegmentInfo(kStreamIndex, kStartTime + 4 * kDuration,
4 * kDuration, !kSubSegment, !kEncrypted)));
EXPECT_CALL(*output(), OnFlush(0u)); EXPECT_CALL(*Output(kOutputIndex), OnFlush(0u));
} }
std::vector<std::shared_ptr<MediaSample>> segment_one_samples = std::vector<std::shared_ptr<MediaSample>> segment_one_samples =
@ -256,27 +257,33 @@ TEST_F(TrickPlayHandlerTest, TrickTrackWithSamplesAndSegments) {
CreateSamples(4 /* sample count */, kStartTime + 4 * kDuration, kDuration, CreateSamples(4 /* sample count */, kStartTime + 4 * kDuration, kDuration,
kKeyFrameRate); kKeyFrameRate);
ASSERT_OK(input()->Dispatch(StreamData::FromStreamInfo( ASSERT_OK(Input(kInputIndex)
kStreamIndex, GetVideoStreamInfo(kTimescale)))); ->Dispatch(StreamData::FromStreamInfo(
kStreamIndex, GetVideoStreamInfo(kTimescale))));
// Segment One // Segment One
for (const auto& sample : segment_one_samples) { for (const auto& sample : segment_one_samples) {
ASSERT_OK( ASSERT_OK(
input()->Dispatch(StreamData::FromMediaSample(kStreamIndex, sample))); Input(kInputIndex)
->Dispatch(StreamData::FromMediaSample(kStreamIndex, sample)));
} }
ASSERT_OK(input()->Dispatch(StreamData::FromSegmentInfo( ASSERT_OK(Input(kInputIndex)
kStreamIndex, GetSegmentInfo(kStartTime, kDuration * 4, !kEncrypted)))); ->Dispatch(StreamData::FromSegmentInfo(
kStreamIndex,
GetSegmentInfo(kStartTime, kDuration * 4, !kEncrypted))));
// Segment Two // Segment Two
for (const auto& sample : segment_two_samples) { for (const auto& sample : segment_two_samples) {
ASSERT_OK( ASSERT_OK(
input()->Dispatch(StreamData::FromMediaSample(kStreamIndex, sample))); Input(kInputIndex)
->Dispatch(StreamData::FromMediaSample(kStreamIndex, sample)));
} }
ASSERT_OK(input()->Dispatch(StreamData::FromSegmentInfo( ASSERT_OK(Input(kInputIndex)
kStreamIndex, ->Dispatch(StreamData::FromSegmentInfo(
GetSegmentInfo(kStartTime + 4 * kDuration, 4 * kDuration, !kEncrypted)))); kStreamIndex, GetSegmentInfo(kStartTime + 4 * kDuration,
4 * kDuration, !kEncrypted))));
ASSERT_OK(input()->FlushAllDownstreams()); ASSERT_OK(Input(kInputIndex)->FlushAllDownstreams());
} }
} // namespace media } // namespace media