Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Side by Side Diff: chromecast/media/audio/audio_output_stream_unittest.cc

Issue 1308153005: [Chromecast] Plumbs raw audio through CMA backend. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: changed default sample rate Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "chromecast/base/task_runner_impl.h"
6 #include "chromecast/media/audio/audio_manager.h"
7 #include "chromecast/media/audio/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"
15
16 namespace {
17 const char kDefaultDeviceId[] = "";
gunsch 2015/09/18 21:23:07 can this be inside the another anonymous namespace
alokp 2015/09/18 21:42:15 Done.
18 } // namespace
19
20 namespace chromecast {
21 namespace media {
22 namespace {
23
24 class FakeClockDevice : public MediaClockDevice {
25 public:
26 FakeClockDevice() : state_(kStateUninitialized), rate_(0.f) {}
27 ~FakeClockDevice() override {}
28
29 State GetState() const override { return state_; }
30 bool SetState(State new_state) override {
31 state_ = new_state;
32 return true;
33 }
34 bool ResetTimeline(int64_t time_microseconds) override { return true; }
35 bool SetRate(float rate) override {
36 rate_ = rate;
37 return true;
38 }
39 int64_t GetTimeMicroseconds() override { return 0; }
40
41 float rate() const { return rate_; }
42
43 private:
44 State state_;
45 float rate_;
46 };
47
48 class FakeAudioPipelineDevice : public AudioPipelineDevice {
49 public:
50 enum PipelineStatus {
51 PIPELINE_STATUS_OK,
52 PIPELINE_STATUS_BUSY,
53 PIPELINE_STATUS_ERROR
54 };
55
56 FakeAudioPipelineDevice()
57 : state_(kStateUninitialized),
58 volume_multiplier_(1.0f),
59 pipeline_status_(PIPELINE_STATUS_OK),
60 pushed_frame_count_(0) {}
61 ~FakeAudioPipelineDevice() override {}
62
63 // AudioPipelineDevice overrides.
64 void SetClient(Client* client) override {}
65 bool SetState(State new_state) override {
66 state_ = new_state;
67 return true;
68 }
69 State GetState() const override { return state_; }
70 bool SetStartPts(int64_t microseconds) override { return false; }
71 FrameStatus PushFrame(DecryptContext* decrypt_context,
72 CastDecoderBuffer* buffer,
73 FrameStatusCB* completion_cb) override {
74 last_frame_decrypt_context_.reset(decrypt_context);
75 last_frame_buffer_.reset(buffer);
76 last_frame_completion_cb_.reset(completion_cb);
77 ++pushed_frame_count_;
78
79 switch (pipeline_status_) {
80 case PIPELINE_STATUS_OK:
81 return kFrameSuccess;
82 case PIPELINE_STATUS_BUSY:
83 return kFramePending;
84 case PIPELINE_STATUS_ERROR:
85 return kFrameFailed;
86 }
87 NOTREACHED();
88 }
89 RenderingDelay GetRenderingDelay() const override { return RenderingDelay(); }
90 bool GetStatistics(Statistics* stats) const override { return false; }
91 bool SetConfig(const AudioConfig& config) override {
92 config_ = config;
93 return true;
94 }
95 void SetStreamVolumeMultiplier(float multiplier) override {
96 volume_multiplier_ = multiplier;
97 }
98
99 const AudioConfig& config() const { return config_; }
100 float volume_multiplier() const { return volume_multiplier_; }
101 void set_pipeline_status(PipelineStatus status) { pipeline_status_ = status; }
102 unsigned pushed_frame_count() const { return pushed_frame_count_; }
103 DecryptContext* last_frame_decrypt_context() {
104 return last_frame_decrypt_context_.get();
105 }
106 CastDecoderBuffer* last_frame_buffer() { return last_frame_buffer_.get(); }
107 FrameStatusCB* last_frame_completion_cb() {
108 return last_frame_completion_cb_.get();
109 }
110
111 private:
112 State state_;
113 AudioConfig config_;
114 float volume_multiplier_;
115
116 PipelineStatus pipeline_status_;
117 unsigned pushed_frame_count_;
118 scoped_ptr<DecryptContext> last_frame_decrypt_context_;
119 scoped_ptr<CastDecoderBuffer> last_frame_buffer_;
120 scoped_ptr<FrameStatusCB> last_frame_completion_cb_;
121 };
122
123 class FakeMediaPipelineBackend : public MediaPipelineBackend {
124 public:
125 ~FakeMediaPipelineBackend() override {}
126
127 MediaClockDevice* GetClock() override {
128 if (!clock_device_)
129 clock_device_.reset(new FakeClockDevice);
130 return clock_device_.get();
131 }
132 AudioPipelineDevice* GetAudio() override {
133 if (!audio_device_)
134 audio_device_.reset(new FakeAudioPipelineDevice);
135 return audio_device_.get();
136 }
137 VideoPipelineDevice* GetVideo() override {
138 NOTREACHED();
139 return nullptr;
140 }
141
142 private:
143 scoped_ptr<FakeClockDevice> clock_device_;
144 scoped_ptr<FakeAudioPipelineDevice> audio_device_;
145 };
146
147 class FakeAudioSourceCallback
148 : public ::media::AudioOutputStream::AudioSourceCallback {
149 public:
150 FakeAudioSourceCallback() : error_(false) {}
151
152 bool error() const { return error_; }
153
154 // ::media::AudioOutputStream::AudioSourceCallback overrides.
155 int OnMoreData(::media::AudioBus* audio_bus,
156 uint32 total_bytes_delay) override {
157 audio_bus->Zero();
158 return audio_bus->frames();
159 }
160 void OnError(::media::AudioOutputStream* stream) override { error_ = true; }
161
162 private:
163 bool error_;
164 };
165
166 class FakeAudioManager : public AudioManager {
167 public:
168 FakeAudioManager()
169 : AudioManager(nullptr), media_pipeline_backend_(nullptr) {}
170 ~FakeAudioManager() override {}
171
172 // AudioManager overrides.
173 scoped_ptr<MediaPipelineBackend> CreateMediaPipelineBackend() override {
174 DCHECK(!media_pipeline_backend_);
175 scoped_ptr<FakeMediaPipelineBackend> backend(new FakeMediaPipelineBackend);
176 // Cache the backend locally to be used by tests.
177 media_pipeline_backend_ = backend.get();
178 return backend.Pass();
179 }
180 void ReleaseOutputStream(::media::AudioOutputStream* stream) override {
181 DCHECK(media_pipeline_backend_);
182 media_pipeline_backend_ = nullptr;
183 AudioManager::ReleaseOutputStream(stream);
184 }
185
186 // Returns the MediaPipelineBackend being used by the AudioOutputStream.
187 // Note: here is a valid MediaPipelineBackend only while the stream is open.
188 // Returns NULL at all other times.
189 FakeMediaPipelineBackend* media_pipeline_backend() {
190 return media_pipeline_backend_;
191 }
192
193 private:
194 FakeMediaPipelineBackend* media_pipeline_backend_;
195 };
196
197 class AudioOutputStreamTest : public ::testing::Test {
198 public:
199 AudioOutputStreamTest()
200 : format_(::media::AudioParameters::AUDIO_PCM_LINEAR),
201 channel_layout_(::media::CHANNEL_LAYOUT_MONO),
202 sample_rate_(::media::AudioParameters::kAudioCDSampleRate),
203 bits_per_sample_(16),
204 frames_per_buffer_(256) {}
205 ~AudioOutputStreamTest() override {}
206
207 protected:
208 void SetUp() override {
209 message_loop_.reset(new base::MessageLoop());
210 audio_manager_.reset(new FakeAudioManager);
211 }
212
213 void TearDown() override {
214 audio_manager_.reset();
215 message_loop_.reset();
216 }
217
218 ::media::AudioParameters GetAudioParams() {
219 return ::media::AudioParameters(format_, channel_layout_, sample_rate_,
220 bits_per_sample_, frames_per_buffer_);
221 }
222 ::media::AudioOutputStream* CreateStream() {
223 return audio_manager_->MakeAudioOutputStream(GetAudioParams(),
224 kDefaultDeviceId);
225 }
226 FakeClockDevice* GetClock() {
227 MediaPipelineBackend* backend = audio_manager_->media_pipeline_backend();
228 return backend ? static_cast<FakeClockDevice*>(backend->GetClock())
229 : nullptr;
230 }
231 FakeAudioPipelineDevice* GetAudio() {
232 MediaPipelineBackend* backend = audio_manager_->media_pipeline_backend();
233 return backend ? static_cast<FakeAudioPipelineDevice*>(backend->GetAudio())
234 : nullptr;
235 }
236
237 scoped_ptr<base::MessageLoop> message_loop_;
238 scoped_ptr<FakeAudioManager> audio_manager_;
239 scoped_ptr<TaskRunnerImpl> audio_task_runner_;
240
241 // AudioParameters used to create AudioOutputStream.
242 // Tests can modify these parameters before calling CreateStream.
243 ::media::AudioParameters::Format format_;
244 ::media::ChannelLayout channel_layout_;
245 int sample_rate_;
246 int bits_per_sample_;
247 int frames_per_buffer_;
248 };
249
250 TEST_F(AudioOutputStreamTest, Format) {
251 ::media::AudioParameters::Format format[] = {
252 ::media::AudioParameters::AUDIO_PCM_LINEAR,
253 ::media::AudioParameters::AUDIO_PCM_LOW_LATENCY};
254 for (size_t i = 0; i < arraysize(format); ++i) {
255 format_ = format[i];
256 ::media::AudioOutputStream* stream = CreateStream();
257 ASSERT_TRUE(stream);
258 EXPECT_TRUE(stream->Open());
259
260 FakeAudioPipelineDevice* audio_device = GetAudio();
261 ASSERT_TRUE(audio_device);
262 const AudioConfig& audio_config = audio_device->config();
263 EXPECT_EQ(kCodecPCM, audio_config.codec);
264 EXPECT_EQ(kSampleFormatS16, audio_config.sample_format);
265 EXPECT_FALSE(audio_config.is_encrypted);
266
267 stream->Close();
268 }
269 }
270
271 TEST_F(AudioOutputStreamTest, ChannelLayout) {
272 ::media::ChannelLayout layout[] = {::media::CHANNEL_LAYOUT_MONO,
273 ::media::CHANNEL_LAYOUT_STEREO};
274 for (size_t i = 0; i < arraysize(layout); ++i) {
275 channel_layout_ = layout[i];
276 ::media::AudioOutputStream* stream = CreateStream();
277 ASSERT_TRUE(stream);
278 EXPECT_TRUE(stream->Open());
279
280 FakeAudioPipelineDevice* audio_device = GetAudio();
281 ASSERT_TRUE(audio_device);
282 const AudioConfig& audio_config = audio_device->config();
283 EXPECT_EQ(::media::ChannelLayoutToChannelCount(channel_layout_),
284 audio_config.channel_number);
285
286 stream->Close();
287 }
288 }
289
290 TEST_F(AudioOutputStreamTest, SampleRate) {
291 sample_rate_ = ::media::AudioParameters::kAudioCDSampleRate;
292 ::media::AudioOutputStream* stream = CreateStream();
293 ASSERT_TRUE(stream);
294 EXPECT_TRUE(stream->Open());
295
296 FakeAudioPipelineDevice* audio_device = GetAudio();
297 ASSERT_TRUE(audio_device);
298 const AudioConfig& audio_config = audio_device->config();
299 EXPECT_EQ(sample_rate_, audio_config.samples_per_second);
300
301 stream->Close();
302 }
303
304 TEST_F(AudioOutputStreamTest, BitsPerSample) {
305 bits_per_sample_ = 16;
306 ::media::AudioOutputStream* stream = CreateStream();
307 ASSERT_TRUE(stream);
308 EXPECT_TRUE(stream->Open());
309
310 FakeAudioPipelineDevice* audio_device = GetAudio();
311 ASSERT_TRUE(audio_device);
312 const AudioConfig& audio_config = audio_device->config();
313 EXPECT_EQ(bits_per_sample_ / 8, audio_config.bytes_per_channel);
314
315 stream->Close();
316 }
317
318 TEST_F(AudioOutputStreamTest, DeviceState) {
319 ::media::AudioOutputStream* stream = CreateStream();
320 ASSERT_TRUE(stream);
321 EXPECT_FALSE(GetAudio());
322
323 EXPECT_TRUE(stream->Open());
324 AudioPipelineDevice* audio_device = GetAudio();
325 ASSERT_TRUE(audio_device);
326 FakeClockDevice* clock_device = GetClock();
327 ASSERT_TRUE(clock_device);
328 EXPECT_EQ(AudioPipelineDevice::kStateIdle, audio_device->GetState());
329 EXPECT_EQ(MediaClockDevice::kStateIdle, clock_device->GetState());
330 EXPECT_EQ(1.f, clock_device->rate());
331
332 scoped_ptr<FakeAudioSourceCallback> source_callback(
333 new FakeAudioSourceCallback);
334 stream->Start(source_callback.get());
335 EXPECT_EQ(AudioPipelineDevice::kStateRunning, audio_device->GetState());
336 EXPECT_EQ(MediaClockDevice::kStateRunning, clock_device->GetState());
337 EXPECT_EQ(1.f, clock_device->rate());
338
339 stream->Stop();
340 EXPECT_EQ(AudioPipelineDevice::kStatePaused, audio_device->GetState());
341 EXPECT_EQ(MediaClockDevice::kStateIdle, clock_device->GetState());
342 EXPECT_EQ(0.f, clock_device->rate());
343
344 stream->Close();
345 EXPECT_FALSE(GetAudio());
346 }
347
348 TEST_F(AudioOutputStreamTest, PushFrame) {
349 ::media::AudioOutputStream* stream = CreateStream();
350 ASSERT_TRUE(stream);
351 EXPECT_TRUE(stream->Open());
352
353 scoped_ptr<FakeAudioSourceCallback> source_callback(
354 new FakeAudioSourceCallback);
355 stream->Start(source_callback.get());
356
357 FakeAudioPipelineDevice* audio_device = GetAudio();
358 ASSERT_TRUE(audio_device);
359
360 EXPECT_EQ(0u, audio_device->pushed_frame_count());
361 EXPECT_FALSE(audio_device->last_frame_decrypt_context());
362 EXPECT_FALSE(audio_device->last_frame_buffer());
363 EXPECT_FALSE(audio_device->last_frame_completion_cb());
364
365 // Let the stream push frames.
366 message_loop_->RunUntilIdle();
367
368 EXPECT_LT(0u, audio_device->pushed_frame_count());
369 // DecryptContext is always NULL becuase of "raw" audio.
370 EXPECT_FALSE(audio_device->last_frame_decrypt_context());
371 EXPECT_TRUE(audio_device->last_frame_buffer());
372 EXPECT_TRUE(audio_device->last_frame_completion_cb());
373
374 // Verify decoder buffer.
375 ::media::AudioParameters audio_params = GetAudioParams();
376 const size_t expected_frame_size =
377 static_cast<size_t>(audio_params.GetBytesPerBuffer());
378 const CastDecoderBuffer* buffer = audio_device->last_frame_buffer();
379 EXPECT_TRUE(buffer->data());
380 EXPECT_EQ(expected_frame_size, buffer->data_size());
381 EXPECT_FALSE(buffer->decrypt_config()); // Null because of raw audio.
382 EXPECT_FALSE(buffer->end_of_stream());
383
384 // No error must be reported to source callback.
385 EXPECT_FALSE(source_callback->error());
386
387 stream->Stop();
388 stream->Close();
389 }
390
391 TEST_F(AudioOutputStreamTest, DeviceBusy) {
392 ::media::AudioOutputStream* stream = CreateStream();
393 ASSERT_TRUE(stream);
394 EXPECT_TRUE(stream->Open());
395
396 FakeAudioPipelineDevice* audio_device = GetAudio();
397 ASSERT_TRUE(audio_device);
398 audio_device->set_pipeline_status(
399 FakeAudioPipelineDevice::PIPELINE_STATUS_BUSY);
400
401 scoped_ptr<FakeAudioSourceCallback> source_callback(
402 new FakeAudioSourceCallback);
403 stream->Start(source_callback.get());
404
405 // Let the stream push frames.
406 message_loop_->RunUntilIdle();
407
408 // Make sure that one frame was pushed.
409 EXPECT_EQ(1u, audio_device->pushed_frame_count());
410 // No error must be reported to source callback.
411 EXPECT_FALSE(source_callback->error());
412
413 // Sleep for a few frames so that when the message loop is drained
414 // AudioOutputStream would have the opportunity to push more frames.
415 ::media::AudioParameters audio_params = GetAudioParams();
416 base::TimeDelta pause = audio_params.GetBufferDuration() * 5;
417 base::PlatformThread::Sleep(pause);
418
419 // Let the stream attempt to push more frames.
420 message_loop_->RunUntilIdle();
421 // But since the device was busy, it must not push more frames.
422 EXPECT_EQ(1u, audio_device->pushed_frame_count());
423
424 // Unblock the pipeline and verify that PushFrame resumes.
425 audio_device->set_pipeline_status(
426 FakeAudioPipelineDevice::PIPELINE_STATUS_OK);
427 audio_device->last_frame_completion_cb()->Run(
428 MediaComponentDevice::kFrameSuccess);
429 base::PlatformThread::Sleep(pause);
430 message_loop_->RunUntilIdle();
431 EXPECT_EQ(2u, audio_device->pushed_frame_count());
432 EXPECT_FALSE(source_callback->error());
433
434 // Make the pipeline busy again, but this time send kFrameFailed.
435 audio_device->set_pipeline_status(
436 FakeAudioPipelineDevice::PIPELINE_STATUS_BUSY);
437 base::PlatformThread::Sleep(pause);
438 message_loop_->RunUntilIdle();
439 EXPECT_EQ(3u, audio_device->pushed_frame_count());
440 EXPECT_FALSE(source_callback->error());
441
442 audio_device->last_frame_completion_cb()->Run(
443 MediaComponentDevice::kFrameFailed);
444 EXPECT_TRUE(source_callback->error());
445
446 stream->Stop();
447 stream->Close();
448 }
449
450 TEST_F(AudioOutputStreamTest, DeviceError) {
451 ::media::AudioOutputStream* stream = CreateStream();
452 ASSERT_TRUE(stream);
453 EXPECT_TRUE(stream->Open());
454
455 FakeAudioPipelineDevice* audio_device = GetAudio();
456 ASSERT_TRUE(audio_device);
457 audio_device->set_pipeline_status(
458 FakeAudioPipelineDevice::PIPELINE_STATUS_ERROR);
459
460 scoped_ptr<FakeAudioSourceCallback> source_callback(
461 new FakeAudioSourceCallback);
462 stream->Start(source_callback.get());
463
464 // Let the stream push frames.
465 message_loop_->RunUntilIdle();
466
467 // Make sure that AudioOutputStream attempted to push the initial frame.
468 EXPECT_LT(0u, audio_device->pushed_frame_count());
469 // AudioOutputStream must report error to source callback.
470 EXPECT_TRUE(source_callback->error());
471
472 stream->Stop();
473 stream->Close();
474 }
475
476 TEST_F(AudioOutputStreamTest, Volume) {
477 ::media::AudioOutputStream* stream = CreateStream();
478 ASSERT_TRUE(stream);
479 ASSERT_TRUE(stream->Open());
480 FakeAudioPipelineDevice* audio_device = GetAudio();
481 ASSERT_TRUE(audio_device);
482
483 double volume = 0.0;
484 stream->GetVolume(&volume);
485 EXPECT_EQ(1.0, volume);
486 EXPECT_EQ(1.0f, audio_device->volume_multiplier());
487
488 stream->SetVolume(0.5);
489 stream->GetVolume(&volume);
490 EXPECT_EQ(0.5, volume);
491 EXPECT_EQ(0.5f, audio_device->volume_multiplier());
492
493 stream->Close();
494 }
495
496 } // namespace
497 } // namespace media
498 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698