Home | History | Annotate | Download | only in acm2
      1 /*
      2  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/modules/audio_coding/acm2/acm_receive_test_oldapi.h"
     12 
     13 #include <assert.h>
     14 #include <stdio.h>
     15 
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 #include "webrtc/modules/audio_coding/include/audio_coding_module.h"
     18 #include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h"
     19 #include "webrtc/modules/audio_coding/neteq/tools/packet.h"
     20 #include "webrtc/modules/audio_coding/neteq/tools/packet_source.h"
     21 
     22 namespace webrtc {
     23 namespace test {
     24 
     25 namespace {
     26 // Returns true if the codec should be registered, otherwise false. Changes
     27 // the number of channels for the Opus codec to always be 1.
     28 bool ModifyAndUseThisCodec(CodecInst* codec_param) {
     29   if (STR_CASE_CMP(codec_param->plname, "CN") == 0 &&
     30       codec_param->plfreq == 48000)
     31     return false;  // Skip 48 kHz comfort noise.
     32 
     33   if (STR_CASE_CMP(codec_param->plname, "telephone-event") == 0)
     34     return false;  // Skip DTFM.
     35 
     36   return true;
     37 }
     38 
     39 // Remaps payload types from ACM's default to those used in the resource file
     40 // neteq_universal_new.rtp. Returns true if the codec should be registered,
     41 // otherwise false. The payload types are set as follows (all are mono codecs):
     42 // PCMu = 0;
     43 // PCMa = 8;
     44 // Comfort noise 8 kHz = 13
     45 // Comfort noise 16 kHz = 98
     46 // Comfort noise 32 kHz = 99
     47 // iLBC = 102
     48 // iSAC wideband = 103
     49 // iSAC super-wideband = 104
     50 // AVT/DTMF = 106
     51 // RED = 117
     52 // PCM16b 8 kHz = 93
     53 // PCM16b 16 kHz = 94
     54 // PCM16b 32 kHz = 95
     55 // G.722 = 94
     56 bool RemapPltypeAndUseThisCodec(const char* plname,
     57                                 int plfreq,
     58                                 size_t channels,
     59                                 int* pltype) {
     60   if (channels != 1)
     61     return false;  // Don't use non-mono codecs.
     62 
     63   // Re-map pltypes to those used in the NetEq test files.
     64   if (STR_CASE_CMP(plname, "PCMU") == 0 && plfreq == 8000) {
     65     *pltype = 0;
     66   } else if (STR_CASE_CMP(plname, "PCMA") == 0 && plfreq == 8000) {
     67     *pltype = 8;
     68   } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 8000) {
     69     *pltype = 13;
     70   } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 16000) {
     71     *pltype = 98;
     72   } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 32000) {
     73     *pltype = 99;
     74   } else if (STR_CASE_CMP(plname, "ILBC") == 0) {
     75     *pltype = 102;
     76   } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 16000) {
     77     *pltype = 103;
     78   } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 32000) {
     79     *pltype = 104;
     80   } else if (STR_CASE_CMP(plname, "telephone-event") == 0) {
     81     *pltype = 106;
     82   } else if (STR_CASE_CMP(plname, "red") == 0) {
     83     *pltype = 117;
     84   } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 8000) {
     85     *pltype = 93;
     86   } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 16000) {
     87     *pltype = 94;
     88   } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 32000) {
     89     *pltype = 95;
     90   } else if (STR_CASE_CMP(plname, "G722") == 0) {
     91     *pltype = 9;
     92   } else {
     93     // Don't use any other codecs.
     94     return false;
     95   }
     96   return true;
     97 }
     98 }  // namespace
     99 
    100 AcmReceiveTestOldApi::AcmReceiveTestOldApi(
    101     PacketSource* packet_source,
    102     AudioSink* audio_sink,
    103     int output_freq_hz,
    104     NumOutputChannels exptected_output_channels)
    105     : clock_(0),
    106       acm_(webrtc::AudioCodingModule::Create(0, &clock_)),
    107       packet_source_(packet_source),
    108       audio_sink_(audio_sink),
    109       output_freq_hz_(output_freq_hz),
    110       exptected_output_channels_(exptected_output_channels) {
    111 }
    112 
    113 void AcmReceiveTestOldApi::RegisterDefaultCodecs() {
    114   CodecInst my_codec_param;
    115   for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
    116     ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
    117     if (ModifyAndUseThisCodec(&my_codec_param)) {
    118       ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param))
    119           << "Couldn't register receive codec.\n";
    120     }
    121   }
    122 }
    123 
    124 void AcmReceiveTestOldApi::RegisterNetEqTestCodecs() {
    125   CodecInst my_codec_param;
    126   for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
    127     ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
    128     if (!ModifyAndUseThisCodec(&my_codec_param)) {
    129       // Skip this codec.
    130       continue;
    131     }
    132 
    133     if (RemapPltypeAndUseThisCodec(my_codec_param.plname,
    134                                    my_codec_param.plfreq,
    135                                    my_codec_param.channels,
    136                                    &my_codec_param.pltype)) {
    137       ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param))
    138           << "Couldn't register receive codec.\n";
    139     }
    140   }
    141 }
    142 
    143 int AcmReceiveTestOldApi::RegisterExternalReceiveCodec(
    144     int rtp_payload_type,
    145     AudioDecoder* external_decoder,
    146     int sample_rate_hz,
    147     int num_channels,
    148     const std::string& name) {
    149   return acm_->RegisterExternalReceiveCodec(rtp_payload_type, external_decoder,
    150                                             sample_rate_hz, num_channels, name);
    151 }
    152 
    153 void AcmReceiveTestOldApi::Run() {
    154   for (rtc::scoped_ptr<Packet> packet(packet_source_->NextPacket()); packet;
    155        packet.reset(packet_source_->NextPacket())) {
    156     // Pull audio until time to insert packet.
    157     while (clock_.TimeInMilliseconds() < packet->time_ms()) {
    158       AudioFrame output_frame;
    159       EXPECT_EQ(0, acm_->PlayoutData10Ms(output_freq_hz_, &output_frame));
    160       EXPECT_EQ(output_freq_hz_, output_frame.sample_rate_hz_);
    161       const size_t samples_per_block =
    162           static_cast<size_t>(output_freq_hz_ * 10 / 1000);
    163       EXPECT_EQ(samples_per_block, output_frame.samples_per_channel_);
    164       if (exptected_output_channels_ != kArbitraryChannels) {
    165         if (output_frame.speech_type_ == webrtc::AudioFrame::kPLC) {
    166           // Don't check number of channels for PLC output, since each test run
    167           // usually starts with a short period of mono PLC before decoding the
    168           // first packet.
    169         } else {
    170           EXPECT_EQ(exptected_output_channels_, output_frame.num_channels_);
    171         }
    172       }
    173       ASSERT_TRUE(audio_sink_->WriteAudioFrame(output_frame));
    174       clock_.AdvanceTimeMilliseconds(10);
    175       AfterGetAudio();
    176     }
    177 
    178     // Insert packet after converting from RTPHeader to WebRtcRTPHeader.
    179     WebRtcRTPHeader header;
    180     header.header = packet->header();
    181     header.frameType = kAudioFrameSpeech;
    182     memset(&header.type.Audio, 0, sizeof(RTPAudioHeader));
    183     EXPECT_EQ(0,
    184               acm_->IncomingPacket(
    185                   packet->payload(),
    186                   static_cast<int32_t>(packet->payload_length_bytes()),
    187                   header))
    188         << "Failure when inserting packet:" << std::endl
    189         << "  PT = " << static_cast<int>(header.header.payloadType) << std::endl
    190         << "  TS = " << header.header.timestamp << std::endl
    191         << "  SN = " << header.header.sequenceNumber;
    192   }
    193 }
    194 
    195 AcmReceiveTestToggleOutputFreqOldApi::AcmReceiveTestToggleOutputFreqOldApi(
    196     PacketSource* packet_source,
    197     AudioSink* audio_sink,
    198     int output_freq_hz_1,
    199     int output_freq_hz_2,
    200     int toggle_period_ms,
    201     NumOutputChannels exptected_output_channels)
    202     : AcmReceiveTestOldApi(packet_source,
    203                            audio_sink,
    204                            output_freq_hz_1,
    205                            exptected_output_channels),
    206       output_freq_hz_1_(output_freq_hz_1),
    207       output_freq_hz_2_(output_freq_hz_2),
    208       toggle_period_ms_(toggle_period_ms),
    209       last_toggle_time_ms_(clock_.TimeInMilliseconds()) {
    210 }
    211 
    212 void AcmReceiveTestToggleOutputFreqOldApi::AfterGetAudio() {
    213   if (clock_.TimeInMilliseconds() >= last_toggle_time_ms_ + toggle_period_ms_) {
    214     output_freq_hz_ = (output_freq_hz_ == output_freq_hz_1_)
    215                           ? output_freq_hz_2_
    216                           : output_freq_hz_1_;
    217     last_toggle_time_ms_ = clock_.TimeInMilliseconds();
    218   }
    219 }
    220 
    221 }  // namespace test
    222 }  // namespace webrtc
    223