Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: content/renderer/media/webrtc_audio_device_impl.h

Issue 9702019: Adds Analog Gain Control (AGC) to the WebRTC client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_DEVICE_IMPL_H_ 5 #ifndef CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_DEVICE_IMPL_H_
6 #define CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_DEVICE_IMPL_H_ 6 #define CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_DEVICE_IMPL_H_
7 #pragma once 7 #pragma once
8 8
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 // external_adm->SetSessionId(1); 42 // external_adm->SetSessionId(1);
43 // VoiceEngine* voe = VoiceEngine::Create(); 43 // VoiceEngine* voe = VoiceEngine::Create();
44 // VoEBase* base = VoEBase::GetInterface(voe); 44 // VoEBase* base = VoEBase::GetInterface(voe);
45 // base->Init(external_adm); 45 // base->Init(external_adm);
46 // int ch = base->CreateChannel(); 46 // int ch = base->CreateChannel();
47 // ... 47 // ...
48 // base->StartReceive(ch) 48 // base->StartReceive(ch)
49 // base->StartPlayout(ch); 49 // base->StartPlayout(ch);
50 // base->StartSending(ch); 50 // base->StartSending(ch);
51 // ... 51 // ...
52 // <== full-duplex audio session ==> 52 // <== full-duplex audio session with AGC enabled ==>
53 // ... 53 // ...
54 // base->DeleteChannel(ch); 54 // base->DeleteChannel(ch);
55 // base->Terminate(); 55 // base->Terminate();
56 // base->Release(); 56 // base->Release();
57 // VoiceEngine::Delete(voe); 57 // VoiceEngine::Delete(voe);
58 // } 58 // }
59 // 59 //
60 // Note that, WebRtcAudioDeviceImpl::RegisterAudioCallback() will 60 // webrtc::VoiceEngine::Init() calls these ADM methods (in this order):
61 // be called by the webrtc::VoiceEngine::Init() call and the
62 // webrtc::VoiceEngine is an webrtc::AudioTransport implementation.
63 // Hence, when the underlying audio layer wants data samples to be played out,
64 // the AudioDevice::RenderCallback() will be called, which in turn uses the
65 // registered webrtc::AudioTransport callback and feeds the data to the
66 // webrtc::VoiceEngine.
67 // 61 //
68 // The picture below illustrates the media flow on the capture side: 62 // RegisterAudioCallback(this)
63 // webrtc::VoiceEngine is an webrtc::AudioTransport implementation and
64 // implements the RecordedDataIsAvailable() and NeedMorePlayData() callbacks.
65 //
66 // Init()
67 // Creates and initializes the AudioDevice and AudioInputDevice objects.
68 //
69 // SetAGC(true)
70 // Enables the adaptive analog mode of the AGC which ensures that a
71 // suitable microphone volume level will be set. This scheme will affect
72 // the actual microphone control slider.
73 //
74 // Media example:
75 //
76 // When the underlying audio layer wants data samples to be played out, the
77 // AudioDevice::RenderCallback() will be called, which in turn uses the
78 // registered webrtc::AudioTransport callback and gets the data to be played
79 // out from the webrtc::VoiceEngine.
80 //
81 // The picture below illustrates the media flow on the capture side where the
82 // AudioInputDevice client acts as link between the renderer and browser
83 // process:
69 // 84 //
70 // .------------------. .----------------------. 85 // .------------------. .----------------------.
71 // (Native audio) => | AudioInputStream |-> OnData ->| AudioInputController |-. 86 // (Native audio) => | AudioInputStream |-> OnData ->| AudioInputController |-.
72 // .------------------. .----------------------. | 87 // .------------------. .----------------------. |
73 // | 88 // |
74 // browser process | 89 // browser process |
75 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (*) 90 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (*)
76 // renderer process | 91 // renderer process |
77 // | 92 // |
78 // .-------------------------------. .------------------. | 93 // .-------------------------------. .------------------. |
79 // .---| WebRtcAudioDeviceImpl |<- Capture <-| AudioInputDevice | <--. 94 // .---| WebRtcAudioDeviceImpl |<- Capture <-| AudioInputDevice | <--.
80 // | .-------------------------------. .------------------. 95 // | .-------------------------------. .------------------.
81 // | 96 // |
82 // | .---------------------. 97 // | .---------------------.
83 // .-> RecordedDataIsAvailable ->| webrtc::VoiceEngine | => (encode+transmit) 98 // .-> RecordedDataIsAvailable ->| webrtc::VoiceEngine | => (encode+transmit)
84 // .---------------------. 99 // .---------------------.
85 // 100 //
86 // (*) Using SyncSocket for inter-process synchronization with low latency. 101 // (*) Using SyncSocket for inter-process synchronization with low latency.
87 // The actual data is transferred via SharedMemory. IPC is not involved 102 // The actual data is transferred via SharedMemory. IPC is not involved
88 // in the actual media transfer. 103 // in the actual media transfer.
89 // 104 //
105 // AGC overview:
106 //
107 // It aims to maintain a constant speech loudness level from the microphone.
108 // This is done by both controlling the analog microphone gain and applying
109 // digital gain. The microphone gain on the sound card is slowly
110 // increased/decreased during speech only. By observing the microphone control
111 // slider you can see it move when you speak. If you scream, the slider moves
112 // downwards and then upwards again when you return to normal. It is not
113 // uncommon that the slider hits the maximum. This means that the maximum
114 // analog gain is not large enough to give the desired loudness. Nevertheless,
115 // we can in general still attain the desired loudness. If the microphone
116 // control slider is moved manually, the gain adaptation restarts and returns
117 // to roughly the same position as before the change if the circumstances are
118 // still the same. When the input microphone signal causes saturation, the
119 // level is decreased dramatically and has to re-adapt towards the old level.
120 // The adaptation is a slowly varying process and at the beginning of capture
121 // this is noticed by a slow increase in volume. Smaller changes in microphone
122 // input level is leveled out by the built-in digital control. For larger
123 // differences we need to rely on the slow adaptation.
124 // See http://en.wikipedia.org/wiki/Automatic_gain_control for more details.
125 //
126 // AGC implementation details:
127 //
128 // The adaptive analog mode of the AGC is always enabled for desktop platforms
129 // in WebRTC.
130 //
131 // Before recording starts, the ADM sets an AGC state in the
132 // AudioInputDevice by calling AudioInputDevice::SetAutomaticGainControl(true).
133 //
134 // A capture session with AGC is started up as follows (simplified):
135 //
136 // [renderer]
137 // |
138 // ADM::StartRecording()
139 // AudioInputDevice::InitializeOnIOThread()
140 // AudioInputHostMsg_CreateStream(..., agc=true) [IPC]
141 // |
142 // [IPC to the browser]
143 // |
144 // AudioInputRendererHost::OnCreateStream()
145 // AudioInputController::CreateLowLatency()
146 // AudioInputController::DoSetAutomaticGainControl(true)
147 // AudioInputStream::SetAutomaticGainControl(true)
148 // |
149 // AGC is now enabled in the media layer and streaming starts (details omitted).
150 // The figure below illustrates the AGC scheme which is active in combination
151 // with the default media flow explained earlier.
152 // |
153 // [browser]
154 // |
155 // AudioInputStream::(Capture thread loop)
156 // AudioInputStreamImpl::QueryAgcVolume() => new volume once per second
157 // AudioInputData::OnData(..., volume)
158 // AudioInputController::OnData(..., volume)
159 // AudioInputSyncWriter::Write(..., volume)
160 // |
161 // [volume | size | data] is sent to the renderer [shared memory]
162 // |
163 // [renderer]
164 // |
165 // AudioInputDevice::AudioThreadCallback::Process()
166 // WebRtcAudioDeviceImpl::Capture(..., volume)
167 // AudioTransport::RecordedDataIsAvailable(...,volume, new_volume)
168 // |
169 // The AGC now uses the current volume input and computes a suitable new
170 // level given by the |new_level| output. This value is only non-zero if the
171 // AGC has take a decision that the microphone level should change.
172 // |
173 // if (new_volume != 0)
174 // AudioInputDevice::SetVolume(new_volume)
175 // AudioInputHostMsg_SetVolume(new_volume) [IPC]
176 // |
177 // [IPC to the browser]
178 // |
179 // AudioInputRendererHost::OnSetVolume()
180 // AudioInputController::SetVolume()
181 // AudioInputStream::SetVolume(scaled_volume)
182 // |
183 // Here we set the new microphone level in the media layer and at the same time
184 // read the new setting (we might not get exactly what is set).
185 // |
186 // AudioInputData::OnData(..., updated_volume)
187 // AudioInputController::OnData(..., updated_volume)
188 // |
189 // |
190 // This process repeats until we stop capturing data. Note that, a common
191 // steady state is that the volume control reaches its max and the new_volume
192 // value from the AGC is zero. A loud voice input is required to break this
193 // state and start lowering the level again.
194 //
90 // Implementation notes: 195 // Implementation notes:
91 // 196 //
92 // - This class must be created on the main render thread. 197 // - This class must be created on the main render thread.
93 // - The webrtc::AudioDeviceModule is reference counted. 198 // - The webrtc::AudioDeviceModule is reference counted.
94 // - Recording is currently not supported on Mac OS X. 199 // - AGC is only supported in combination with the WASAPI-based audio layer
200 // on Windows, i.e., it is not supported on Windows XP.
201 // - All volume levels required for the AGC scheme are transfered in a
202 // normalized range [0.0, 1.0]. Scaling takes place in both endpoints
203 // (WebRTC client a media layer). This approach ensures that we can avoid
204 // transferring maximum levels between the renderer and the browser.
95 // 205 //
96 class CONTENT_EXPORT WebRtcAudioDeviceImpl 206 class CONTENT_EXPORT WebRtcAudioDeviceImpl
97 : NON_EXPORTED_BASE(public webrtc::AudioDeviceModule), 207 : NON_EXPORTED_BASE(public webrtc::AudioDeviceModule),
98 public media::AudioRendererSink::RenderCallback, 208 public media::AudioRendererSink::RenderCallback,
99 public AudioInputDevice::CaptureCallback, 209 public AudioInputDevice::CaptureCallback,
100 public AudioInputDevice::CaptureEventHandler { 210 public AudioInputDevice::CaptureEventHandler {
101 public: 211 public:
102 // Methods called on main render thread. 212 // Methods called on main render thread.
103 WebRtcAudioDeviceImpl(); 213 WebRtcAudioDeviceImpl();
104 214
105 // webrtc::RefCountedModule implementation. 215 // webrtc::RefCountedModule implementation.
106 // The creator must call AddRef() after construction and use Release() 216 // The creator must call AddRef() after construction and use Release()
107 // to release the reference and delete this object. 217 // to release the reference and delete this object.
108 virtual int32_t AddRef() OVERRIDE; 218 virtual int32_t AddRef() OVERRIDE;
109 virtual int32_t Release() OVERRIDE; 219 virtual int32_t Release() OVERRIDE;
110 220
111 // We need this one to support runnable method tasks. 221 // We need this one to support runnable method tasks.
112 static bool ImplementsThreadSafeReferenceCounting() { return true; } 222 static bool ImplementsThreadSafeReferenceCounting() { return true; }
113 223
114 // AudioDevice::RenderCallback implementation. 224 // AudioDevice::RenderCallback implementation.
115 virtual size_t Render(const std::vector<float*>& audio_data, 225 virtual size_t Render(const std::vector<float*>& audio_data,
116 size_t number_of_frames, 226 size_t number_of_frames,
117 size_t audio_delay_milliseconds) OVERRIDE; 227 size_t audio_delay_milliseconds) OVERRIDE;
118 virtual void OnRenderError() OVERRIDE; 228 virtual void OnRenderError() OVERRIDE;
119 229
120 // AudioInputDevice::CaptureCallback implementation. 230 // AudioInputDevice::CaptureCallback implementation.
121 virtual void Capture(const std::vector<float*>& audio_data, 231 virtual void Capture(const std::vector<float*>& audio_data,
122 size_t number_of_frames, 232 size_t number_of_frames,
123 size_t audio_delay_milliseconds) OVERRIDE; 233 size_t audio_delay_milliseconds,
234 double volume) OVERRIDE;
124 virtual void OnCaptureError() OVERRIDE; 235 virtual void OnCaptureError() OVERRIDE;
125 236
126 // AudioInputDevice::CaptureEventHandler implementation. 237 // AudioInputDevice::CaptureEventHandler implementation.
127 virtual void OnDeviceStarted(const std::string& device_id) OVERRIDE; 238 virtual void OnDeviceStarted(const std::string& device_id) OVERRIDE;
128 virtual void OnDeviceStopped() OVERRIDE; 239 virtual void OnDeviceStopped() OVERRIDE;
129 240
130 // webrtc::Module implementation. 241 // webrtc::Module implementation.
131 virtual int32_t ChangeUniqueId(const int32_t id) OVERRIDE; 242 virtual int32_t ChangeUniqueId(const int32_t id) OVERRIDE;
132 virtual int32_t TimeUntilNextProcess() OVERRIDE; 243 virtual int32_t TimeUntilNextProcess() OVERRIDE;
133 virtual int32_t Process() OVERRIDE; 244 virtual int32_t Process() OVERRIDE;
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 440
330 // Protects |recording_|, |output_delay_ms_|, |input_delay_ms_|. 441 // Protects |recording_|, |output_delay_ms_|, |input_delay_ms_|.
331 mutable base::Lock lock_; 442 mutable base::Lock lock_;
332 443
333 int bytes_per_sample_; 444 int bytes_per_sample_;
334 445
335 bool initialized_; 446 bool initialized_;
336 bool playing_; 447 bool playing_;
337 bool recording_; 448 bool recording_;
338 449
450 // Local copy of the current Automatic Gain Control state.
451 bool agc_is_enabled_;
452
339 DISALLOW_COPY_AND_ASSIGN(WebRtcAudioDeviceImpl); 453 DISALLOW_COPY_AND_ASSIGN(WebRtcAudioDeviceImpl);
340 }; 454 };
341 455
342 #endif // CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_DEVICE_IMPL_H_ 456 #endif // CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_DEVICE_IMPL_H_
OLDNEW
« no previous file with comments | « content/renderer/media/audio_input_device.cc ('k') | content/renderer/media/webrtc_audio_device_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698