Add GetAudioFrame API to VoiceEngine.
Allows the caller to pull frames from a channel instead of sending them to the output mixer. BUG= Review URL: https://webrtc-codereview.appspot.com/973012 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3273 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
b718619f0a
commit
1b60ceb499
@ -1133,6 +1133,7 @@ Channel::Channel(const WebRtc_Word32 channelId,
|
||||
_rtcpObserverPtr(NULL),
|
||||
_outputIsOnHold(false),
|
||||
_externalPlayout(false),
|
||||
_externalMixing(false),
|
||||
_inputIsOnHold(false),
|
||||
_playing(false),
|
||||
_sending(false),
|
||||
@ -1601,13 +1602,16 @@ Channel::StartPlayout()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// Add participant as candidates for mixing.
|
||||
if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0)
|
||||
{
|
||||
_engineStatisticsPtr->SetLastError(
|
||||
VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
|
||||
"StartPlayout() failed to add participant to mixer");
|
||||
return -1;
|
||||
|
||||
if (!_externalMixing) {
|
||||
// Add participant as candidates for mixing.
|
||||
if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0)
|
||||
{
|
||||
_engineStatisticsPtr->SetLastError(
|
||||
VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
|
||||
"StartPlayout() failed to add participant to mixer");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_playing = true;
|
||||
@ -1627,13 +1631,16 @@ Channel::StopPlayout()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// Remove participant as candidates for mixing
|
||||
if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0)
|
||||
{
|
||||
_engineStatisticsPtr->SetLastError(
|
||||
VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
|
||||
"StartPlayout() failed to remove participant from mixer");
|
||||
return -1;
|
||||
|
||||
if (!_externalMixing) {
|
||||
// Remove participant as candidates for mixing
|
||||
if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0)
|
||||
{
|
||||
_engineStatisticsPtr->SetLastError(
|
||||
VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
|
||||
"StopPlayout() failed to remove participant from mixer");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_playing = false;
|
||||
@ -5981,6 +5988,24 @@ int Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Channel::SetExternalMixing(bool enabled) {
|
||||
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
|
||||
"Channel::SetExternalMixing(enabled=%d)", enabled);
|
||||
|
||||
if (_playing)
|
||||
{
|
||||
_engineStatisticsPtr->SetLastError(
|
||||
VE_INVALID_OPERATION, kTraceError,
|
||||
"Channel::SetExternalMixing() "
|
||||
"external mixing cannot be changed while playing.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
_externalMixing = enabled;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Channel::ResetRTCPStatistics()
|
||||
{
|
||||
|
||||
@ -231,6 +231,7 @@ public:
|
||||
int RegisterExternalMediaProcessing(ProcessingTypes type,
|
||||
VoEMediaProcess& processObject);
|
||||
int DeRegisterExternalMediaProcessing(ProcessingTypes type);
|
||||
int SetExternalMixing(bool enabled);
|
||||
|
||||
// VoEVolumeControl
|
||||
int GetSpeechOutputLevel(WebRtc_UWord32& level) const;
|
||||
@ -494,6 +495,10 @@ public:
|
||||
{
|
||||
return _externalTransport;
|
||||
}
|
||||
bool ExternalMixing() const
|
||||
{
|
||||
return _externalMixing;
|
||||
}
|
||||
bool OutputIsOnHold() const
|
||||
{
|
||||
return _outputIsOnHold;
|
||||
@ -611,6 +616,7 @@ private:
|
||||
// VoEBase
|
||||
bool _outputIsOnHold;
|
||||
bool _externalPlayout;
|
||||
bool _externalMixing;
|
||||
bool _inputIsOnHold;
|
||||
bool _playing;
|
||||
bool _sending;
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
namespace webrtc {
|
||||
|
||||
class VoiceEngine;
|
||||
class AudioFrame;
|
||||
|
||||
class WEBRTC_DLLEXPORT VoEMediaProcess
|
||||
{
|
||||
@ -104,6 +105,16 @@ public:
|
||||
WebRtc_Word16 speechData10ms[], int samplingFreqHz,
|
||||
int current_delay_ms, int& lengthSamples) = 0;
|
||||
|
||||
// Pulls an audio frame from the specified |channel| for external mixing.
|
||||
// If the |desired_sample_rate_hz| is 0, the signal will be returned with
|
||||
// its native frequency, otherwise it will be resampled. Valid frequencies
|
||||
// are 16, 22, 32, 44 or 48 kHz.
|
||||
virtual int GetAudioFrame(int channel, int desired_sample_rate_hz,
|
||||
AudioFrame* frame) = 0;
|
||||
|
||||
// Sets the state of external mixing. Cannot be changed during playback.
|
||||
virtual int SetExternalMixing(int channel, bool enable) = 0;
|
||||
|
||||
protected:
|
||||
VoEExternalMedia() {}
|
||||
virtual ~VoEExternalMedia() {}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "modules/interface/module_common_types.h"
|
||||
#include "voice_engine/include/voe_external_media.h"
|
||||
#include "voice_engine/test/auto_test/fakes/fake_media_process.h"
|
||||
#include "voice_engine/test/auto_test/fixtures/after_streaming_fixture.h"
|
||||
@ -82,3 +83,80 @@ TEST_F(ExternalMediaTest,
|
||||
TEST_LOG("Speak and verify your voice is distorted.\n");
|
||||
TestRegisterExternalMedia(-1, webrtc::kRecordingAllChannelsMixed);
|
||||
}
|
||||
|
||||
TEST_F(ExternalMediaTest,
|
||||
ExternalMixingCannotBeChangedDuringPlayback) {
|
||||
EXPECT_EQ(-1, voe_xmedia_->SetExternalMixing(channel_, true));
|
||||
EXPECT_EQ(-1, voe_xmedia_->SetExternalMixing(channel_, false));
|
||||
}
|
||||
|
||||
TEST_F(ExternalMediaTest,
|
||||
ExternalMixingIsRequiredForGetAudioFrame) {
|
||||
webrtc::AudioFrame frame;
|
||||
EXPECT_EQ(-1, voe_xmedia_->GetAudioFrame(channel_, 0, &frame));
|
||||
}
|
||||
|
||||
TEST_F(ExternalMediaTest,
|
||||
ExternalMixingPreventsAndRestoresRegularPlayback) {
|
||||
PausePlaying();
|
||||
ASSERT_EQ(0, voe_xmedia_->SetExternalMixing(channel_, true));
|
||||
TEST_LOG("Verify that no sound is played out.\n");
|
||||
ResumePlaying();
|
||||
Sleep(1000);
|
||||
PausePlaying();
|
||||
ASSERT_EQ(0, voe_xmedia_->SetExternalMixing(channel_, false));
|
||||
ResumePlaying();
|
||||
TEST_LOG("Verify that sound is played out.\n");
|
||||
ResumePlaying();
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
TEST_F(ExternalMediaTest,
|
||||
ExternalMixingWorks) {
|
||||
webrtc::AudioFrame frame;
|
||||
PausePlaying();
|
||||
EXPECT_EQ(0, voe_xmedia_->SetExternalMixing(channel_, true));
|
||||
ResumePlaying();
|
||||
EXPECT_EQ(0, voe_xmedia_->GetAudioFrame(channel_, 0, &frame));
|
||||
EXPECT_LT(0, frame.sample_rate_hz_);
|
||||
EXPECT_LT(0, frame.samples_per_channel_);
|
||||
PausePlaying();
|
||||
EXPECT_EQ(0, voe_xmedia_->SetExternalMixing(channel_, false));
|
||||
ResumePlaying();
|
||||
}
|
||||
|
||||
TEST_F(ExternalMediaTest,
|
||||
ExternalMixingResamplesToDesiredFrequency) {
|
||||
const int kValidFrequencies[] = {8000, 16000, 22000, 32000, 48000};
|
||||
webrtc::AudioFrame frame;
|
||||
PausePlaying();
|
||||
EXPECT_EQ(0, voe_xmedia_->SetExternalMixing(channel_, true));
|
||||
ResumePlaying();
|
||||
for (size_t i = 0; i < sizeof(kValidFrequencies) / sizeof(int); i++) {
|
||||
int f = kValidFrequencies[i];
|
||||
EXPECT_EQ(0, voe_xmedia_->GetAudioFrame(channel_, f, &frame))
|
||||
<< "Resampling succeeds for freq=" << f;
|
||||
EXPECT_EQ(f, frame.sample_rate_hz_);
|
||||
EXPECT_EQ(f / 100, frame.samples_per_channel_);
|
||||
}
|
||||
PausePlaying();
|
||||
EXPECT_EQ(0, voe_xmedia_->SetExternalMixing(channel_, false));
|
||||
ResumePlaying();
|
||||
}
|
||||
|
||||
TEST_F(ExternalMediaTest,
|
||||
ExternalMixingResamplingToInvalidFrequenciesFails) {
|
||||
const int kInvalidFrequencies[] = {-8000, -1, 1, 1000, 8001, 16001};
|
||||
webrtc::AudioFrame frame;
|
||||
PausePlaying();
|
||||
EXPECT_EQ(0, voe_xmedia_->SetExternalMixing(channel_, true));
|
||||
ResumePlaying();
|
||||
for (size_t i = 0; i < sizeof(kInvalidFrequencies) / sizeof(int); i++) {
|
||||
int f = kInvalidFrequencies[i];
|
||||
EXPECT_EQ(-1, voe_xmedia_->GetAudioFrame(channel_, f, &frame))
|
||||
<< "Resampling fails for freq=" << f;
|
||||
}
|
||||
PausePlaying();
|
||||
EXPECT_EQ(0, voe_xmedia_->SetExternalMixing(channel_, false));
|
||||
ResumePlaying();
|
||||
}
|
||||
|
||||
@ -346,6 +346,66 @@ int VoEExternalMediaImpl::ExternalPlayoutGetData(
|
||||
#endif
|
||||
}
|
||||
|
||||
int VoEExternalMediaImpl::GetAudioFrame(int channel, int desired_sample_rate_hz,
|
||||
AudioFrame* frame) {
|
||||
WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
|
||||
VoEId(shared_->instance_id(), channel),
|
||||
"GetAudioFrame(channel=%d, desired_sample_rate_hz=%d)",
|
||||
channel, desired_sample_rate_hz);
|
||||
if (!shared_->statistics().Initialized())
|
||||
{
|
||||
shared_->SetLastError(VE_NOT_INITED, kTraceError);
|
||||
return -1;
|
||||
}
|
||||
voe::ScopedChannel sc(shared_->channel_manager(), channel);
|
||||
voe::Channel* channelPtr = sc.ChannelPtr();
|
||||
if (channelPtr == NULL)
|
||||
{
|
||||
shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
|
||||
"GetAudioFrame() failed to locate channel");
|
||||
return -1;
|
||||
}
|
||||
if (!channelPtr->ExternalMixing()) {
|
||||
shared_->SetLastError(VE_INVALID_OPERATION, kTraceError,
|
||||
"GetAudioFrame() was called on channel that is not"
|
||||
" externally mixed.");
|
||||
return -1;
|
||||
}
|
||||
if (!channelPtr->Playing()) {
|
||||
shared_->SetLastError(VE_INVALID_OPERATION, kTraceError,
|
||||
"GetAudioFrame() was called on channel that is not playing.");
|
||||
return -1;
|
||||
}
|
||||
if (desired_sample_rate_hz == -1) {
|
||||
shared_->SetLastError(VE_BAD_ARGUMENT, kTraceError,
|
||||
"GetAudioFrame() was called with bad sample rate.");
|
||||
return -1;
|
||||
}
|
||||
frame->sample_rate_hz_ = desired_sample_rate_hz == 0 ? -1 :
|
||||
desired_sample_rate_hz;
|
||||
return channelPtr->GetAudioFrame(channel, *frame);
|
||||
}
|
||||
|
||||
int VoEExternalMediaImpl::SetExternalMixing(int channel, bool enable) {
|
||||
WEBRTC_TRACE(kTraceApiCall, kTraceVoice,
|
||||
VoEId(shared_->instance_id(), channel),
|
||||
"SetExternalMixing(channel=%d, enable=%d)", channel, enable);
|
||||
if (!shared_->statistics().Initialized())
|
||||
{
|
||||
shared_->SetLastError(VE_NOT_INITED, kTraceError);
|
||||
return -1;
|
||||
}
|
||||
voe::ScopedChannel sc(shared_->channel_manager(), channel);
|
||||
voe::Channel* channelPtr = sc.ChannelPtr();
|
||||
if (channelPtr == NULL)
|
||||
{
|
||||
shared_->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
|
||||
"SetExternalMixing() failed to locate channel");
|
||||
return -1;
|
||||
}
|
||||
return channelPtr->SetExternalMixing(enable);
|
||||
}
|
||||
|
||||
#endif // WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -44,6 +44,11 @@ public:
|
||||
int current_delay_ms,
|
||||
int& lengthSamples);
|
||||
|
||||
virtual int GetAudioFrame(int channel, int desired_sample_rate_hz,
|
||||
AudioFrame* frame);
|
||||
|
||||
virtual int SetExternalMixing(int channel, bool enable);
|
||||
|
||||
protected:
|
||||
VoEExternalMediaImpl(voe::SharedData* shared);
|
||||
virtual ~VoEExternalMediaImpl();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user