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

Side by Side Diff: content/browser/media/audio_output_impl.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
(Empty)
1 // Copyright 2016 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 #if defined(OS_WIN)
6 #include <windows.h>
7 #endif
8
9 #include "base/memory/shared_memory.h"
10 #include "content/browser/media/audio_output_impl.h"
11 #include "content/browser/media/audio_output_stream_impl.h"
12 #include "content/public/browser/render_frame_host.h"
13 #include "mojo/edk/embedder/embedder.h"
14 #include "mojo/public/cpp/system/handle.h"
15
16 namespace content {
17
18 namespace {
19 base::SyncSocket::TransitDescriptor DuplicateSocket(
20 base::SyncSocket::TransitDescriptor socket_descriptor) {
21 base::SyncSocket::TransitDescriptor socket_descriptor_dup;
22
23 #if defined(OS_WIN)
24 socket_descriptor_dup = 0;
25 if (!::DuplicateHandle(GetCurrentProcess(), // hSourceProcessHandle
26 socket_descriptor,
27 GetCurrentProcess(), // hTargetProcessHandle
28 &socket_descriptor_dup,
29 0, // dwDesiredAccess ignored due to SAME_ACCESS
30 FALSE, // !bInheritHandle
31 DUPLICATE_SAME_ACCESS)) {
32 LOG(ERROR) << "Unable to duplicate socket handle.";
33 }
34
35 #else
36 socket_descriptor_dup.fd = dup(socket_descriptor.fd);
37 #endif
38 return socket_descriptor_dup;
39 }
40 }
41
42 AudioOutputImpl::AudioOutputImpl(RenderProcessHost* process,
43 int render_frame_id,
44 media::mojom::AudioOutputRequest request)
45 : process_(process), render_frame_id_(render_frame_id), binding_(this) {
46 DCHECK_CURRENTLY_ON(BrowserThread::IO);
47 binding_.Bind(std::move(request));
48 binding_.set_connection_error_handler(base::Bind(
49 &AudioOutputImpl::Disconnect, process->GetID(), render_frame_id));
50
51 LOG(ERROR) << "AudioOutputImpl";
52 }
53
54 AudioOutputImpl::~AudioOutputImpl() {
55 Disconnect(render_frame_id_, render_frame_id_);
56 for (auto it = create_stream_callbacks_.begin();
57 it != create_stream_callbacks_.end(); ++it)
58 it->second.reset();
59 create_stream_callbacks_.clear();
60 LOG(ERROR) << "~AudioOutputImpl";
61 }
62
63 // static
64 void AudioOutputImpl::CreateService(RenderProcessHost* process,
65 int render_frame_id,
66 media::mojom::AudioOutputRequest request) {
67 DCHECK_CURRENTLY_ON(BrowserThread::UI);
68
69 BrowserThread::PostTask(
70 BrowserThread::IO, FROM_HERE,
71 base::Bind(&AudioOutputImpl::CreateServiceOnIOThread, process,
72 render_frame_id, base::Passed(&request)));
73 }
74
75 // static
76 void AudioOutputImpl::CreateServiceOnIOThread(
77 RenderProcessHost* process,
78 int render_frame_id,
79 media::mojom::AudioOutputRequest request) {
80 if (request.is_pending()) {
81 DCHECK_CURRENTLY_ON(BrowserThread::IO);
82 }
83
84 new AudioOutputImpl(process, render_frame_id, std::move(request));
85 }
86
87 void AudioOutputImpl::CreateStream(int stream_id,
88 const media::AudioParameters& params,
89 const CreateStreamCallback& callback) {
90 DCHECK_CURRENTLY_ON(BrowserThread::IO);
91
92 create_stream_callbacks_.insert(std::make_pair(stream_id, callback));
93 process_->audio_renderer_host()->CreateStream(stream_id, render_frame_id_,
94 params, this);
95 }
96
97 void AudioOutputImpl::StreamFactory(
98 int stream_id,
99 base::SharedMemory* shared_memory,
100 base::SyncSocket::TransitDescriptor socket_descriptor) {
101 DCHECK_CURRENTLY_ON(BrowserThread::IO);
102
103 auto callback = create_stream_callbacks_.find(stream_id);
104 if (callback == create_stream_callbacks_.end()) {
105 return;
106 }
107
108 media::mojom::AudioOutputStreamPtr stream_ptr =
109 media::mojom::AudioOutputStreamPtr();
110 std::unique_ptr<AudioOutputStreamImpl> stream(new AudioOutputStreamImpl(
111 stream_id, render_frame_id_, this, mojo::GetProxy(&stream_ptr)));
112
113 DCHECK(stream_impls_.insert(std::make_pair(stream_id, std::move(stream)))
114 .second);
115
116 base::SharedMemoryHandle shared_memory_handle =
117 base::SharedMemory::DuplicateHandle(shared_memory->handle());
118
119 MojoHandle mojo_foreign_memory_handle;
120
121 MojoResult shared_buffer_result = mojo::edk::CreateSharedBufferWrapper(
122 shared_memory_handle, shared_memory->requested_size(), false,
123 &mojo_foreign_memory_handle);
124
125 if (shared_buffer_result != MOJO_RESULT_OK) {
126 DLOG(WARNING) << "Failed to wrap transit descriptor. Closing: "
127 << shared_buffer_result;
128 ReportErrorAndCloseStream(stream_id);
129 return;
130 }
131
132 mojo::ScopedSharedBufferHandle shared_buffer_handle =
133 mojo::ScopedSharedBufferHandle(
134 mojo::SharedBufferHandle(mojo_foreign_memory_handle));
135
136 MojoHandle socket_descriptor_handle;
137 MojoResult platform_handle_result;
138
139 // The socket handle is going to be closed when |mojo_application_host_| is
140 // reset. The renderer is going to need to close the socket handle
141 // too when the output steam is closed. This is going to cause an issue
142 // because both of them are going to close the same socket handle.
143 // This is why a duplicate of the socket handler is going to be created,
144 // stored in |socket_descriptor_dup| and sent through Mojo to the renderer so
145 // it can be used by AudioOutputIPCDelegate.
146
147 base::SyncSocket::TransitDescriptor socket_descriptor_dup =
148 DuplicateSocket(socket_descriptor);
149 #if defined(OS_WIN)
150 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper(
151 mojo::edk::ScopedPlatformHandle(
152 mojo::edk::PlatformHandle(socket_descriptor_dup),
153 &socket_descriptor_handle);
154 #else
155 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper(
156 mojo::edk::ScopedPlatformHandle(
157 mojo::edk::PlatformHandle(socket_descriptor_dup.fd)),
158 &socket_descriptor_handle);
159 #endif
160
161 if (platform_handle_result != MOJO_RESULT_OK) {
162 DLOG(WARNING) << "Failed to wrap platform handle. Closing: "
163 << platform_handle_result;
164 ReportErrorAndCloseStream(stream_id);
165 return;
166 }
167
168 mojo::ScopedHandle socket_handle =
169 mojo::ScopedHandle(mojo::Handle(socket_descriptor_handle));
170 callback->second.Run(
171 stream_id, std::move(stream_ptr),
172 std::move(shared_buffer_handle), std::move(socket_handle));
173
174 callback->second.reset();
175 create_stream_callbacks_.erase(stream_id);
176 }
177
178 bool AudioOutputImpl::CloseStream(int stream_id) {
179 process_->audio_renderer_host()->CloseStream(stream_id);
180
181 auto stream = stream_impls_.find(stream_id);
182 if (stream == stream_impls_.end()) {
183 return false;
184 }
185 stream_impls_.erase(stream_id);
186
187 auto callback = create_stream_callbacks_.find(stream_id);
188
189 if (callback != create_stream_callbacks_.end()) {
190 callback->second.reset();
191 create_stream_callbacks_.erase(stream_id);
192 }
193 return true;
194 }
195
196 // static
197 void AudioOutputImpl::Disconnect(int process_id, int render_frame_id) {
198 LOG(ERROR) << "Disconnect";
199 }
200
201 void AudioOutputImpl::ReportErrorAndCloseStream(int stream_id) {
202 DCHECK_CURRENTLY_ON(BrowserThread::IO);
203
204 // Make sure this isn't a stray callback executing after the stream has been
205 // closed, so error notifications aren't sent after clients believe the stream
206 // is closed.
207 auto callback = create_stream_callbacks_.find(stream_id);
208
209 mojo::ScopedSharedBufferHandle shared_buffer_handle =
210 mojo::ScopedSharedBufferHandle(mojo::SharedBufferHandle());
211
212 mojo::ScopedHandle socket_handle = mojo::ScopedHandle(mojo::Handle());
213
214 callback->second.Run(stream_id, media::mojom::AudioOutputStreamPtr(),
215 std::move(shared_buffer_handle),
216 std::move(socket_handle));
217
218 process_->audio_renderer_host()->get_audio_log()->OnError(stream_id);
219 CloseStream(stream_id);
220 }
221
222 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698