diff options
Diffstat (limited to 'modules/audio_coding/main/acm2/acm_receive_test.cc')
-rw-r--r-- | modules/audio_coding/main/acm2/acm_receive_test.cc | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/modules/audio_coding/main/acm2/acm_receive_test.cc b/modules/audio_coding/main/acm2/acm_receive_test.cc new file mode 100644 index 00000000..43d623d1 --- /dev/null +++ b/modules/audio_coding/main/acm2/acm_receive_test.cc @@ -0,0 +1,181 @@ +/* + * 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. + + if (STR_CASE_CMP(codec_param->plname, "opus") == 0) + codec_param->channels = 1; // Always register Opus as mono. + else if (codec_param->channels > 1) + return false; // Skip all non-mono codecs. + + 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) + : clock_(0), + acm_(webrtc::AudioCodingModule::Create(0, &clock_)), + packet_source_(packet_source), + audio_sink_(audio_sink), + output_freq_hz_(output_freq_hz) { +} + +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_); + EXPECT_EQ(1, 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 |