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

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: render_frame_id Created 4 years, 7 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
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 "media/mojo/common/media_type_converters.h"
29 #include "mojo/edk/embedder/embedder.h"
27 #include "testing/gmock/include/gmock/gmock.h" 30 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h" 31 #include "testing/gtest/include/gtest/gtest.h"
29 32
30 using ::testing::_; 33 using ::testing::_;
31 using ::testing::Assign; 34 using ::testing::Assign;
32 using ::testing::DoAll; 35 using ::testing::DoAll;
33 using ::testing::NotNull; 36 using ::testing::NotNull;
34 37
35 namespace { 38 namespace {
36 const int kRenderProcessId = 1; 39 const int kRenderProcessId = 1;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 MediaStreamManager* media_stream_manager, 71 MediaStreamManager* media_stream_manager,
69 const ResourceContext::SaltCallback& salt_callback) 72 const ResourceContext::SaltCallback& salt_callback)
70 : AudioRendererHost(kRenderProcessId, 73 : AudioRendererHost(kRenderProcessId,
71 audio_manager, 74 audio_manager,
72 mirroring_manager, 75 mirroring_manager,
73 media_internals, 76 media_internals,
74 media_stream_manager, 77 media_stream_manager,
75 salt_callback), 78 salt_callback),
76 shared_memory_length_(0) {} 79 shared_memory_length_(0) {}
77 80
81 AudioOutputImpl* Init(scoped_refptr<MockAudioRendererHost> host) {
82 media::mojom::AudioOutputPtr* stream =
83 new media::mojom::AudioOutputPtr();
84 audio_output_impl_ = (new AudioOutputImpl(0, mojo::GetProxy(stream)));
85 return audio_output_impl_;
86 }
87
78 // A list of mock methods. 88 // A list of mock methods.
79 MOCK_METHOD4(OnDeviceAuthorized, 89 MOCK_METHOD4(OnDeviceAuthorized,
80 void(int stream_id, 90 void(int stream_id,
81 media::OutputDeviceStatus device_status, 91 media::OutputDeviceStatus device_status,
82 const media::AudioParameters& output_params, 92 const media::AudioParameters& output_params,
83 const std::string& matched_device_id)); 93 const std::string& matched_device_id));
84 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length)); 94 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length));
85 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); 95 MOCK_METHOD1(OnStreamPlaying, void(int stream_id));
86 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); 96 MOCK_METHOD1(OnStreamPaused, void(int stream_id));
87 MOCK_METHOD1(OnStreamError, void(int stream_id)); 97 MOCK_METHOD1(OnStreamError, void(int stream_id));
88 98
99 void OnNotifyStreamCreated(
100 int stream_id,
101 base::SharedMemoryHandle handle,
102 base::SyncSocket::TransitDescriptor socket_descriptor,
103 uint32_t length) {
104 // Maps the shared memory.
105 shared_memory_.reset(new base::SharedMemory(handle, false));
106 CHECK(shared_memory_->Map(length));
107 CHECK(shared_memory_->memory());
108 shared_memory_length_ = length;
109
110 // Create the SyncSocket using the handle.
111 base::SyncSocket::Handle sync_socket_handle =
112 base::SyncSocket::UnwrapHandle(socket_descriptor);
113 sync_socket_.reset(new base::SyncSocket(sync_socket_handle));
114
115 // And then delegate the call to the mock method.
116 OnStreamCreated(stream_id, length);
117 }
118
89 private: 119 private:
90 virtual ~MockAudioRendererHost() { 120 virtual ~MockAudioRendererHost() {
91 // Make sure all audio streams have been deleted. 121 // Make sure all audio streams have been deleted.
92 EXPECT_TRUE(audio_entries_.empty()); 122 EXPECT_TRUE(audio_entries_.empty());
93 } 123 }
94 124
95 // This method is used to dispatch IPC messages to the renderer. We intercept 125 // 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 126 // these messages here and dispatch to our mock methods to verify the
97 // conversation between this object and the renderer. 127 // conversation between this object and the renderer.
98 virtual bool Send(IPC::Message* message) { 128 virtual bool Send(IPC::Message* message) {
99 CHECK(message); 129 CHECK(message);
100 130
101 // In this method we dispatch the messages to the according handlers as if 131 // In this method we dispatch the messages to the according handlers as if
102 // we are the renderer. 132 // we are the renderer.
103 bool handled = true; 133 bool handled = true;
104 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message) 134 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message)
105 IPC_MESSAGE_HANDLER(AudioMsg_NotifyDeviceAuthorized, 135 IPC_MESSAGE_HANDLER(AudioMsg_NotifyDeviceAuthorized,
106 OnNotifyDeviceAuthorized) 136 OnNotifyDeviceAuthorized)
107 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated,
108 OnNotifyStreamCreated)
109 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged, 137 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged,
110 OnNotifyStreamStateChanged) 138 OnNotifyStreamStateChanged)
111 IPC_MESSAGE_UNHANDLED(handled = false) 139 IPC_MESSAGE_UNHANDLED(handled = false)
112 IPC_END_MESSAGE_MAP() 140 IPC_END_MESSAGE_MAP()
113 EXPECT_TRUE(handled); 141 EXPECT_TRUE(handled);
114 142
115 delete message; 143 delete message;
116 return true; 144 return true;
117 } 145 }
118 146
119 void OnNotifyDeviceAuthorized(int stream_id, 147 void OnNotifyDeviceAuthorized(int stream_id,
120 media::OutputDeviceStatus device_status, 148 media::OutputDeviceStatus device_status,
121 const media::AudioParameters& output_params, 149 const media::AudioParameters& output_params,
122 const std::string& matched_device_id) { 150 const std::string& matched_device_id) {
123 OnDeviceAuthorized(stream_id, device_status, output_params, 151 OnDeviceAuthorized(stream_id, device_status, output_params,
124 matched_device_id); 152 matched_device_id);
125 } 153 }
126 154
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, 155 void OnNotifyStreamStateChanged(int stream_id,
148 media::AudioOutputIPCDelegateState state) { 156 media::AudioOutputIPCDelegateState state) {
149 switch (state) { 157 switch (state) {
150 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PLAYING: 158 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PLAYING:
151 OnStreamPlaying(stream_id); 159 OnStreamPlaying(stream_id);
152 break; 160 break;
153 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED: 161 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED:
154 OnStreamPaused(stream_id); 162 OnStreamPaused(stream_id);
155 break; 163 break;
156 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR: 164 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; 208 base::RunLoop run_loop;
201 media_stream_manager_->audio_output_device_enumerator()->Enumerate( 209 media_stream_manager_->audio_output_device_enumerator()->Enumerate(
202 base::Bind(&WaitForEnumeration, &run_loop)); 210 base::Bind(&WaitForEnumeration, &run_loop));
203 run_loop.Run(); 211 run_loop.Run();
204 212
205 host_ = new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_, 213 host_ = new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_,
206 MediaInternals::GetInstance(), 214 MediaInternals::GetInstance(),
207 media_stream_manager_.get(), 215 media_stream_manager_.get(),
208 GetMockSaltCallback()); 216 GetMockSaltCallback());
209 217
218 audio_output_impl_.reset(host_->Init(host_.get()));
219
210 // Simulate IPC channel connected. 220 // Simulate IPC channel connected.
211 host_->set_peer_process_for_testing(base::Process::Current()); 221 host_->set_peer_process_for_testing(base::Process::Current());
212 } 222 }
213 223
214 ~AudioRendererHostTest() override { 224 ~AudioRendererHostTest() override {
215 // Simulate closing the IPC channel and give the audio thread time to close 225 // Simulate closing the IPC channel and give the audio thread time to close
216 // the underlying streams. 226 // the underlying streams.
217 host_->OnChannelClosing(); 227 host_->OnChannelClosing();
218 SyncWithAudioThread(); 228 SyncWithAudioThread();
219 229
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 media::AudioParameters::kAudioCDSampleRate / 10); 265 media::AudioParameters::kAudioCDSampleRate / 10);
256 int session_id = 0; 266 int session_id = 0;
257 if (unified_stream) { 267 if (unified_stream) {
258 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to 268 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to
259 // pass the permission check. 269 // pass the permission check.
260 session_id = AudioInputDeviceManager::kFakeOpenSessionId; 270 session_id = AudioInputDeviceManager::kFakeOpenSessionId;
261 } 271 }
262 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, 272 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
263 device_id, security_origin); 273 device_id, security_origin);
264 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) { 274 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) {
265 host_->OnCreateStream(kStreamId, kRenderFrameId, params); 275 host_->CreateStream(kStreamId, kRenderFrameId, params,
276 base::Bind(&AudioRendererHostTest::CreateCallback,
277 base::Unretained(this)));
266 278
267 // At some point in the future, a corresponding RemoveDiverter() call must 279 // At some point in the future, a corresponding RemoveDiverter() call must
268 // be made. 280 // be made.
269 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())) 281 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
270 .RetiresOnSaturation(); 282 .RetiresOnSaturation();
271 } 283 }
272 SyncWithAudioThread(); 284 SyncWithAudioThread();
273 } 285 }
274 286
287 void CreateCallback(int stream_id,
288 media::mojom::AudioOutputStreamPtr stream,
289 mojo::ScopedSharedBufferHandle shared_buffer,
290 mojo::ScopedHandle socket_descriptor) {
291 base::SharedMemoryHandle shared_memory_handle;
292 size_t length;
293 MojoResult pass_shared_memory_result = mojo::edk::PassSharedMemoryHandle(
294 shared_buffer.release().value(), &shared_memory_handle, &length,
295 nullptr);
296
297 if (pass_shared_memory_result != MOJO_RESULT_OK) {
298 LOG(ERROR) << "Failed to pass shared memory. Closing: "
299 << pass_shared_memory_result;
300 return;
301 }
302 mojo::edk::ScopedPlatformHandle platform_handle;
303
304 MojoResult pass_platform_handle_result =
305 mojo::edk::PassWrappedPlatformHandle(
306 socket_descriptor.release().value(), &platform_handle);
307
308 if (pass_platform_handle_result != MOJO_RESULT_OK) {
309 LOG(ERROR) << "Failed to pass transit descriptor. Closing: "
310 << pass_platform_handle_result;
311 return;
312 }
313
314 base::SyncSocket::TransitDescriptor descriptor;
315 #if defined(OS_WIN)
316 descriptor = platform_handle.release().handle;
317 #else
318 descriptor.fd = platform_handle.release().handle;
319 #endif
320
321 host_->OnNotifyStreamCreated(stream_id, shared_memory_handle, descriptor,
322 length);
323
324 streams_.insert(
325 std::pair<int, std::unique_ptr<media::mojom::AudioOutputStreamPtr>>
326 (stream_id,
327 std::unique_ptr<media::mojom::AudioOutputStreamPtr>
328 (new media::mojom::AudioOutputStreamPtr(std::move(stream)))));
329 }
330
275 void Close() { 331 void Close() {
276 // Send a message to AudioRendererHost to tell it we want to close the 332 // Send a message to AudioRendererHost to tell it we want to close the
277 // stream. 333 // stream.
278 host_->OnCloseStream(kStreamId); 334 host_->OnCloseStream(kStreamId);
279 SyncWithAudioThread(); 335 SyncWithAudioThread();
280 } 336 }
281 337
282 void Play() { 338 void Play() {
283 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId)); 339 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId));
284 host_->OnPlayStream(kStreamId); 340 host_->OnPlayStream(kStreamId);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 void SyncWithAudioThread() { 374 void SyncWithAudioThread() {
319 base::RunLoop().RunUntilIdle(); 375 base::RunLoop().RunUntilIdle();
320 376
321 base::RunLoop run_loop; 377 base::RunLoop run_loop;
322 audio_manager_->GetTaskRunner()->PostTask( 378 audio_manager_->GetTaskRunner()->PostTask(
323 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure())); 379 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
324 run_loop.Run(); 380 run_loop.Run();
325 } 381 }
326 382
327 private: 383 private:
384 typedef std::map<int,
385 std::unique_ptr<media::mojom::AudioOutputStreamPtr>>
386 ScopedAudioOutputStreamPtrMap;
328 // MediaStreamManager uses a DestructionObserver, so it must outlive the 387 // MediaStreamManager uses a DestructionObserver, so it must outlive the
329 // TestBrowserThreadBundle. 388 // TestBrowserThreadBundle.
330 std::unique_ptr<MediaStreamManager> media_stream_manager_; 389 std::unique_ptr<MediaStreamManager> media_stream_manager_;
331 TestBrowserThreadBundle thread_bundle_; 390 TestBrowserThreadBundle thread_bundle_;
332 media::ScopedAudioManagerPtr audio_manager_; 391 media::ScopedAudioManagerPtr audio_manager_;
333 MockAudioMirroringManager mirroring_manager_; 392 MockAudioMirroringManager mirroring_manager_;
334 scoped_refptr<MockAudioRendererHost> host_; 393 scoped_refptr<MockAudioRendererHost> host_;
394 std::unique_ptr<AudioOutputImpl> audio_output_impl_;
395 ScopedAudioOutputStreamPtrMap streams_;
335 396
336 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); 397 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
337 }; 398 };
338 399
339 TEST_F(AudioRendererHostTest, CreateAndClose) { 400 TEST_F(AudioRendererHostTest, CreateAndClose) {
340 Create(); 401 Create();
341 Close(); 402 Close();
342 } 403 }
343 404
344 // Simulate the case where a stream is not properly closed. 405 // Simulate the case where a stream is not properly closed.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 } 468 }
408 469
409 TEST_F(AudioRendererHostTest, CreateInvalidDevice) { 470 TEST_F(AudioRendererHostTest, CreateInvalidDevice) {
410 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin))); 471 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)));
411 Close(); 472 Close();
412 } 473 }
413 474
414 // TODO(hclam): Add tests for data conversation in low latency mode. 475 // TODO(hclam): Add tests for data conversation in low latency mode.
415 476
416 } // namespace content 477 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/media/audio_renderer_host.cc ('k') | content/browser/renderer_host/render_process_host_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698