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

Side by Side Diff: webrtc/modules/audio_mixer/audio_mixer.cc

Issue 2111293003: Removed callback between old AudioConferenceMixer and OutputMixer. The audio frame with mixed audio… (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@new_mixer_format
Patch Set: Removed asserts, decreased lock holding time & minor changes. Created 4 years, 5 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
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/audio_mixer/audio_mixer.h"
12
13 #include "webrtc/base/format_macros.h"
14 #include "webrtc/modules/audio_processing/include/audio_processing.h"
15 #include "webrtc/modules/utility/include/audio_frame_operations.h"
16 #include "webrtc/system_wrappers/include/file_wrapper.h"
17 #include "webrtc/system_wrappers/include/trace.h"
18 #include "webrtc/voice_engine/include/voe_external_media.h"
19 #include "webrtc/voice_engine/statistics.h"
20 #include "webrtc/voice_engine/utility.h"
21
22 namespace webrtc {
23 namespace voe {
24
25 void AudioMixer::PlayNotification(int32_t id, uint32_t durationMs) {
26 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
27 "AudioMixer::PlayNotification(id=%d, durationMs=%d)", id,
28 durationMs);
29 // Not implement yet
30 }
31
32 void AudioMixer::RecordNotification(int32_t id, uint32_t durationMs) {
33 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
34 "AudioMixer::RecordNotification(id=%d, durationMs=%d)", id,
35 durationMs);
36
37 // Not implement yet
38 }
39
40 void AudioMixer::PlayFileEnded(int32_t id) {
41 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
42 "AudioMixer::PlayFileEnded(id=%d)", id);
43
44 // not needed
45 }
46
47 void AudioMixer::RecordFileEnded(int32_t id) {
48 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
49 "AudioMixer::RecordFileEnded(id=%d)", id);
50 assert(id == _instanceId);
ivoc 2016/07/07 13:46:16 Please convert asserts to DCHECKs in this file as
51
52 rtc::CritScope cs(&_fileCritSect);
53 _outputFileRecording = false;
54 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, -1),
55 "AudioMixer::RecordFileEnded() =>"
56 "output file recorder module is shutdown");
57 }
58
59 int32_t AudioMixer::Create(AudioMixer*& mixer, uint32_t instanceId) {
60 WEBRTC_TRACE(kTraceMemory, kTraceVoice, instanceId,
61 "AudioMixer::Create(instanceId=%d)", instanceId);
62 mixer = new AudioMixer(instanceId);
63 if (mixer == NULL) {
64 WEBRTC_TRACE(kTraceMemory, kTraceVoice, instanceId,
65 "AudioMixer::Create() unable to allocate memory for"
66 "mixer");
67 return -1;
68 }
69 return 0;
70 }
71
72 AudioMixer::AudioMixer(uint32_t instanceId)
73 : _mixerModule(*NewAudioConferenceMixer::Create(instanceId)),
74 _audioLevel(),
75 _instanceId(instanceId),
76 _externalMediaCallbackPtr(NULL),
77 _externalMedia(false),
78 _panLeft(1.0f),
79 _panRight(1.0f),
80 _mixingFrequencyHz(8000),
81 _outputFileRecorderPtr(NULL),
82 _outputFileRecording(false) {
83 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, -1),
84 "AudioMixer::AudioMixer() - ctor");
85 }
86
87 void AudioMixer::Destroy(AudioMixer*& mixer) {
88 if (mixer) {
89 delete mixer;
90 mixer = NULL;
91 }
92 }
93
94 AudioMixer::~AudioMixer() {
95 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, -1),
96 "AudioMixer::~AudioMixer() - dtor");
97 if (_externalMedia) {
98 DeRegisterExternalMediaProcessing();
99 }
100 {
101 rtc::CritScope cs(&_fileCritSect);
102 if (_outputFileRecorderPtr) {
103 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
104 _outputFileRecorderPtr->StopRecording();
105 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
106 _outputFileRecorderPtr = NULL;
107 }
108 }
109 delete &_mixerModule;
110 }
111
112 int32_t AudioMixer::SetEngineInformation(voe::Statistics& engineStatistics) {
113 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
114 "AudioMixer::SetEngineInformation()");
115 _engineStatisticsPtr = &engineStatistics;
116 return 0;
117 }
118
119 int32_t AudioMixer::SetAudioProcessingModule(
120 AudioProcessing* audioProcessingModule) {
121 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
122 "AudioMixer::SetAudioProcessingModule("
123 "audioProcessingModule=0x%x)",
124 audioProcessingModule);
125 _audioProcessingModulePtr = audioProcessingModule;
126 return 0;
127 }
128
129 int AudioMixer::RegisterExternalMediaProcessing(
130 VoEMediaProcess& proccess_object) {
131 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
132 "AudioMixer::RegisterExternalMediaProcessing()");
133
134 rtc::CritScope cs(&_callbackCritSect);
135 _externalMediaCallbackPtr = &proccess_object;
136 _externalMedia = true;
137
138 return 0;
139 }
140
141 int AudioMixer::DeRegisterExternalMediaProcessing() {
142 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
143 "AudioMixer::DeRegisterExternalMediaProcessing()");
144
145 rtc::CritScope cs(&_callbackCritSect);
146 _externalMedia = false;
147 _externalMediaCallbackPtr = NULL;
148
149 return 0;
150 }
151
152 int32_t AudioMixer::SetMixabilityStatus(MixerAudioSource& participant,
153 bool mixable) {
154 return _mixerModule.SetMixabilityStatus(&participant, mixable);
155 }
156
157 int32_t AudioMixer::SetAnonymousMixabilityStatus(MixerAudioSource& participant,
158 bool mixable) {
159 return _mixerModule.SetAnonymousMixabilityStatus(&participant, mixable);
160 }
161
162 int32_t AudioMixer::MixActiveChannels() {
163 _mixerModule.Mix(&_audioFrame);
164 return 0;
165 }
166
167 int AudioMixer::GetSpeechOutputLevel(uint32_t& level) {
168 int8_t currentLevel = _audioLevel.Level();
169 level = static_cast<uint32_t>(currentLevel);
170 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, -1),
171 "GetSpeechOutputLevel() => level=%u", level);
172 return 0;
173 }
174
175 int AudioMixer::GetSpeechOutputLevelFullRange(uint32_t& level) {
176 int16_t currentLevel = _audioLevel.LevelFullRange();
177 level = static_cast<uint32_t>(currentLevel);
178 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, -1),
179 "GetSpeechOutputLevelFullRange() => level=%u", level);
180 return 0;
181 }
182
183 int AudioMixer::SetOutputVolumePan(float left, float right) {
184 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
185 "AudioMixer::SetOutputVolumePan()");
186 _panLeft = left;
187 _panRight = right;
188 return 0;
189 }
190
191 int AudioMixer::GetOutputVolumePan(float& left, float& right) {
192 left = _panLeft;
193 right = _panRight;
194 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, -1),
195 "GetOutputVolumePan() => left=%2.1f, right=%2.1f", left, right);
196 return 0;
197 }
198
199 int AudioMixer::StartRecordingPlayout(const char* fileName,
200 const CodecInst* codecInst) {
201 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
202 "AudioMixer::StartRecordingPlayout(fileName=%s)", fileName);
203
204 if (_outputFileRecording) {
205 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
206 "StartRecordingPlayout() is already recording");
207 return 0;
208 }
209
210 FileFormats format;
211 const uint32_t notificationTime(0);
212 CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
213
214 if ((codecInst != NULL) &&
215 ((codecInst->channels < 1) || (codecInst->channels > 2))) {
216 _engineStatisticsPtr->SetLastError(
217 VE_BAD_ARGUMENT, kTraceError,
218 "StartRecordingPlayout() invalid compression");
219 return (-1);
220 }
221 if (codecInst == NULL) {
222 format = kFileFormatPcm16kHzFile;
223 codecInst = &dummyCodec;
224 } else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
225 (STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
226 (STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
227 format = kFileFormatWavFile;
228 } else {
229 format = kFileFormatCompressedFile;
230 }
231
232 rtc::CritScope cs(&_fileCritSect);
233
234 // Destroy the old instance
235 if (_outputFileRecorderPtr) {
236 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
237 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
238 _outputFileRecorderPtr = NULL;
239 }
240
241 _outputFileRecorderPtr =
242 FileRecorder::CreateFileRecorder(_instanceId, (const FileFormats)format);
243 if (_outputFileRecorderPtr == NULL) {
244 _engineStatisticsPtr->SetLastError(
245 VE_INVALID_ARGUMENT, kTraceError,
246 "StartRecordingPlayout() fileRecorder format isnot correct");
247 return -1;
248 }
249
250 if (_outputFileRecorderPtr->StartRecordingAudioFile(
251 fileName, (const CodecInst&)*codecInst, notificationTime) != 0) {
252 _engineStatisticsPtr->SetLastError(
253 VE_BAD_FILE, kTraceError,
254 "StartRecordingAudioFile() failed to start file recording");
255 _outputFileRecorderPtr->StopRecording();
256 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
257 _outputFileRecorderPtr = NULL;
258 return -1;
259 }
260 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
261 _outputFileRecording = true;
262
263 return 0;
264 }
265
266 int AudioMixer::StartRecordingPlayout(OutStream* stream,
267 const CodecInst* codecInst) {
268 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
269 "AudioMixer::StartRecordingPlayout()");
270
271 if (_outputFileRecording) {
272 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
273 "StartRecordingPlayout() is already recording");
274 return 0;
275 }
276
277 FileFormats format;
278 const uint32_t notificationTime(0);
279 CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
280
281 if (codecInst != NULL && codecInst->channels != 1) {
282 _engineStatisticsPtr->SetLastError(
283 VE_BAD_ARGUMENT, kTraceError,
284 "StartRecordingPlayout() invalid compression");
285 return (-1);
286 }
287 if (codecInst == NULL) {
288 format = kFileFormatPcm16kHzFile;
289 codecInst = &dummyCodec;
290 } else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
291 (STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
292 (STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
293 format = kFileFormatWavFile;
294 } else {
295 format = kFileFormatCompressedFile;
296 }
297
298 rtc::CritScope cs(&_fileCritSect);
299
300 // Destroy the old instance
301 if (_outputFileRecorderPtr) {
302 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
303 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
304 _outputFileRecorderPtr = NULL;
305 }
306
307 _outputFileRecorderPtr =
308 FileRecorder::CreateFileRecorder(_instanceId, (const FileFormats)format);
309 if (_outputFileRecorderPtr == NULL) {
310 _engineStatisticsPtr->SetLastError(
311 VE_INVALID_ARGUMENT, kTraceError,
312 "StartRecordingPlayout() fileRecorder format isnot correct");
313 return -1;
314 }
315
316 if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, *codecInst,
317 notificationTime) != 0) {
318 _engineStatisticsPtr->SetLastError(
319 VE_BAD_FILE, kTraceError,
320 "StartRecordingAudioFile() failed to start file recording");
321 _outputFileRecorderPtr->StopRecording();
322 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
323 _outputFileRecorderPtr = NULL;
324 return -1;
325 }
326
327 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
328 _outputFileRecording = true;
329
330 return 0;
331 }
332
333 int AudioMixer::StopRecordingPlayout() {
334 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
335 "AudioMixer::StopRecordingPlayout()");
336
337 if (!_outputFileRecording) {
338 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1),
339 "StopRecordingPlayout() file isnot recording");
340 return -1;
341 }
342
343 rtc::CritScope cs(&_fileCritSect);
344
345 if (_outputFileRecorderPtr->StopRecording() != 0) {
346 _engineStatisticsPtr->SetLastError(
347 VE_STOP_RECORDING_FAILED, kTraceError,
348 "StopRecording(), could not stop recording");
349 return -1;
350 }
351 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
352 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
353 _outputFileRecorderPtr = NULL;
354 _outputFileRecording = false;
355
356 return 0;
357 }
358
359 int AudioMixer::GetMixedAudio(int sample_rate_hz,
360 size_t num_channels,
361 AudioFrame* frame) {
362 WEBRTC_TRACE(
363 kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
364 "AudioMixer::GetMixedAudio(sample_rate_hz=%d, num_channels=%" PRIuS ")",
365 sample_rate_hz, num_channels);
366
367 // --- Record playout if enabled
368 {
369 rtc::CritScope cs(&_fileCritSect);
370 if (_outputFileRecording && _outputFileRecorderPtr)
371 _outputFileRecorderPtr->RecordAudioToFile(_audioFrame);
372 }
373
374 frame->num_channels_ = num_channels;
375 frame->sample_rate_hz_ = sample_rate_hz;
376 // TODO(andrew): Ideally the downmixing would occur much earlier, in
377 // AudioCodingModule.
378 RemixAndResample(_audioFrame, &resampler_, frame);
379 return 0;
380 }
381
382 int32_t AudioMixer::DoOperationsOnCombinedSignal(bool feed_data_to_apm) {
383 if (_audioFrame.sample_rate_hz_ != _mixingFrequencyHz) {
384 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, -1),
385 "AudioMixer::DoOperationsOnCombinedSignal() => "
386 "mixing frequency = %d",
387 _audioFrame.sample_rate_hz_);
388 _mixingFrequencyHz = _audioFrame.sample_rate_hz_;
389 }
390
391 // Scale left and/or right channel(s) if balance is active
392 if (_panLeft != 1.0 || _panRight != 1.0) {
393 if (_audioFrame.num_channels_ == 1) {
394 AudioFrameOperations::MonoToStereo(&_audioFrame);
395 } else {
396 // Pure stereo mode (we are receiving a stereo signal).
397 }
398
399 assert(_audioFrame.num_channels_ == 2);
400 AudioFrameOperations::Scale(_panLeft, _panRight, _audioFrame);
401 }
402
403 // --- Far-end Voice Quality Enhancement (AudioProcessing Module)
404 if (feed_data_to_apm) {
405 if (_audioProcessingModulePtr->ProcessReverseStream(&_audioFrame) != 0) {
406 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
407 "AudioProcessingModule::ProcessReverseStream() => error");
408 RTC_DCHECK(false);
409 }
410 }
411
412 // --- External media processing
413 {
414 rtc::CritScope cs(&_callbackCritSect);
415 if (_externalMedia) {
416 const bool is_stereo = (_audioFrame.num_channels_ == 2);
417 if (_externalMediaCallbackPtr) {
418 _externalMediaCallbackPtr->Process(
419 -1, kPlaybackAllChannelsMixed,
420 reinterpret_cast<int16_t*>(_audioFrame.data_),
421 _audioFrame.samples_per_channel_, _audioFrame.sample_rate_hz_,
422 is_stereo);
423 }
424 }
425 }
426
427 // --- Measure audio level (0-9) for the combined signal
428 _audioLevel.ComputeLevel(_audioFrame);
429
430 return 0;
431 }
432 } // namespace voe
433 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698