1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromecast/base/task_runner_impl.h"
6 #include "chromecast/media/audio/cast_audio_manager.h"
7 #include "chromecast/media/audio/cast_audio_output_stream.h"
8 #include "chromecast/public/media/audio_pipeline_device.h"
9 #include "chromecast/public/media/cast_decoder_buffer.h"
10 #include "chromecast/public/media/decoder_config.h"
11 #include "chromecast/public/media/decrypt_context.h"
12 #include "chromecast/public/media/media_clock_device.h"
13 #include "chromecast/public/media/media_pipeline_backend.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace chromecast
{
19 const char kDefaultDeviceId
[] = "";
21 class FakeClockDevice
: public MediaClockDevice
{
23 FakeClockDevice() : state_(kStateUninitialized
), rate_(0.f
) {}
24 ~FakeClockDevice() override
{}
26 State
GetState() const override
{ return state_
; }
27 bool SetState(State new_state
) override
{
31 bool ResetTimeline(int64_t time_microseconds
) override
{ return true; }
32 bool SetRate(float rate
) override
{
36 int64_t GetTimeMicroseconds() override
{ return 0; }
38 float rate() const { return rate_
; }
45 class FakeAudioPipelineDevice
: public AudioPipelineDevice
{
53 FakeAudioPipelineDevice()
54 : state_(kStateUninitialized
),
55 volume_multiplier_(1.0f
),
56 pipeline_status_(PIPELINE_STATUS_OK
),
57 pushed_frame_count_(0) {}
58 ~FakeAudioPipelineDevice() override
{}
60 // AudioPipelineDevice overrides.
61 void SetClient(Client
* client
) override
{}
62 bool SetState(State new_state
) override
{
66 State
GetState() const override
{ return state_
; }
67 bool SetStartPts(int64_t microseconds
) override
{ return false; }
68 FrameStatus
PushFrame(DecryptContext
* decrypt_context
,
69 CastDecoderBuffer
* buffer
,
70 FrameStatusCB
* completion_cb
) override
{
71 last_frame_decrypt_context_
.reset(decrypt_context
);
72 last_frame_buffer_
.reset(buffer
);
73 last_frame_completion_cb_
.reset(completion_cb
);
74 ++pushed_frame_count_
;
76 switch (pipeline_status_
) {
77 case PIPELINE_STATUS_OK
:
79 case PIPELINE_STATUS_BUSY
:
81 case PIPELINE_STATUS_ERROR
:
87 // This will never be reached but is necessary for compiler warnings.
90 RenderingDelay
GetRenderingDelay() const override
{ return RenderingDelay(); }
91 bool GetStatistics(Statistics
* stats
) const override
{ return false; }
92 bool SetConfig(const AudioConfig
& config
) override
{
96 void SetStreamVolumeMultiplier(float multiplier
) override
{
97 volume_multiplier_
= multiplier
;
100 const AudioConfig
& config() const { return config_
; }
101 float volume_multiplier() const { return volume_multiplier_
; }
102 void set_pipeline_status(PipelineStatus status
) { pipeline_status_
= status
; }
103 unsigned pushed_frame_count() const { return pushed_frame_count_
; }
104 DecryptContext
* last_frame_decrypt_context() {
105 return last_frame_decrypt_context_
.get();
107 CastDecoderBuffer
* last_frame_buffer() { return last_frame_buffer_
.get(); }
108 FrameStatusCB
* last_frame_completion_cb() {
109 return last_frame_completion_cb_
.get();
115 float volume_multiplier_
;
117 PipelineStatus pipeline_status_
;
118 unsigned pushed_frame_count_
;
119 scoped_ptr
<DecryptContext
> last_frame_decrypt_context_
;
120 scoped_ptr
<CastDecoderBuffer
> last_frame_buffer_
;
121 scoped_ptr
<FrameStatusCB
> last_frame_completion_cb_
;
124 class FakeMediaPipelineBackend
: public MediaPipelineBackend
{
126 ~FakeMediaPipelineBackend() override
{}
128 MediaClockDevice
* GetClock() override
{
130 clock_device_
.reset(new FakeClockDevice
);
131 return clock_device_
.get();
133 AudioPipelineDevice
* GetAudio() override
{
135 audio_device_
.reset(new FakeAudioPipelineDevice
);
136 return audio_device_
.get();
138 VideoPipelineDevice
* GetVideo() override
{
144 scoped_ptr
<FakeClockDevice
> clock_device_
;
145 scoped_ptr
<FakeAudioPipelineDevice
> audio_device_
;
148 class FakeAudioSourceCallback
149 : public ::media::AudioOutputStream::AudioSourceCallback
{
151 FakeAudioSourceCallback() : error_(false) {}
153 bool error() const { return error_
; }
155 // ::media::AudioOutputStream::AudioSourceCallback overrides.
156 int OnMoreData(::media::AudioBus
* audio_bus
,
157 uint32 total_bytes_delay
) override
{
159 return audio_bus
->frames();
161 void OnError(::media::AudioOutputStream
* stream
) override
{ error_
= true; }
167 class FakeAudioManager
: public CastAudioManager
{
170 : CastAudioManager(nullptr), media_pipeline_backend_(nullptr) {}
171 ~FakeAudioManager() override
{}
173 // CastAudioManager overrides.
174 scoped_ptr
<MediaPipelineBackend
> CreateMediaPipelineBackend() override
{
175 DCHECK(!media_pipeline_backend_
);
176 scoped_ptr
<FakeMediaPipelineBackend
> backend(new FakeMediaPipelineBackend
);
177 // Cache the backend locally to be used by tests.
178 media_pipeline_backend_
= backend
.get();
179 return backend
.Pass();
181 void ReleaseOutputStream(::media::AudioOutputStream
* stream
) override
{
182 DCHECK(media_pipeline_backend_
);
183 media_pipeline_backend_
= nullptr;
184 CastAudioManager::ReleaseOutputStream(stream
);
187 // Returns the MediaPipelineBackend being used by the AudioOutputStream.
188 // Note: here is a valid MediaPipelineBackend only while the stream is open.
189 // Returns NULL at all other times.
190 FakeMediaPipelineBackend
* media_pipeline_backend() {
191 return media_pipeline_backend_
;
195 FakeMediaPipelineBackend
* media_pipeline_backend_
;
198 class AudioOutputStreamTest
: public ::testing::Test
{
200 AudioOutputStreamTest()
201 : format_(::media::AudioParameters::AUDIO_PCM_LINEAR
),
202 channel_layout_(::media::CHANNEL_LAYOUT_MONO
),
203 sample_rate_(::media::AudioParameters::kAudioCDSampleRate
),
204 bits_per_sample_(16),
205 frames_per_buffer_(256) {}
206 ~AudioOutputStreamTest() override
{}
209 void SetUp() override
{
210 message_loop_
.reset(new base::MessageLoop());
211 audio_manager_
.reset(new FakeAudioManager
);
214 void TearDown() override
{
215 audio_manager_
.reset();
216 message_loop_
.reset();
219 ::media::AudioParameters
GetAudioParams() {
220 return ::media::AudioParameters(format_
, channel_layout_
, sample_rate_
,
221 bits_per_sample_
, frames_per_buffer_
);
223 ::media::AudioOutputStream
* CreateStream() {
224 return audio_manager_
->MakeAudioOutputStream(GetAudioParams(),
227 FakeClockDevice
* GetClock() {
228 MediaPipelineBackend
* backend
= audio_manager_
->media_pipeline_backend();
229 return backend
? static_cast<FakeClockDevice
*>(backend
->GetClock())
232 FakeAudioPipelineDevice
* GetAudio() {
233 MediaPipelineBackend
* backend
= audio_manager_
->media_pipeline_backend();
234 return backend
? static_cast<FakeAudioPipelineDevice
*>(backend
->GetAudio())
238 scoped_ptr
<base::MessageLoop
> message_loop_
;
239 scoped_ptr
<FakeAudioManager
> audio_manager_
;
240 scoped_ptr
<TaskRunnerImpl
> audio_task_runner_
;
242 // AudioParameters used to create AudioOutputStream.
243 // Tests can modify these parameters before calling CreateStream.
244 ::media::AudioParameters::Format format_
;
245 ::media::ChannelLayout channel_layout_
;
247 int bits_per_sample_
;
248 int frames_per_buffer_
;
251 TEST_F(AudioOutputStreamTest
, Format
) {
252 ::media::AudioParameters::Format format
[] = {
253 ::media::AudioParameters::AUDIO_PCM_LINEAR
,
254 ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY
};
255 for (size_t i
= 0; i
< arraysize(format
); ++i
) {
257 ::media::AudioOutputStream
* stream
= CreateStream();
259 EXPECT_TRUE(stream
->Open());
261 FakeAudioPipelineDevice
* audio_device
= GetAudio();
262 ASSERT_TRUE(audio_device
);
263 const AudioConfig
& audio_config
= audio_device
->config();
264 EXPECT_EQ(kCodecPCM
, audio_config
.codec
);
265 EXPECT_EQ(kSampleFormatS16
, audio_config
.sample_format
);
266 EXPECT_FALSE(audio_config
.is_encrypted
);
272 TEST_F(AudioOutputStreamTest
, ChannelLayout
) {
273 ::media::ChannelLayout layout
[] = {::media::CHANNEL_LAYOUT_MONO
,
274 ::media::CHANNEL_LAYOUT_STEREO
};
275 for (size_t i
= 0; i
< arraysize(layout
); ++i
) {
276 channel_layout_
= layout
[i
];
277 ::media::AudioOutputStream
* stream
= CreateStream();
279 EXPECT_TRUE(stream
->Open());
281 FakeAudioPipelineDevice
* audio_device
= GetAudio();
282 ASSERT_TRUE(audio_device
);
283 const AudioConfig
& audio_config
= audio_device
->config();
284 EXPECT_EQ(::media::ChannelLayoutToChannelCount(channel_layout_
),
285 audio_config
.channel_number
);
291 TEST_F(AudioOutputStreamTest
, SampleRate
) {
292 sample_rate_
= ::media::AudioParameters::kAudioCDSampleRate
;
293 ::media::AudioOutputStream
* stream
= CreateStream();
295 EXPECT_TRUE(stream
->Open());
297 FakeAudioPipelineDevice
* audio_device
= GetAudio();
298 ASSERT_TRUE(audio_device
);
299 const AudioConfig
& audio_config
= audio_device
->config();
300 EXPECT_EQ(sample_rate_
, audio_config
.samples_per_second
);
305 TEST_F(AudioOutputStreamTest
, BitsPerSample
) {
306 bits_per_sample_
= 16;
307 ::media::AudioOutputStream
* stream
= CreateStream();
309 EXPECT_TRUE(stream
->Open());
311 FakeAudioPipelineDevice
* audio_device
= GetAudio();
312 ASSERT_TRUE(audio_device
);
313 const AudioConfig
& audio_config
= audio_device
->config();
314 EXPECT_EQ(bits_per_sample_
/ 8, audio_config
.bytes_per_channel
);
319 TEST_F(AudioOutputStreamTest
, DeviceState
) {
320 ::media::AudioOutputStream
* stream
= CreateStream();
322 EXPECT_FALSE(GetAudio());
324 EXPECT_TRUE(stream
->Open());
325 AudioPipelineDevice
* audio_device
= GetAudio();
326 ASSERT_TRUE(audio_device
);
327 FakeClockDevice
* clock_device
= GetClock();
328 ASSERT_TRUE(clock_device
);
329 EXPECT_EQ(AudioPipelineDevice::kStateIdle
, audio_device
->GetState());
330 EXPECT_EQ(MediaClockDevice::kStateIdle
, clock_device
->GetState());
331 EXPECT_EQ(1.f
, clock_device
->rate());
333 scoped_ptr
<FakeAudioSourceCallback
> source_callback(
334 new FakeAudioSourceCallback
);
335 stream
->Start(source_callback
.get());
336 EXPECT_EQ(AudioPipelineDevice::kStateRunning
, audio_device
->GetState());
337 EXPECT_EQ(MediaClockDevice::kStateRunning
, clock_device
->GetState());
338 EXPECT_EQ(1.f
, clock_device
->rate());
341 EXPECT_EQ(AudioPipelineDevice::kStatePaused
, audio_device
->GetState());
342 EXPECT_EQ(MediaClockDevice::kStateIdle
, clock_device
->GetState());
343 EXPECT_EQ(0.f
, clock_device
->rate());
346 EXPECT_FALSE(GetAudio());
349 TEST_F(AudioOutputStreamTest
, PushFrame
) {
350 ::media::AudioOutputStream
* stream
= CreateStream();
352 EXPECT_TRUE(stream
->Open());
354 scoped_ptr
<FakeAudioSourceCallback
> source_callback(
355 new FakeAudioSourceCallback
);
356 stream
->Start(source_callback
.get());
358 FakeAudioPipelineDevice
* audio_device
= GetAudio();
359 ASSERT_TRUE(audio_device
);
361 EXPECT_EQ(0u, audio_device
->pushed_frame_count());
362 EXPECT_FALSE(audio_device
->last_frame_decrypt_context());
363 EXPECT_FALSE(audio_device
->last_frame_buffer());
364 EXPECT_FALSE(audio_device
->last_frame_completion_cb());
366 // Let the stream push frames.
367 message_loop_
->RunUntilIdle();
369 EXPECT_LT(0u, audio_device
->pushed_frame_count());
370 // DecryptContext is always NULL becuase of "raw" audio.
371 EXPECT_FALSE(audio_device
->last_frame_decrypt_context());
372 EXPECT_TRUE(audio_device
->last_frame_buffer());
373 EXPECT_TRUE(audio_device
->last_frame_completion_cb());
375 // Verify decoder buffer.
376 ::media::AudioParameters audio_params
= GetAudioParams();
377 const size_t expected_frame_size
=
378 static_cast<size_t>(audio_params
.GetBytesPerBuffer());
379 const CastDecoderBuffer
* buffer
= audio_device
->last_frame_buffer();
380 EXPECT_TRUE(buffer
->data());
381 EXPECT_EQ(expected_frame_size
, buffer
->data_size());
382 EXPECT_FALSE(buffer
->decrypt_config()); // Null because of raw audio.
383 EXPECT_FALSE(buffer
->end_of_stream());
385 // No error must be reported to source callback.
386 EXPECT_FALSE(source_callback
->error());
392 TEST_F(AudioOutputStreamTest
, DeviceBusy
) {
393 ::media::AudioOutputStream
* stream
= CreateStream();
395 EXPECT_TRUE(stream
->Open());
397 FakeAudioPipelineDevice
* audio_device
= GetAudio();
398 ASSERT_TRUE(audio_device
);
399 audio_device
->set_pipeline_status(
400 FakeAudioPipelineDevice::PIPELINE_STATUS_BUSY
);
402 scoped_ptr
<FakeAudioSourceCallback
> source_callback(
403 new FakeAudioSourceCallback
);
404 stream
->Start(source_callback
.get());
406 // Let the stream push frames.
407 message_loop_
->RunUntilIdle();
409 // Make sure that one frame was pushed.
410 EXPECT_EQ(1u, audio_device
->pushed_frame_count());
411 // No error must be reported to source callback.
412 EXPECT_FALSE(source_callback
->error());
414 // Sleep for a few frames so that when the message loop is drained
415 // AudioOutputStream would have the opportunity to push more frames.
416 ::media::AudioParameters audio_params
= GetAudioParams();
417 base::TimeDelta pause
= audio_params
.GetBufferDuration() * 5;
418 base::PlatformThread::Sleep(pause
);
420 // Let the stream attempt to push more frames.
421 message_loop_
->RunUntilIdle();
422 // But since the device was busy, it must not push more frames.
423 EXPECT_EQ(1u, audio_device
->pushed_frame_count());
425 // Unblock the pipeline and verify that PushFrame resumes.
426 audio_device
->set_pipeline_status(
427 FakeAudioPipelineDevice::PIPELINE_STATUS_OK
);
428 audio_device
->last_frame_completion_cb()->Run(
429 MediaComponentDevice::kFrameSuccess
);
430 base::PlatformThread::Sleep(pause
);
431 message_loop_
->RunUntilIdle();
432 EXPECT_EQ(2u, audio_device
->pushed_frame_count());
433 EXPECT_FALSE(source_callback
->error());
435 // Make the pipeline busy again, but this time send kFrameFailed.
436 audio_device
->set_pipeline_status(
437 FakeAudioPipelineDevice::PIPELINE_STATUS_BUSY
);
438 base::PlatformThread::Sleep(pause
);
439 message_loop_
->RunUntilIdle();
440 EXPECT_EQ(3u, audio_device
->pushed_frame_count());
441 EXPECT_FALSE(source_callback
->error());
443 audio_device
->last_frame_completion_cb()->Run(
444 MediaComponentDevice::kFrameFailed
);
445 EXPECT_TRUE(source_callback
->error());
451 TEST_F(AudioOutputStreamTest
, DeviceError
) {
452 ::media::AudioOutputStream
* stream
= CreateStream();
454 EXPECT_TRUE(stream
->Open());
456 FakeAudioPipelineDevice
* audio_device
= GetAudio();
457 ASSERT_TRUE(audio_device
);
458 audio_device
->set_pipeline_status(
459 FakeAudioPipelineDevice::PIPELINE_STATUS_ERROR
);
461 scoped_ptr
<FakeAudioSourceCallback
> source_callback(
462 new FakeAudioSourceCallback
);
463 stream
->Start(source_callback
.get());
465 // Let the stream push frames.
466 message_loop_
->RunUntilIdle();
468 // Make sure that AudioOutputStream attempted to push the initial frame.
469 EXPECT_LT(0u, audio_device
->pushed_frame_count());
470 // AudioOutputStream must report error to source callback.
471 EXPECT_TRUE(source_callback
->error());
477 TEST_F(AudioOutputStreamTest
, Volume
) {
478 ::media::AudioOutputStream
* stream
= CreateStream();
480 ASSERT_TRUE(stream
->Open());
481 FakeAudioPipelineDevice
* audio_device
= GetAudio();
482 ASSERT_TRUE(audio_device
);
485 stream
->GetVolume(&volume
);
486 EXPECT_EQ(1.0, volume
);
487 EXPECT_EQ(1.0f
, audio_device
->volume_multiplier());
489 stream
->SetVolume(0.5);
490 stream
->GetVolume(&volume
);
491 EXPECT_EQ(0.5, volume
);
492 EXPECT_EQ(0.5f
, audio_device
->volume_multiplier());
499 } // namespace chromecast