Add external media hook for preprocessed audio.

Review URL: https://webrtc-codereview.appspot.com/879007

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2960 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
andrew@webrtc.org 2012-10-19 17:30:56 +00:00
parent 9a5b904cbe
commit 21ab3ba8f8
6 changed files with 125 additions and 48 deletions

View File

@ -131,7 +131,8 @@ enum ProcessingTypes
kPlaybackPerChannel = 0,
kPlaybackAllChannelsMixed,
kRecordingPerChannel,
kRecordingAllChannelsMixed
kRecordingAllChannelsMixed,
kRecordingPreprocessing
};
// Encryption enums

View File

@ -202,8 +202,8 @@ TransmitMixer::TransmitMixer(const WebRtc_UWord32 instanceId) :
_instanceId(instanceId),
_mixFileWithMicrophone(false),
_captureLevel(0),
_externalMedia(false),
_externalMediaCallbackPtr(NULL),
external_postproc_ptr_(NULL),
external_preproc_ptr_(NULL),
_mute(false),
_remainingMuteMicTimeMs(0),
_mixingFrequency(0),
@ -223,10 +223,8 @@ TransmitMixer::~TransmitMixer()
{
_processThreadPtr->DeRegisterModule(&_monitorModule);
}
if (_externalMedia)
{
DeRegisterExternalMediaProcessing();
}
DeRegisterExternalMediaProcessing(kRecordingAllChannelsMixed);
DeRegisterExternalMediaProcessing(kRecordingPreprocessing);
{
CriticalSectionScoped cs(&_critSect);
if (_fileRecorderPtr)
@ -362,6 +360,17 @@ TransmitMixer::PrepareDemux(const void* audioSamples,
return -1;
}
{
CriticalSectionScoped cs(&_callbackCritSect);
if (external_preproc_ptr_) {
external_preproc_ptr_->Process(-1, kRecordingPreprocessing,
_audioFrame.data_,
_audioFrame.samples_per_channel_,
_audioFrame.sample_rate_hz_,
_audioFrame.num_channels_ == 2);
}
}
// --- Near-end Voice Quality Enhancement (APM) processing
APMProcessStream(totalDelayMS, clockDrift, currentMicLevel);
@ -413,22 +422,15 @@ TransmitMixer::PrepareDemux(const void* audioSamples,
RecordAudioToFile(_mixingFrequency);
}
// --- External media processing
if (_externalMedia)
{
CriticalSectionScoped cs(&_callbackCritSect);
const bool isStereo = (_audioFrame.num_channels_ == 2);
if (_externalMediaCallbackPtr)
{
_externalMediaCallbackPtr->Process(
-1,
kRecordingAllChannelsMixed,
(WebRtc_Word16*) _audioFrame.data_,
_audioFrame.samples_per_channel_,
_audioFrame.sample_rate_hz_,
isStereo);
}
CriticalSectionScoped cs(&_callbackCritSect);
if (external_postproc_ptr_) {
external_postproc_ptr_->Process(-1, kRecordingAllChannelsMixed,
_audioFrame.data_,
_audioFrame.samples_per_channel_,
_audioFrame.sample_rate_hz_,
_audioFrame.num_channels_ == 2);
}
}
return 0;
@ -1095,28 +1097,40 @@ TransmitMixer::SetMixWithMicStatus(bool mix)
}
int TransmitMixer::RegisterExternalMediaProcessing(
VoEMediaProcess& proccess_object)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::RegisterExternalMediaProcessing()");
VoEMediaProcess* object,
ProcessingTypes type) {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::RegisterExternalMediaProcessing()");
CriticalSectionScoped cs(&_callbackCritSect);
_externalMediaCallbackPtr = &proccess_object;
_externalMedia = true;
CriticalSectionScoped cs(&_callbackCritSect);
if (!object) {
return -1;
}
return 0;
// Store the callback object according to the processing type.
if (type == kRecordingAllChannelsMixed) {
external_postproc_ptr_ = object;
} else if (type == kRecordingPreprocessing) {
external_preproc_ptr_ = object;
} else {
return -1;
}
return 0;
}
int TransmitMixer::DeRegisterExternalMediaProcessing()
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::DeRegisterExternalMediaProcessing()");
int TransmitMixer::DeRegisterExternalMediaProcessing(ProcessingTypes type) {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::DeRegisterExternalMediaProcessing()");
CriticalSectionScoped cs(&_callbackCritSect);
_externalMedia = false;
_externalMediaCallbackPtr = NULL;
return 0;
CriticalSectionScoped cs(&_callbackCritSect);
if (type == kRecordingAllChannelsMixed) {
external_postproc_ptr_ = NULL;
} else if (type == kRecordingPreprocessing) {
external_preproc_ptr_ = NULL;
} else {
return -1;
}
return 0;
}
int

