Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chromecast / media / audio / cast_audio_output_stream_unittest.cc
blob8d885f957c98cf9adc13feb332def5b7097624c0
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 {
17 namespace media {
18 namespace {
19 const char kDefaultDeviceId[] = "";
21 class FakeClockDevice : public MediaClockDevice {
22 public:
23 FakeClockDevice() : state_(kStateUninitialized), rate_(0.f) {}
24 ~FakeClockDevice() override {}
26 State GetState() const override { return state_; }
27 bool SetState(State new_state) override {
28 state_ = new_state;
29 return true;
31 bool ResetTimeline(int64_t time_microseconds) override { return true; }
32 bool SetRate(float rate) override {
33 rate_ = rate;
34 return true;
36 int64_t GetTimeMicroseconds() override { return 0; }
38 float rate() const { return rate_; }
40 private:
41 State state_;
42 float rate_;
45 class FakeAudioPipelineDevice : public AudioPipelineDevice {
46 public:
47 enum PipelineStatus {
48 PIPELINE_STATUS_OK,
49 PIPELINE_STATUS_BUSY,
50 PIPELINE_STATUS_ERROR
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 {
63 state_ = new_state;
64 return true;
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:
78 return kFrameSuccess;
79 case PIPELINE_STATUS_BUSY:
80 return kFramePending;
81 case PIPELINE_STATUS_ERROR:
82 return kFrameFailed;
83 default:
84 NOTREACHED();
87 // This will never be reached but is necessary for compiler warnings.
88 return kFrameFailed;
90 RenderingDelay GetRenderingDelay() const override { return RenderingDelay(); }
91 bool GetStatistics(Statistics* stats) const override { return false; }
92 bool SetConfig(const AudioConfig& config) override {
93 config_ = config;
94 return true;
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();
112 private:
113 State state_;
114 AudioConfig config_;
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 {
125 public:
126 ~FakeMediaPipelineBackend() override {}
128 MediaClockDevice* GetClock() override {
129 if (!clock_device_)
130 clock_device_.reset(new FakeClockDevice);
131 return clock_device_.get();
133 AudioPipelineDevice* GetAudio() override {
134 if (!audio_device_)
135 audio_device_.reset(new FakeAudioPipelineDevice);
136 return audio_device_.get();
138 VideoPipelineDevice* GetVideo() override {
139 NOTREACHED();
140 return nullptr;
143 private:
144 scoped_ptr<FakeClockDevice> clock_device_;
145 scoped_ptr<FakeAudioPipelineDevice> audio_device_;
148 class FakeAudioSourceCallback
149 : public ::media::AudioOutputStream::AudioSourceCallback {
150 public:
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 {
158 audio_bus->Zero();
159 return audio_bus->frames();
161 void OnError(::media::AudioOutputStream* stream) override { error_ = true; }
163 private:
164 bool error_;
167 class FakeAudioManager : public CastAudioManager {
168 public:
169 FakeAudioManager()
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_;
194 private:
195 FakeMediaPipelineBackend* media_pipeline_backend_;
198 class AudioOutputStreamTest : public ::testing::Test {
199 public:
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 {}
208 protected:
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(),
225 kDefaultDeviceId);
227 FakeClockDevice* GetClock() {
228 MediaPipelineBackend* backend = audio_manager_->media_pipeline_backend();
229 return backend ? static_cast<FakeClockDevice*>(backend->GetClock())
230 : nullptr;
232 FakeAudioPipelineDevice* GetAudio() {
233 MediaPipelineBackend* backend = audio_manager_->media_pipeline_backend();
234 return backend ? static_cast<FakeAudioPipelineDevice*>(backend->GetAudio())
235 : nullptr;
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_;
246 int sample_rate_;
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) {
256 format_ = format[i];
257 ::media::AudioOutputStream* stream = CreateStream();
258 ASSERT_TRUE(stream);
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);
268 stream->Close();
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();
278 ASSERT_TRUE(stream);
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);
287 stream->Close();
291 TEST_F(AudioOutputStreamTest, SampleRate) {
292 sample_rate_ = ::media::AudioParameters::kAudioCDSampleRate;
293 ::media::AudioOutputStream* stream = CreateStream();
294 ASSERT_TRUE(stream);
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);
302 stream->Close();
305 TEST_F(AudioOutputStreamTest, BitsPerSample) {
306 bits_per_sample_ = 16;
307 ::media::AudioOutputStream* stream = CreateStream();
308 ASSERT_TRUE(stream);
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);
316 stream->Close();
319 TEST_F(AudioOutputStreamTest, DeviceState) {
320 ::media::AudioOutputStream* stream = CreateStream();
321 ASSERT_TRUE(stream);
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());
340 stream->Stop();
341 EXPECT_EQ(AudioPipelineDevice::kStatePaused, audio_device->GetState());
342 EXPECT_EQ(MediaClockDevice::kStateIdle, clock_device->GetState());
343 EXPECT_EQ(0.f, clock_device->rate());
345 stream->Close();
346 EXPECT_FALSE(GetAudio());
349 TEST_F(AudioOutputStreamTest, PushFrame) {
350 ::media::AudioOutputStream* stream = CreateStream();
351 ASSERT_TRUE(stream);
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());
388 stream->Stop();
389 stream->Close();
392 TEST_F(AudioOutputStreamTest, DeviceBusy) {
393 ::media::AudioOutputStream* stream = CreateStream();
394 ASSERT_TRUE(stream);
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());
447 stream->Stop();
448 stream->Close();
451 TEST_F(AudioOutputStreamTest, DeviceError) {
452 ::media::AudioOutputStream* stream = CreateStream();
453 ASSERT_TRUE(stream);
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());
473 stream->Stop();
474 stream->Close();
477 TEST_F(AudioOutputStreamTest, Volume) {
478 ::media::AudioOutputStream* stream = CreateStream();
479 ASSERT_TRUE(stream);
480 ASSERT_TRUE(stream->Open());
481 FakeAudioPipelineDevice* audio_device = GetAudio();
482 ASSERT_TRUE(audio_device);
484 double volume = 0.0;
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());
494 stream->Close();
497 } // namespace
498 } // namespace media
499 } // namespace chromecast