Home | History | Annotate | Download | only in media
      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.
      4 
      5 #include "content/renderer/media/webaudio_capturer_source.h"
      6 
      7 #include "base/logging.h"
      8 #include "content/renderer/media/webrtc_audio_capturer.h"
      9 
     10 using media::AudioBus;
     11 using media::AudioFifo;
     12 using media::AudioParameters;
     13 using media::ChannelLayout;
     14 using media::CHANNEL_LAYOUT_MONO;
     15 using media::CHANNEL_LAYOUT_STEREO;
     16 
     17 static const int kFifoSize = 2048;
     18 
     19 namespace content {
     20 
     21 WebAudioCapturerSource::WebAudioCapturerSource(WebRtcAudioCapturer* capturer)
     22     : capturer_(capturer),
     23       set_format_channels_(0),
     24       callback_(0),
     25       started_(false) {
     26 }
     27 
     28 WebAudioCapturerSource::~WebAudioCapturerSource() {
     29 }
     30 
     31 void WebAudioCapturerSource::setFormat(
     32     size_t number_of_channels, float sample_rate) {
     33   DVLOG(1) << "WebAudioCapturerSource::setFormat(sample_rate="
     34            << sample_rate << ")";
     35   if (number_of_channels <= 2) {
     36     set_format_channels_ = number_of_channels;
     37     ChannelLayout channel_layout =
     38         number_of_channels == 1 ? CHANNEL_LAYOUT_MONO : CHANNEL_LAYOUT_STEREO;
     39     capturer_->SetCapturerSource(this, channel_layout, sample_rate);
     40   } else {
     41     // TODO(crogers): Handle more than just the mono and stereo cases.
     42     LOG(WARNING) << "WebAudioCapturerSource::setFormat() : unhandled format.";
     43   }
     44 }
     45 
     46 void WebAudioCapturerSource::Initialize(
     47     const media::AudioParameters& params,
     48     media::AudioCapturerSource::CaptureCallback* callback,
     49     int session_id) {
     50   // The downstream client should be configured the same as what WebKit
     51   // is feeding it.
     52   DCHECK_EQ(set_format_channels_, params.channels());
     53 
     54   base::AutoLock auto_lock(lock_);
     55   params_ = params;
     56   callback_ = callback;
     57   wrapper_bus_ = AudioBus::CreateWrapper(params.channels());
     58   capture_bus_ = AudioBus::Create(params);
     59   fifo_.reset(new AudioFifo(params.channels(), kFifoSize));
     60 }
     61 
     62 void WebAudioCapturerSource::Start() {
     63   started_ = true;
     64 }
     65 
     66 void WebAudioCapturerSource::Stop() {
     67   started_ = false;
     68 }
     69 
     70 void WebAudioCapturerSource::consumeAudio(
     71     const WebKit::WebVector<const float*>& audio_data,
     72     size_t number_of_frames) {
     73   base::AutoLock auto_lock(lock_);
     74 
     75   if (!callback_)
     76     return;
     77 
     78   wrapper_bus_->set_frames(number_of_frames);
     79 
     80   // Make sure WebKit is honoring what it told us up front
     81   // about the channels.
     82   DCHECK_EQ(set_format_channels_, static_cast<int>(audio_data.size()));
     83   DCHECK_EQ(set_format_channels_, wrapper_bus_->channels());
     84 
     85   for (size_t i = 0; i < audio_data.size(); ++i)
     86     wrapper_bus_->SetChannelData(i, const_cast<float*>(audio_data[i]));
     87 
     88   // Handle mismatch between WebAudio buffer-size and WebRTC.
     89   int available = fifo_->max_frames() - fifo_->frames();
     90   if (available < static_cast<int>(number_of_frames)) {
     91     LOG(ERROR) << "WebAudioCapturerSource::Consume() : FIFO overrun.";
     92     return;
     93   }
     94 
     95   fifo_->Push(wrapper_bus_.get());
     96   int capture_frames = params_.frames_per_buffer();
     97   while (fifo_->frames() >= capture_frames) {
     98     fifo_->Consume(capture_bus_.get(), 0, capture_frames);
     99     callback_->Capture(capture_bus_.get(), 0, 1.0);
    100   }
    101 }
    102 
    103 }  // namespace content
    104