| Index: chromecast/media/audio/cast_audio_output_stream_unittest.cc
|
| diff --git a/chromecast/media/audio/cast_audio_output_stream_unittest.cc b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
|
| index 89744ec381e3e23d4a70c7c027363830782f95d7..f055c95e156e9a0fa874d245fc80a2e7cf75e8bb 100644
|
| --- a/chromecast/media/audio/cast_audio_output_stream_unittest.cc
|
| +++ b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
|
| @@ -15,14 +15,19 @@
|
| #include "base/time/time.h"
|
| #include "chromecast/base/metrics/cast_metrics_test_helper.h"
|
| #include "chromecast/media/audio/cast_audio_manager.h"
|
| +#include "chromecast/media/audio/cast_audio_mixer.h"
|
| +#include "chromecast/media/cma/test/mock_media_pipeline_backend_factory.h"
|
| #include "chromecast/public/media/cast_decoder_buffer.h"
|
| #include "chromecast/public/media/media_pipeline_backend.h"
|
| +#include "chromecast/public/task_runner.h"
|
| +#include "media/audio/mock_audio_source_callback.h"
|
| #include "media/audio/test_audio_thread.h"
|
| #include "testing/gmock/include/gmock/gmock.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| -using ::testing::Invoke;
|
| -using ::testing::_;
|
| +using testing::_;
|
| +using testing::Invoke;
|
| +using testing::NiceMock;
|
|
|
| namespace chromecast {
|
| namespace media {
|
| @@ -39,6 +44,20 @@ int OnMoreData(base::TimeDelta /* delay */,
|
| return dest->frames();
|
| }
|
|
|
| +class NotifyPushBufferCompleteTask : public chromecast::TaskRunner::Task {
|
| + public:
|
| + NotifyPushBufferCompleteTask(
|
| + MediaPipelineBackend::Decoder::Delegate* delegate)
|
| + : delegate_(delegate) {}
|
| + ~NotifyPushBufferCompleteTask() override = default;
|
| + void Run() override {
|
| + delegate_->OnPushBufferComplete(MediaPipelineBackend::kBufferSuccess);
|
| + }
|
| +
|
| + private:
|
| + MediaPipelineBackend::Decoder::Delegate* const delegate_;
|
| +};
|
| +
|
| class FakeAudioDecoder : public MediaPipelineBackend::AudioDecoder {
|
| public:
|
| enum PipelineStatus {
|
| @@ -48,8 +67,9 @@ class FakeAudioDecoder : public MediaPipelineBackend::AudioDecoder {
|
| PIPELINE_STATUS_ASYNC_ERROR,
|
| };
|
|
|
| - FakeAudioDecoder()
|
| - : volume_(1.0f),
|
| + FakeAudioDecoder(const MediaPipelineDeviceParams& params)
|
| + : params_(params),
|
| + volume_(1.0f),
|
| pipeline_status_(PIPELINE_STATUS_OK),
|
| pending_push_(false),
|
| pushed_buffer_count_(0),
|
| @@ -99,7 +119,8 @@ class FakeAudioDecoder : public MediaPipelineBackend::AudioDecoder {
|
| void set_pipeline_status(PipelineStatus status) {
|
| if (status == PIPELINE_STATUS_OK && pending_push_) {
|
| pending_push_ = false;
|
| - delegate_->OnPushBufferComplete(MediaPipelineBackend::kBufferSuccess);
|
| + params_.task_runner->PostTask(new NotifyPushBufferCompleteTask(delegate_),
|
| + 0);
|
| }
|
| pipeline_status_ = status;
|
| }
|
| @@ -110,6 +131,7 @@ class FakeAudioDecoder : public MediaPipelineBackend::AudioDecoder {
|
| CastDecoderBuffer* last_buffer() { return last_buffer_; }
|
|
|
| private:
|
| + const MediaPipelineDeviceParams params_;
|
| AudioConfig config_;
|
| float volume_;
|
|
|
| @@ -125,13 +147,14 @@ class FakeMediaPipelineBackend : public MediaPipelineBackend {
|
| public:
|
| enum State { kStateStopped, kStateRunning, kStatePaused };
|
|
|
| - FakeMediaPipelineBackend() : state_(kStateStopped), audio_decoder_(nullptr) {}
|
| + FakeMediaPipelineBackend(const MediaPipelineDeviceParams& params)
|
| + : params_(params), state_(kStateStopped), audio_decoder_(nullptr) {}
|
| ~FakeMediaPipelineBackend() override {}
|
|
|
| // MediaPipelineBackend implementation:
|
| AudioDecoder* CreateAudioDecoder() override {
|
| DCHECK(!audio_decoder_);
|
| - audio_decoder_ = base::MakeUnique<FakeAudioDecoder>();
|
| + audio_decoder_ = base::MakeUnique<FakeAudioDecoder>(params_);
|
| return audio_decoder_.get();
|
| }
|
| VideoDecoder* CreateVideoDecoder() override {
|
| @@ -166,62 +189,17 @@ class FakeMediaPipelineBackend : public MediaPipelineBackend {
|
| FakeAudioDecoder* decoder() const { return audio_decoder_.get(); }
|
|
|
| private:
|
| + const MediaPipelineDeviceParams params_;
|
| State state_;
|
| std::unique_ptr<FakeAudioDecoder> audio_decoder_;
|
| };
|
|
|
| -class MockAudioSourceCallback
|
| - : public ::media::AudioOutputStream::AudioSourceCallback {
|
| - public:
|
| - // ::media::AudioOutputStream::AudioSourceCallback overrides.
|
| - MOCK_METHOD4(OnMoreData,
|
| - int(base::TimeDelta, base::TimeTicks, int, ::media::AudioBus*));
|
| - MOCK_METHOD0(OnError, void());
|
| -};
|
| -
|
| -class FakeAudioManager : public CastAudioManager {
|
| - public:
|
| - FakeAudioManager()
|
| - : CastAudioManager(base::MakeUnique<::media::TestAudioThread>(),
|
| - nullptr,
|
| - nullptr,
|
| - nullptr),
|
| - media_pipeline_backend_(nullptr) {}
|
| - ~FakeAudioManager() override {}
|
| -
|
| - // CastAudioManager overrides.
|
| - std::unique_ptr<MediaPipelineBackend> CreateMediaPipelineBackend(
|
| - const MediaPipelineDeviceParams& params) override {
|
| - DCHECK(GetTaskRunner()->BelongsToCurrentThread());
|
| - DCHECK(!media_pipeline_backend_);
|
| -
|
| - std::unique_ptr<FakeMediaPipelineBackend> backend(
|
| - new FakeMediaPipelineBackend());
|
| - // Cache the backend locally to be used by tests.
|
| - media_pipeline_backend_ = backend.get();
|
| - return std::move(backend);
|
| - }
|
| - void ReleaseOutputStream(::media::AudioOutputStream* stream) override {
|
| - DCHECK(media_pipeline_backend_);
|
| - media_pipeline_backend_ = nullptr;
|
| - CastAudioManager::ReleaseOutputStream(stream);
|
| - }
|
| -
|
| - // Returns the MediaPipelineBackend being used by the AudioOutputStream.
|
| - // Note: here is a valid MediaPipelineBackend only while the stream is open.
|
| - // Returns NULL at all other times.
|
| - FakeMediaPipelineBackend* media_pipeline_backend() {
|
| - return media_pipeline_backend_;
|
| - }
|
| -
|
| - private:
|
| - FakeMediaPipelineBackend* media_pipeline_backend_;
|
| -};
|
| -
|
| class CastAudioOutputStreamTest : public ::testing::Test {
|
| public:
|
| CastAudioOutputStreamTest()
|
| - : format_(::media::AudioParameters::AUDIO_PCM_LINEAR),
|
| + : media_thread_("CastMediaThread"),
|
| + media_pipeline_backend_(nullptr),
|
| + format_(::media::AudioParameters::AUDIO_PCM_LINEAR),
|
| channel_layout_(::media::CHANNEL_LAYOUT_MONO),
|
| sample_rate_(::media::AudioParameters::kAudioCDSampleRate),
|
| bits_per_sample_(16),
|
| @@ -231,7 +209,18 @@ class CastAudioOutputStreamTest : public ::testing::Test {
|
| protected:
|
| void SetUp() override {
|
| metrics::InitializeMetricsHelperForTesting();
|
| - audio_manager_ = base::MakeUnique<FakeAudioManager>();
|
| +
|
| + CHECK(media_thread_.Start());
|
| + auto backend_factory =
|
| + base::MakeUnique<NiceMock<MockMediaPipelineBackendFactory>>();
|
| + ON_CALL(*backend_factory, CreateBackend(_))
|
| + .WillByDefault(Invoke([this](const MediaPipelineDeviceParams& params) {
|
| + media_pipeline_backend_ = new FakeMediaPipelineBackend(params);
|
| + return base::WrapUnique(media_pipeline_backend_);
|
| + }));
|
| + audio_manager_ = base::MakeUnique<CastAudioManager>(
|
| + base::MakeUnique<::media::TestAudioThread>(), nullptr,
|
| + std::move(backend_factory), media_thread_.task_runner(), false);
|
| }
|
|
|
| void TearDown() override { audio_manager_->Shutdown(); }
|
| @@ -241,9 +230,7 @@ class CastAudioOutputStreamTest : public ::testing::Test {
|
| bits_per_sample_, frames_per_buffer_);
|
| }
|
|
|
| - FakeMediaPipelineBackend* GetBackend() {
|
| - return audio_manager_->media_pipeline_backend();
|
| - }
|
| + FakeMediaPipelineBackend* GetBackend() { return media_pipeline_backend_; }
|
|
|
| FakeAudioDecoder* GetAudio() {
|
| FakeMediaPipelineBackend* backend = GetBackend();
|
| @@ -269,7 +256,10 @@ class CastAudioOutputStreamTest : public ::testing::Test {
|
| }
|
|
|
| base::MessageLoop message_loop_;
|
| - std::unique_ptr<FakeAudioManager> audio_manager_;
|
| + base::Thread media_thread_;
|
| + std::unique_ptr<CastAudioManager> audio_manager_;
|
| + // MockMediaPipelineBackendFactory* backend_factory_;
|
| + FakeMediaPipelineBackend* media_pipeline_backend_;
|
| // AudioParameters used to create AudioOutputStream.
|
| // Tests can modify these parameters before calling CreateStream.
|
| ::media::AudioParameters::Format format_;
|
| @@ -281,7 +271,7 @@ class CastAudioOutputStreamTest : public ::testing::Test {
|
|
|
| TEST_F(CastAudioOutputStreamTest, Format) {
|
| ::media::AudioParameters::Format format[] = {
|
| - //::media::AudioParameters::AUDIO_PCM_LINEAR,
|
| + ::media::AudioParameters::AUDIO_PCM_LINEAR,
|
| ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY};
|
| for (size_t i = 0; i < arraysize(format); ++i) {
|
| format_ = format[i];
|
| @@ -350,7 +340,6 @@ TEST_F(CastAudioOutputStreamTest, BitsPerSample) {
|
| TEST_F(CastAudioOutputStreamTest, DeviceState) {
|
| ::media::AudioOutputStream* stream = CreateStream();
|
| ASSERT_TRUE(stream);
|
| - EXPECT_FALSE(GetAudio());
|
|
|
| EXPECT_TRUE(stream->Open());
|
| FakeAudioDecoder* audio_decoder = GetAudio();
|
| @@ -359,17 +348,18 @@ TEST_F(CastAudioOutputStreamTest, DeviceState) {
|
| ASSERT_TRUE(backend);
|
| EXPECT_EQ(FakeMediaPipelineBackend::kStateStopped, backend->state());
|
|
|
| - auto source_callback(base::MakeUnique<MockAudioSourceCallback>());
|
| - ON_CALL(*source_callback, OnMoreData(_, _, _, _))
|
| - .WillByDefault(Invoke(OnMoreData));
|
| - stream->Start(source_callback.get());
|
| + ::media::MockAudioSourceCallback source_callback;
|
| + EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
|
| + .WillRepeatedly(Invoke(OnMoreData));
|
| + stream->Start(&source_callback);
|
| + media_thread_.FlushForTesting();
|
| EXPECT_EQ(FakeMediaPipelineBackend::kStateRunning, backend->state());
|
|
|
| stream->Stop();
|
| + media_thread_.FlushForTesting();
|
| EXPECT_EQ(FakeMediaPipelineBackend::kStatePaused, backend->state());
|
|
|
| stream->Close();
|
| - EXPECT_FALSE(GetAudio());
|
| }
|
|
|
| TEST_F(CastAudioOutputStreamTest, PushFrame) {
|
| @@ -383,12 +373,12 @@ TEST_F(CastAudioOutputStreamTest, PushFrame) {
|
| EXPECT_EQ(0u, audio_decoder->pushed_buffer_count());
|
| EXPECT_FALSE(audio_decoder->last_buffer());
|
|
|
| - auto source_callback(base::MakeUnique<MockAudioSourceCallback>());
|
| - ON_CALL(*source_callback, OnMoreData(_, _, _, _))
|
| - .WillByDefault(Invoke(OnMoreData));
|
| + ::media::MockAudioSourceCallback source_callback;
|
| + EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
|
| + .WillRepeatedly(Invoke(OnMoreData));
|
| // No error must be reported to source callback.
|
| - EXPECT_CALL(*source_callback, OnError()).Times(0);
|
| - stream->Start(source_callback.get());
|
| + EXPECT_CALL(source_callback, OnError()).Times(0);
|
| + stream->Start(&source_callback);
|
| RunMessageLoopFor(2);
|
| stream->Stop();
|
|
|
| @@ -418,12 +408,12 @@ TEST_F(CastAudioOutputStreamTest, DeviceBusy) {
|
| ASSERT_TRUE(audio_decoder);
|
| audio_decoder->set_pipeline_status(FakeAudioDecoder::PIPELINE_STATUS_BUSY);
|
|
|
| - auto source_callback(base::MakeUnique<MockAudioSourceCallback>());
|
| - ON_CALL(*source_callback, OnMoreData(_, _, _, _))
|
| - .WillByDefault(Invoke(OnMoreData));
|
| + ::media::MockAudioSourceCallback source_callback;
|
| + EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
|
| + .WillRepeatedly(Invoke(OnMoreData));
|
| // No error must be reported to source callback.
|
| - EXPECT_CALL(*source_callback, OnError()).Times(0);
|
| - stream->Start(source_callback.get());
|
| + EXPECT_CALL(source_callback, OnError()).Times(0);
|
| + stream->Start(&source_callback);
|
| RunMessageLoopFor(5);
|
| // Make sure that one frame was pushed.
|
| EXPECT_EQ(1u, audio_decoder->pushed_buffer_count());
|
| @@ -451,12 +441,12 @@ TEST_F(CastAudioOutputStreamTest, DeviceError) {
|
| ASSERT_TRUE(audio_decoder);
|
| audio_decoder->set_pipeline_status(FakeAudioDecoder::PIPELINE_STATUS_ERROR);
|
|
|
| - auto source_callback(base::MakeUnique<MockAudioSourceCallback>());
|
| - ON_CALL(*source_callback, OnMoreData(_, _, _, _))
|
| - .WillByDefault(Invoke(OnMoreData));
|
| + ::media::MockAudioSourceCallback source_callback;
|
| + EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
|
| + .WillRepeatedly(Invoke(OnMoreData));
|
| // AudioOutputStream must report error to source callback.
|
| - EXPECT_CALL(*source_callback, OnError());
|
| - stream->Start(source_callback.get());
|
| + EXPECT_CALL(source_callback, OnError());
|
| + stream->Start(&source_callback);
|
| RunMessageLoopFor(2);
|
| // Make sure that AudioOutputStream attempted to push the initial frame.
|
| EXPECT_LT(0u, audio_decoder->pushed_buffer_count());
|
| @@ -475,12 +465,12 @@ TEST_F(CastAudioOutputStreamTest, DeviceAsyncError) {
|
| audio_decoder->set_pipeline_status(
|
| FakeAudioDecoder::PIPELINE_STATUS_ASYNC_ERROR);
|
|
|
| - auto source_callback(base::MakeUnique<MockAudioSourceCallback>());
|
| - ON_CALL(*source_callback, OnMoreData(_, _, _, _))
|
| - .WillByDefault(Invoke(OnMoreData));
|
| + ::media::MockAudioSourceCallback source_callback;
|
| + EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
|
| + .WillRepeatedly(Invoke(OnMoreData));
|
| // AudioOutputStream must report error to source callback.
|
| - EXPECT_CALL(*source_callback, OnError());
|
| - stream->Start(source_callback.get());
|
| + EXPECT_CALL(source_callback, OnError());
|
| + stream->Start(&source_callback);
|
| RunMessageLoopFor(5);
|
|
|
| // Make sure that one frame was pushed.
|
| @@ -503,6 +493,7 @@ TEST_F(CastAudioOutputStreamTest, Volume) {
|
| EXPECT_EQ(1.0f, audio_decoder->volume());
|
|
|
| stream->SetVolume(0.5);
|
| + media_thread_.FlushForTesting();
|
| stream->GetVolume(&volume);
|
| EXPECT_EQ(0.5, volume);
|
| EXPECT_EQ(0.5f, audio_decoder->volume());
|
| @@ -515,13 +506,13 @@ TEST_F(CastAudioOutputStreamTest, StartStopStart) {
|
| ASSERT_TRUE(stream);
|
| ASSERT_TRUE(stream->Open());
|
|
|
| - auto source_callback(base::MakeUnique<MockAudioSourceCallback>());
|
| - ON_CALL(*source_callback, OnMoreData(_, _, _, _))
|
| - .WillByDefault(Invoke(OnMoreData));
|
| - stream->Start(source_callback.get());
|
| + ::media::MockAudioSourceCallback source_callback;
|
| + EXPECT_CALL(source_callback, OnMoreData(_, _, _, _))
|
| + .WillRepeatedly(Invoke(OnMoreData));
|
| + stream->Start(&source_callback);
|
| RunMessageLoopFor(2);
|
| stream->Stop();
|
| - stream->Start(source_callback.get());
|
| + stream->Start(&source_callback);
|
| RunMessageLoopFor(2);
|
|
|
| FakeAudioDecoder* audio_device = GetAudio();
|
| @@ -549,14 +540,14 @@ TEST_F(CastAudioOutputStreamTest, AudioDelay) {
|
| MediaPipelineBackend::AudioDecoder::RenderingDelay(kDelayUs,
|
| kDelayTimestampUs));
|
|
|
| - auto source_callback(base::MakeUnique<MockAudioSourceCallback>());
|
| + ::media::MockAudioSourceCallback source_callback;
|
| const base::TimeDelta delay(base::TimeDelta::FromMicroseconds(kDelayUs));
|
| const base::TimeTicks delay_timestamp(
|
| base::TimeTicks() + base::TimeDelta::FromMicroseconds(kDelayTimestampUs));
|
| - EXPECT_CALL(*source_callback, OnMoreData(delay, delay_timestamp, _, _))
|
| + EXPECT_CALL(source_callback, OnMoreData(delay, delay_timestamp, _, _))
|
| .WillRepeatedly(Invoke(OnMoreData));
|
|
|
| - stream->Start(source_callback.get());
|
| + stream->Start(&source_callback);
|
| RunMessageLoopFor(2);
|
| stream->Stop();
|
| stream->Close();
|
|
|