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

Side by Side Diff: content/renderer/media/audio_output_ipc_factory.cc

Issue 2289543003: IPC->mojo of audio_renderer_host (Closed)
Patch Set: It builds \o/. Created 4 years, 3 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 #include "content/renderer/media/audio_output_ipc_factory.h"
6
7 #include <string>
8 #include <utility>
9
10 #include "base/files/file.h"
11 #include "base/memory/shared_memory_handle.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/sync_socket.h"
14 #include "content/renderer/media/webrtc_logging.h"
15 #include "media/base/audio_parameters.h"
16 #include "media/mojo/interfaces/audio_output.mojom.h"
17 #include "mojo/edk/embedder/embedder.h"
18 #include "mojo/public/c/system/buffer.h"
19 #include "mojo/public/cpp/bindings/binding.h"
20 #include "mojo/public/cpp/bindings/interface_request.h"
21 #include "mojo/public/cpp/system/handle.h"
22 #include "mojo/public/cpp/system/platform_handle.h"
23 #include "services/shell/public/cpp/interface_provider.h"
24
25 namespace content {
26
27 class AudioOutputIPCFactory::MojoAudioOutputIPC
28 : public media::AudioOutputIPC,
29 private media::mojom::AudioOutputStreamClient {
30 public:
31 MojoAudioOutputIPC(const scoped_refptr<AudioOutputIPCFactory> output_client,
32 const media::mojom::AudioOutputPtr* output_service,
33 int render_frame_id)
34 : output_client_(output_client),
35 output_service_(output_service),
36 delegate_(nullptr),
37 render_frame_id_(render_frame_id),
38 stream_created_(false),
39 weak_ptr_factory_(this) {}
40
41 ~MojoAudioOutputIPC() override { StopClient(false); }
42
43 private:
44 // media::AudioOutputIPC implementation
45 void RequestDeviceAuthorization(media::AudioOutputIPCDelegate* delegate,
o1ka 2016/09/02 07:31:46 Could you split declaration and definition of meth
Max Morin 2016/09/02 10:27:07 Yes. I'll go through this class later.
46 int session_id,
47 const std::string& device_id,
48 const url::Origin& origin) override {
49 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
50 DCHECK(delegate);
51 DCHECK(!delegate_); // Request exists/completed
52 DCHECK(!stream_created_); // Active stream exists
53
54 delegate_ = delegate;
55 stream_id_ = output_client_->delegates_.Add(delegate);
56 (*output_service_)
57 ->RequestDeviceAuthorization(
58 stream_id_, render_frame_id_, session_id, device_id, origin,
59 base::Bind(&MojoAudioOutputIPC::RequestDeviceAuthorizationCallback,
60 weak_ptr_factory_.GetWeakPtr()));
61 }
62
63 void CreateStream(media::AudioOutputIPCDelegate* delegate,
64 const media::AudioParameters& params) override {
65 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
66 DCHECK(!stream_created_);
67 DCHECK(delegate);
68 DCHECK(!delegate_ || delegate_ == delegate); // Ensure same delegate.
69
70 if (!delegate_)
71 stream_id_ = output_client_->delegates_.Add(delegate);
72 delegate_ = delegate;
o1ka 2016/09/02 07:31:46 Do we really want to continue if (delegate_ == del
73 media::mojom::AudioOutputStreamClientPtr client;
74 binding_.reset(new mojo::Binding<media::mojom::AudioOutputStreamClient>(
75 this, mojo::GetProxy(&client)));
76 binding_->set_connection_error_handler(base::Bind(
77 &MojoAudioOutputIPC::OnError, weak_ptr_factory_.GetWeakPtr()));
78
79 (*output_service_)
80 ->CreateStream(stream_id_, render_frame_id_, std::move(client), params,
81 base::Bind(&MojoAudioOutputIPC::CreateStreamCallback,
82 weak_ptr_factory_.GetWeakPtr()));
83 stream_created_ = true;
84 }
85
86 void PlayStream() override {
87 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
88 DCHECK(stream_created_);
89
90 output_stream_service_->Play();
91 }
92
93 void PauseStream() override {
94 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
95 DCHECK(stream_created_);
96
97 output_stream_service_->Pause();
98 }
99
100 void SetVolume(double volume) override {
101 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
102 DCHECK(stream_created_);
103
104 output_stream_service_->SetVolume(volume);
105 }
106
107 void CloseStream() override {
108 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
109
110 stream_created_ = false;
111 StopClient(false);
112 }
113
114 // media::mojom::AudioOutputStreamClient implementation
115 void OnStreamStateChange(
116 media::mojom::AudioOutputStreamState state) override {
117 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
118
119 if (state == media::mojom::AudioOutputStreamState::ERROR) {
120 StopClient(true);
121 } else if (delegate_) {
122 // delegate_->OnStateChanged(state);
123 }
124 }
125
126 // This error handler is used by |output_stream_service_| on a connection
127 // error.
128 void OnError() {
129 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
130
131 OnStreamStateChange(media::mojom::AudioOutputStreamState::ERROR);
132 }
133
134 void StopClient(bool error) {
135 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
136
137 if (delegate_) {
138 if (error)
139 delegate_->OnStateChanged(media::mojom::AudioOutputStreamState::ERROR);
140 // |output_client_| may have called NotifyConnectionClose()
141 if (output_client_->delegates_.Lookup(stream_id_) == delegate_)
142 output_client_->delegates_.Remove(stream_id_);
143 }
144
145 if (output_stream_service_.is_bound())
146 (*output_service_)->CloseStream(stream_id_);
147
148 delegate_ = nullptr;
149 output_stream_service_.reset();
150 binding_.reset();
151 }
152
153 // Callback implementations
154 void RequestDeviceAuthorizationCallback(
155 int device_status,
156 const media::AudioParameters& output_params,
157 mojo::String matched_device_id) {
158 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
159
160 if (!delegate_)
161 return;
162 delegate_->OnDeviceAuthorized(
163 static_cast<media::OutputDeviceStatus>(device_status), output_params,
164 matched_device_id.get());
165 }
166
167 void CreateStreamCallback(media::mojom::AudioOutputStreamPtr stream,
168 mojo::ScopedSharedBufferHandle shared_buffer,
169 mojo::ScopedHandle socket_descriptor) {
170 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
171
172 // If stream creation failed, inform the delegate.
173 if (!stream.is_bound())
174 return OnError();
175 output_stream_service_ = std::move(stream);
176 output_stream_service_.set_connection_error_handler(base::Bind(
177 &MojoAudioOutputIPC::OnError, weak_ptr_factory_.GetWeakPtr()));
178
179 base::SharedMemoryHandle handle;
180 size_t length;
181 bool read_only;
182 MojoResult unwrap_shared_memory_result = mojo::UnwrapSharedMemoryHandle(
183 std::move(shared_buffer), &handle, &length, &read_only);
184
185 if (unwrap_shared_memory_result != MOJO_RESULT_OK) {
186 DLOG(ERROR) << "Failed to pass shared memory. Closing: "
187 << unwrap_shared_memory_result;
188 return OnError();
189 }
190
191 base::SyncSocket::TransitDescriptor descriptor;
192 MojoResult unwrap_platform_file_result =
193 mojo::UnwrapPlatformFile(std::move(socket_descriptor),
194 #if defined(OS_WIN)
195 &descriptor);
196 #else
197 &descriptor.fd);
198 #endif
199 if (unwrap_platform_file_result != MOJO_RESULT_OK) {
200 DLOG(ERROR) << "Failed to pass transit descriptor. Closing: "
201 << unwrap_platform_file_result;
202 return OnError();
203 }
204
205 base::SyncSocket::Handle socket_handle =
206 base::SyncSocket::UnwrapHandle(descriptor);
207 if (!delegate_) {
208 base::SharedMemory::CloseHandle(handle);
209 base::SyncSocket socket(socket_handle);
210 return;
211 }
212 delegate_->OnStreamCreated(handle, socket_handle, length);
213 }
214
215 const scoped_refptr<AudioOutputIPCFactory> output_client_;
216 const media::mojom::AudioOutputPtr* output_service_;
217 media::mojom::AudioOutputStreamPtr output_stream_service_;
218 media::AudioOutputIPCDelegate* delegate_;
219
220 const int render_frame_id_;
221 int stream_id_;
222 bool stream_created_;
223
224 std::unique_ptr<mojo::Binding<media::mojom::AudioOutputStreamClient>>
225 binding_;
226
227 base::WeakPtrFactory<MojoAudioOutputIPC> weak_ptr_factory_;
228
229 DISALLOW_COPY_AND_ASSIGN(MojoAudioOutputIPC);
230 };
231
232 AudioOutputIPCFactory::AudioOutputIPCFactory(
233 const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
234 shell::InterfaceProvider* interface_provider)
235 : io_task_runner_(io_task_runner) {
236 DCHECK(!g_audio_output_ipc_factory);
237 g_audio_output_ipc_factory = this;
238
239 interface_provider->GetInterface(&output_service_);
240 output_service_.Bind(output_service_.PassInterface(), io_task_runner_);
241 }
242
243 AudioOutputIPCFactory::~AudioOutputIPCFactory() {
244 DCHECK(g_audio_output_ipc_factory == this);
245 g_audio_output_ipc_factory = nullptr;
246
247 io_task_runner_->PostTask(
248 FROM_HERE, base::Bind(&AudioOutputIPCFactory::NotifyConnectionClose,
249 base::RetainedRef(this)));
250 }
251
252 AudioOutputIPCFactory* AudioOutputIPCFactory::g_audio_output_ipc_factory =
253 nullptr;
254
255 // static
256 const scoped_refptr<AudioOutputIPCFactory> AudioOutputIPCFactory::Get() {
257 return g_audio_output_ipc_factory;
258 }
259
260 std::unique_ptr<media::AudioOutputIPC>
261 AudioOutputIPCFactory::CreateAudioOutputIPC(int render_frame_id) {
262 return std::unique_ptr<media::AudioOutputIPC>(
263 new MojoAudioOutputIPC(this, &output_service_, render_frame_id));
264 }
265
266 void AudioOutputIPCFactory::OnConnectionError() {
267 DCHECK(io_task_runner_->BelongsToCurrentThread());
268
269 NotifyConnectionClose();
270 }
271
272 void AudioOutputIPCFactory::NotifyConnectionClose() {
273 DCHECK(io_task_runner_->BelongsToCurrentThread());
274
275 output_service_.reset();
276 IDMap<media::AudioOutputIPCDelegate>::iterator it(&delegates_);
277 while (!it.IsAtEnd()) {
278 it.GetCurrentValue()->OnIPCClosed();
279 delegates_.Remove(it.GetCurrentKey());
280 it.Advance();
281 }
282 }
283
284 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698