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