OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/webrtc_audio_renderer.h" | 5 #include "content/renderer/media/webrtc_audio_renderer.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <utility> | 8 #include <utility> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
| 11 #include "base/bind.h" |
11 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
12 #include "base/single_thread_task_runner.h" | |
13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
14 #include "content/public/renderer/media_stream_audio_renderer.h" | 14 #include "content/public/renderer/media_stream_audio_renderer.h" |
15 #include "content/renderer/media/audio_device_factory.h" | 15 #include "content/renderer/media/restartable_audio_output_device_factory.h" |
16 #include "content/renderer/media/audio_message_filter.h" | |
17 #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.
h" | |
18 #include "content/renderer/media/webrtc_audio_device_impl.h" | 16 #include "content/renderer/media/webrtc_audio_device_impl.h" |
19 #include "media/audio/audio_output_device.h" | 17 #include "media/base/restartable_audio_output_device.h" |
20 #include "media/audio/audio_output_ipc.h" | |
21 #include "media/base/audio_bus.h" | |
22 #include "media/base/mock_audio_renderer_sink.h" | |
23 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
24 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
25 #include "third_party/WebKit/public/platform/WebMediaStream.h" | 20 #include "third_party/WebKit/public/platform/WebMediaStream.h" |
26 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" | 21 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" |
27 #include "third_party/WebKit/public/web/WebHeap.h" | 22 #include "third_party/WebKit/public/web/WebHeap.h" |
28 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" | 23 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" |
29 | 24 |
30 using testing::Return; | 25 using testing::Return; |
31 using testing::_; | 26 using testing::_; |
32 | 27 |
33 namespace content { | 28 namespace content { |
34 | 29 |
35 namespace { | 30 namespace { |
36 | 31 |
37 const int kHardwareSampleRate = 44100; | 32 const int kHardwareSampleRate = 44100; |
38 const int kHardwareBufferSize = 512; | 33 const int kHardwareBufferSize = 512; |
39 const char kDefaultOutputDeviceId[] = ""; | 34 const char kDefaultOutputDeviceId[] = ""; |
40 const char kOtherOutputDeviceId[] = "other-output-device"; | 35 const char kOtherOutputDeviceId[] = "other-output-device"; |
41 const char kInvalidOutputDeviceId[] = "invalid-device"; | 36 const char kInvalidOutputDeviceId[] = "invalid-device"; |
42 | 37 |
43 class MockAudioOutputIPC : public media::AudioOutputIPC { | 38 class FakeAudioOutputDevice |
| 39 : NON_EXPORTED_BASE(public media::RestartableAudioOutputDevice) { |
44 public: | 40 public: |
45 MockAudioOutputIPC() {} | 41 FakeAudioOutputDevice(const std::string& device_id) : device_id_(device_id) {} |
46 virtual ~MockAudioOutputIPC() {} | 42 MOCK_METHOD2(Initialize, |
47 | 43 void(const media::AudioParameters&, RenderCallback*)); |
48 MOCK_METHOD4(RequestDeviceAuthorization, | |
49 void(media::AudioOutputIPCDelegate* delegate, | |
50 int session_id, | |
51 const std::string& device_id, | |
52 const url::Origin& security_origin)); | |
53 MOCK_METHOD2(CreateStream, | |
54 void(media::AudioOutputIPCDelegate* delegate, | |
55 const media::AudioParameters& params)); | |
56 MOCK_METHOD0(PlayStream, void()); | |
57 MOCK_METHOD0(PauseStream, void()); | |
58 MOCK_METHOD0(CloseStream, void()); | |
59 MOCK_METHOD1(SetVolume, void(double volume)); | |
60 MOCK_METHOD2(SwitchOutputDevice, | |
61 void(const std::string& device_id, | |
62 const url::Origin& security_origin)); | |
63 }; | |
64 | |
65 class FakeAudioOutputDevice | |
66 : NON_EXPORTED_BASE(public media::AudioOutputDevice) { | |
67 public: | |
68 FakeAudioOutputDevice( | |
69 scoped_ptr<media::AudioOutputIPC> ipc, | |
70 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, | |
71 const std::string& device_id) | |
72 : AudioOutputDevice(std::move(ipc), | |
73 io_task_runner, | |
74 0, | |
75 std::string(), | |
76 url::Origin()), | |
77 device_id_(device_id) {} | |
78 MOCK_METHOD0(Start, void()); | 44 MOCK_METHOD0(Start, void()); |
79 MOCK_METHOD0(Stop, void()); | 45 MOCK_METHOD0(Stop, void()); |
80 MOCK_METHOD0(Pause, void()); | 46 MOCK_METHOD0(Pause, void()); |
81 MOCK_METHOD0(Play, void()); | 47 MOCK_METHOD0(Play, void()); |
82 MOCK_METHOD1(SetVolume, bool(double volume)); | 48 MOCK_METHOD1(SetVolume, bool(double volume)); |
| 49 MOCK_METHOD0(GetOutputDevice, OutputDevice*()); |
| 50 MOCK_METHOD3(SwitchOutputDevice, |
| 51 void(const std::string&, |
| 52 const url::Origin&, |
| 53 const media::SwitchOutputDeviceCB&)); |
83 | 54 |
84 media::OutputDeviceStatus GetDeviceStatus() override { | 55 media::OutputDeviceStatus GetDeviceStatus() override { |
85 return device_id_ == kInvalidOutputDeviceId | 56 return device_id_ == kInvalidOutputDeviceId |
86 ? media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL | 57 ? media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL |
87 : media::OUTPUT_DEVICE_STATUS_OK; | 58 : media::OUTPUT_DEVICE_STATUS_OK; |
88 } | 59 } |
89 | 60 |
90 std::string GetDeviceId() const { return device_id_; } | 61 std::string GetDeviceId() const { return device_id_; } |
91 | 62 |
92 media::AudioParameters GetOutputParameters() override { | 63 media::AudioParameters GetOutputParameters() override { |
(...skipping 17 matching lines...) Expand all Loading... |
110 int sample_rate, | 81 int sample_rate, |
111 int audio_delay_milliseconds, | 82 int audio_delay_milliseconds, |
112 base::TimeDelta* current_time)); | 83 base::TimeDelta* current_time)); |
113 MOCK_METHOD1(RemoveAudioRenderer, void(WebRtcAudioRenderer* renderer)); | 84 MOCK_METHOD1(RemoveAudioRenderer, void(WebRtcAudioRenderer* renderer)); |
114 MOCK_METHOD0(AudioRendererThreadStopped, void()); | 85 MOCK_METHOD0(AudioRendererThreadStopped, void()); |
115 }; | 86 }; |
116 | 87 |
117 } // namespace | 88 } // namespace |
118 | 89 |
119 class WebRtcAudioRendererTest : public testing::Test, | 90 class WebRtcAudioRendererTest : public testing::Test, |
120 public AudioDeviceFactory { | 91 public RestartableAudioOutputDeviceFactory { |
121 public: | 92 public: |
122 MOCK_METHOD1(MockSwitchDeviceCallback, void(media::OutputDeviceStatus)); | 93 MOCK_METHOD1(MockSwitchDeviceCallback, void(media::OutputDeviceStatus)); |
123 void SwitchDeviceCallback(base::RunLoop* loop, | 94 void SwitchDeviceCallback(base::RunLoop* loop, |
124 media::OutputDeviceStatus result) { | 95 media::OutputDeviceStatus result) { |
125 MockSwitchDeviceCallback(result); | 96 MockSwitchDeviceCallback(result); |
126 loop->Quit(); | 97 loop->Quit(); |
127 } | 98 } |
128 | 99 |
129 protected: | 100 protected: |
130 WebRtcAudioRendererTest() | 101 WebRtcAudioRendererTest() |
131 : message_loop_(new base::MessageLoopForIO), | 102 : message_loop_(new base::MessageLoopForIO), |
132 mock_ipc_(nullptr), | |
133 source_(new MockAudioRendererSource()) { | 103 source_(new MockAudioRendererSource()) { |
134 blink::WebVector<blink::WebMediaStreamTrack> dummy_tracks; | 104 blink::WebVector<blink::WebMediaStreamTrack> dummy_tracks; |
135 stream_.initialize("new stream", dummy_tracks, dummy_tracks); | 105 stream_.initialize("new stream", dummy_tracks, dummy_tracks); |
136 } | 106 } |
137 | 107 |
138 void SetupRenderer(const std::string& device_id) { | 108 void SetupRenderer(const std::string& device_id) { |
139 renderer_ = new WebRtcAudioRenderer(message_loop_->task_runner(), stream_, | 109 renderer_ = new WebRtcAudioRenderer(message_loop_->task_runner(), stream_, |
140 1, 1, device_id, url::Origin()); | 110 1, 1, device_id, url::Origin()); |
141 EXPECT_CALL(*this, MockCreateOutputDevice(1, _, device_id, _)); | 111 EXPECT_CALL(*this, MockCreateOutputDevice( |
| 112 RestartableAudioOutputDeviceFactory::kSourceWebRTC, |
| 113 _, _, device_id, _)); |
142 EXPECT_TRUE(renderer_->Initialize(source_.get())); | 114 EXPECT_TRUE(renderer_->Initialize(source_.get())); |
143 | 115 |
144 renderer_proxy_ = renderer_->CreateSharedAudioRendererProxy(stream_); | 116 renderer_proxy_ = renderer_->CreateSharedAudioRendererProxy(stream_); |
145 } | 117 } |
146 | 118 |
147 MOCK_METHOD1(CreateInputDevice, media::AudioInputDevice*(int)); | 119 MOCK_METHOD5(MockCreateOutputDevice, |
148 MOCK_METHOD4(MockCreateOutputDevice, | 120 media::RestartableAudioOutputDevice*(SourceType, |
149 media::AudioOutputDevice*(int, | 121 int, |
150 int, | 122 int, |
151 const std::string&, | 123 const std::string&, |
152 const url::Origin&)); | 124 const url::Origin&)); |
153 media::AudioOutputDevice* CreateOutputDevice( | 125 media::RestartableAudioOutputDevice* CreateOutputDevice( |
| 126 SourceType source_type, |
154 int render_frame_id, | 127 int render_frame_id, |
155 int session_id, | 128 int session_id, |
156 const std::string& device_id, | 129 const std::string& device_id, |
157 const url::Origin& security_origin) { | 130 const url::Origin& security_origin) { |
158 MockAudioOutputIPC* fake_ipc = new MockAudioOutputIPC(); | 131 FakeAudioOutputDevice* fake_device = new FakeAudioOutputDevice(device_id); |
159 FakeAudioOutputDevice* fake_device = | |
160 new FakeAudioOutputDevice(scoped_ptr<media::AudioOutputIPC>(fake_ipc), | |
161 message_loop_->task_runner(), device_id); | |
162 if (device_id != kInvalidOutputDeviceId) { | 132 if (device_id != kInvalidOutputDeviceId) { |
163 mock_output_device_ = fake_device; | 133 mock_output_device_ = fake_device; |
164 mock_ipc_ = fake_ipc; | |
165 EXPECT_CALL(*mock_output_device_.get(), Start()); | 134 EXPECT_CALL(*mock_output_device_.get(), Start()); |
166 } | 135 } |
167 | 136 |
168 MockCreateOutputDevice(render_frame_id, session_id, device_id, | 137 MockCreateOutputDevice(source_type, render_frame_id, session_id, device_id, |
169 security_origin); | 138 security_origin); |
170 return fake_device; | 139 return fake_device; |
171 } | 140 } |
172 | 141 |
173 void TearDown() override { | 142 void TearDown() override { |
174 renderer_proxy_ = nullptr; | 143 renderer_proxy_ = nullptr; |
175 renderer_ = nullptr; | 144 renderer_ = nullptr; |
176 stream_.reset(); | 145 stream_.reset(); |
177 source_.reset(); | 146 source_.reset(); |
178 mock_output_device_ = nullptr; | 147 mock_output_device_ = nullptr; |
179 blink::WebHeap::collectAllGarbageForTesting(); | 148 blink::WebHeap::collectAllGarbageForTesting(); |
180 } | 149 } |
181 | 150 |
182 // Used to construct |mock_output_device_|. | |
183 scoped_ptr<base::MessageLoopForIO> message_loop_; | 151 scoped_ptr<base::MessageLoopForIO> message_loop_; |
184 MockAudioOutputIPC* mock_ipc_; // Owned by AudioOuputDevice. | |
185 | |
186 scoped_refptr<FakeAudioOutputDevice> mock_output_device_; | 152 scoped_refptr<FakeAudioOutputDevice> mock_output_device_; |
187 scoped_ptr<MockAudioRendererSource> source_; | 153 scoped_ptr<MockAudioRendererSource> source_; |
188 blink::WebMediaStream stream_; | 154 blink::WebMediaStream stream_; |
189 scoped_refptr<WebRtcAudioRenderer> renderer_; | 155 scoped_refptr<WebRtcAudioRenderer> renderer_; |
190 scoped_refptr<MediaStreamAudioRenderer> renderer_proxy_; | 156 scoped_refptr<MediaStreamAudioRenderer> renderer_proxy_; |
191 }; | 157 }; |
192 | 158 |
193 // Verify that the renderer will be stopped if the only proxy is stopped. | 159 // Verify that the renderer will be stopped if the only proxy is stopped. |
194 TEST_F(WebRtcAudioRendererTest, StopRenderer) { | 160 TEST_F(WebRtcAudioRendererTest, StopRenderer) { |
195 SetupRenderer(kDefaultOutputDeviceId); | 161 SetupRenderer(kDefaultOutputDeviceId); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get())); | 240 EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get())); |
275 renderer_proxy_->Stop(); | 241 renderer_proxy_->Stop(); |
276 } | 242 } |
277 | 243 |
278 TEST_F(WebRtcAudioRendererTest, SwitchOutputDevice) { | 244 TEST_F(WebRtcAudioRendererTest, SwitchOutputDevice) { |
279 SetupRenderer(kDefaultOutputDeviceId); | 245 SetupRenderer(kDefaultOutputDeviceId); |
280 EXPECT_EQ(kDefaultOutputDeviceId, mock_output_device_->GetDeviceId()); | 246 EXPECT_EQ(kDefaultOutputDeviceId, mock_output_device_->GetDeviceId()); |
281 renderer_proxy_->Start(); | 247 renderer_proxy_->Start(); |
282 | 248 |
283 EXPECT_CALL(*mock_output_device_.get(), Stop()); | 249 EXPECT_CALL(*mock_output_device_.get(), Stop()); |
284 EXPECT_CALL(*this, MockCreateOutputDevice(_, _, kOtherOutputDeviceId, _)); | 250 EXPECT_CALL(*this, MockCreateOutputDevice( |
| 251 RestartableAudioOutputDeviceFactory::kSourceWebRTC, _, |
| 252 _, kOtherOutputDeviceId, _)); |
285 EXPECT_CALL(*source_.get(), AudioRendererThreadStopped()); | 253 EXPECT_CALL(*source_.get(), AudioRendererThreadStopped()); |
286 EXPECT_CALL(*this, MockSwitchDeviceCallback(media::OUTPUT_DEVICE_STATUS_OK)); | 254 EXPECT_CALL(*this, MockSwitchDeviceCallback(media::OUTPUT_DEVICE_STATUS_OK)); |
287 base::RunLoop loop; | 255 base::RunLoop loop; |
288 renderer_proxy_->GetOutputDevice()->SwitchOutputDevice( | 256 renderer_proxy_->GetOutputDevice()->SwitchOutputDevice( |
289 kOtherOutputDeviceId, url::Origin(), | 257 kOtherOutputDeviceId, url::Origin(), |
290 base::Bind(&WebRtcAudioRendererTest::SwitchDeviceCallback, | 258 base::Bind(&WebRtcAudioRendererTest::SwitchDeviceCallback, |
291 base::Unretained(this), &loop)); | 259 base::Unretained(this), &loop)); |
292 loop.Run(); | 260 loop.Run(); |
293 EXPECT_EQ(kOtherOutputDeviceId, mock_output_device_->GetDeviceId()); | 261 EXPECT_EQ(kOtherOutputDeviceId, mock_output_device_->GetDeviceId()); |
294 | 262 |
295 EXPECT_CALL(*mock_output_device_.get(), Stop()); | 263 EXPECT_CALL(*mock_output_device_.get(), Stop()); |
296 EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get())); | 264 EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get())); |
297 renderer_proxy_->Stop(); | 265 renderer_proxy_->Stop(); |
298 } | 266 } |
299 | 267 |
300 TEST_F(WebRtcAudioRendererTest, SwitchOutputDeviceInvalidDevice) { | 268 TEST_F(WebRtcAudioRendererTest, SwitchOutputDeviceInvalidDevice) { |
301 SetupRenderer(kDefaultOutputDeviceId); | 269 SetupRenderer(kDefaultOutputDeviceId); |
302 EXPECT_EQ(kDefaultOutputDeviceId, mock_output_device_->GetDeviceId()); | 270 EXPECT_EQ(kDefaultOutputDeviceId, mock_output_device_->GetDeviceId()); |
303 renderer_proxy_->Start(); | 271 renderer_proxy_->Start(); |
304 | 272 |
305 EXPECT_CALL(*this, MockCreateOutputDevice(_, _, kInvalidOutputDeviceId, _)); | 273 EXPECT_CALL(*this, MockCreateOutputDevice( |
| 274 RestartableAudioOutputDeviceFactory::kSourceWebRTC, _, |
| 275 _, kInvalidOutputDeviceId, _)); |
306 EXPECT_CALL(*this, MockSwitchDeviceCallback( | 276 EXPECT_CALL(*this, MockSwitchDeviceCallback( |
307 media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL)); | 277 media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL)); |
308 base::RunLoop loop; | 278 base::RunLoop loop; |
309 renderer_proxy_->GetOutputDevice()->SwitchOutputDevice( | 279 renderer_proxy_->GetOutputDevice()->SwitchOutputDevice( |
310 kInvalidOutputDeviceId, url::Origin(), | 280 kInvalidOutputDeviceId, url::Origin(), |
311 base::Bind(&WebRtcAudioRendererTest::SwitchDeviceCallback, | 281 base::Bind(&WebRtcAudioRendererTest::SwitchDeviceCallback, |
312 base::Unretained(this), &loop)); | 282 base::Unretained(this), &loop)); |
313 loop.Run(); | 283 loop.Run(); |
314 EXPECT_EQ(kDefaultOutputDeviceId, mock_output_device_->GetDeviceId()); | 284 EXPECT_EQ(kDefaultOutputDeviceId, mock_output_device_->GetDeviceId()); |
315 | 285 |
316 EXPECT_CALL(*mock_output_device_.get(), Stop()); | 286 EXPECT_CALL(*mock_output_device_.get(), Stop()); |
317 EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get())); | 287 EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get())); |
318 renderer_proxy_->Stop(); | 288 renderer_proxy_->Stop(); |
319 } | 289 } |
320 | 290 |
321 } // namespace content | 291 } // namespace content |
OLD | NEW |