/* * 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_oldapi.h" #include #include #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/audio_coding/main/include/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 // 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, "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 AcmReceiveTestOldApi::AcmReceiveTestOldApi( 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 AcmReceiveTestOldApi::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 AcmReceiveTestOldApi::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"; } } } int AcmReceiveTestOldApi::RegisterExternalReceiveCodec( int rtp_payload_type, AudioDecoder* external_decoder, int sample_rate_hz, int num_channels) { return acm_->RegisterExternalReceiveCodec(rtp_payload_type, external_decoder, sample_rate_hz, num_channels); } void AcmReceiveTestOldApi::Run() { for (rtc::scoped_ptr 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 size_t samples_per_block = static_cast(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); AfterGetAudio(); } // 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(packet->payload_length_bytes()), header)) << "Failure when inserting packet:" << std::endl << " PT = " << static_cast(header.header.payloadType) << std::endl << " TS = " << header.header.timestamp << std::endl << " SN = " << header.header.sequenceNumber; } } AcmReceiveTestToggleOutputFreqOldApi::AcmReceiveTestToggleOutputFreqOldApi( PacketSource* packet_source, AudioSink* audio_sink, int output_freq_hz_1, int output_freq_hz_2, int toggle_period_ms, NumOutputChannels exptected_output_channels) : AcmReceiveTestOldApi(packet_source, audio_sink, output_freq_hz_1, exptected_output_channels), output_freq_hz_1_(output_freq_hz_1), output_freq_hz_2_(output_freq_hz_2), toggle_period_ms_(toggle_period_ms), last_toggle_time_ms_(clock_.TimeInMilliseconds()) { } void AcmReceiveTestToggleOutputFreqOldApi::AfterGetAudio() { if (clock_.TimeInMilliseconds() >= last_toggle_time_ms_ + toggle_period_ms_) { output_freq_hz_ = (output_freq_hz_ == output_freq_hz_1_) ? output_freq_hz_2_ : output_freq_hz_1_; last_toggle_time_ms_ = clock_.TimeInMilliseconds(); } } } // namespace test } // namespace webrtc