OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/voice_engine/output_mixer.h" | 11 #include "webrtc/voice_engine/output_mixer.h" |
12 | 12 |
13 #include "webrtc/base/format_macros.h" | 13 #include "webrtc/base/format_macros.h" |
14 #include "webrtc/modules/audio_processing/include/audio_processing.h" | 14 #include "webrtc/modules/audio_processing/include/audio_processing.h" |
15 #include "webrtc/modules/utility/include/audio_frame_operations.h" | 15 #include "webrtc/modules/utility/include/audio_frame_operations.h" |
16 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | |
17 #include "webrtc/system_wrappers/include/file_wrapper.h" | 16 #include "webrtc/system_wrappers/include/file_wrapper.h" |
18 #include "webrtc/system_wrappers/include/trace.h" | 17 #include "webrtc/system_wrappers/include/trace.h" |
19 #include "webrtc/voice_engine/include/voe_external_media.h" | 18 #include "webrtc/voice_engine/include/voe_external_media.h" |
20 #include "webrtc/voice_engine/statistics.h" | 19 #include "webrtc/voice_engine/statistics.h" |
21 #include "webrtc/voice_engine/utility.h" | 20 #include "webrtc/voice_engine/utility.h" |
22 | 21 |
23 namespace webrtc { | 22 namespace webrtc { |
24 namespace voe { | 23 namespace voe { |
25 | 24 |
26 void | 25 void |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 | 60 |
62 // not needed | 61 // not needed |
63 } | 62 } |
64 | 63 |
65 void OutputMixer::RecordFileEnded(int32_t id) | 64 void OutputMixer::RecordFileEnded(int32_t id) |
66 { | 65 { |
67 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1), | 66 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,-1), |
68 "OutputMixer::RecordFileEnded(id=%d)", id); | 67 "OutputMixer::RecordFileEnded(id=%d)", id); |
69 assert(id == _instanceId); | 68 assert(id == _instanceId); |
70 | 69 |
71 CriticalSectionScoped cs(&_fileCritSect); | 70 rtc::CritScope cs(&_fileCritSect); |
72 _outputFileRecording = false; | 71 _outputFileRecording = false; |
73 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), | 72 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1), |
74 "OutputMixer::RecordFileEnded() =>" | 73 "OutputMixer::RecordFileEnded() =>" |
75 "output file recorder module is shutdown"); | 74 "output file recorder module is shutdown"); |
76 } | 75 } |
77 | 76 |
78 int32_t | 77 int32_t |
79 OutputMixer::Create(OutputMixer*& mixer, uint32_t instanceId) | 78 OutputMixer::Create(OutputMixer*& mixer, uint32_t instanceId) |
80 { | 79 { |
81 WEBRTC_TRACE(kTraceMemory, kTraceVoice, instanceId, | 80 WEBRTC_TRACE(kTraceMemory, kTraceVoice, instanceId, |
82 "OutputMixer::Create(instanceId=%d)", instanceId); | 81 "OutputMixer::Create(instanceId=%d)", instanceId); |
83 mixer = new OutputMixer(instanceId); | 82 mixer = new OutputMixer(instanceId); |
84 if (mixer == NULL) | 83 if (mixer == NULL) |
85 { | 84 { |
86 WEBRTC_TRACE(kTraceMemory, kTraceVoice, instanceId, | 85 WEBRTC_TRACE(kTraceMemory, kTraceVoice, instanceId, |
87 "OutputMixer::Create() unable to allocate memory for" | 86 "OutputMixer::Create() unable to allocate memory for" |
88 "mixer"); | 87 "mixer"); |
89 return -1; | 88 return -1; |
90 } | 89 } |
91 return 0; | 90 return 0; |
92 } | 91 } |
93 | 92 |
94 OutputMixer::OutputMixer(uint32_t instanceId) : | 93 OutputMixer::OutputMixer(uint32_t instanceId) : |
95 _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()), | |
96 _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()), | |
97 _mixerModule(*AudioConferenceMixer::Create(instanceId)), | 94 _mixerModule(*AudioConferenceMixer::Create(instanceId)), |
98 _audioLevel(), | 95 _audioLevel(), |
99 _dtmfGenerator(instanceId), | 96 _dtmfGenerator(instanceId), |
100 _instanceId(instanceId), | 97 _instanceId(instanceId), |
101 _externalMediaCallbackPtr(NULL), | 98 _externalMediaCallbackPtr(NULL), |
102 _externalMedia(false), | 99 _externalMedia(false), |
103 _panLeft(1.0f), | 100 _panLeft(1.0f), |
104 _panRight(1.0f), | 101 _panRight(1.0f), |
105 _mixingFrequencyHz(8000), | 102 _mixingFrequencyHz(8000), |
106 _outputFileRecorderPtr(NULL), | 103 _outputFileRecorderPtr(NULL), |
(...skipping 24 matching lines...) Expand all Loading... |
131 | 128 |
132 OutputMixer::~OutputMixer() | 129 OutputMixer::~OutputMixer() |
133 { | 130 { |
134 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,-1), | 131 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,-1), |
135 "OutputMixer::~OutputMixer() - dtor"); | 132 "OutputMixer::~OutputMixer() - dtor"); |
136 if (_externalMedia) | 133 if (_externalMedia) |
137 { | 134 { |
138 DeRegisterExternalMediaProcessing(); | 135 DeRegisterExternalMediaProcessing(); |
139 } | 136 } |
140 { | 137 { |
141 CriticalSectionScoped cs(&_fileCritSect); | 138 rtc::CritScope cs(&_fileCritSect); |
142 if (_outputFileRecorderPtr) | 139 if (_outputFileRecorderPtr) |
143 { | 140 { |
144 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); | 141 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); |
145 _outputFileRecorderPtr->StopRecording(); | 142 _outputFileRecorderPtr->StopRecording(); |
146 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); | 143 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); |
147 _outputFileRecorderPtr = NULL; | 144 _outputFileRecorderPtr = NULL; |
148 } | 145 } |
149 } | 146 } |
150 _mixerModule.UnRegisterMixedStreamCallback(); | 147 _mixerModule.UnRegisterMixedStreamCallback(); |
151 delete &_mixerModule; | 148 delete &_mixerModule; |
152 delete &_callbackCritSect; | |
153 delete &_fileCritSect; | |
154 } | 149 } |
155 | 150 |
156 int32_t | 151 int32_t |
157 OutputMixer::SetEngineInformation(voe::Statistics& engineStatistics) | 152 OutputMixer::SetEngineInformation(voe::Statistics& engineStatistics) |
158 { | 153 { |
159 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), | 154 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), |
160 "OutputMixer::SetEngineInformation()"); | 155 "OutputMixer::SetEngineInformation()"); |
161 _engineStatisticsPtr = &engineStatistics; | 156 _engineStatisticsPtr = &engineStatistics; |
162 return 0; | 157 return 0; |
163 } | 158 } |
164 | 159 |
165 int32_t | 160 int32_t |
166 OutputMixer::SetAudioProcessingModule(AudioProcessing* audioProcessingModule) | 161 OutputMixer::SetAudioProcessingModule(AudioProcessing* audioProcessingModule) |
167 { | 162 { |
168 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), | 163 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), |
169 "OutputMixer::SetAudioProcessingModule(" | 164 "OutputMixer::SetAudioProcessingModule(" |
170 "audioProcessingModule=0x%x)", audioProcessingModule); | 165 "audioProcessingModule=0x%x)", audioProcessingModule); |
171 _audioProcessingModulePtr = audioProcessingModule; | 166 _audioProcessingModulePtr = audioProcessingModule; |
172 return 0; | 167 return 0; |
173 } | 168 } |
174 | 169 |
175 int OutputMixer::RegisterExternalMediaProcessing( | 170 int OutputMixer::RegisterExternalMediaProcessing( |
176 VoEMediaProcess& proccess_object) | 171 VoEMediaProcess& proccess_object) |
177 { | 172 { |
178 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), | 173 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), |
179 "OutputMixer::RegisterExternalMediaProcessing()"); | 174 "OutputMixer::RegisterExternalMediaProcessing()"); |
180 | 175 |
181 CriticalSectionScoped cs(&_callbackCritSect); | 176 rtc::CritScope cs(&_callbackCritSect); |
182 _externalMediaCallbackPtr = &proccess_object; | 177 _externalMediaCallbackPtr = &proccess_object; |
183 _externalMedia = true; | 178 _externalMedia = true; |
184 | 179 |
185 return 0; | 180 return 0; |
186 } | 181 } |
187 | 182 |
188 int OutputMixer::DeRegisterExternalMediaProcessing() | 183 int OutputMixer::DeRegisterExternalMediaProcessing() |
189 { | 184 { |
190 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), | 185 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), |
191 "OutputMixer::DeRegisterExternalMediaProcessing()"); | 186 "OutputMixer::DeRegisterExternalMediaProcessing()"); |
192 | 187 |
193 CriticalSectionScoped cs(&_callbackCritSect); | 188 rtc::CritScope cs(&_callbackCritSect); |
194 _externalMedia = false; | 189 _externalMedia = false; |
195 _externalMediaCallbackPtr = NULL; | 190 _externalMediaCallbackPtr = NULL; |
196 | 191 |
197 return 0; | 192 return 0; |
198 } | 193 } |
199 | 194 |
200 int OutputMixer::PlayDtmfTone(uint8_t eventCode, int lengthMs, | 195 int OutputMixer::PlayDtmfTone(uint8_t eventCode, int lengthMs, |
201 int attenuationDb) | 196 int attenuationDb) |
202 { | 197 { |
203 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1), | 198 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1), |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) || | 302 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) || |
308 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0)) | 303 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0)) |
309 { | 304 { |
310 format = kFileFormatWavFile; | 305 format = kFileFormatWavFile; |
311 } | 306 } |
312 else | 307 else |
313 { | 308 { |
314 format = kFileFormatCompressedFile; | 309 format = kFileFormatCompressedFile; |
315 } | 310 } |
316 | 311 |
317 CriticalSectionScoped cs(&_fileCritSect); | 312 rtc::CritScope cs(&_fileCritSect); |
318 | 313 |
319 // Destroy the old instance | 314 // Destroy the old instance |
320 if (_outputFileRecorderPtr) | 315 if (_outputFileRecorderPtr) |
321 { | 316 { |
322 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); | 317 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); |
323 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); | 318 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); |
324 _outputFileRecorderPtr = NULL; | 319 _outputFileRecorderPtr = NULL; |
325 } | 320 } |
326 | 321 |
327 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder( | 322 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder( |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) || | 382 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) || |
388 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0)) | 383 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0)) |
389 { | 384 { |
390 format = kFileFormatWavFile; | 385 format = kFileFormatWavFile; |
391 } | 386 } |
392 else | 387 else |
393 { | 388 { |
394 format = kFileFormatCompressedFile; | 389 format = kFileFormatCompressedFile; |
395 } | 390 } |
396 | 391 |
397 CriticalSectionScoped cs(&_fileCritSect); | 392 rtc::CritScope cs(&_fileCritSect); |
398 | 393 |
399 // Destroy the old instance | 394 // Destroy the old instance |
400 if (_outputFileRecorderPtr) | 395 if (_outputFileRecorderPtr) |
401 { | 396 { |
402 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); | 397 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); |
403 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); | 398 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); |
404 _outputFileRecorderPtr = NULL; | 399 _outputFileRecorderPtr = NULL; |
405 } | 400 } |
406 | 401 |
407 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder( | 402 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder( |
(...skipping 30 matching lines...) Expand all Loading... |
438 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), | 433 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), |
439 "OutputMixer::StopRecordingPlayout()"); | 434 "OutputMixer::StopRecordingPlayout()"); |
440 | 435 |
441 if (!_outputFileRecording) | 436 if (!_outputFileRecording) |
442 { | 437 { |
443 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1), | 438 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1), |
444 "StopRecordingPlayout() file isnot recording"); | 439 "StopRecordingPlayout() file isnot recording"); |
445 return -1; | 440 return -1; |
446 } | 441 } |
447 | 442 |
448 CriticalSectionScoped cs(&_fileCritSect); | 443 rtc::CritScope cs(&_fileCritSect); |
449 | 444 |
450 if (_outputFileRecorderPtr->StopRecording() != 0) | 445 if (_outputFileRecorderPtr->StopRecording() != 0) |
451 { | 446 { |
452 _engineStatisticsPtr->SetLastError( | 447 _engineStatisticsPtr->SetLastError( |
453 VE_STOP_RECORDING_FAILED, kTraceError, | 448 VE_STOP_RECORDING_FAILED, kTraceError, |
454 "StopRecording(), could not stop recording"); | 449 "StopRecording(), could not stop recording"); |
455 return -1; | 450 return -1; |
456 } | 451 } |
457 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); | 452 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); |
458 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); | 453 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); |
459 _outputFileRecorderPtr = NULL; | 454 _outputFileRecorderPtr = NULL; |
460 _outputFileRecording = false; | 455 _outputFileRecording = false; |
461 | 456 |
462 return 0; | 457 return 0; |
463 } | 458 } |
464 | 459 |
465 int OutputMixer::GetMixedAudio(int sample_rate_hz, | 460 int OutputMixer::GetMixedAudio(int sample_rate_hz, |
466 size_t num_channels, | 461 size_t num_channels, |
467 AudioFrame* frame) { | 462 AudioFrame* frame) { |
468 WEBRTC_TRACE( | 463 WEBRTC_TRACE( |
469 kTraceStream, kTraceVoice, VoEId(_instanceId,-1), | 464 kTraceStream, kTraceVoice, VoEId(_instanceId,-1), |
470 "OutputMixer::GetMixedAudio(sample_rate_hz=%d, num_channels=%" PRIuS ")", | 465 "OutputMixer::GetMixedAudio(sample_rate_hz=%d, num_channels=%" PRIuS ")", |
471 sample_rate_hz, num_channels); | 466 sample_rate_hz, num_channels); |
472 | 467 |
473 // --- Record playout if enabled | 468 // --- Record playout if enabled |
474 { | 469 { |
475 CriticalSectionScoped cs(&_fileCritSect); | 470 rtc::CritScope cs(&_fileCritSect); |
476 if (_outputFileRecording && _outputFileRecorderPtr) | 471 if (_outputFileRecording && _outputFileRecorderPtr) |
477 _outputFileRecorderPtr->RecordAudioToFile(_audioFrame); | 472 _outputFileRecorderPtr->RecordAudioToFile(_audioFrame); |
478 } | 473 } |
479 | 474 |
480 frame->num_channels_ = num_channels; | 475 frame->num_channels_ = num_channels; |
481 frame->sample_rate_hz_ = sample_rate_hz; | 476 frame->sample_rate_hz_ = sample_rate_hz; |
482 // TODO(andrew): Ideally the downmixing would occur much earlier, in | 477 // TODO(andrew): Ideally the downmixing would occur much earlier, in |
483 // AudioCodingModule. | 478 // AudioCodingModule. |
484 RemixAndResample(_audioFrame, &resampler_, frame); | 479 RemixAndResample(_audioFrame, &resampler_, frame); |
485 return 0; | 480 return 0; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 | 524 |
530 if (_audioProcessingModulePtr->AnalyzeReverseStream(&frame) != 0) { | 525 if (_audioProcessingModulePtr->AnalyzeReverseStream(&frame) != 0) { |
531 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1), | 526 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1), |
532 "AudioProcessingModule::AnalyzeReverseStream() => error"); | 527 "AudioProcessingModule::AnalyzeReverseStream() => error"); |
533 RTC_DCHECK(false); | 528 RTC_DCHECK(false); |
534 } | 529 } |
535 } | 530 } |
536 | 531 |
537 // --- External media processing | 532 // --- External media processing |
538 { | 533 { |
539 CriticalSectionScoped cs(&_callbackCritSect); | 534 rtc::CritScope cs(&_callbackCritSect); |
540 if (_externalMedia) | 535 if (_externalMedia) |
541 { | 536 { |
542 const bool is_stereo = (_audioFrame.num_channels_ == 2); | 537 const bool is_stereo = (_audioFrame.num_channels_ == 2); |
543 if (_externalMediaCallbackPtr) | 538 if (_externalMediaCallbackPtr) |
544 { | 539 { |
545 _externalMediaCallbackPtr->Process( | 540 _externalMediaCallbackPtr->Process( |
546 -1, | 541 -1, |
547 kPlaybackAllChannelsMixed, | 542 kPlaybackAllChannelsMixed, |
548 (int16_t*)_audioFrame.data_, | 543 (int16_t*)_audioFrame.data_, |
549 _audioFrame.samples_per_channel_, | 544 _audioFrame.samples_per_channel_, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 _audioFrame.data_[2 * i + 1] = 0; | 597 _audioFrame.data_[2 * i + 1] = 0; |
603 } | 598 } |
604 } | 599 } |
605 assert(_audioFrame.samples_per_channel_ == toneSamples); | 600 assert(_audioFrame.samples_per_channel_ == toneSamples); |
606 | 601 |
607 return 0; | 602 return 0; |
608 } | 603 } |
609 | 604 |
610 } // namespace voe | 605 } // namespace voe |
611 } // namespace webrtc | 606 } // namespace webrtc |
OLD | NEW |