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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/webrtc_audio_renderer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/audio_device_factory.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/webrtc_audio_device_impl.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/render_thread_impl.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/audio_output_device.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_parameters.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/sample_rates.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/audio_hardware_config.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/windows_version.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/win/core_audio_util_win.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Supported hardware sample rates for output sides.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) || defined(OS_MACOSX)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// AudioHardwareConfig::GetOutputSampleRate() asks the audio layer for its
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// current sample rate (set by the user) on Windows and Mac OS X.  The listed
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// rates below adds restrictions and Initialize() will fail if the user selects
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// any rate outside these ranges.
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kValidOutputRates[] = {96000, 48000, 44100, 32000, 16000};
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX) || defined(OS_OPENBSD)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kValidOutputRates[] = {48000, 44100};
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(leozwang): We want to use native sampling rate on Android to achieve
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// low latency, currently 16000 is used to work around audio problem on some
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Android devices.
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kValidOutputRates[] = {48000, 44100, 16000};
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const int kDefaultOutputBufferSize = 2048;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kValidOutputRates[] = {44100};
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(xians): Merge the following code to WebRtcAudioCapturer, or remove.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum AudioFramesPerBuffer {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  k160,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  k320,
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  k440,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  k480,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  k640,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  k880,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  k960,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  k1440,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  k1920,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kUnexpectedAudioBufferSize  // Must always be last!
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper method to convert integral values to their respective enum values
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// above, or kUnexpectedAudioBufferSize if no match exists.
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// We map 441 to k440 to avoid changes in the XML part for histograms.
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// It is still possible to map the histogram result to the actual buffer size.
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// See http://crbug.com/243450 for details.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioFramesPerBuffer AsAudioFramesPerBuffer(int frames_per_buffer) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (frames_per_buffer) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 160: return k160;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 320: return k320;
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 441: return k440;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 480: return k480;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 640: return k640;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 880: return k880;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 960: return k960;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1440: return k1440;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1920: return k1920;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kUnexpectedAudioBufferSize;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddHistogramFramesPerBuffer(int param) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioFramesPerBuffer afpb = AsAudioFramesPerBuffer(param);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (afpb != kUnexpectedAudioBufferSize) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioOutputFramesPerBuffer",
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              afpb, kUnexpectedAudioBufferSize);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Report unexpected sample rates using a unique histogram name.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS("WebRTC.AudioOutputFramesPerBufferUnexpected", param);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebRtcAudioRenderer::WebRtcAudioRenderer(int source_render_view_id)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : state_(UNINITIALIZED),
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      source_render_view_id_(source_render_view_id),
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      source_(NULL),
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      play_ref_count_(0),
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      audio_delay_milliseconds_(0),
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      fifo_delay_milliseconds_(0) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebRtcAudioRenderer::~WebRtcAudioRenderer() {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, UNINITIALIZED);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer_.reset();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "WebRtcAudioRenderer::Initialize()";
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, UNINITIALIZED);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(source);
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!sink_.get());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!source_);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Use stereo output on all platforms exept Android.
118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  media::ChannelLayout channel_layout = media::CHANNEL_LAYOUT_STEREO;
119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#if defined(OS_ANDROID)
120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(1) << "Using mono audio output for Android";
121a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  channel_layout = media::CHANNEL_LAYOUT_MONO;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ask the renderer for the default audio output hardware sample-rate.
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  media::AudioHardwareConfig* hardware_config =
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RenderThreadImpl::current()->GetAudioHardwareConfig();
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int sample_rate = hardware_config->GetOutputSampleRate();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Audio output hardware sample rate: " << sample_rate;
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // WebRTC does not yet support higher rates than 96000 on the client side
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // and 48000 is the preferred sample rate. Therefore, if 192000 is detected,
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // we change the rate to 48000 instead. The consequence is that the native
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // layer will be opened up at 192kHz but WebRTC will provide data at 48kHz
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // which will then be resampled by the audio converted on the browser side
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to match the native audio layer.
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (sample_rate == 192000) {
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DVLOG(1) << "Resampling from 48000 to 192000 is required";
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sample_rate = 48000;
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  media::AudioSampleRate asr = media::AsAudioSampleRate(sample_rate);
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (asr != media::kUnexpectedAudioSampleRate) {
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    UMA_HISTOGRAM_ENUMERATION(
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        "WebRTC.AudioOutputSampleRate", asr, media::kUnexpectedAudioSampleRate);
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    UMA_HISTOGRAM_COUNTS("WebRTC.AudioOutputSampleRateUnexpected", sample_rate);
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that the reported output hardware sample rate is supported
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the current platform.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (std::find(&kValidOutputRates[0],
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                &kValidOutputRates[0] + arraysize(kValidOutputRates),
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sample_rate) ==
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    &kValidOutputRates[arraysize(kValidOutputRates)]) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << sample_rate << " is not a supported output rate.";
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set up audio parameters for the source, i.e., the WebRTC client.
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The WebRTC client only supports multiples of 10ms as buffer size where
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // 10ms is preferred for lowest possible delay.
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  media::AudioParameters source_params;
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int buffer_size = (sample_rate / 100);
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DVLOG(1) << "Using WebRTC output buffer size: " << buffer_size;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int channels = ChannelLayoutToChannelCount(channel_layout);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source_params.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      channel_layout, channels, 0,
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      sample_rate, 16, buffer_size);
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set up audio parameters for the sink, i.e., the native audio output stream.
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We strive to open up using native parameters to achieve best possible
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // performance and to ensure that no FIFO is needed on the browser side to
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // match the client request. Any mismatch between the source and the sink is
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // taken care of in this class instead using a pull FIFO.
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  media::AudioParameters sink_params;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_ANDROID)
1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  buffer_size = kDefaultOutputBufferSize;
1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#else
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  buffer_size = hardware_config->GetOutputBufferSize();
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sink_params.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    channel_layout, channels, 0, sample_rate, 16, buffer_size);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create a FIFO if re-buffering is required to match the source input with
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the sink request. The source acts as provider here and the sink as
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // consumer.
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  fifo_delay_milliseconds_ = 0;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (source_params.frames_per_buffer() != sink_params.frames_per_buffer()) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Rebuffering from " << source_params.frames_per_buffer()
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << " to " << sink_params.frames_per_buffer();
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_.reset(new media::AudioPullFifo(
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        source_params.channels(),
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        source_params.frames_per_buffer(),
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &WebRtcAudioRenderer::SourceCallback,
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::Unretained(this))));
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (sink_params.frames_per_buffer() > source_params.frames_per_buffer()) {
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      int frame_duration_milliseconds = base::Time::kMillisecondsPerSecond /
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          static_cast<double>(source_params.sample_rate());
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      fifo_delay_milliseconds_ = (sink_params.frames_per_buffer() -
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        source_params.frames_per_buffer()) * frame_duration_milliseconds;
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate local audio buffers based on the parameters above.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is assumed that each audio sample contains 16 bits and each
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // audio frame contains one or two audio samples depending on the
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // number of channels.
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  buffer_.reset(
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new int16[source_params.frames_per_buffer() * source_params.channels()]);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_ = source;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->SetRenderFormat(source_params);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Configure the audio rendering client and start rendering.
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sink_ = AudioDeviceFactory::NewOutputDevice(source_render_view_id_);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sink_->Initialize(sink_params, this);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sink_->Start();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // User must call Play() before any audio can be heard.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = PAUSED;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioOutputChannelLayout",
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            source_params.channel_layout(),
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            media::CHANNEL_LAYOUT_MAX);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioOutputFramesPerBuffer",
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            source_params.frames_per_buffer(),
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            kUnexpectedAudioBufferSize);
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddHistogramFramesPerBuffer(source_params.frames_per_buffer());
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioRenderer::Start() {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(xians): refactor to make usage of Start/Stop more symmetric.
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTIMPLEMENTED();
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebRtcAudioRenderer::Play() {
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "WebRtcAudioRenderer::Play()";
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == UNINITIALIZED)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(play_ref_count_ == 0 || state_ == PLAYING);
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ++play_ref_count_;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = PLAYING;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (audio_fifo_) {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_delay_milliseconds_ = 0;
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_->Clear();
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebRtcAudioRenderer::Pause() {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "WebRtcAudioRenderer::Pause()";
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == UNINITIALIZED)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(state_, PLAYING);
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GT(play_ref_count_, 0);
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!--play_ref_count_)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    state_ = PAUSED;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebRtcAudioRenderer::Stop() {
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "WebRtcAudioRenderer::Stop()";
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == UNINITIALIZED)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source_->RemoveAudioRenderer(this);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_ = NULL;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sink_->Stop();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = UNINITIALIZED;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebRtcAudioRenderer::SetVolume(float volume) {
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == UNINITIALIZED)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sink_->SetVolume(volume);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::TimeDelta WebRtcAudioRenderer::GetCurrentRenderTime() const {
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::TimeDelta();
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WebRtcAudioRenderer::IsLocalRenderer() const {
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int WebRtcAudioRenderer::Render(media::AudioBus* audio_bus,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int audio_delay_milliseconds) {
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoLock auto_lock(lock_);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!source_)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(2) << "WebRtcAudioRenderer::Render()";
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(2) << "audio_delay_milliseconds: " << audio_delay_milliseconds;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  audio_delay_milliseconds_ = audio_delay_milliseconds;
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (audio_fifo_)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_->Consume(audio_bus, audio_bus->frames());
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SourceCallback(0, audio_bus);
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (state_ == PLAYING) ? audio_bus->frames() : 0;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebRtcAudioRenderer::OnRenderError() {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(ERROR) << "OnRenderError()";
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called by AudioPullFifo when more data is necessary.
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioRenderer::SourceCallback(
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int fifo_frame_delay, media::AudioBus* audio_bus) {
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(2) << "WebRtcAudioRenderer::SourceCallback("
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << fifo_frame_delay << ", "
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << audio_bus->frames() << ")";
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int output_delay_milliseconds = audio_delay_milliseconds_;
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  output_delay_milliseconds += fifo_delay_milliseconds_;
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(2) << "output_delay_milliseconds: " << output_delay_milliseconds;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We need to keep render data for the |source_| regardless of |state_|,
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // otherwise the data will be buffered up inside |source_|.
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source_->RenderData(reinterpret_cast<uint8*>(buffer_.get()),
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      audio_bus->channels(), audio_bus->frames(),
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      output_delay_milliseconds);
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Avoid filling up the audio bus if we are not playing; instead
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // return here and ensure that the returned value in Render() is 0.
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (state_ != PLAYING) {
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_bus->Zero();
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // De-interleave each channel and convert to 32-bit floating-point
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // with nominal range -1.0 -> +1.0 to match the callback format.
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  audio_bus->FromInterleaved(buffer_.get(),
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             audio_bus->frames(),
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             sizeof(buffer_[0]));
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
360