mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-23 16:37:30 +00:00
396 lines
10 KiB
C++
396 lines
10 KiB
C++
|
/*
|
||
|
* 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 "webrtc/modules/audio_coding/main/test/TestVADDTX.h"
|
||
|
|
||
|
#include <iostream>
|
||
|
|
||
|
#include "webrtc/common_types.h"
|
||
|
#include "webrtc/engine_configurations.h"
|
||
|
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
||
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
|
||
|
#include "webrtc/modules/audio_coding/main/test/utility.h"
|
||
|
#include "webrtc/system_wrappers/interface/trace.h"
|
||
|
#include "webrtc/test/testsupport/fileutils.h"
|
||
|
|
||
|
namespace webrtc {
|
||
|
|
||
|
TestVADDTX::TestVADDTX()
|
||
|
: _acmA(AudioCodingModule::Create(0)),
|
||
|
_acmB(AudioCodingModule::Create(1)),
|
||
|
_channelA2B(NULL) {}
|
||
|
|
||
|
TestVADDTX::~TestVADDTX() {
|
||
|
if (_channelA2B != NULL) {
|
||
|
delete _channelA2B;
|
||
|
_channelA2B = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TestVADDTX::Perform() {
|
||
|
const std::string file_name = webrtc::test::ResourcePath(
|
||
|
"audio_coding/testfile32kHz", "pcm");
|
||
|
_inFileA.Open(file_name, 32000, "rb");
|
||
|
|
||
|
EXPECT_EQ(0, _acmA->InitializeReceiver());
|
||
|
EXPECT_EQ(0, _acmB->InitializeReceiver());
|
||
|
|
||
|
uint8_t numEncoders = _acmA->NumberOfCodecs();
|
||
|
CodecInst myCodecParam;
|
||
|
for (uint8_t n = 0; n < numEncoders; n++) {
|
||
|
EXPECT_EQ(0, _acmB->Codec(n, &myCodecParam));
|
||
|
if (!strcmp(myCodecParam.plname, "opus")) {
|
||
|
// Register Opus as mono.
|
||
|
myCodecParam.channels = 1;
|
||
|
}
|
||
|
EXPECT_EQ(0, _acmB->RegisterReceiveCodec(myCodecParam));
|
||
|
}
|
||
|
|
||
|
// Create and connect the channel
|
||
|
_channelA2B = new Channel;
|
||
|
_acmA->RegisterTransportCallback(_channelA2B);
|
||
|
_channelA2B->RegisterReceiverACM(_acmB.get());
|
||
|
|
||
|
_acmA->RegisterVADCallback(&_monitor);
|
||
|
|
||
|
int16_t testCntr = 1;
|
||
|
|
||
|
#ifdef WEBRTC_CODEC_ISAC
|
||
|
// Open outputfile
|
||
|
OpenOutFile(testCntr++);
|
||
|
|
||
|
// Register iSAC WB as send codec
|
||
|
char nameISAC[] = "ISAC";
|
||
|
RegisterSendCodec('A', nameISAC, 16000);
|
||
|
|
||
|
// Run the five test cased
|
||
|
runTestCases();
|
||
|
|
||
|
// Close file
|
||
|
_outFileB.Close();
|
||
|
|
||
|
// Open outputfile
|
||
|
OpenOutFile(testCntr++);
|
||
|
|
||
|
// Register iSAC SWB as send codec
|
||
|
RegisterSendCodec('A', nameISAC, 32000);
|
||
|
|
||
|
// Run the five test cased
|
||
|
runTestCases();
|
||
|
|
||
|
// Close file
|
||
|
_outFileB.Close();
|
||
|
#endif
|
||
|
#ifdef WEBRTC_CODEC_ILBC
|
||
|
// Open outputfile
|
||
|
OpenOutFile(testCntr++);
|
||
|
|
||
|
// Register iLBC as send codec
|
||
|
char nameILBC[] = "ilbc";
|
||
|
RegisterSendCodec('A', nameILBC);
|
||
|
|
||
|
// Run the five test cased
|
||
|
runTestCases();
|
||
|
|
||
|
// Close file
|
||
|
_outFileB.Close();
|
||
|
|
||
|
#endif
|
||
|
#ifdef WEBRTC_CODEC_OPUS
|
||
|
// Open outputfile
|
||
|
OpenOutFile(testCntr++);
|
||
|
|
||
|
// Register Opus as send codec
|
||
|
char nameOPUS[] = "opus";
|
||
|
RegisterSendCodec('A', nameOPUS);
|
||
|
|
||
|
// Run the five test cased
|
||
|
runTestCases();
|
||
|
|
||
|
// Close file
|
||
|
_outFileB.Close();
|
||
|
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void TestVADDTX::runTestCases() {
|
||
|
// #1 DTX = OFF, VAD = ON, VADNormal
|
||
|
SetVAD(false, true, VADNormal);
|
||
|
Run();
|
||
|
VerifyTest();
|
||
|
|
||
|
// #2 DTX = OFF, VAD = ON, VADAggr
|
||
|
SetVAD(false, true, VADAggr);
|
||
|
Run();
|
||
|
VerifyTest();
|
||
|
|
||
|
// #3 DTX = ON, VAD = ON, VADLowBitrate
|
||
|
SetVAD(true, true, VADLowBitrate);
|
||
|
Run();
|
||
|
VerifyTest();
|
||
|
|
||
|
// #4 DTX = ON, VAD = ON, VADVeryAggr
|
||
|
SetVAD(true, true, VADVeryAggr);
|
||
|
Run();
|
||
|
VerifyTest();
|
||
|
|
||
|
// #5 DTX = ON, VAD = OFF, VADNormal
|
||
|
SetVAD(true, false, VADNormal);
|
||
|
Run();
|
||
|
VerifyTest();
|
||
|
}
|
||
|
|
||
|
void TestVADDTX::runTestInternalDTX(int expected_result) {
|
||
|
// #6 DTX = ON, VAD = ON, VADNormal
|
||
|
SetVAD(true, true, VADNormal);
|
||
|
EXPECT_EQ(expected_result, _acmA->ReplaceInternalDTXWithWebRtc(true));
|
||
|
if (expected_result == 0) {
|
||
|
Run();
|
||
|
VerifyTest();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TestVADDTX::SetVAD(bool statusDTX, bool statusVAD, int16_t vadMode) {
|
||
|
bool dtxEnabled, vadEnabled;
|
||
|
ACMVADMode vadModeSet;
|
||
|
|
||
|
EXPECT_EQ(0, _acmA->SetVAD(statusDTX, statusVAD, (ACMVADMode) vadMode));
|
||
|
EXPECT_EQ(0, _acmA->VAD(&dtxEnabled, &vadEnabled, &vadModeSet));
|
||
|
|
||
|
// Requested VAD/DTX settings
|
||
|
_setStruct.statusDTX = statusDTX;
|
||
|
_setStruct.statusVAD = statusVAD;
|
||
|
_setStruct.vadMode = (ACMVADMode) vadMode;
|
||
|
|
||
|
// VAD settings after setting VAD in ACM
|
||
|
_getStruct.statusDTX = dtxEnabled;
|
||
|
_getStruct.statusVAD = vadEnabled;
|
||
|
_getStruct.vadMode = vadModeSet;
|
||
|
}
|
||
|
|
||
|
VADDTXstruct TestVADDTX::GetVAD() {
|
||
|
VADDTXstruct retStruct;
|
||
|
bool dtxEnabled, vadEnabled;
|
||
|
ACMVADMode vadModeSet;
|
||
|
|
||
|
EXPECT_EQ(0, _acmA->VAD(&dtxEnabled, &vadEnabled, &vadModeSet));
|
||
|
|
||
|
retStruct.statusDTX = dtxEnabled;
|
||
|
retStruct.statusVAD = vadEnabled;
|
||
|
retStruct.vadMode = vadModeSet;
|
||
|
return retStruct;
|
||
|
}
|
||
|
|
||
|
int16_t TestVADDTX::RegisterSendCodec(char side, char* codecName,
|
||
|
int32_t samplingFreqHz,
|
||
|
int32_t rateKbps) {
|
||
|
std::cout << std::flush;
|
||
|
AudioCodingModule* myACM;
|
||
|
switch (side) {
|
||
|
case 'A': {
|
||
|
myACM = _acmA.get();
|
||
|
break;
|
||
|
}
|
||
|
case 'B': {
|
||
|
myACM = _acmB.get();
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (myACM == NULL) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
CodecInst myCodecParam;
|
||
|
for (int16_t codecCntr = 0; codecCntr < myACM->NumberOfCodecs();
|
||
|
codecCntr++) {
|
||
|
EXPECT_EQ(0, myACM->Codec((uint8_t) codecCntr, &myCodecParam));
|
||
|
if (!STR_CASE_CMP(myCodecParam.plname, codecName)) {
|
||
|
if ((samplingFreqHz == -1) || (myCodecParam.plfreq == samplingFreqHz)) {
|
||
|
if ((rateKbps == -1) || (myCodecParam.rate == rateKbps)) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// We only allow VAD/DTX when sending mono.
|
||
|
myCodecParam.channels = 1;
|
||
|
EXPECT_EQ(0, myACM->RegisterSendCodec(myCodecParam));
|
||
|
|
||
|
// initialization was succesful
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void TestVADDTX::Run() {
|
||
|
AudioFrame audioFrame;
|
||
|
|
||
|
uint16_t SamplesIn10MsecA = _inFileA.PayloadLength10Ms();
|
||
|
uint32_t timestampA = 1;
|
||
|
int32_t outFreqHzB = _outFileB.SamplingFrequency();
|
||
|
|
||
|
while (!_inFileA.EndOfFile()) {
|
||
|
_inFileA.Read10MsData(audioFrame);
|
||
|
audioFrame.timestamp_ = timestampA;
|
||
|
timestampA += SamplesIn10MsecA;
|
||
|
EXPECT_EQ(0, _acmA->Add10MsData(audioFrame));
|
||
|
EXPECT_GT(_acmA->Process(), -1);
|
||
|
EXPECT_EQ(0, _acmB->PlayoutData10Ms(outFreqHzB, &audioFrame));
|
||
|
_outFileB.Write10MsData(audioFrame.data_, audioFrame.samples_per_channel_);
|
||
|
}
|
||
|
#ifdef PRINT_STAT
|
||
|
_monitor.PrintStatistics();
|
||
|
#endif
|
||
|
_inFileA.Rewind();
|
||
|
_monitor.GetStatistics(_statCounter);
|
||
|
_monitor.ResetStatistics();
|
||
|
}
|
||
|
|
||
|
void TestVADDTX::OpenOutFile(int16_t test_number) {
|
||
|
std::string file_name;
|
||
|
std::stringstream file_stream;
|
||
|
file_stream << webrtc::test::OutputPath();
|
||
|
file_stream << "testVADDTX_outFile_";
|
||
|
file_stream << test_number << ".pcm";
|
||
|
file_name = file_stream.str();
|
||
|
_outFileB.Open(file_name, 16000, "wb");
|
||
|
}
|
||
|
|
||
|
int16_t TestVADDTX::VerifyTest() {
|
||
|
// Verify empty frame result
|
||
|
uint8_t statusEF = 0;
|
||
|
uint8_t vadPattern = 0;
|
||
|
uint8_t emptyFramePattern[6];
|
||
|
CodecInst myCodecParam;
|
||
|
_acmA->SendCodec(&myCodecParam);
|
||
|
bool dtxInUse = true;
|
||
|
bool isReplaced = false;
|
||
|
if ((STR_CASE_CMP(myCodecParam.plname, "G729") == 0)
|
||
|
|| (STR_CASE_CMP(myCodecParam.plname, "G723") == 0)
|
||
|
|| (STR_CASE_CMP(myCodecParam.plname, "AMR") == 0)
|
||
|
|| (STR_CASE_CMP(myCodecParam.plname, "AMR-wb") == 0)
|
||
|
|| (STR_CASE_CMP(myCodecParam.plname, "speex") == 0)) {
|
||
|
_acmA->IsInternalDTXReplacedWithWebRtc(&isReplaced);
|
||
|
if (!isReplaced) {
|
||
|
dtxInUse = false;
|
||
|
}
|
||
|
} else if (STR_CASE_CMP(myCodecParam.plname, "opus") == 0) {
|
||
|
if (_getStruct.statusDTX != false) {
|
||
|
// DTX status doesn't match expected.
|
||
|
vadPattern |= 4;
|
||
|
} else if (_getStruct.statusVAD != false) {
|
||
|
// Mismatch in VAD setting.
|
||
|
vadPattern |= 2;
|
||
|
} else {
|
||
|
_setStruct.statusDTX = false;
|
||
|
_setStruct.statusVAD = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Check for error in VAD/DTX settings
|
||
|
if (_getStruct.statusDTX != _setStruct.statusDTX) {
|
||
|
// DTX status doesn't match expected
|
||
|
vadPattern |= 4;
|
||
|
}
|
||
|
if (_getStruct.statusDTX) {
|
||
|
if ((!_getStruct.statusVAD && dtxInUse)
|
||
|
|| (!dtxInUse && (_getStruct.statusVAD != _setStruct.statusVAD))) {
|
||
|
// Missmatch in VAD setting
|
||
|
vadPattern |= 2;
|
||
|
}
|
||
|
} else {
|
||
|
if (_getStruct.statusVAD != _setStruct.statusVAD) {
|
||
|
// VAD status doesn't match expected
|
||
|
vadPattern |= 2;
|
||
|
}
|
||
|
}
|
||
|
if (_getStruct.vadMode != _setStruct.vadMode) {
|
||
|
// VAD Mode doesn't match expected
|
||
|
vadPattern |= 1;
|
||
|
}
|
||
|
|
||
|
// Set expected empty frame pattern
|
||
|
int ii;
|
||
|
for (ii = 0; ii < 6; ii++) {
|
||
|
emptyFramePattern[ii] = 0;
|
||
|
}
|
||
|
// 0 - "kNoEncoding", not important to check.
|
||
|
// Codecs with packetsize != 80 samples will get this output.
|
||
|
// 1 - "kActiveNormalEncoded", expect to receive some frames with this label .
|
||
|
// 2 - "kPassiveNormalEncoded".
|
||
|
// 3 - "kPassiveDTXNB".
|
||
|
// 4 - "kPassiveDTXWB".
|
||
|
// 5 - "kPassiveDTXSWB".
|
||
|
emptyFramePattern[0] = 1;
|
||
|
emptyFramePattern[1] = 1;
|
||
|
emptyFramePattern[2] = (((!_getStruct.statusDTX && _getStruct.statusVAD)
|
||
|
|| (!dtxInUse && _getStruct.statusDTX)));
|
||
|
emptyFramePattern[3] = ((_getStruct.statusDTX && dtxInUse
|
||
|
&& (_acmA->SendFrequency() == 8000)));
|
||
|
emptyFramePattern[4] = ((_getStruct.statusDTX && dtxInUse
|
||
|
&& (_acmA->SendFrequency() == 16000)));
|
||
|
emptyFramePattern[5] = ((_getStruct.statusDTX && dtxInUse
|
||
|
&& (_acmA->SendFrequency() == 32000)));
|
||
|
|
||
|
// Check pattern 1-5 (skip 0)
|
||
|
for (int ii = 1; ii < 6; ii++) {
|
||
|
if (emptyFramePattern[ii]) {
|
||
|
statusEF |= (_statCounter[ii] == 0);
|
||
|
} else {
|
||
|
statusEF |= (_statCounter[ii] > 0);
|
||
|
}
|
||
|
}
|
||
|
EXPECT_EQ(0, statusEF);
|
||
|
EXPECT_EQ(0, vadPattern);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
ActivityMonitor::ActivityMonitor() {
|
||
|
_counter[0] = _counter[1] = _counter[2] = _counter[3] = _counter[4] =
|
||
|
_counter[5] = 0;
|
||
|
}
|
||
|
|
||
|
ActivityMonitor::~ActivityMonitor() {
|
||
|
}
|
||
|
|
||
|
int32_t ActivityMonitor::InFrameType(int16_t frameType) {
|
||
|
_counter[frameType]++;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void ActivityMonitor::PrintStatistics() {
|
||
|
printf("\n");
|
||
|
printf("kActiveNormalEncoded kPassiveNormalEncoded kPassiveDTXWB ");
|
||
|
printf("kPassiveDTXNB kPassiveDTXSWB kFrameEmpty\n");
|
||
|
printf("%19u", _counter[1]);
|
||
|
printf("%22u", _counter[2]);
|
||
|
printf("%14u", _counter[3]);
|
||
|
printf("%14u", _counter[4]);
|
||
|
printf("%14u", _counter[5]);
|
||
|
printf("%11u", _counter[0]);
|
||
|
printf("\n\n");
|
||
|
}
|
||
|
|
||
|
void ActivityMonitor::ResetStatistics() {
|
||
|
_counter[0] = _counter[1] = _counter[2] = _counter[3] = _counter[4] =
|
||
|
_counter[5] = 0;
|
||
|
}
|
||
|
|
||
|
void ActivityMonitor::GetStatistics(uint32_t* getCounter) {
|
||
|
for (int ii = 0; ii < 6; ii++) {
|
||
|
getCounter[ii] = _counter[ii];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // namespace webrtc
|