| 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 |