1 // Copyright 2014 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 <vector> 6 7 #include "content/renderer/media/audio_device_factory.h" 8 #include "content/renderer/media/audio_message_filter.h" 9 #include "content/renderer/media/media_stream_audio_renderer.h" 10 #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" 11 #include "content/renderer/media/webrtc_audio_device_impl.h" 12 #include "content/renderer/media/webrtc_audio_renderer.h" 13 #include "media/audio/audio_output_device.h" 14 #include "media/audio/audio_output_ipc.h" 15 #include "media/base/audio_bus.h" 16 #include "media/base/mock_audio_renderer_sink.h" 17 #include "testing/gmock/include/gmock/gmock.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" 20 21 using testing::Return; 22 23 namespace content { 24 25 namespace { 26 27 const int kHardwareSampleRate = 44100; 28 const int kHardwareBufferSize = 512; 29 30 class MockAudioOutputIPC : public media::AudioOutputIPC { 31 public: 32 MockAudioOutputIPC() {} 33 virtual ~MockAudioOutputIPC() {} 34 35 MOCK_METHOD3(CreateStream, void(media::AudioOutputIPCDelegate* delegate, 36 const media::AudioParameters& params, 37 int session_id)); 38 MOCK_METHOD0(PlayStream, void()); 39 MOCK_METHOD0(PauseStream, void()); 40 MOCK_METHOD0(CloseStream, void()); 41 MOCK_METHOD1(SetVolume, void(double volume)); 42 }; 43 44 class FakeAudioOutputDevice 45 : NON_EXPORTED_BASE(public media::AudioOutputDevice) { 46 public: 47 FakeAudioOutputDevice( 48 scoped_ptr<media::AudioOutputIPC> ipc, 49 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) 50 : AudioOutputDevice(ipc.Pass(), 51 io_task_runner) {} 52 MOCK_METHOD0(Start, void()); 53 MOCK_METHOD0(Stop, void()); 54 MOCK_METHOD0(Pause, void()); 55 MOCK_METHOD0(Play, void()); 56 MOCK_METHOD1(SetVolume, bool(double volume)); 57 58 protected: 59 virtual ~FakeAudioOutputDevice() {} 60 }; 61 62 class MockAudioDeviceFactory : public AudioDeviceFactory { 63 public: 64 MockAudioDeviceFactory() {} 65 virtual ~MockAudioDeviceFactory() {} 66 MOCK_METHOD1(CreateOutputDevice, media::AudioOutputDevice*(int)); 67 MOCK_METHOD1(CreateInputDevice, media::AudioInputDevice*(int)); 68 }; 69 70 class MockAudioRendererSource : public WebRtcAudioRendererSource { 71 public: 72 MockAudioRendererSource() {} 73 virtual ~MockAudioRendererSource() {} 74 MOCK_METHOD4(RenderData, void(media::AudioBus* audio_bus, 75 int sample_rate, 76 int audio_delay_milliseconds, 77 base::TimeDelta* current_time)); 78 MOCK_METHOD1(RemoveAudioRenderer, void(WebRtcAudioRenderer* renderer)); 79 }; 80 81 } // namespace 82 83 class WebRtcAudioRendererTest : public testing::Test { 84 protected: 85 WebRtcAudioRendererTest() 86 : message_loop_(new base::MessageLoopForIO), 87 mock_ipc_(new MockAudioOutputIPC()), 88 mock_output_device_(new FakeAudioOutputDevice( 89 scoped_ptr<media::AudioOutputIPC>(mock_ipc_), 90 message_loop_->message_loop_proxy())), 91 factory_(new MockAudioDeviceFactory()), 92 source_(new MockAudioRendererSource()), 93 stream_(new rtc::RefCountedObject<MockMediaStream>("label")), 94 renderer_(new WebRtcAudioRenderer(stream_, 1, 1, 1, 44100, 95 kHardwareBufferSize)) { 96 EXPECT_CALL(*factory_.get(), CreateOutputDevice(1)) 97 .WillOnce(Return(mock_output_device_.get())); 98 EXPECT_CALL(*mock_output_device_.get(), Start()); 99 EXPECT_TRUE(renderer_->Initialize(source_.get())); 100 renderer_proxy_ = renderer_->CreateSharedAudioRendererProxy(stream_); 101 } 102 103 // Used to construct |mock_output_device_|. 104 scoped_ptr<base::MessageLoopForIO> message_loop_; 105 MockAudioOutputIPC* mock_ipc_; // Owned by AudioOuputDevice. 106 107 scoped_refptr<FakeAudioOutputDevice> mock_output_device_; 108 scoped_ptr<MockAudioDeviceFactory> factory_; 109 scoped_ptr<MockAudioRendererSource> source_; 110 scoped_refptr<webrtc::MediaStreamInterface> stream_; 111 scoped_refptr<WebRtcAudioRenderer> renderer_; 112 scoped_refptr<MediaStreamAudioRenderer> renderer_proxy_; 113 }; 114 115 // Verify that the renderer will be stopped if the only proxy is stopped. 116 TEST_F(WebRtcAudioRendererTest, StopRenderer) { 117 renderer_proxy_->Start(); 118 119 // |renderer_| has only one proxy, stopping the proxy should stop the sink of 120 // |renderer_|. 121 EXPECT_CALL(*mock_output_device_.get(), Stop()); 122 EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get())); 123 renderer_proxy_->Stop(); 124 } 125 126 // Verify that the renderer will not be stopped unless the last proxy is 127 // stopped. 128 TEST_F(WebRtcAudioRendererTest, MultipleRenderers) { 129 renderer_proxy_->Start(); 130 131 // Create a vector of renderer proxies from the |renderer_|. 132 std::vector<scoped_refptr<MediaStreamAudioRenderer> > renderer_proxies_; 133 static const int kNumberOfRendererProxy = 5; 134 for (int i = 0; i < kNumberOfRendererProxy; ++i) { 135 scoped_refptr<MediaStreamAudioRenderer> renderer_proxy( 136 renderer_->CreateSharedAudioRendererProxy(stream_)); 137 renderer_proxy->Start(); 138 renderer_proxies_.push_back(renderer_proxy); 139 } 140 141 // Stop the |renderer_proxy_| should not stop the sink since it is used by 142 // other proxies. 143 EXPECT_CALL(*mock_output_device_.get(), Stop()).Times(0); 144 renderer_proxy_->Stop(); 145 146 for (int i = 0; i < kNumberOfRendererProxy; ++i) { 147 if (i != kNumberOfRendererProxy -1) { 148 EXPECT_CALL(*mock_output_device_.get(), Stop()).Times(0); 149 } else { 150 // When the last proxy is stopped, the sink will stop. 151 EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get())); 152 EXPECT_CALL(*mock_output_device_.get(), Stop()); 153 } 154 renderer_proxies_[i]->Stop(); 155 } 156 } 157 158 // Verify that the sink of the renderer is using the expected sample rate and 159 // buffer size. 160 TEST_F(WebRtcAudioRendererTest, VerifySinkParameters) { 161 renderer_proxy_->Start(); 162 #if defined(OS_LINUX) || defined(OS_MACOSX) 163 static const int kExpectedBufferSize = kHardwareSampleRate / 100; 164 #elif defined(OS_ANDROID) 165 static const int kExpectedBufferSize = 2 * kHardwareSampleRate / 100; 166 #else 167 // Windows. 168 static const int kExpectedBufferSize = kHardwareBufferSize; 169 #endif 170 EXPECT_EQ(kExpectedBufferSize, renderer_->frames_per_buffer()); 171 EXPECT_EQ(kHardwareSampleRate, renderer_->sample_rate()); 172 EXPECT_EQ(2, renderer_->channels()); 173 174 EXPECT_CALL(*mock_output_device_.get(), Stop()); 175 EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get())); 176 renderer_proxy_->Stop(); 177 } 178 179 } // namespace content 180