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

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

Issue 2289543003: IPC->mojo of audio_renderer_host (Closed)
Patch Set: New interface. 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,
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;
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 // This error handler is used by |output_stream_service_| on a connection
115 // error.
116 void OnError() {
117 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
118 StopClient(true);
119 }
120
121 void StopClient(bool error) {
122 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
123
124 if (delegate_) {
125 if (error)
126 //
127 delegate_->OnStateChanged(media::mojom::AudioOutputStreamState::ERROR);
128 // |output_client_| may have called NotifyConnectionClose()
129 if (output_client_->delegates_.Lookup(stream_id_) == delegate_)
130 output_client_->delegates_.Remove(stream_id_);
131 }
132
133 if (output_stream_service_.is_bound())
134 (*output_service_)->CloseStream(stream_id_);
135
136 delegate_ = nullptr;
137 output_stream_service_.reset();
138 binding_.reset();
139 }
140
141 // Callback implementations
142 void RequestDeviceAuthorizationCallback(
143 int device_status,
144 const media::AudioParameters& output_params,
145 mojo::String matched_device_id) {
146 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
147
148 if (!delegate_)
149 return;
150 delegate_->OnDeviceAuthorized(
151 static_cast<media::OutputDeviceStatus>(device_status), output_params,
152 matched_device_id.get());
153 }
154
155 void CreateStreamCallback(media::mojom::AudioOutputStreamPtr stream,
156 mojo::ScopedSharedBufferHandle shared_buffer,
157 mojo::ScopedHandle socket_descriptor) {
158 DCHECK(output_client_->io_task_runner_->BelongsToCurrentThread());
159
160 // If stream creation failed, inform the delegate.
161 if (!stream.is_bound())
162 return OnError();
163 output_stream_service_ = std::move(stream);
164 output_stream_service_.set_connection_error_handler(base::Bind(
165 &MojoAudioOutputIPC::OnError, weak_ptr_factory_.GetWeakPtr()));
166
167 base::SharedMemoryHandle handle;
168 size_t length;
169 bool read_only;
170 MojoResult unwrap_shared_memory_result = mojo::UnwrapSharedMemoryHandle(
171 std::move(shared_buffer), &handle, &length, &read_only);
172
173 if (unwrap_shared_memory_result != MOJO_RESULT_OK) {
174 DLOG(ERROR) << "Failed to pass shared memory. Closing: "
175 << unwrap_shared_memory_result;
176 return OnError();
177 }
178
179 base::SyncSocket::TransitDescriptor descriptor;
180 MojoResult unwrap_platform_file_result =
181 mojo::UnwrapPlatformFile(std::move(socket_descriptor),
182 #if defined(OS_WIN)
183 &descriptor);
184 #else
185 &descriptor.fd);
186 #endif
187 if (unwrap_platform_file_result != MOJO_RESULT_OK) {
188 DLOG(ERROR) << "Failed to pass transit descriptor. Closing: "
189 << unwrap_platform_file_result;
190 return OnError();
191 }
192
193 base::SyncSocket::Handle socket_handle =
194 base::SyncSocket::UnwrapHandle(descriptor);
195 if (!delegate_) {
196 base::SharedMemory::CloseHandle(handle);
197 base::SyncSocket socket(socket_handle);
198 return;
199 }
200 delegate_->OnStreamCreated(handle, socket_handle, length);
201 }
202
203 const scoped_refptr<AudioOutputIPCFactory> output_client_;
204 const media::mojom::AudioOutputPtr* output_service_;
205 media::mojom::AudioOutputStreamPtr output_stream_service_;
206 media::AudioOutputIPCDelegate* delegate_;
207
208 const int render_frame_id_;
209 int stream_id_;
210 bool stream_created_;
211
212 std::unique_ptr<mojo::Binding<media::mojom::AudioOutputStreamClient>>
213 binding_;
214
215 base::WeakPtrFactory<MojoAudioOutputIPC> weak_ptr_factory_;
216
217 DISALLOW_COPY_AND_ASSIGN(MojoAudioOutputIPC);
218 };
219
220 AudioOutputIPCFactory::AudioOutputIPCFactory(
221 const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
222 shell::InterfaceProvider* interface_provider)
223 : io_task_runner_(io_task_runner) {
224 DCHECK(!g_audio_output_ipc_factory);
225 g_audio_output_ipc_factory = this;
226
227 interface_provider->GetInterface(&output_service_);
228 output_service_.Bind(output_service_.PassInterface(), io_task_runner_);
229 }
230
231 AudioOutputIPCFactory::~AudioOutputIPCFactory() {
232 DCHECK(g_audio_output_ipc_factory == this);
233 g_audio_output_ipc_factory = nullptr;
234
235 io_task_runner_->PostTask(
236 FROM_HERE, base::Bind(&AudioOutputIPCFactory::NotifyConnectionClose,
237 base::RetainedRef(this)));
238 }
239
240 AudioOutputIPCFactory* AudioOutputIPCFactory::g_audio_output_ipc_factory =
241 nullptr;
242
243 // static
244 const scoped_refptr<AudioOutputIPCFactory> AudioOutputIPCFactory::Get() {
245 return g_audio_output_ipc_factory;
246 }
247
248 std::unique_ptr<media::AudioOutputIPC>
249 AudioOutputIPCFactory::CreateAudioOutputIPC(int render_frame_id) {
250 return std::unique_ptr<media::AudioOutputIPC>(
251 new MojoAudioOutputIPC(this, &output_service_, render_frame_id));
252 }
253
254 void AudioOutputIPCFactory::OnConnectionError() {
255 DCHECK(io_task_runner_->BelongsToCurrentThread());
256
257 NotifyConnectionClose();
258 }
259
260 void AudioOutputIPCFactory::NotifyConnectionClose() {
261 DCHECK(io_task_runner_->BelongsToCurrentThread());
262
263 output_service_.reset();
264 IDMap<media::AudioOutputIPCDelegate>::iterator it(&delegates_);
265 while (!it.IsAtEnd()) {
266 it.GetCurrentValue()->OnIPCClosed();
267 delegates_.Remove(it.GetCurrentKey());
268 it.Advance();
269 }
270 }
271 */
272 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698