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; | |
tommi (sloooow) - chröme
2013/09/12 20:40:55
kMaxNumberOfBuffers (plural) or kMaxBufferCount
no longer working on chromium
2013/09/17 13:08:01
Done.
| |
19 static const size_t kWebAudioRenderBufferSize = 128; | |
tommi (sloooow) - chröme
2013/09/12 20:40:55
Ideally this should be the same constant as used i
no longer working on chromium
2013/09/17 13:08:01
Done.
| |
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 | |
37 // Use the native audio output hardware sample-rate for the sink. | |
38 if (RenderThreadImpl::current()) { | |
39 media::AudioHardwareConfig* hardware_config = | |
40 RenderThreadImpl::current()->GetAudioHardwareConfig(); | |
41 int sample_rate = hardware_config->GetOutputSampleRate(); | |
42 sink_params_.Reset( | |
43 source_params.format(), media::CHANNEL_LAYOUT_STEREO, 2, 0, | |
44 sample_rate, source_params.bits_per_sample(), | |
45 kWebAudioRenderBufferSize); | |
46 } else { | |
47 // This happens on unittests which does not have a valid RenderThreadImpl, | |
48 // the unittests should have injected their own |sink_params_| for testing. | |
49 sink_params_.IsValid(); | |
tommi (sloooow) - chröme
2013/09/12 20:40:55
missing DCHECK()
no longer working on chromium
2013/09/17 13:08:01
Done.
| |
50 } | |
51 | |
52 base::AutoLock auto_lock(lock_); | |
53 source_params_ = source_params; | |
54 // Create the audio converter with |disable_fifo| as false so that the | |
55 // converter will request source_params.frames_per_buffer() each time. | |
56 // This will not increase the complexity as there is only one client to | |
57 // the converter. | |
58 audio_converter_.reset( | |
59 new media::AudioConverter(source_params, sink_params_, false)); | |
60 audio_converter_->AddInput(this); | |
61 fifo_.reset(new media::AudioFifo( | |
62 source_params.channels(), | |
63 kMaxNumberOfBuffer * source_params.frames_per_buffer())); | |
64 } | |
65 | |
66 void WebRtcLocalAudioSourceProvider::DeliverData( | |
67 media::AudioBus* audio_source, | |
68 int audio_delay_milliseconds, | |
69 int volume, | |
70 bool key_pressed) { | |
71 base::AutoLock auto_lock(lock_); | |
72 if (!is_enabled_) | |
73 return; | |
74 | |
75 DCHECK(fifo_.get()); | |
76 | |
77 if (fifo_->frames() + audio_source->frames() <= fifo_->max_frames()) { | |
78 fifo_->Push(audio_source); | |
79 } else { | |
80 // This can happen if the data in FIFO is too slowed to be consumed or | |
81 // WebAudio stops consuming data. | |
82 DLOG(WARNING) << "Local source provicer FIFO is full" << fifo_->frames(); | |
83 } | |
84 | |
85 // Cache the values for GetAudioProcessingParams(). | |
86 last_fill_ = base::TimeTicks::Now(); | |
87 audio_delay_ms_ = audio_delay_milliseconds; | |
88 volume_ = volume; | |
89 key_pressed_ = key_pressed; | |
90 } | |
91 | |
92 void WebRtcLocalAudioSourceProvider::GetAudioProcessingParams( | |
93 int* delay_ms, int* volume, bool* key_pressed) { | |
94 int elapsed_ms = 0; | |
95 if (!last_fill_.is_null()) { | |
96 elapsed_ms = static_cast<int>( | |
97 (base::TimeTicks::Now() - last_fill_).InMilliseconds()); | |
98 } | |
99 *delay_ms = audio_delay_ms_ + elapsed_ms + static_cast<int>( | |
100 1000 * fifo_->frames() / source_params_.sample_rate() + 0.5); | |
101 *volume = volume_; | |
102 *key_pressed = key_pressed_; | |
103 } | |
104 | |
105 void WebRtcLocalAudioSourceProvider::setClient( | |
106 WebKit::WebAudioSourceProviderClient* client) { | |
107 NOTREACHED(); | |
108 } | |
109 | |
110 void WebRtcLocalAudioSourceProvider::provideInput( | |
111 const WebVector<float*>& audio_data, size_t number_of_frames) { | |
112 DCHECK_EQ(number_of_frames, kWebAudioRenderBufferSize); | |
113 if (!bus_wrapper_ || | |
114 static_cast<size_t>(bus_wrapper_->channels()) != audio_data.size()) { | |
115 bus_wrapper_ = media::AudioBus::CreateWrapper(audio_data.size()); | |
116 } | |
117 | |
118 bus_wrapper_->set_frames(number_of_frames); | |
119 for (size_t i = 0; i < audio_data.size(); ++i) | |
120 bus_wrapper_->SetChannelData(i, audio_data[i]); | |
121 | |
122 base::AutoLock auto_lock(lock_); | |
123 DCHECK(audio_converter_.get()); | |
124 DCHECK(fifo_.get()); | |
125 is_enabled_ = true; | |
126 audio_converter_->Convert(bus_wrapper_.get()); | |
127 } | |
128 | |
129 double WebRtcLocalAudioSourceProvider::ProvideInput( | |
130 media::AudioBus* audio_bus, base::TimeDelta buffer_delay) { | |
131 if (fifo_->frames() >= audio_bus->frames()) { | |
132 fifo_->Consume(audio_bus, 0, audio_bus->frames()); | |
133 } else { | |
134 audio_bus->Zero(); | |
135 if (!last_fill_.is_null()) { | |
136 DLOG(WARNING) << "Underrun, FIFO has data " << fifo_->frames() | |
137 << " samples but " << audio_bus->frames() | |
138 << " samples are needed"; | |
139 } | |
140 } | |
141 | |
142 return 1.0; | |
143 } | |
144 | |
145 void WebRtcLocalAudioSourceProvider::SetSinkParamsForTesting( | |
146 const media::AudioParameters& sink_params) { | |
147 DCHECK(thread_checker_.CalledOnValidThread()); | |
148 sink_params_ = sink_params; | |
149 } | |
150 | |
151 } // namespace content | |
OLD | NEW |