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/main/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/main/interface/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 // iSAC fullband = 124
     51 // AVT/DTMF = 106
     52 // RED = 117
     53 // PCM16b 8 kHz = 93
     54 // PCM16b 16 kHz = 94
     55 // PCM16b 32 kHz = 95
     56 // G.722 = 94
     57 bool RemapPltypeAndUseThisCodec(const char* plname,
     58                                 int plfreq,
     59                                 int channels,
     60                                 int* pltype) {
     61   if (channels != 1)
     62     return false;  // Don't use non-mono codecs.
     63 
     64   // Re-map pltypes to those used in the NetEq test files.
     65   if (STR_CASE_CMP(plname, "PCMU") == 0 && plfreq == 8000) {
     66     *pltype = 0;
     67   } else if (STR_CASE_CMP(plname, "PCMA") == 0 && plfreq == 8000) {
     68     *pltype = 8;
     69   } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 8000) {
     70     *pltype = 13;
     71   } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 16000) {
     72     *pltype = 98;
     73   } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 32000) {
     74     *pltype = 99;
     75   } else if (STR_CASE_CMP(plname, "ILBC") == 0) {
     76     *pltype = 102;
     77   } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 16000) {
     78     *pltype = 103;
     79   } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 32000) {
     80     *pltype = 104;
     81   } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 48000) {
     82     *pltype = 124;
     83   } else if (STR_CASE_CMP(plname, "telephone-event") == 0) {
     84     *pltype = 106;
     85   } else if (STR_CASE_CMP(plname, "red") == 0) {
     86     *pltype = 117;
     87   } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 8000) {
     88     *pltype = 93;
     89   } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 16000) {
     90     *pltype = 94;
     91   } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 32000) {
     92     *pltype = 95;
     93   } else if (STR_CASE_CMP(plname, "G722") == 0) {
     94     *pltype = 9;
     95   } else {
     96     // Don't use any other codecs.
     97     return false;
     98   }
     99   return true;
    100 }
    101 }  // namespace
    102 
    103 AcmReceiveTestOldApi::AcmReceiveTestOldApi(
    104     PacketSource* packet_source,
    105     AudioSink* audio_sink,
    106     int output_freq_hz,
    107     NumOutputChannels exptected_output_channels)
    108     : clock_(0),
    109       acm_(webrtc::AudioCodingModule::Create(0, &clock_)),
    110       packet_source_(packet_source),
    111       audio_sink_(audio_sink),
    112       output_freq_hz_(output_freq_hz),
    113       exptected_output_channels_(exptected_output_channels) {
    114 }
    115 
    116 void AcmReceiveTestOldApi::RegisterDefaultCodecs() {
    117   CodecInst my_codec_param;
    118   for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
    119     ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
    120     if (ModifyAndUseThisCodec(&my_codec_param)) {
    121       ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param))
    122           << "Couldn't register receive codec.\n";
    123     }
    124   }
    125 }
    126 
    127 void AcmReceiveTestOldApi::RegisterNetEqTestCodecs() {
    128   CodecInst my_codec_param;
    129   for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
    130     ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
    131     if (!ModifyAndUseThisCodec(&my_codec_param)) {
    132       // Skip this codec.
    133       continue;
    134     }
    135 
    136     if (RemapPltypeAndUseThisCodec(my_codec_param.plname,
    137                                    my_codec_param.plfreq,
    138                                    my_codec_param.channels,
    139                                    &my_codec_param.pltype)) {
    140       ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param))
    141           << "Couldn't register receive codec.\n";
    142     }
    143   }
    144 }
    145 
    146 void AcmReceiveTestOldApi::Run() {
    147   for (scoped_ptr<Packet> packet(packet_source_->NextPacket()); packet;
    148        packet.reset(packet_source_->NextPacket())) {
    149     // Pull audio until time to insert packet.
    150     while (clock_.TimeInMilliseconds() < packet->time_ms()) {
    151       AudioFrame output_frame;
    152       EXPECT_EQ(0, acm_->PlayoutData10Ms(output_freq_hz_, &output_frame));
    153       EXPECT_EQ(output_freq_hz_, output_frame.sample_rate_hz_);
    154       const int samples_per_block = output_freq_hz_ * 10 / 1000;
    155       EXPECT_EQ(samples_per_block, output_frame.samples_per_channel_);
    156       if (exptected_output_channels_ != kArbitraryChannels) {
    157         if (output_frame.speech_type_ == webrtc::AudioFrame::kPLC) {
    158           // Don't check number of channels for PLC output, since each test run
    159           // usually starts with a short period of mono PLC before decoding the
    160           // first packet.
    161         } else {
    162           EXPECT_EQ(exptected_output_channels_, output_frame.num_channels_);
    163         }
    164       }
    165       ASSERT_TRUE(audio_sink_->WriteAudioFrame(output_frame));
    166       clock_.AdvanceTimeMilliseconds(10);
    167     }
    168 
    169     // Insert packet after converting from RTPHeader to WebRtcRTPHeader.
    170     WebRtcRTPHeader header;
    171     header.header = packet->header();
    172     header.frameType = kAudioFrameSpeech;
    173     memset(&header.type.Audio, 0, sizeof(RTPAudioHeader));
    174     EXPECT_EQ(0,
    175               acm_->IncomingPacket(
    176                   packet->payload(),
    177                   static_cast<int32_t>(packet->payload_length_bytes()),
    178                   header))
    179         << "Failure when inserting packet:" << std::endl
    180         << "  PT = " << static_cast<int>(header.header.payloadType) << std::endl
    181         << "  TS = " << header.header.timestamp << std::endl
    182         << "  SN = " << header.header.sequenceNumber;
    183   }
    184 }
    185 
    186 }  // namespace test
    187 }  // namespace webrtc
    188