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_output.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "build/build_config.h"
13 #include "content/child/child_process.h"
14 #include "content/common/media/audio_messages.h"
15 #include "content/renderer/media/audio_message_filter.h"
16 #include "content/renderer/pepper/audio_helper.h"
17 #include "content/renderer/render_thread_impl.h"
18 #include "media/base/audio_hardware_config.h"
19 #include "ppapi/shared_impl/ppb_audio_config_shared.h"
24 PepperPlatformAudioOutput
* PepperPlatformAudioOutput::Create(
26 int frames_per_buffer
,
27 int source_render_frame_id
,
28 AudioHelper
* client
) {
29 scoped_refptr
<PepperPlatformAudioOutput
> audio_output(
30 new PepperPlatformAudioOutput());
31 if (audio_output
->Initialize(sample_rate
,
33 source_render_frame_id
,
35 // Balanced by Release invoked in
36 // PepperPlatformAudioOutput::ShutDownOnIOThread().
37 audio_output
->AddRef();
38 return audio_output
.get();
43 bool PepperPlatformAudioOutput::StartPlayback() {
45 io_task_runner_
->PostTask(
47 base::Bind(&PepperPlatformAudioOutput::StartPlaybackOnIOThread
, this));
53 bool PepperPlatformAudioOutput::StopPlayback() {
55 io_task_runner_
->PostTask(
57 base::Bind(&PepperPlatformAudioOutput::StopPlaybackOnIOThread
, this));
63 void PepperPlatformAudioOutput::ShutDown() {
64 // Called on the main thread to stop all audio callbacks. We must only change
65 // the client on the main thread, and the delegates from the I/O thread.
67 io_task_runner_
->PostTask(
69 base::Bind(&PepperPlatformAudioOutput::ShutDownOnIOThread
, this));
72 void PepperPlatformAudioOutput::OnStateChanged(
73 media::AudioOutputIPCDelegateState state
) {}
75 void PepperPlatformAudioOutput::OnStreamCreated(
76 base::SharedMemoryHandle handle
,
77 base::SyncSocket::Handle socket_handle
,
81 DCHECK(socket_handle
);
83 DCHECK(base::SharedMemory::IsHandleValid(handle
));
84 DCHECK_NE(-1, socket_handle
);
88 if (base::ThreadTaskRunnerHandle::Get().get() == main_task_runner_
.get()) {
89 // Must dereference the client only on the main thread. Shutdown may have
90 // occurred while the request was in-flight, so we need to NULL check.
92 client_
->StreamCreated(handle
, length
, socket_handle
);
94 main_task_runner_
->PostTask(
95 FROM_HERE
, base::Bind(&PepperPlatformAudioOutput::OnStreamCreated
, this,
96 handle
, socket_handle
, length
));
100 void PepperPlatformAudioOutput::OnOutputDeviceSwitched(
102 media::SwitchOutputDeviceResult result
) {}
104 void PepperPlatformAudioOutput::OnIPCClosed() { ipc_
.reset(); }
106 PepperPlatformAudioOutput::~PepperPlatformAudioOutput() {
107 // Make sure we have been shut down. Warning: this will usually happen on
113 PepperPlatformAudioOutput::PepperPlatformAudioOutput()
115 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
116 io_task_runner_(ChildProcess::current()->io_task_runner()) {
119 bool PepperPlatformAudioOutput::Initialize(int sample_rate
,
120 int frames_per_buffer
,
121 int source_render_frame_id
,
122 AudioHelper
* client
) {
126 RenderThreadImpl
* const render_thread
= RenderThreadImpl::current();
127 ipc_
= render_thread
->audio_message_filter()->CreateAudioOutputIPC(
128 source_render_frame_id
);
131 media::AudioParameters
params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY
,
132 media::CHANNEL_LAYOUT_STEREO
,
134 ppapi::kBitsPerAudioOutputSample
,
137 io_task_runner_
->PostTask(
138 FROM_HERE
, base::Bind(&PepperPlatformAudioOutput::InitializeOnIOThread
,
143 void PepperPlatformAudioOutput::InitializeOnIOThread(
144 const media::AudioParameters
& params
) {
145 DCHECK(io_task_runner_
->BelongsToCurrentThread());
146 const int kSessionId
= 0;
148 ipc_
->CreateStream(this, params
, kSessionId
);
151 void PepperPlatformAudioOutput::StartPlaybackOnIOThread() {
152 DCHECK(io_task_runner_
->BelongsToCurrentThread());
157 void PepperPlatformAudioOutput::StopPlaybackOnIOThread() {
158 DCHECK(io_task_runner_
->BelongsToCurrentThread());
163 void PepperPlatformAudioOutput::ShutDownOnIOThread() {
164 DCHECK(io_task_runner_
->BelongsToCurrentThread());
166 // Make sure we don't call shutdown more than once.
173 Release(); // Release for the delegate, balances out the reference taken in
174 // PepperPlatformAudioOutput::Create.
177 } // namespace content