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

Side by Side Diff: content/browser/renderer_host/media/audio_renderer_host_unittest.cc

Issue 1930393002: Switch stream creation and closing in Chrome audio rendering from IPC to Mojo (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: unique_ptr for Binding Created 4 years, 6 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
« no previous file with comments | « content/browser/renderer_host/media/audio_renderer_host.cc ('k') | content/common/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/browser/renderer_host/media/audio_renderer_host.h" 5 #include "content/browser/renderer_host/media/audio_renderer_host.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/run_loop.h" 14 #include "base/run_loop.h"
15 #include "base/sync_socket.h" 15 #include "base/sync_socket.h"
16 #include "content/browser/media/audio_output_impl.h"
16 #include "content/browser/media/capture/audio_mirroring_manager.h" 17 #include "content/browser/media/capture/audio_mirroring_manager.h"
17 #include "content/browser/media/media_internals.h" 18 #include "content/browser/media/media_internals.h"
18 #include "content/browser/renderer_host/media/audio_input_device_manager.h" 19 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
19 #include "content/browser/renderer_host/media/media_stream_manager.h" 20 #include "content/browser/renderer_host/media/media_stream_manager.h"
20 #include "content/common/media/audio_messages.h" 21 #include "content/common/media/audio_messages.h"
21 #include "content/public/common/content_switches.h" 22 #include "content/public/common/content_switches.h"
22 #include "content/public/test/test_browser_thread_bundle.h" 23 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "ipc/ipc_message_utils.h" 24 #include "ipc/ipc_message_utils.h"
24 #include "media/audio/audio_manager.h" 25 #include "media/audio/audio_manager.h"
25 #include "media/base/bind_to_current_loop.h" 26 #include "media/base/bind_to_current_loop.h"
26 #include "media/base/media_switches.h" 27 #include "media/base/media_switches.h"
28 #include "mojo/edk/embedder/embedder.h"
27 #include "testing/gmock/include/gmock/gmock.h" 29 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h" 30 #include "testing/gtest/include/gtest/gtest.h"
29 31 /*
30 using ::testing::_; 32 using ::testing::_;
31 using ::testing::Assign; 33 using ::testing::Assign;
32 using ::testing::DoAll; 34 using ::testing::DoAll;
33 using ::testing::NotNull; 35 using ::testing::NotNull;
34 36
35 namespace { 37 namespace {
36 const int kRenderProcessId = 1; 38 const int kRenderProcessId = 1;
37 const int kRenderFrameId = 5; 39 const int kRenderFrameId = 5;
38 const int kStreamId = 50; 40 const int kStreamId = 50;
39 const char kSecurityOrigin[] = "http://localhost"; 41 const char kSecurityOrigin[] = "http://localhost";
(...skipping 26 matching lines...) Expand all
66 AudioMirroringManager* mirroring_manager, 68 AudioMirroringManager* mirroring_manager,
67 MediaInternals* media_internals, 69 MediaInternals* media_internals,
68 MediaStreamManager* media_stream_manager, 70 MediaStreamManager* media_stream_manager,
69 const ResourceContext::SaltCallback& salt_callback) 71 const ResourceContext::SaltCallback& salt_callback)
70 : AudioRendererHost(kRenderProcessId, 72 : AudioRendererHost(kRenderProcessId,
71 audio_manager, 73 audio_manager,
72 mirroring_manager, 74 mirroring_manager,
73 media_internals, 75 media_internals,
74 media_stream_manager, 76 media_stream_manager,
75 salt_callback), 77 salt_callback),
76 shared_memory_length_(0) {} 78 shared_memory_length_(0) {
79 LOG(ERROR) << "rm MockAudioRendererHost";
80 }
81
82 AudioOutputImpl* Init(scoped_refptr<MockAudioRendererHost> host) {
83 media::mojom::AudioOutputPtr* stream = new media::mojom::AudioOutputPtr();
84 set_audio_output_impl(
85 kRenderFrameId,
86 new AudioOutputImpl(0, kRenderFrameId, mojo::GetProxy(stream)));
87 return get_audio_output_impl(kRenderFrameId);
88 }
77 89
78 // A list of mock methods. 90 // A list of mock methods.
79 MOCK_METHOD4(OnDeviceAuthorized, 91 MOCK_METHOD4(OnDeviceAuthorized,
80 void(int stream_id, 92 void(int stream_id,
81 media::OutputDeviceStatus device_status, 93 media::OutputDeviceStatus device_status,
82 const media::AudioParameters& output_params, 94 const media::AudioParameters& output_params,
83 const std::string& matched_device_id)); 95 const std::string& matched_device_id));
84 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length)); 96 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length));
85 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); 97 MOCK_METHOD1(OnStreamPlaying, void(int stream_id));
86 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); 98 MOCK_METHOD1(OnStreamPaused, void(int stream_id));
87 MOCK_METHOD1(OnStreamError, void(int stream_id)); 99 MOCK_METHOD1(OnStreamError, void(int stream_id));
88 100
89 private: 101 private:
90 virtual ~MockAudioRendererHost() { 102 virtual ~MockAudioRendererHost() {
103 LOG(ERROR) << "rrm MockAudioRendererHost";
91 // Make sure all audio streams have been deleted. 104 // Make sure all audio streams have been deleted.
92 EXPECT_TRUE(audio_entries_.empty()); 105 EXPECT_TRUE(audio_entries_.empty());
93 } 106 }
94 107
95 // This method is used to dispatch IPC messages to the renderer. We intercept 108 // This method is used to dispatch IPC messages to the renderer. We intercept
96 // these messages here and dispatch to our mock methods to verify the 109 // these messages here and dispatch to our mock methods to verify the
97 // conversation between this object and the renderer. 110 // conversation between this object and the renderer.
98 virtual bool Send(IPC::Message* message) { 111 virtual bool Send(IPC::Message* message) {
99 CHECK(message); 112 CHECK(message);
100 113
101 // In this method we dispatch the messages to the according handlers as if 114 // In this method we dispatch the messages to the according handlers as if
102 // we are the renderer. 115 // we are the renderer.
103 bool handled = true; 116 bool handled = true;
104 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message) 117 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message)
105 IPC_MESSAGE_HANDLER(AudioMsg_NotifyDeviceAuthorized, 118 IPC_MESSAGE_HANDLER(AudioMsg_NotifyDeviceAuthorized,
106 OnNotifyDeviceAuthorized) 119 OnNotifyDeviceAuthorized)
107 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated,
108 OnNotifyStreamCreated)
109 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged, 120 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged,
110 OnNotifyStreamStateChanged) 121 OnNotifyStreamStateChanged)
111 IPC_MESSAGE_UNHANDLED(handled = false) 122 IPC_MESSAGE_UNHANDLED(handled = false)
112 IPC_END_MESSAGE_MAP() 123 IPC_END_MESSAGE_MAP()
113 EXPECT_TRUE(handled); 124 EXPECT_TRUE(handled);
114 125
115 delete message; 126 delete message;
116 return true; 127 return true;
117 } 128 }
118 129
119 void OnNotifyDeviceAuthorized(int stream_id, 130 void OnNotifyDeviceAuthorized(int stream_id,
120 media::OutputDeviceStatus device_status, 131 media::OutputDeviceStatus device_status,
121 const media::AudioParameters& output_params, 132 const media::AudioParameters& output_params,
122 const std::string& matched_device_id) { 133 const std::string& matched_device_id) {
123 OnDeviceAuthorized(stream_id, device_status, output_params, 134 OnDeviceAuthorized(stream_id, device_status, output_params,
124 matched_device_id); 135 matched_device_id);
125 } 136 }
126 137
127 void OnNotifyStreamCreated(
128 int stream_id,
129 base::SharedMemoryHandle handle,
130 base::SyncSocket::TransitDescriptor socket_descriptor,
131 uint32_t length) {
132 // Maps the shared memory.
133 shared_memory_.reset(new base::SharedMemory(handle, false));
134 CHECK(shared_memory_->Map(length));
135 CHECK(shared_memory_->memory());
136 shared_memory_length_ = length;
137
138 // Create the SyncSocket using the handle.
139 base::SyncSocket::Handle sync_socket_handle =
140 base::SyncSocket::UnwrapHandle(socket_descriptor);
141 sync_socket_.reset(new base::SyncSocket(sync_socket_handle));
142
143 // And then delegate the call to the mock method.
144 OnStreamCreated(stream_id, length);
145 }
146
147 void OnNotifyStreamStateChanged(int stream_id, 138 void OnNotifyStreamStateChanged(int stream_id,
148 media::AudioOutputIPCDelegateState state) { 139 media::AudioOutputIPCDelegateState state) {
149 switch (state) { 140 switch (state) {
150 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PLAYING: 141 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PLAYING:
151 OnStreamPlaying(stream_id); 142 OnStreamPlaying(stream_id);
152 break; 143 break;
153 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED: 144 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED:
154 OnStreamPaused(stream_id); 145 OnStreamPaused(stream_id);
155 break; 146 break;
156 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR: 147 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR:
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 base::RunLoop run_loop; 191 base::RunLoop run_loop;
201 media_stream_manager_->audio_output_device_enumerator()->Enumerate( 192 media_stream_manager_->audio_output_device_enumerator()->Enumerate(
202 base::Bind(&WaitForEnumeration, &run_loop)); 193 base::Bind(&WaitForEnumeration, &run_loop));
203 run_loop.Run(); 194 run_loop.Run();
204 195
205 host_ = new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_, 196 host_ = new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_,
206 MediaInternals::GetInstance(), 197 MediaInternals::GetInstance(),
207 media_stream_manager_.get(), 198 media_stream_manager_.get(),
208 GetMockSaltCallback()); 199 GetMockSaltCallback());
209 200
201 audio_output_impl_.reset(host_->Init(host_.get()));
202
210 // Simulate IPC channel connected. 203 // Simulate IPC channel connected.
211 host_->set_peer_process_for_testing(base::Process::Current()); 204 host_->set_peer_process_for_testing(base::Process::Current());
212 } 205 }
213 206
214 ~AudioRendererHostTest() override { 207 ~AudioRendererHostTest() override {
215 // Simulate closing the IPC channel and give the audio thread time to close 208 // Simulate closing the IPC channel and give the audio thread time to close
216 // the underlying streams. 209 // the underlying streams.
217 host_->OnChannelClosing(); 210 host_->OnChannelClosing();
218 SyncWithAudioThread(); 211 SyncWithAudioThread();
219 212
(...skipping 10 matching lines...) Expand all
230 void Create(bool unified_stream, 223 void Create(bool unified_stream,
231 const std::string& device_id, 224 const std::string& device_id,
232 const url::Origin& security_origin) { 225 const url::Origin& security_origin) {
233 media::OutputDeviceStatus expected_device_status = 226 media::OutputDeviceStatus expected_device_status =
234 device_id == kDefaultDeviceId 227 device_id == kDefaultDeviceId
235 ? media::OUTPUT_DEVICE_STATUS_OK 228 ? media::OUTPUT_DEVICE_STATUS_OK
236 : device_id == kBadDeviceId 229 : device_id == kBadDeviceId
237 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED 230 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED
238 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND; 231 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND;
239 232
240 EXPECT_CALL(*host_.get(),
241 OnDeviceAuthorized(kStreamId, expected_device_status, _, _));
242
243 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) { 233 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) {
244 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _)); 234 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
245 EXPECT_CALL(mirroring_manager_, 235 EXPECT_CALL(mirroring_manager_,
246 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull())) 236 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()))
247 .RetiresOnSaturation(); 237 .RetiresOnSaturation();
248 } 238 }
249 239
250 // Send a create stream message to the audio output stream and wait until 240 // Send a create stream message to the audio output stream and wait until
251 // we receive the created message. 241 // we receive the created message.
252 media::AudioParameters params( 242 media::AudioParameters params(
253 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, 243 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
254 media::AudioParameters::kAudioCDSampleRate, 16, 244 media::AudioParameters::kAudioCDSampleRate, 16,
255 media::AudioParameters::kAudioCDSampleRate / 10); 245 media::AudioParameters::kAudioCDSampleRate / 10);
256 int session_id = 0; 246 int session_id = 0;
257 if (unified_stream) { 247 if (unified_stream) {
258 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to 248 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to
259 // pass the permission check. 249 // pass the permission check.
260 session_id = AudioInputDeviceManager::kFakeOpenSessionId; 250 session_id = AudioInputDeviceManager::kFakeOpenSessionId;
261 } 251 }
262 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, 252 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
263 device_id, security_origin); 253 device_id, security_origin);
264 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) { 254 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) {
265 host_->OnCreateStream(kStreamId, kRenderFrameId, params); 255 host_->CreateStream(kStreamId, kRenderFrameId, params,
256 base::Bind(&AudioRendererHostTest::CreateCallback,
257 base::Unretained(this)));
266 258
267 // At some point in the future, a corresponding RemoveDiverter() call must 259 // At some point in the future, a corresponding RemoveDiverter() call must
268 // be made. 260 // be made.
269 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())) 261 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
270 .RetiresOnSaturation(); 262 .RetiresOnSaturation();
271 } 263 }
272 SyncWithAudioThread(); 264 SyncWithAudioThread();
273 } 265 }
274 266
267 void CreateCallback(int stream_id,
268 media::mojom::AudioOutputStreamPtr stream,
269 mojo::ScopedSharedBufferHandle shared_buffer,
270 mojo::ScopedHandle socket_descriptor) {
271 base::SharedMemoryHandle shared_memory_handle;
272 size_t length;
273 MojoResult pass_shared_memory_result = mojo::edk::PassSharedMemoryHandle(
274 shared_buffer.release().value(), &shared_memory_handle, &length,
275 nullptr);
276
277 if (pass_shared_memory_result != MOJO_RESULT_OK) {
278 LOG(ERROR) << "Failed to pass shared memory. Closing: "
279 << pass_shared_memory_result;
280 return;
281 }
282 mojo::edk::ScopedPlatformHandle platform_handle;
283
284 MojoResult pass_platform_handle_result =
285 mojo::edk::PassWrappedPlatformHandle(
286 socket_descriptor.release().value(), &platform_handle);
287
288 if (pass_platform_handle_result != MOJO_RESULT_OK) {
289 LOG(ERROR) << "Failed to pass transit descriptor. Closing: "
290 << pass_platform_handle_result;
291 return;
292 }
293
294 base::SyncSocket::TransitDescriptor descriptor;
295 #if defined(OS_WIN)
296 descriptor = platform_handle.release().handle;
297 #else
298 descriptor.fd = platform_handle.release().handle;
299 #endif
300
301 // Maps the shared memory.
302 base::SharedMemory shared_memory(shared_memory_handle, false);
303 CHECK(shared_memory.Map(length));
304 CHECK(shared_memory.memory());
305
306 // Create the SyncSocket using the handle.
307 base::SyncSocket::Handle sync_socket_handle =
308 base::SyncSocket::UnwrapHandle(descriptor);
309 base::SyncSocket sync_socket(sync_socket_handle);
310
311 // And then delegate the call to the mock method.
312 host_->OnStreamCreated(stream_id, length);
313 // |stream| will be released when its corresponding AudioOutputStreamImpl
314 // will be destructed in |audio_output_impl_| destructor.
315 // |stream| needs to be moved to somewhere else, otherwise it will be reset
316 // twice: once when it goes out of scope in this function and once in
317 // |audio_output_impl_| destructor in AudioOutputImpl which will cause an
318 // error.
319 streams_.insert(std::make_pair(
320 stream_id,
321 std::unique_ptr<media::mojom::AudioOutputStreamPtr>(
322 new media::mojom::AudioOutputStreamPtr(std::move(stream)))));
323 }
324
275 void Close() { 325 void Close() {
276 // Send a message to AudioRendererHost to tell it we want to close the 326 // Send a message to AudioRendererHost to tell it we want to close the
277 // stream. 327 // stream.
278 host_->OnCloseStream(kStreamId); 328 host_->CloseStream(kStreamId);
279 SyncWithAudioThread(); 329 SyncWithAudioThread();
280 } 330 }
281 331
282 void Play() { 332 void Play() {
283 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId)); 333 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId));
284 host_->OnPlayStream(kStreamId); 334 host_->OnPlayStream(kStreamId);
285 SyncWithAudioThread(); 335 SyncWithAudioThread();
286 } 336 }
287 337
288 void Pause() { 338 void Pause() {
(...skipping 29 matching lines...) Expand all
318 void SyncWithAudioThread() { 368 void SyncWithAudioThread() {
319 base::RunLoop().RunUntilIdle(); 369 base::RunLoop().RunUntilIdle();
320 370
321 base::RunLoop run_loop; 371 base::RunLoop run_loop;
322 audio_manager_->GetTaskRunner()->PostTask( 372 audio_manager_->GetTaskRunner()->PostTask(
323 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure())); 373 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
324 run_loop.Run(); 374 run_loop.Run();
325 } 375 }
326 376
327 private: 377 private:
378 typedef std::map<int, std::unique_ptr<media::mojom::AudioOutputStreamPtr>>
379 ScopedAudioOutputStreamPtrMap;
328 // MediaStreamManager uses a DestructionObserver, so it must outlive the 380 // MediaStreamManager uses a DestructionObserver, so it must outlive the
329 // TestBrowserThreadBundle. 381 // TestBrowserThreadBundle.
330 std::unique_ptr<MediaStreamManager> media_stream_manager_; 382 std::unique_ptr<MediaStreamManager> media_stream_manager_;
331 TestBrowserThreadBundle thread_bundle_; 383 TestBrowserThreadBundle thread_bundle_;
332 media::ScopedAudioManagerPtr audio_manager_; 384 media::ScopedAudioManagerPtr audio_manager_;
333 MockAudioMirroringManager mirroring_manager_; 385 MockAudioMirroringManager mirroring_manager_;
334 scoped_refptr<MockAudioRendererHost> host_; 386 scoped_refptr<MockAudioRendererHost> host_;
387 std::unique_ptr<AudioOutputImpl> audio_output_impl_;
388 ScopedAudioOutputStreamPtrMap streams_;
335 389
336 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); 390 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
337 }; 391 };
338 392
339 TEST_F(AudioRendererHostTest, CreateAndClose) { 393 TEST_F(AudioRendererHostTest, CreateAndClose) {
340 Create(); 394 Create();
341 Close(); 395 Close();
342 } 396 }
343 397
344 // Simulate the case where a stream is not properly closed. 398 // Simulate the case where a stream is not properly closed.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 } 461 }
408 462
409 TEST_F(AudioRendererHostTest, CreateInvalidDevice) { 463 TEST_F(AudioRendererHostTest, CreateInvalidDevice) {
410 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin))); 464 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)));
411 Close(); 465 Close();
412 } 466 }
413 467
414 // TODO(hclam): Add tests for data conversation in low latency mode. 468 // TODO(hclam): Add tests for data conversation in low latency mode.
415 469
416 } // namespace content 470 } // namespace content
471 */
OLDNEW
« no previous file with comments | « content/browser/renderer_host/media/audio_renderer_host.cc ('k') | content/common/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698