This time reverts the Cl that actually broke the tests. Got the wrong rev before. :/ BUG=3520 TESTED=Locally with CHECKOUT_SOURCE_ROOT=`pwd` build/android/test_runner.py gtest -s modules_unittests --gtest_filter=AcmReceiverBitExactness.8kHzOutput --verbose --isolate-file-path=webrtc/modules/modules_unittests.isolate TBR=henrik.lundin@webrtc.org Review URL: https://webrtc-codereview.appspot.com/26579004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7264 4adac7df-926f-26a2-2b94-8c16560cd09d
187 lines
6.7 KiB
C++
187 lines
6.7 KiB
C++
/*
|
|
* Copyright (c) 2014 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/acm2/acm_receive_test.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
|
|
#include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h"
|
|
#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
|
|
#include "webrtc/modules/audio_coding/neteq/tools/packet_source.h"
|
|
|
|
namespace webrtc {
|
|
namespace test {
|
|
|
|
namespace {
|
|
// Returns true if the codec should be registered, otherwise false. Changes
|
|
// the number of channels for the Opus codec to always be 1.
|
|
bool ModifyAndUseThisCodec(CodecInst* codec_param) {
|
|
if (STR_CASE_CMP(codec_param->plname, "CN") == 0 &&
|
|
codec_param->plfreq == 48000)
|
|
return false; // Skip 48 kHz comfort noise.
|
|
|
|
if (STR_CASE_CMP(codec_param->plname, "telephone-event") == 0)
|
|
return false; // Skip DTFM.
|
|
|
|
return true;
|
|
}
|
|
|
|
// Remaps payload types from ACM's default to those used in the resource file
|
|
// neteq_universal_new.rtp. Returns true if the codec should be registered,
|
|
// otherwise false. The payload types are set as follows (all are mono codecs):
|
|
// PCMu = 0;
|
|
// PCMa = 8;
|
|
// Comfort noise 8 kHz = 13
|
|
// Comfort noise 16 kHz = 98
|
|
// Comfort noise 32 kHz = 99
|
|
// iLBC = 102
|
|
// iSAC wideband = 103
|
|
// iSAC super-wideband = 104
|
|
// iSAC fullband = 124
|
|
// AVT/DTMF = 106
|
|
// RED = 117
|
|
// PCM16b 8 kHz = 93
|
|
// PCM16b 16 kHz = 94
|
|
// PCM16b 32 kHz = 95
|
|
// G.722 = 94
|
|
bool RemapPltypeAndUseThisCodec(const char* plname,
|
|
int plfreq,
|
|
int channels,
|
|
int* pltype) {
|
|
if (channels != 1)
|
|
return false; // Don't use non-mono codecs.
|
|
|
|
// Re-map pltypes to those used in the NetEq test files.
|
|
if (STR_CASE_CMP(plname, "PCMU") == 0 && plfreq == 8000) {
|
|
*pltype = 0;
|
|
} else if (STR_CASE_CMP(plname, "PCMA") == 0 && plfreq == 8000) {
|
|
*pltype = 8;
|
|
} else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 8000) {
|
|
*pltype = 13;
|
|
} else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 16000) {
|
|
*pltype = 98;
|
|
} else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 32000) {
|
|
*pltype = 99;
|
|
} else if (STR_CASE_CMP(plname, "ILBC") == 0) {
|
|
*pltype = 102;
|
|
} else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 16000) {
|
|
*pltype = 103;
|
|
} else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 32000) {
|
|
*pltype = 104;
|
|
} else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 48000) {
|
|
*pltype = 124;
|
|
} else if (STR_CASE_CMP(plname, "telephone-event") == 0) {
|
|
*pltype = 106;
|
|
} else if (STR_CASE_CMP(plname, "red") == 0) {
|
|
*pltype = 117;
|
|
} else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 8000) {
|
|
*pltype = 93;
|
|
} else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 16000) {
|
|
*pltype = 94;
|
|
} else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 32000) {
|
|
*pltype = 95;
|
|
} else if (STR_CASE_CMP(plname, "G722") == 0) {
|
|
*pltype = 9;
|
|
} else {
|
|
// Don't use any other codecs.
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
} // namespace
|
|
|
|
AcmReceiveTest::AcmReceiveTest(PacketSource* packet_source,
|
|
AudioSink* audio_sink,
|
|
int output_freq_hz,
|
|
NumOutputChannels exptected_output_channels)
|
|
: clock_(0),
|
|
acm_(webrtc::AudioCodingModule::Create(0, &clock_)),
|
|
packet_source_(packet_source),
|
|
audio_sink_(audio_sink),
|
|
output_freq_hz_(output_freq_hz),
|
|
exptected_output_channels_(exptected_output_channels) {
|
|
}
|
|
|
|
void AcmReceiveTest::RegisterDefaultCodecs() {
|
|
CodecInst my_codec_param;
|
|
for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
|
|
ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
|
|
if (ModifyAndUseThisCodec(&my_codec_param)) {
|
|
ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param))
|
|
<< "Couldn't register receive codec.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
void AcmReceiveTest::RegisterNetEqTestCodecs() {
|
|
CodecInst my_codec_param;
|
|
for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
|
|
ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
|
|
if (!ModifyAndUseThisCodec(&my_codec_param)) {
|
|
// Skip this codec.
|
|
continue;
|
|
}
|
|
|
|
if (RemapPltypeAndUseThisCodec(my_codec_param.plname,
|
|
my_codec_param.plfreq,
|
|
my_codec_param.channels,
|
|
&my_codec_param.pltype)) {
|
|
ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param))
|
|
<< "Couldn't register receive codec.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
void AcmReceiveTest::Run() {
|
|
for (scoped_ptr<Packet> packet(packet_source_->NextPacket()); packet;
|
|
packet.reset(packet_source_->NextPacket())) {
|
|
// Pull audio until time to insert packet.
|
|
while (clock_.TimeInMilliseconds() < packet->time_ms()) {
|
|
AudioFrame output_frame;
|
|
EXPECT_EQ(0, acm_->PlayoutData10Ms(output_freq_hz_, &output_frame));
|
|
EXPECT_EQ(output_freq_hz_, output_frame.sample_rate_hz_);
|
|
const int samples_per_block = output_freq_hz_ * 10 / 1000;
|
|
EXPECT_EQ(samples_per_block, output_frame.samples_per_channel_);
|
|
if (exptected_output_channels_ != kArbitraryChannels) {
|
|
if (output_frame.speech_type_ == webrtc::AudioFrame::kPLC) {
|
|
// Don't check number of channels for PLC output, since each test run
|
|
// usually starts with a short period of mono PLC before decoding the
|
|
// first packet.
|
|
} else {
|
|
EXPECT_EQ(exptected_output_channels_, output_frame.num_channels_);
|
|
}
|
|
}
|
|
ASSERT_TRUE(audio_sink_->WriteAudioFrame(output_frame));
|
|
clock_.AdvanceTimeMilliseconds(10);
|
|
}
|
|
|
|
// Insert packet after converting from RTPHeader to WebRtcRTPHeader.
|
|
WebRtcRTPHeader header;
|
|
header.header = packet->header();
|
|
header.frameType = kAudioFrameSpeech;
|
|
memset(&header.type.Audio, 0, sizeof(RTPAudioHeader));
|
|
EXPECT_EQ(0,
|
|
acm_->IncomingPacket(
|
|
packet->payload(),
|
|
static_cast<int32_t>(packet->payload_length_bytes()),
|
|
header))
|
|
<< "Failure when inserting packet:" << std::endl
|
|
<< " PT = " << static_cast<int>(header.header.payloadType) << std::endl
|
|
<< " TS = " << header.header.timestamp << std::endl
|
|
<< " SN = " << header.header.sequenceNumber;
|
|
}
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace webrtc
|