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

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

Issue 2821203005: Add a mojo implementation of AudioOutputIPC. (Closed)
Patch Set: Use ScopedClosureRunner. Created 3 years, 6 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 2017 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/mojo_audio_output_ipc.h"
6
7 #include <utility>
8
9 #include "media/audio/audio_device_description.h"
10 #include "mojo/public/cpp/system/platform_handle.h"
11
12 namespace content {
13
14 namespace {
15
16 void TrivialAuthorizedCallback(media::OutputDeviceStatus,
17 const media::AudioParameters&,
18 const std::string&) {}
19
20 } // namespace
21
22 MojoAudioOutputIPC::MojoAudioOutputIPC(FactoryAccessorCB factory_accessor)
23 : factory_accessor_(std::move(factory_accessor)), weak_factory_(this) {
24 DETACH_FROM_THREAD(thread_checker_);
25 }
26
27 MojoAudioOutputIPC::~MojoAudioOutputIPC() {
28 DCHECK(!AuthorizationRequested() && !StreamCreationRequested())
29 << "CloseStream must be called before destructing the AudioOutputIPC";
30 // No thread check.
31 // Destructing |weak_factory_| on any thread is safe since it's not used after
32 // the final call to CloseStream, where its pointers are invalidated.
33 }
34
35 void MojoAudioOutputIPC::RequestDeviceAuthorization(
36 media::AudioOutputIPCDelegate* delegate,
37 int session_id,
38 const std::string& device_id,
39 const url::Origin& security_origin) {
40 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
41 DCHECK(delegate);
42 DCHECK(!delegate_);
43 DCHECK(!AuthorizationRequested());
44 DCHECK(!StreamCreationRequested());
45 delegate_ = delegate;
46
47 // We pass in a ScopedClosureRunner to detect the case when the mojo
48 // connection is terminated prior to receiving the response. In this case,
49 // the closure runner will be destructed and call ReceivedDeviceAuthorization
50 // with an error.
51 DoRequestDeviceAuthorization(
52 session_id, device_id,
53 base::BindOnce(
54 &MojoAudioOutputIPC::ReceivedDeviceAuthorization,
55 weak_factory_.GetWeakPtr(),
56 base::ScopedClosureRunner(base::Bind(
57 &MojoAudioOutputIPC::ReceivedDeviceAuthorization,
58 weak_factory_.GetWeakPtr(),
59 base::Passed(base::ScopedClosureRunner()),
60 media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL,
61 media::AudioParameters::UnavailableDeviceParams(),
62 std::string()))));
63 }
64
65 void MojoAudioOutputIPC::CreateStream(media::AudioOutputIPCDelegate* delegate,
66 const media::AudioParameters& params) {
67 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
68 DCHECK(delegate);
69 DCHECK(!StreamCreationRequested());
70 if (!AuthorizationRequested()) {
71 DCHECK(!delegate_);
72 delegate_ = delegate;
73 // No authorization requested yet. Request one for the default device.
74 // Since the delegate didn't explicitly request authorization, we shouldn't
75 // send a callback to it.
76 if (!DoRequestDeviceAuthorization(
77 0, media::AudioDeviceDescription::kDefaultDeviceId,
78 base::Bind(&TrivialAuthorizedCallback))) {
79 return;
80 }
81 }
82
83 DCHECK_EQ(delegate_, delegate);
84 // Since the creation callback won't fire if the provider binding is gone
85 // and |this| owns |stream_provider_|, unretained is safe.
86 stream_provider_->Acquire(
87 mojo::MakeRequest(&stream_), params,
88 base::Bind(&MojoAudioOutputIPC::StreamCreated, base::Unretained(this)));
89
90 // Unretained is safe because |delegate_| must remain valid until
91 // CloseStream is called, and |stream_provider_| is reset in CloseStream.
92 stream_.set_connection_error_handler(base::Bind(
93 &media::AudioOutputIPCDelegate::OnError, base::Unretained(delegate_)));
94 }
95
96 void MojoAudioOutputIPC::PlayStream() {
97 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
98 if (stream_.is_bound())
99 stream_->Play();
100 }
101
102 void MojoAudioOutputIPC::PauseStream() {
103 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
104 if (stream_.is_bound())
105 stream_->Pause();
106 }
107
108 void MojoAudioOutputIPC::CloseStream() {
109 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
110 stream_provider_.reset();
111 stream_.reset();
112 delegate_ = nullptr;
113
114 // Cancel any pending callbacks for this stream.
115 weak_factory_.InvalidateWeakPtrs();
116 }
117
118 void MojoAudioOutputIPC::SetVolume(double volume) {
119 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
120 if (stream_.is_bound())
121 stream_->SetVolume(volume);
122 }
123
124 bool MojoAudioOutputIPC::AuthorizationRequested() {
125 return stream_provider_.is_bound();
126 }
127
128 bool MojoAudioOutputIPC::StreamCreationRequested() {
129 return stream_.is_bound();
130 }
131
132 media::mojom::AudioOutputStreamProviderRequest
133 MojoAudioOutputIPC::MakeProviderRequest() {
134 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
135 DCHECK(!AuthorizationRequested());
136 media::mojom::AudioOutputStreamProviderRequest request =
137 mojo::MakeRequest(&stream_provider_);
138
139 // Unretained is safe because |delegate_| must remain valid until
140 // CloseStream is called, and |stream_provider_| is reset in CloseStream.
141 stream_provider_.set_connection_error_handler(base::Bind(
142 &media::AudioOutputIPCDelegate::OnError, base::Unretained(delegate_)));
143 return request;
144 }
145
146 bool MojoAudioOutputIPC::DoRequestDeviceAuthorization(
147 int session_id,
148 const std::string& device_id,
149 AuthorizationCB callback) {
150 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
151 auto* factory = factory_accessor_.Run();
152 if (!factory) {
153 LOG(ERROR) << "MojoAudioOutputIPC failed to acquire factory";
154
155 media::AudioOutputIPCDelegate* delegate = delegate_;
156 CloseStream();
157 delegate->OnIPCClosed(); // deletes |this|.
158 return false;
159 }
160
161 factory->RequestDeviceAuthorization(MakeProviderRequest(), session_id,
162 device_id, std::move(callback));
163 return true;
164 }
165
166 void MojoAudioOutputIPC::ReceivedDeviceAuthorization(
167 base::ScopedClosureRunner fallback_closure,
168 media::OutputDeviceStatus status,
169 const media::AudioParameters& params,
170 const std::string& device_id) const {
171 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
172 DCHECK(delegate_);
173 ignore_result(fallback_closure.Release());
174 delegate_->OnDeviceAuthorized(status, params, device_id);
175 }
176
177 void MojoAudioOutputIPC::StreamCreated(
178 mojo::ScopedSharedBufferHandle shared_memory,
179 mojo::ScopedHandle socket) {
180 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
181 DCHECK(delegate_);
182 DCHECK(socket.is_valid());
183 DCHECK(shared_memory.is_valid());
184
185 base::PlatformFile socket_handle;
186 auto result = mojo::UnwrapPlatformFile(std::move(socket), &socket_handle);
187 DCHECK_EQ(result, MOJO_RESULT_OK);
188
189 base::SharedMemoryHandle memory_handle;
190 bool read_only = false;
191 size_t memory_length = 0;
192 result = mojo::UnwrapSharedMemoryHandle(
193 std::move(shared_memory), &memory_handle, &memory_length, &read_only);
194 DCHECK_EQ(result, MOJO_RESULT_OK);
195 DCHECK(!read_only);
196
197 delegate_->OnStreamCreated(memory_handle, socket_handle, memory_length);
198 }
199
200 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/mojo_audio_output_ipc.h ('k') | content/renderer/media/mojo_audio_output_ipc_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698