blob: 0793744cbe8929bdc850d19f2511e6db8a95bff7 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/media/cma/base/buffering_frame_provider.h"
#include <stddef.h>
#include <list>
#include <memory>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "chromecast/media/cma/test/frame_generator_for_test.h"
#include "chromecast/media/cma/test/mock_frame_consumer.h"
#include "chromecast/media/cma/test/mock_frame_provider.h"
#include "chromecast/public/media/cast_decoder_buffer.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/decoder_buffer.h"
#include "media/base/video_decoder_config.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromecast {
namespace media {
class BufferingFrameProviderTest : public testing::Test {
public:
BufferingFrameProviderTest();
~BufferingFrameProviderTest() override;
// Setup the test.
void Configure(
size_t frame_count,
const std::vector<bool>& provider_delayed_pattern,
const std::vector<bool>& consumer_delayed_pattern);
// Start the test.
void Start();
protected:
std::unique_ptr<BufferingFrameProvider> buffering_frame_provider_;
std::unique_ptr<MockFrameConsumer> frame_consumer_;
private:
void OnTestTimeout();
void OnTestCompleted();
DISALLOW_COPY_AND_ASSIGN(BufferingFrameProviderTest);
};
BufferingFrameProviderTest::BufferingFrameProviderTest() {
}
BufferingFrameProviderTest::~BufferingFrameProviderTest() {
}
void BufferingFrameProviderTest::Configure(
size_t frame_count,
const std::vector<bool>& provider_delayed_pattern,
const std::vector<bool>& consumer_delayed_pattern) {
DCHECK_GE(frame_count, 1u);
// Frame generation on the producer and consumer side.
std::vector<FrameGeneratorForTest::FrameSpec> frame_specs(frame_count);
for (size_t k = 0; k < frame_specs.size() - 1; k++) {
frame_specs[k].has_config = (k == 0);
frame_specs[k].timestamp = base::TimeDelta::FromMilliseconds(40) * k;
frame_specs[k].size = 512;
frame_specs[k].has_decrypt_config = ((k % 3) == 0);
}
frame_specs.back().is_eos = true;
std::unique_ptr<FrameGeneratorForTest> frame_generator_provider(
new FrameGeneratorForTest(frame_specs));
std::unique_ptr<FrameGeneratorForTest> frame_generator_consumer(
new FrameGeneratorForTest(frame_specs));
std::unique_ptr<MockFrameProvider> frame_provider(new MockFrameProvider());
frame_provider->Configure(provider_delayed_pattern,
std::move(frame_generator_provider));
size_t max_frame_size = 10 * 1024;
size_t buffer_size = 10 * max_frame_size;
buffering_frame_provider_.reset(new BufferingFrameProvider(
std::unique_ptr<CodedFrameProvider>(frame_provider.release()),
buffer_size, max_frame_size, BufferingFrameProvider::FrameBufferedCB()));
frame_consumer_.reset(
new MockFrameConsumer(buffering_frame_provider_.get()));
frame_consumer_->Configure(consumer_delayed_pattern, false,
std::move(frame_generator_consumer));
}
void BufferingFrameProviderTest::Start() {
frame_consumer_->Start(
base::Bind(&BufferingFrameProviderTest::OnTestCompleted,
base::Unretained(this)));
}
void BufferingFrameProviderTest::OnTestTimeout() {
ADD_FAILURE() << "Test timed out";
if (base::MessageLoop::current())
base::MessageLoop::current()->QuitWhenIdle();
}
void BufferingFrameProviderTest::OnTestCompleted() {
base::MessageLoop::current()->QuitWhenIdle();
}
TEST_F(BufferingFrameProviderTest, FastProviderSlowConsumer) {
bool provider_delayed_pattern[] = { false };
bool consumer_delayed_pattern[] = { true };
const size_t frame_count = 100u;
Configure(
frame_count,
std::vector<bool>(
provider_delayed_pattern,
provider_delayed_pattern + arraysize(provider_delayed_pattern)),
std::vector<bool>(
consumer_delayed_pattern,
consumer_delayed_pattern + arraysize(consumer_delayed_pattern)));
std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
message_loop->task_runner()->PostTask(
FROM_HERE,
base::Bind(&BufferingFrameProviderTest::Start, base::Unretained(this)));
base::RunLoop().Run();
}
TEST_F(BufferingFrameProviderTest, SlowProviderFastConsumer) {
bool provider_delayed_pattern[] = { true };
bool consumer_delayed_pattern[] = { false };
const size_t frame_count = 100u;
Configure(
frame_count,
std::vector<bool>(
provider_delayed_pattern,
provider_delayed_pattern + arraysize(provider_delayed_pattern)),
std::vector<bool>(
consumer_delayed_pattern,
consumer_delayed_pattern + arraysize(consumer_delayed_pattern)));
std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
message_loop->task_runner()->PostTask(
FROM_HERE,
base::Bind(&BufferingFrameProviderTest::Start, base::Unretained(this)));
base::RunLoop().Run();
}
TEST_F(BufferingFrameProviderTest, SlowFastProducerConsumer) {
// Lengths are prime between each other so we can test a lot of combinations.
bool provider_delayed_pattern[] = {
true, true, true, true, true,
false, false, false, false
};
bool consumer_delayed_pattern[] = {
true, true, true, true, true, true, true,
false, false, false, false, false, false, false
};
const size_t frame_count = 100u;
Configure(
frame_count,
std::vector<bool>(
provider_delayed_pattern,
provider_delayed_pattern + arraysize(provider_delayed_pattern)),
std::vector<bool>(
consumer_delayed_pattern,
consumer_delayed_pattern + arraysize(consumer_delayed_pattern)));
std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
message_loop->task_runner()->PostTask(
FROM_HERE,
base::Bind(&BufferingFrameProviderTest::Start, base::Unretained(this)));
base::RunLoop().Run();
}
} // namespace media
} // namespace chromecast