View File

@ -73,9 +73,9 @@ public:
void UpdateMuteMicrophoneTime(const WebRtc_UWord32 lengthMs);
// VoEExternalMedia
int RegisterExternalMediaProcessing(VoEMediaProcess& proccess_object);
int DeRegisterExternalMediaProcessing();
int RegisterExternalMediaProcessing(VoEMediaProcess* object,
ProcessingTypes type);
int DeRegisterExternalMediaProcessing(ProcessingTypes type);
int GetMixingFrequency();
@ -193,8 +193,8 @@ private:
// owns
MonitorModule _monitorModule;
AudioFrame _audioFrame;
Resampler _audioResampler; // ADM sample rate -> mixing rate
FilePlayer* _filePlayerPtr;
Resampler _audioResampler; // ADM sample rate -> mixing rate
FilePlayer* _filePlayerPtr;
FileRecorder* _fileRecorderPtr;
FileRecorder* _fileCallRecorderPtr;
int _filePlayerId;
@ -228,8 +228,8 @@ private:
int _instanceId;
bool _mixFileWithMicrophone;
WebRtc_UWord32 _captureLevel;
bool _externalMedia;
VoEMediaProcess* _externalMediaCallbackPtr;
VoEMediaProcess* external_postproc_ptr_;
VoEMediaProcess* external_preproc_ptr_;
bool _mute;
WebRtc_Word32 _remainingMuteMicTimeMs;
int _mixingFrequency;

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "voice_engine/transmit_mixer.h"
#include "gtest/gtest.h"
#include "voice_engine/include/voe_external_media.h"
namespace webrtc {
namespace voe {
namespace {
class MediaCallback : public VoEMediaProcess {
public:
virtual void Process(const int channel, const ProcessingTypes type,
int16_t audio[], const int samples_per_channel,
const int sample_rate_hz, const bool is_stereo) {
}
};
// TODO(andrew): Mock VoEMediaProcess, and verify the behavior when calling
// PrepareDemux().
TEST(TransmitMixerTest, RegisterExternalMediaCallback) {
TransmitMixer* tm = NULL;
ASSERT_EQ(0, TransmitMixer::Create(tm, 0));
ASSERT_TRUE(tm != NULL);
MediaCallback callback;
EXPECT_EQ(-1, tm->RegisterExternalMediaProcessing(NULL,
kRecordingPreprocessing));
EXPECT_EQ(-1, tm->RegisterExternalMediaProcessing(&callback,
kPlaybackPerChannel));
EXPECT_EQ(-1, tm->RegisterExternalMediaProcessing(&callback,
kPlaybackAllChannelsMixed));
EXPECT_EQ(-1, tm->RegisterExternalMediaProcessing(&callback,
kRecordingPerChannel));
EXPECT_EQ(0, tm->RegisterExternalMediaProcessing(&callback,
kRecordingAllChannelsMixed));
EXPECT_EQ(0, tm->RegisterExternalMediaProcessing(&callback,
kRecordingPreprocessing));
EXPECT_EQ(-1, tm->DeRegisterExternalMediaProcessing(kPlaybackPerChannel));
EXPECT_EQ(-1, tm->DeRegisterExternalMediaProcessing(
kPlaybackAllChannelsMixed));
EXPECT_EQ(-1, tm->DeRegisterExternalMediaProcessing(kRecordingPerChannel));
EXPECT_EQ(0, tm->DeRegisterExternalMediaProcessing(
kRecordingAllChannelsMixed));
EXPECT_EQ(0, tm->DeRegisterExternalMediaProcessing(kRecordingPreprocessing));
TransmitMixer::Destroy(tm);
}
} // namespace
} // namespace voe
} // namespace webrtc

View File

@ -88,9 +88,10 @@ int VoEExternalMediaImpl::RegisterExternalMediaProcessing(
processObject);
}
case kRecordingAllChannelsMixed:
case kRecordingPreprocessing:
{
return shared_->transmit_mixer()->RegisterExternalMediaProcessing(
processObject);
&processObject, type);
}
}
return -1;
@ -131,9 +132,10 @@ int VoEExternalMediaImpl::DeRegisterExternalMediaProcessing(
DeRegisterExternalMediaProcessing();
}
case kRecordingAllChannelsMixed:
case kRecordingPreprocessing:
{
return shared_->transmit_mixer()->
DeRegisterExternalMediaProcessing();
DeRegisterExternalMediaProcessing(type);
}
}
return -1;

View File

@ -144,6 +144,7 @@
'sources': [
'channel_unittest.cc',
'output_mixer_unittest.cc',
'transmit_mixer_unittest.cc',
'voe_audio_processing_unittest.cc',
],
},