| 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/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[] = ""; | 
|  | 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(kSampleFormatPlanarS16, 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 | 
| OLD | NEW | 
|---|