blob: 7ca4e09b2e40283a0c11c43a2fc09b3dbd57d38f [file] [log] [blame]
/*
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "media/filters/shell_audio_renderer.h"
#include "base/bind.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/memory/ref_counted.h"
#include "media/base/audio_bus.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/gmock_callback_support.h"
#include "media/base/mock_audio_renderer_sink.h"
#include "media/base/mock_filters.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::AtMost;
using ::testing::InSequence;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::ReturnRef;
namespace media {
class ShellAudioRendererTest : public ::testing::Test {
public:
ShellAudioRendererTest()
: audio_decoder_config_(kCodecVorbis,
32,
CHANNEL_LAYOUT_MONO,
44100,
NULL,
0,
false),
sink_(new NiceMock<MockAudioRendererSink>),
demuxer_stream_(new NiceMock<MockDemuxerStream>),
decoder_(new NiceMock<MockAudioDecoder>) {
renderer_ = ShellAudioRenderer::Create(sink_, SetDecryptorReadyCB(),
base::MessageLoopProxy::current());
ON_CALL(*demuxer_stream_, type())
.WillByDefault(Return(DemuxerStream::AUDIO));
ON_CALL(*demuxer_stream_, audio_decoder_config())
.WillByDefault(ReturnRef(audio_decoder_config_));
ON_CALL(*decoder_, bits_per_channel()).WillByDefault(Return(32));
ON_CALL(*decoder_, channel_layout())
.WillByDefault(Return(CHANNEL_LAYOUT_MONO));
ON_CALL(*decoder_, samples_per_second()).WillByDefault(Return(44100));
ON_CALL(*decoder_, Reset(_)).WillByDefault(RunCallback<0>());
}
MOCK_METHOD1(OnPipelineStatus, void(PipelineStatus));
MOCK_METHOD1(OnPipelineStatistics, void(const PipelineStatistics&));
MOCK_METHOD0(OnUnderflow, void());
MOCK_METHOD0(OnEnded, void());
MOCK_METHOD0(OnDisabled, void());
MOCK_METHOD1(OnError, void(PipelineStatus));
MOCK_METHOD0(OnStopped, void());
void OnAudioTimeCallback(base::TimeDelta current_time,
base::TimeDelta max_time) {
CHECK(current_time <= max_time);
}
void InitializeWithoutWaitForPendingTasks() { Initialize(false); }
void InitializeAndWaitForPendingTasks() { Initialize(true); }
void Preroll() {
renderer_->Preroll(base::TimeDelta(),
base::Bind(&ShellAudioRendererTest::OnPipelineStatus,
base::Unretained(this)));
}
void StopAndWaitForPendingTasks() {
EXPECT_CALL(*this, OnStopped()).Times(1);
renderer_->Stop(
base::Bind(&ShellAudioRendererTest::OnStopped, base::Unretained(this)));
#if !defined(__LB_PS3__)
// The extra Render call is required by the ShellAudioRendererImpl when the
// renderer starts to running.
scoped_ptr<AudioBus> audio_bus = AudioBus::Create(1, 1024, 4, false);
renderer_->Render(audio_bus.get(), 0);
#endif // !defined(__LB_PS3__)
FinishPendingTasks();
}
void FinishPendingTasks() { message_loop_.RunUntilIdle(); }
private:
void Initialize(bool wait_until_finished) {
EXPECT_CALL(*decoder_, Initialize(_, _, _))
.WillOnce(RunCallback<1>(PIPELINE_OK));
if (wait_until_finished) {
EXPECT_CALL(*this, OnPipelineStatus(_)).Times(1);
} else {
EXPECT_CALL(*this, OnPipelineStatus(_)).Times(AtMost(1));
}
AudioRenderer::AudioDecoderList decoders;
decoders.push_back(decoder_);
renderer_->Initialize(
demuxer_stream_, decoders,
base::Bind(&ShellAudioRendererTest::OnPipelineStatus,
base::Unretained(this)),
base::Bind(&ShellAudioRendererTest::OnPipelineStatistics,
base::Unretained(this)),
base::Bind(&ShellAudioRendererTest::OnUnderflow,
base::Unretained(this)),
base::Bind(&ShellAudioRendererTest::OnAudioTimeCallback,
base::Unretained(this)),
base::Bind(&ShellAudioRendererTest::OnEnded, base::Unretained(this)),
base::Bind(&ShellAudioRendererTest::OnDisabled, base::Unretained(this)),
base::Bind(&ShellAudioRendererTest::OnError, base::Unretained(this)));
if (wait_until_finished) {
FinishPendingTasks();
}
}
AudioDecoderConfig audio_decoder_config_;
scoped_refptr<NiceMock<MockAudioRendererSink> > sink_;
scoped_refptr<NiceMock<MockDemuxerStream> > demuxer_stream_;
scoped_refptr<NiceMock<MockAudioDecoder> > decoder_;
scoped_refptr<ShellAudioRenderer> renderer_;
MessageLoop message_loop_;
};
TEST_F(ShellAudioRendererTest, Initialize) {
InSequence in_sequence;
InitializeAndWaitForPendingTasks();
StopAndWaitForPendingTasks();
}
TEST_F(ShellAudioRendererTest, StopImmediatelyAfterInitialize) {
// Not using InSequence here as the audio renderer may call init_cb after
// stop_cb is called.
InitializeWithoutWaitForPendingTasks();
StopAndWaitForPendingTasks();
}
TEST_F(ShellAudioRendererTest, Preroll) {
InSequence in_sequence;
InitializeAndWaitForPendingTasks();
Preroll();
FinishPendingTasks();
StopAndWaitForPendingTasks();
}
TEST_F(ShellAudioRendererTest, StopImmediatelyAfterPreroll) {
InSequence in_sequence;
InitializeAndWaitForPendingTasks();
Preroll();
StopAndWaitForPendingTasks();
}
} // namespace media