15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/renderer/pepper/pepper_platform_audio_output.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/child_process.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/media/audio_messages.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/audio_message_filter.h"
14558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/renderer/pepper/audio_helper.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/render_thread_impl.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/audio_hardware_config.h"
1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ppapi/shared_impl/ppb_audio_config_shared.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
22558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochPepperPlatformAudioOutput* PepperPlatformAudioOutput::Create(
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int sample_rate,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int frames_per_buffer,
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int source_render_view_id,
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int source_render_frame_id,
27558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    AudioHelper* client) {
28558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  scoped_refptr<PepperPlatformAudioOutput> audio_output(
29558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      new PepperPlatformAudioOutput());
30a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (audio_output->Initialize(sample_rate,
31a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                               frames_per_buffer,
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                               source_render_view_id,
33a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                               source_render_frame_id,
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               client)) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Balanced by Release invoked in
36558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    // PepperPlatformAudioOutput::ShutDownOnIOThread().
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_output->AddRef();
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return audio_output.get();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochbool PepperPlatformAudioOutput::StartPlayback() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ipc_) {
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    io_message_loop_proxy_->PostTask(
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
47558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        base::Bind(&PepperPlatformAudioOutput::StartPlaybackOnIOThread, this));
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochbool PepperPlatformAudioOutput::StopPlayback() {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ipc_) {
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    io_message_loop_proxy_->PostTask(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
57558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        base::Bind(&PepperPlatformAudioOutput::StopPlaybackOnIOThread, this));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid PepperPlatformAudioOutput::ShutDown() {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the main thread to stop all audio callbacks. We must only change
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the client on the main thread, and the delegates from the I/O thread.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_ = NULL;
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  io_message_loop_proxy_->PostTask(
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
69558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      base::Bind(&PepperPlatformAudioOutput::ShutDownOnIOThread, this));
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid PepperPlatformAudioOutput::OnStateChanged(
73a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    media::AudioOutputIPCDelegate::State state) {}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid PepperPlatformAudioOutput::OnStreamCreated(
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle handle,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SyncSocket::Handle socket_handle,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int length) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(handle);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(socket_handle);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(-1, handle.fd);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(-1, socket_handle);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(length);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (base::MessageLoopProxy::current().get() ==
89a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      main_message_loop_proxy_.get()) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Must dereference the client only on the main thread. Shutdown may have
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // occurred while the request was in-flight, so we need to NULL check.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (client_)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_->StreamCreated(handle, length, socket_handle);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    main_message_loop_proxy_->PostTask(
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        FROM_HERE,
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        base::Bind(&PepperPlatformAudioOutput::OnStreamCreated,
98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   this,
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   handle,
100a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   socket_handle,
101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   length));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid PepperPlatformAudioOutput::OnIPCClosed() { ipc_.reset(); }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
107558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochPepperPlatformAudioOutput::~PepperPlatformAudioOutput() {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we have been shut down. Warning: this will usually happen on
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the I/O thread!
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!ipc_);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!client_);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochPepperPlatformAudioOutput::PepperPlatformAudioOutput()
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : client_(NULL),
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      main_message_loop_proxy_(base::MessageLoopProxy::current()),
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()) {
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
120a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool PepperPlatformAudioOutput::Initialize(int sample_rate,
121a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                           int frames_per_buffer,
122a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                           int source_render_view_id,
123a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                           int source_render_frame_id,
124a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                           AudioHelper* client) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(client);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_ = client;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RenderThreadImpl* const render_thread = RenderThreadImpl::current();
129a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ipc_ = render_thread->audio_message_filter()->CreateAudioOutputIPC(
130a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      source_render_view_id, source_render_frame_id);
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(ipc_);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                media::CHANNEL_LAYOUT_STEREO,
135a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                sample_rate,
136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                ppapi::kBitsPerAudioOutputSample,
137a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                frames_per_buffer);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  io_message_loop_proxy_->PostTask(
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      base::Bind(
142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          &PepperPlatformAudioOutput::InitializeOnIOThread, this, params));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
146558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid PepperPlatformAudioOutput::InitializeOnIOThread(
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const media::AudioParameters& params) {
148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int kSessionId = 0;
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (ipc_)
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ipc_->CreateStream(this, params, kSessionId);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
154558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid PepperPlatformAudioOutput::StartPlaybackOnIOThread() {
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (ipc_)
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ipc_->PlayStream();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
160558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid PepperPlatformAudioOutput::StopPlaybackOnIOThread() {
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (ipc_)
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ipc_->PauseStream();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
166558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid PepperPlatformAudioOutput::ShutDownOnIOThread() {
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we don't call shutdown more than once.
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!ipc_)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ipc_->CloseStream();
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ipc_.reset();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Release for the delegate, balances out the reference taken in
1773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch              // PepperPlatformAudioOutput::Create.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
181