OLD | NEW |
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 Loading... |
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 Loading... |
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_ |
OLD | NEW |