Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2013 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/webrtc_local_audio_source_provider.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "content/renderer/render_thread_impl.h" | |
| 9 #include "media/audio/audio_parameters.h" | |
| 10 #include "media/base/audio_fifo.h" | |
| 11 #include "media/base/audio_hardware_config.h" | |
| 12 #include "third_party/WebKit/public/web/WebAudioSourceProviderClient.h" | |
| 13 | |
| 14 using WebKit::WebVector; | |
| 15 | |
| 16 namespace content { | |
| 17 | |
| 18 static const size_t kMaxNumberOfBuffer = 10; | |
| 19 static const size_t kWebAudioRenderBufferSize = 128; | |
| 20 | |
| 21 WebRtcLocalAudioSourceProvider::WebRtcLocalAudioSourceProvider() | |
| 22 : audio_delay_ms_(0), | |
| 23 volume_(1), | |
| 24 key_pressed_(false), | |
| 25 is_enabled_(false) { | |
| 26 } | |
| 27 | |
| 28 WebRtcLocalAudioSourceProvider::~WebRtcLocalAudioSourceProvider() { | |
| 29 if (audio_converter_.get()) | |
| 30 audio_converter_->RemoveInput(this); | |
| 31 } | |
| 32 | |
| 33 void WebRtcLocalAudioSourceProvider::Initialize( | |
| 34 const media::AudioParameters& source_params) { | |
| 35 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 36 // Use the native audio output hardware sample-rate for the sink. | |
| 37 media::AudioHardwareConfig* hardware_config = | |
|
tommi (sloooow) - chröme
2013/09/06 11:20:30
FYI this needs to change probably before you can l
no longer working on chromium
2013/09/10 12:43:15
As discussed offline, we have to keep this for now
| |
| 38 RenderThreadImpl::current()->GetAudioHardwareConfig(); | |
| 39 int sample_rate = hardware_config->GetOutputSampleRate(); | |
| 40 media::AudioParameters sink_params( | |
| 41 source_params.format(), media::CHANNEL_LAYOUT_STEREO, | |
| 42 sample_rate, source_params.bits_per_sample(), kWebAudioRenderBufferSize); | |
| 43 | |
| 44 base::AutoLock auto_lock(lock_); | |
| 45 source_params_ = source_params; | |
| 46 audio_converter_.reset( | |
| 47 new media::AudioConverter(source_params, sink_params, true)); | |
| 48 audio_converter_->AddInput(this); | |
| 49 fifo_.reset(new media::AudioFifo( | |
| 50 source_params.channels(), | |
| 51 kMaxNumberOfBuffer * source_params.frames_per_buffer())); | |
| 52 } | |
| 53 | |
| 54 void WebRtcLocalAudioSourceProvider::DeliverData( | |
| 55 media::AudioBus* audio_source, | |
| 56 int audio_delay_milliseconds, | |
| 57 int volume, | |
| 58 bool key_pressed) { | |
| 59 base::AutoLock auto_lock(lock_); | |
| 60 if (!is_enabled_) | |
| 61 return; | |
| 62 | |
| 63 DCHECK(fifo_.get()); | |
| 64 | |
| 65 if (fifo_->frames() + audio_source->frames() <= fifo_->max_frames()) { | |
| 66 fifo_->Push(audio_source); | |
| 67 } else { | |
| 68 // This can happen if the data in FIFO is too slowed to be consumed or | |
| 69 // WebAudio stops consuming data. | |
| 70 DLOG(WARNING) << "Local source provicer FIFO is full" << fifo_->frames(); | |
| 71 } | |
| 72 | |
| 73 // Cache the values for GetStreamInfo(). | |
|
tommi (sloooow) - chröme
2013/09/06 11:20:30
if you change the function name, please also updat
no longer working on chromium
2013/09/10 12:43:15
Done.
| |
| 74 last_fill_ = base::TimeTicks::Now(); | |
| 75 audio_delay_ms_ = audio_delay_milliseconds; | |
| 76 volume_ = volume; | |
| 77 key_pressed_ = key_pressed; | |
| 78 } | |
| 79 | |
| 80 void WebRtcLocalAudioSourceProvider::GetStreamInfo( | |
| 81 int* delay_ms, int* volume, bool* key_pressed) { | |
| 82 int elapsed_ms = 0; | |
| 83 if (!last_fill_.is_null()) { | |
|
tommi (sloooow) - chröme
2013/09/06 11:20:30
there's no locking here. add a thread check?
no longer working on chromium
2013/09/10 12:43:15
I have already added a thread check for the Initia
| |
| 84 elapsed_ms = static_cast<int>( | |
| 85 (base::TimeTicks::Now() - last_fill_).InMilliseconds()); | |
| 86 } | |
| 87 *delay_ms = audio_delay_ms_ + elapsed_ms + | |
| 88 static_cast<int>(1000 * fifo_->frames() / source_params_.sample_rate()); | |
| 89 *volume = volume_; | |
| 90 *key_pressed = key_pressed_; | |
| 91 } | |
| 92 | |
| 93 void WebRtcLocalAudioSourceProvider::setClient( | |
| 94 WebKit::WebAudioSourceProviderClient* client) { | |
| 95 NOTIMPLEMENTED(); | |
| 96 } | |
| 97 | |
| 98 void WebRtcLocalAudioSourceProvider::provideInput( | |
| 99 const WebVector<float*>& audio_data, size_t number_of_frames) { | |
| 100 DCHECK_EQ(number_of_frames, kWebAudioRenderBufferSize); | |
| 101 if (!bus_wrapper_ || | |
| 102 static_cast<size_t>(bus_wrapper_->channels()) != audio_data.size()) { | |
| 103 bus_wrapper_ = media::AudioBus::CreateWrapper(audio_data.size()); | |
| 104 } | |
| 105 | |
| 106 bus_wrapper_->set_frames(number_of_frames); | |
| 107 for (size_t i = 0; i < audio_data.size(); ++i) | |
| 108 bus_wrapper_->SetChannelData(i, audio_data[i]); | |
| 109 | |
| 110 base::AutoLock auto_lock(lock_); | |
| 111 DCHECK(audio_converter_.get()); | |
| 112 DCHECK(fifo_.get()); | |
| 113 is_enabled_ = true; | |
| 114 audio_converter_->Convert(bus_wrapper_.get()); | |
| 115 } | |
| 116 | |
| 117 double WebRtcLocalAudioSourceProvider::ProvideInput( | |
| 118 media::AudioBus* audio_bus, base::TimeDelta buffer_delay) { | |
| 119 if (fifo_->frames() >= audio_bus->frames()) { | |
| 120 fifo_->Consume(audio_bus, 0, audio_bus->frames()); | |
| 121 } else { | |
| 122 DLOG(WARNING) << "Underrun, FIFO has data " << fifo_->frames() | |
| 123 << " samples but " << audio_bus->frames() | |
| 124 << " samples are needed"; | |
| 125 fifo_->Consume(audio_bus, 0, fifo_->frames()); | |
| 126 } | |
| 127 | |
| 128 return 1.0; | |
| 129 } | |
| 130 | |
| 131 } // namespace content | |
| OLD | NEW |