Disable ContentSettingBubbleModelTest.RPHAllow which is flaky.
[chromium-blink-merge.git] / content / renderer / pepper / pepper_platform_audio_input_impl.cc
blob76afa17c2780db3dfd794de1b2be4445b03f1de6
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
3 // found in the LICENSE file.
5 #include "content/renderer/pepper/pepper_platform_audio_input_impl.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop_proxy.h"
10 #include "build/build_config.h"
11 #include "content/common/child_process.h"
12 #include "content/renderer/media/audio_input_message_filter.h"
13 #include "content/renderer/pepper/pepper_plugin_delegate_impl.h"
14 #include "content/renderer/render_thread_impl.h"
15 #include "media/audio/audio_manager_base.h"
17 namespace content {
19 // static
20 PepperPlatformAudioInputImpl* PepperPlatformAudioInputImpl::Create(
21 const base::WeakPtr<PepperPluginDelegateImpl>& plugin_delegate,
22 const std::string& device_id,
23 int sample_rate,
24 int frames_per_buffer,
25 webkit::ppapi::PluginDelegate::PlatformAudioInputClient* client) {
26 scoped_refptr<PepperPlatformAudioInputImpl> audio_input(
27 new PepperPlatformAudioInputImpl());
28 if (audio_input->Initialize(plugin_delegate, device_id, sample_rate,
29 frames_per_buffer, client)) {
30 // Balanced by Release invoked in
31 // PepperPlatformAudioInputImpl::ShutDownOnIOThread().
32 audio_input->AddRef();
33 return audio_input.get();
35 return NULL;
38 void PepperPlatformAudioInputImpl::StartCapture() {
39 DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
41 ChildProcess::current()->io_message_loop()->PostTask(
42 FROM_HERE,
43 base::Bind(&PepperPlatformAudioInputImpl::StartCaptureOnIOThread, this));
46 void PepperPlatformAudioInputImpl::StopCapture() {
47 DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
49 ChildProcess::current()->io_message_loop()->PostTask(
50 FROM_HERE,
51 base::Bind(&PepperPlatformAudioInputImpl::StopCaptureOnIOThread, this));
54 void PepperPlatformAudioInputImpl::ShutDown() {
55 DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
57 // Make sure we don't call shutdown more than once.
58 if (!client_)
59 return;
61 // Called on the main thread to stop all audio callbacks. We must only change
62 // the client on the main thread, and the delegates from the I/O thread.
63 client_ = NULL;
64 ChildProcess::current()->io_message_loop()->PostTask(
65 FROM_HERE,
66 base::Bind(&PepperPlatformAudioInputImpl::ShutDownOnIOThread, this));
69 void PepperPlatformAudioInputImpl::OnStreamCreated(
70 base::SharedMemoryHandle handle,
71 base::SyncSocket::Handle socket_handle,
72 int length,
73 int total_segments) {
74 #if defined(OS_WIN)
75 DCHECK(handle);
76 DCHECK(socket_handle);
77 #else
78 DCHECK_NE(-1, handle.fd);
79 DCHECK_NE(-1, socket_handle);
80 #endif
81 DCHECK(length);
82 // TODO(yzshen): Make use of circular buffer scheme. crbug.com/181449.
83 DCHECK_EQ(1, total_segments);
85 if (base::MessageLoopProxy::current() != main_message_loop_proxy_) {
86 // If shutdown has occurred, |client_| will be NULL and the handles will be
87 // cleaned up on the main thread.
88 main_message_loop_proxy_->PostTask(
89 FROM_HERE,
90 base::Bind(&PepperPlatformAudioInputImpl::OnStreamCreated, this,
91 handle, socket_handle, length, total_segments));
92 } else {
93 // Must dereference the client only on the main thread. Shutdown may have
94 // occurred while the request was in-flight, so we need to NULL check.
95 if (client_) {
96 client_->StreamCreated(handle, length, socket_handle);
97 } else {
98 // Clean up the handles.
99 base::SyncSocket temp_socket(socket_handle);
100 base::SharedMemory temp_shared_memory(handle, false);
105 void PepperPlatformAudioInputImpl::OnVolume(double volume) {}
107 void PepperPlatformAudioInputImpl::OnStateChanged(
108 media::AudioInputIPCDelegate::State state) {
111 void PepperPlatformAudioInputImpl::OnIPCClosed() {
112 ipc_.reset();
115 PepperPlatformAudioInputImpl::~PepperPlatformAudioInputImpl() {
116 // Make sure we have been shut down. Warning: this may happen on the I/O
117 // thread!
118 // Although these members should be accessed on a specific thread (either the
119 // main thread or the I/O thread), it should be fine to examine their value
120 // here.
121 DCHECK(!ipc_);
122 DCHECK(!client_);
123 DCHECK(label_.empty());
126 PepperPlatformAudioInputImpl::PepperPlatformAudioInputImpl()
127 : client_(NULL),
128 main_message_loop_proxy_(base::MessageLoopProxy::current()) {
131 bool PepperPlatformAudioInputImpl::Initialize(
132 const base::WeakPtr<PepperPluginDelegateImpl>& plugin_delegate,
133 const std::string& device_id,
134 int sample_rate,
135 int frames_per_buffer,
136 webkit::ppapi::PluginDelegate::PlatformAudioInputClient* client) {
137 DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
139 if (!plugin_delegate || !client)
140 return false;
142 ipc_ = RenderThreadImpl::current()->audio_input_message_filter()->
143 CreateAudioInputIPC(plugin_delegate->GetRoutingID());
145 plugin_delegate_ = plugin_delegate;
146 client_ = client;
148 params_.Reset(media::AudioParameters::AUDIO_PCM_LINEAR,
149 media::CHANNEL_LAYOUT_MONO, 1, 0,
150 sample_rate, 16, frames_per_buffer);
152 // We need to open the device and obtain the label and session ID before
153 // initializing.
154 plugin_delegate_->OpenDevice(
155 PP_DEVICETYPE_DEV_AUDIOCAPTURE,
156 device_id.empty() ? media::AudioManagerBase::kDefaultDeviceId : device_id,
157 base::Bind(&PepperPlatformAudioInputImpl::OnDeviceOpened, this));
159 return true;
162 void PepperPlatformAudioInputImpl::InitializeOnIOThread(int session_id) {
163 DCHECK(ChildProcess::current()->io_message_loop_proxy()->
164 BelongsToCurrentThread());
166 if (!ipc_)
167 return;
169 // We will be notified by OnStreamCreated().
170 ipc_->CreateStream(this, session_id, params_, false, 1);
173 void PepperPlatformAudioInputImpl::StartCaptureOnIOThread() {
174 DCHECK(ChildProcess::current()->io_message_loop_proxy()->
175 BelongsToCurrentThread());
177 if (ipc_)
178 ipc_->RecordStream();
181 void PepperPlatformAudioInputImpl::StopCaptureOnIOThread() {
182 DCHECK(ChildProcess::current()->io_message_loop_proxy()->
183 BelongsToCurrentThread());
185 // TODO(yzshen): We cannot re-start capturing if the stream is closed.
186 if (ipc_) {
187 ipc_->CloseStream();
188 ipc_.reset();
192 void PepperPlatformAudioInputImpl::ShutDownOnIOThread() {
193 DCHECK(ChildProcess::current()->io_message_loop_proxy()->
194 BelongsToCurrentThread());
196 StopCaptureOnIOThread();
198 main_message_loop_proxy_->PostTask(
199 FROM_HERE,
200 base::Bind(&PepperPlatformAudioInputImpl::CloseDevice, this));
202 Release(); // Release for the delegate, balances out the reference taken in
203 // PepperPluginDelegateImpl::CreateAudioInput.
206 void PepperPlatformAudioInputImpl::OnDeviceOpened(int request_id,
207 bool succeeded,
208 const std::string& label) {
209 DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
211 if (succeeded && plugin_delegate_) {
212 DCHECK(!label.empty());
213 label_ = label;
215 if (client_) {
216 int session_id = plugin_delegate_->GetSessionID(
217 PP_DEVICETYPE_DEV_AUDIOCAPTURE, label);
218 ChildProcess::current()->io_message_loop()->PostTask(
219 FROM_HERE,
220 base::Bind(&PepperPlatformAudioInputImpl::InitializeOnIOThread,
221 this, session_id));
222 } else {
223 // Shutdown has occurred.
224 CloseDevice();
226 } else {
227 NotifyStreamCreationFailed();
231 void PepperPlatformAudioInputImpl::CloseDevice() {
232 DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
234 if (plugin_delegate_ && !label_.empty()) {
235 plugin_delegate_->CloseDevice(label_);
236 label_.clear();
240 void PepperPlatformAudioInputImpl::NotifyStreamCreationFailed() {
241 DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
243 if (client_)
244 client_->StreamCreationFailed();
247 } // namespace content