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

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: 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::interfaces::AudioOutputPtr* stream =
83 new media::interfaces::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(
Henrik Grunell 2016/05/02 12:12:23 As we talked about offline, this function should e
rchtara 2016/05/23 16:38:17 Done.
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));
Henrik Grunell 2016/05/02 12:12:23 As we talked about offline, storing in member vari
rchtara 2016/05/23 16:38:17 Done.
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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 base::RunLoop run_loop; 207 base::RunLoop run_loop;
200 media_stream_manager_->audio_output_device_enumerator()->Enumerate( 208 media_stream_manager_->audio_output_device_enumerator()->Enumerate(
201 base::Bind(&WaitForEnumeration, &run_loop)); 209 base::Bind(&WaitForEnumeration, &run_loop));
202 run_loop.Run(); 210 run_loop.Run();
203 211
204 host_ = new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_, 212 host_ = new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_,
205 MediaInternals::GetInstance(), 213 MediaInternals::GetInstance(),
206 media_stream_manager_.get(), 214 media_stream_manager_.get(),
207 GetMockSaltCallback()); 215 GetMockSaltCallback());
208 216
217 audio_output_impl_.reset(host_->Init(host_.get()));
218
209 // Simulate IPC channel connected. 219 // Simulate IPC channel connected.
210 host_->set_peer_process_for_testing(base::Process::Current()); 220 host_->set_peer_process_for_testing(base::Process::Current());
211 } 221 }
212 222
213 ~AudioRendererHostTest() override { 223 ~AudioRendererHostTest() override {
214 // Simulate closing the IPC channel and give the audio thread time to close 224 // Simulate closing the IPC channel and give the audio thread time to close
215 // the underlying streams. 225 // the underlying streams.
216 host_->OnChannelClosing(); 226 host_->OnChannelClosing();
217 SyncWithAudioThread(); 227 SyncWithAudioThread();
218 228
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 media::AudioParameters::kAudioCDSampleRate / 10); 264 media::AudioParameters::kAudioCDSampleRate / 10);
255 int session_id = 0; 265 int session_id = 0;
256 if (unified_stream) { 266 if (unified_stream) {
257 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to 267 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to
258 // pass the permission check. 268 // pass the permission check.
259 session_id = AudioInputDeviceManager::kFakeOpenSessionId; 269 session_id = AudioInputDeviceManager::kFakeOpenSessionId;
260 } 270 }
261 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, 271 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
262 device_id, security_origin); 272 device_id, security_origin);
263 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) { 273 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) {
264 host_->OnCreateStream(kStreamId, kRenderFrameId, params); 274 host_->CreateStream(kStreamId, kRenderFrameId, params,
275 base::Bind(&AudioRendererHostTest::CreateCallback,
276 base::Unretained(this)));
265 277
266 // At some point in the future, a corresponding RemoveDiverter() call must 278 // At some point in the future, a corresponding RemoveDiverter() call must
267 // be made. 279 // be made.
268 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())) 280 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
269 .RetiresOnSaturation(); 281 .RetiresOnSaturation();
270 } 282 }
271 SyncWithAudioThread(); 283 SyncWithAudioThread();
272 } 284 }
273 285
286 void CreateCallback(int stream_id,
287 media::interfaces::AudioOutputStreamPtr stream,
288 mojo::ScopedSharedBufferHandle shared_buffer,
289 mojo::ScopedHandle socket_descriptor) {
290 base::SharedMemoryHandle shared_memory_handle;
291 size_t length;
292 MojoResult pass_shared_memory_result = mojo::edk::PassSharedMemoryHandle(
293 shared_buffer.release().value(), &shared_memory_handle, &length,
294 nullptr);
295
296 if (pass_shared_memory_result != MOJO_RESULT_OK) {
297 LOG(ERROR) << "Failed to pass shared memory. Closing: "
298 << pass_shared_memory_result;
299 return;
300 }
301 mojo::edk::ScopedPlatformHandle platform_handle;
302
303 MojoResult pass_platform_handle_result =
304 mojo::edk::PassWrappedPlatformHandle(
305 socket_descriptor.release().value(), &platform_handle);
306
307 if (pass_platform_handle_result != MOJO_RESULT_OK) {
308 LOG(ERROR) << "Failed to pass transit descriptor. Closing: "
309 << pass_platform_handle_result;
310 return;
311 }
312
313 base::SyncSocket::TransitDescriptor descriptor;
314 #if defined(OS_WIN)
315 descriptor = platform_handle.release().handle;
316 #else
317 descriptor.fd = platform_handle.release().handle;
318 #endif
319
320 host_->OnNotifyStreamCreated(stream_id, shared_memory_handle, descriptor,
321 length);
322 streams_[stream_id] = make_scoped_ptr(
Henrik Grunell 2016/05/02 12:12:23 This isn't used anywhere. We talked about this off
rchtara 2016/05/23 16:38:17 it's not needed anymore.
323 new media::interfaces::AudioOutputStreamPtr(std::move(stream)));
324 }
325
274 void Close() { 326 void Close() {
275 // Send a message to AudioRendererHost to tell it we want to close the 327 // Send a message to AudioRendererHost to tell it we want to close the
276 // stream. 328 // stream.
277 host_->OnCloseStream(kStreamId); 329 host_->OnCloseStream(kStreamId);
278 SyncWithAudioThread(); 330 SyncWithAudioThread();
279 } 331 }
280 332
281 void Play() { 333 void Play() {
282 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId)); 334 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId));
283 host_->OnPlayStream(kStreamId); 335 host_->OnPlayStream(kStreamId);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 void SyncWithAudioThread() { 369 void SyncWithAudioThread() {
318 base::RunLoop().RunUntilIdle(); 370 base::RunLoop().RunUntilIdle();
319 371
320 base::RunLoop run_loop; 372 base::RunLoop run_loop;
321 audio_manager_->GetTaskRunner()->PostTask( 373 audio_manager_->GetTaskRunner()->PostTask(
322 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure())); 374 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
323 run_loop.Run(); 375 run_loop.Run();
324 } 376 }
325 377
326 private: 378 private:
379 typedef std::map<int,
380 std::unique_ptr<media::interfaces::AudioOutputStreamPtr>>
381 ScopedAudioOutputStreamPtrMap;
327 // MediaStreamManager uses a DestructionObserver, so it must outlive the 382 // MediaStreamManager uses a DestructionObserver, so it must outlive the
328 // TestBrowserThreadBundle. 383 // TestBrowserThreadBundle.
329 std::unique_ptr<MediaStreamManager> media_stream_manager_; 384 std::unique_ptr<MediaStreamManager> media_stream_manager_;
330 TestBrowserThreadBundle thread_bundle_; 385 TestBrowserThreadBundle thread_bundle_;
331 std::unique_ptr<media::AudioManager> audio_manager_; 386 std::unique_ptr<media::AudioManager> audio_manager_;
332 MockAudioMirroringManager mirroring_manager_; 387 MockAudioMirroringManager mirroring_manager_;
333 scoped_refptr<MockAudioRendererHost> host_; 388 scoped_refptr<MockAudioRendererHost> host_;
389 std::unique_ptr<AudioOutputImpl> audio_output_impl_;
390 ScopedAudioOutputStreamPtrMap streams_;
334 391
335 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); 392 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
336 }; 393 };
337 394
338 TEST_F(AudioRendererHostTest, CreateAndClose) { 395 TEST_F(AudioRendererHostTest, CreateAndClose) {
339 Create(); 396 Create();
340 Close(); 397 Close();
341 } 398 }
342 399
343 // Simulate the case where a stream is not properly closed. 400 // Simulate the case where a stream is not properly closed.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 } 463 }
407 464
408 TEST_F(AudioRendererHostTest, CreateInvalidDevice) { 465 TEST_F(AudioRendererHostTest, CreateInvalidDevice) {
409 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin))); 466 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)));
410 Close(); 467 Close();
411 } 468 }
412 469
413 // TODO(hclam): Add tests for data conversation in low latency mode. 470 // TODO(hclam): Add tests for data conversation in low latency mode.
414 471
415 } // namespace content 472 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698