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/logging.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "build/build_config.h"
11 #include "content/child/child_process.h"
12 #include "content/common/media/audio_messages.h"
13 #include "content/renderer/media/audio_message_filter.h"
14 #include "content/renderer/pepper/audio_helper.h"
15 #include "content/renderer/render_thread_impl.h"
16 #include "media/base/audio_hardware_config.h"
17 #include "ppapi/shared_impl/ppb_audio_config_shared.h"
22 PepperPlatformAudioOutput* PepperPlatformAudioOutput::Create(
24 int frames_per_buffer,
25 int source_render_view_id,
26 AudioHelper* client) {
27 scoped_refptr<PepperPlatformAudioOutput> audio_output(
28 new PepperPlatformAudioOutput());
29 if (audio_output->Initialize(sample_rate, frames_per_buffer,
30 source_render_view_id, client)) {
31 // Balanced by Release invoked in
32 // PepperPlatformAudioOutput::ShutDownOnIOThread().
33 audio_output->AddRef();
34 return audio_output.get();
39 bool PepperPlatformAudioOutput::StartPlayback() {
41 io_message_loop_proxy_->PostTask(
43 base::Bind(&PepperPlatformAudioOutput::StartPlaybackOnIOThread, this));
49 bool PepperPlatformAudioOutput::StopPlayback() {
51 io_message_loop_proxy_->PostTask(
53 base::Bind(&PepperPlatformAudioOutput::StopPlaybackOnIOThread, this));
59 void PepperPlatformAudioOutput::ShutDown() {
60 // Called on the main thread to stop all audio callbacks. We must only change
61 // the client on the main thread, and the delegates from the I/O thread.
63 io_message_loop_proxy_->PostTask(
65 base::Bind(&PepperPlatformAudioOutput::ShutDownOnIOThread, this));
68 void PepperPlatformAudioOutput::OnStateChanged(
69 media::AudioOutputIPCDelegate::State state) {
72 void PepperPlatformAudioOutput::OnStreamCreated(
73 base::SharedMemoryHandle handle,
74 base::SyncSocket::Handle socket_handle,
78 DCHECK(socket_handle);
80 DCHECK_NE(-1, handle.fd);
81 DCHECK_NE(-1, socket_handle);
85 if (base::MessageLoopProxy::current().get() ==
86 main_message_loop_proxy_.get()) {
87 // Must dereference the client only on the main thread. Shutdown may have
88 // occurred while the request was in-flight, so we need to NULL check.
90 client_->StreamCreated(handle, length, socket_handle);
92 main_message_loop_proxy_->PostTask(FROM_HERE,
93 base::Bind(&PepperPlatformAudioOutput::OnStreamCreated, this, handle,
94 socket_handle, length));
98 void PepperPlatformAudioOutput::OnIPCClosed() {
102 PepperPlatformAudioOutput::~PepperPlatformAudioOutput() {
103 // Make sure we have been shut down. Warning: this will usually happen on
109 PepperPlatformAudioOutput::PepperPlatformAudioOutput()
111 main_message_loop_proxy_(base::MessageLoopProxy::current()),
112 io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()) {
115 bool PepperPlatformAudioOutput::Initialize(
117 int frames_per_buffer,
118 int source_render_view_id,
119 AudioHelper* client) {
123 RenderThreadImpl* const render_thread = RenderThreadImpl::current();
124 ipc_ = render_thread->audio_message_filter()->
125 CreateAudioOutputIPC(source_render_view_id);
128 media::AudioParameters params(
129 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
130 media::CHANNEL_LAYOUT_STEREO, sample_rate,
131 ppapi::kBitsPerAudioOutputSample, frames_per_buffer);
133 io_message_loop_proxy_->PostTask(
135 base::Bind(&PepperPlatformAudioOutput::InitializeOnIOThread, this,
140 void PepperPlatformAudioOutput::InitializeOnIOThread(
141 const media::AudioParameters& params) {
142 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
143 const int kSessionId = 0;
145 ipc_->CreateStream(this, params, kSessionId);
148 void PepperPlatformAudioOutput::StartPlaybackOnIOThread() {
149 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
154 void PepperPlatformAudioOutput::StopPlaybackOnIOThread() {
155 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
160 void PepperPlatformAudioOutput::ShutDownOnIOThread() {
161 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
163 // Make sure we don't call shutdown more than once.
170 Release(); // Release for the delegate, balances out the reference taken in
171 // PepperPlatformAudioOutput::Create.
174 } // namespace content