Home | History | Annotate | Download | only in acm2
      1 /*
      2  *  Copyright (c) 2013 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_receiver.h"
     12 
     13 #include <algorithm>  // std::min
     14 
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
     17 #include "webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h"
     18 #include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
     19 #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
     20 #include "webrtc/system_wrappers/interface/clock.h"
     21 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
     22 #include "webrtc/test/test_suite.h"
     23 #include "webrtc/test/testsupport/fileutils.h"
     24 #include "webrtc/test/testsupport/gtest_disable.h"
     25 
     26 namespace webrtc {
     27 
     28 namespace acm2 {
     29 namespace {
     30 
     31 bool CodecsEqual(const CodecInst& codec_a, const CodecInst& codec_b) {
     32     if (strcmp(codec_a.plname, codec_b.plname) != 0 ||
     33         codec_a.plfreq != codec_b.plfreq ||
     34         codec_a.pltype != codec_b.pltype ||
     35         codec_b.channels != codec_a.channels)
     36       return false;
     37     return true;
     38 }
     39 
     40 }  // namespace
     41 
     42 class AcmReceiverTestOldApi : public AudioPacketizationCallback,
     43                               public ::testing::Test {
     44  protected:
     45   AcmReceiverTestOldApi()
     46       : timestamp_(0),
     47         packet_sent_(false),
     48         last_packet_send_timestamp_(timestamp_),
     49         last_frame_type_(kFrameEmpty) {
     50     AudioCodingModule::Config config;
     51     acm_.reset(new AudioCodingModuleImpl(config));
     52     receiver_.reset(new AcmReceiver(config));
     53   }
     54 
     55   ~AcmReceiverTestOldApi() {}
     56 
     57   virtual void SetUp() OVERRIDE {
     58     ASSERT_TRUE(receiver_.get() != NULL);
     59     ASSERT_TRUE(acm_.get() != NULL);
     60     for (int n = 0; n < ACMCodecDB::kNumCodecs; n++) {
     61       ASSERT_EQ(0, ACMCodecDB::Codec(n, &codecs_[n]));
     62     }
     63 
     64     acm_->InitializeReceiver();
     65     acm_->InitializeSender();
     66     acm_->RegisterTransportCallback(this);
     67 
     68     rtp_header_.header.sequenceNumber = 0;
     69     rtp_header_.header.timestamp = 0;
     70     rtp_header_.header.markerBit = false;
     71     rtp_header_.header.ssrc = 0x12345678;  // Arbitrary.
     72     rtp_header_.header.numCSRCs = 0;
     73     rtp_header_.header.payloadType = 0;
     74     rtp_header_.frameType = kAudioFrameSpeech;
     75     rtp_header_.type.Audio.isCNG = false;
     76   }
     77 
     78   virtual void TearDown() OVERRIDE {
     79   }
     80 
     81   void InsertOnePacketOfSilence(int codec_id) {
     82     CodecInst codec;
     83     ACMCodecDB::Codec(codec_id, &codec);
     84     if (timestamp_ == 0) {  // This is the first time inserting audio.
     85       ASSERT_EQ(0, acm_->RegisterSendCodec(codec));
     86     } else {
     87       CodecInst current_codec;
     88       ASSERT_EQ(0, acm_->SendCodec(&current_codec));
     89       if (!CodecsEqual(codec, current_codec))
     90         ASSERT_EQ(0, acm_->RegisterSendCodec(codec));
     91     }
     92     AudioFrame frame;
     93     // Frame setup according to the codec.
     94     frame.sample_rate_hz_ = codec.plfreq;
     95     frame.samples_per_channel_ = codec.plfreq / 100;  // 10 ms.
     96     frame.num_channels_ = codec.channels;
     97     memset(frame.data_, 0, frame.samples_per_channel_ * frame.num_channels_ *
     98            sizeof(int16_t));
     99     int num_bytes = 0;
    100     packet_sent_ = false;
    101     last_packet_send_timestamp_ = timestamp_;
    102     while (num_bytes == 0) {
    103       frame.timestamp_ = timestamp_;
    104       timestamp_ += frame.samples_per_channel_;
    105       ASSERT_EQ(0, acm_->Add10MsData(frame));
    106       num_bytes = acm_->Process();
    107       ASSERT_GE(num_bytes, 0);
    108     }
    109     ASSERT_TRUE(packet_sent_);  // Sanity check.
    110   }
    111 
    112   // Last element of id should be negative.
    113   void AddSetOfCodecs(const int* id) {
    114     int n = 0;
    115     while (id[n] >= 0) {
    116       ASSERT_EQ(0, receiver_->AddCodec(id[n], codecs_[id[n]].pltype,
    117                                        codecs_[id[n]].channels, NULL));
    118       ++n;
    119     }
    120   }
    121 
    122   virtual int SendData(
    123       FrameType frame_type,
    124       uint8_t payload_type,
    125       uint32_t timestamp,
    126       const uint8_t* payload_data,
    127       uint16_t payload_len_bytes,
    128       const RTPFragmentationHeader* fragmentation) OVERRIDE {
    129     if (frame_type == kFrameEmpty)
    130       return 0;
    131 
    132     rtp_header_.header.payloadType = payload_type;
    133     rtp_header_.frameType = frame_type;
    134     if (frame_type == kAudioFrameSpeech)
    135       rtp_header_.type.Audio.isCNG = false;
    136     else
    137       rtp_header_.type.Audio.isCNG = true;
    138     rtp_header_.header.timestamp = timestamp;
    139 
    140     int ret_val = receiver_->InsertPacket(rtp_header_, payload_data,
    141                                           payload_len_bytes);
    142     if (ret_val < 0) {
    143       assert(false);
    144       return -1;
    145     }
    146     rtp_header_.header.sequenceNumber++;
    147     packet_sent_ = true;
    148     last_frame_type_ = frame_type;
    149     return 0;
    150   }
    151 
    152   scoped_ptr<AcmReceiver> receiver_;
    153   CodecInst codecs_[ACMCodecDB::kMaxNumCodecs];
    154   scoped_ptr<AudioCodingModule> acm_;
    155   WebRtcRTPHeader rtp_header_;
    156   uint32_t timestamp_;
    157   bool packet_sent_;  // Set when SendData is called reset when inserting audio.
    158   uint32_t last_packet_send_timestamp_;
    159   FrameType last_frame_type_;
    160 };
    161 
    162 TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecGetCodec)) {
    163   // Add codec.
    164   for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) {
    165     if (n & 0x1)  // Just add codecs with odd index.
    166       EXPECT_EQ(0, receiver_->AddCodec(n, codecs_[n].pltype,
    167                                        codecs_[n].channels, NULL));
    168   }
    169   // Get codec and compare.
    170   for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) {
    171     CodecInst my_codec;
    172     if (n & 0x1) {
    173       // Codecs with odd index should match the reference.
    174       EXPECT_EQ(0, receiver_->DecoderByPayloadType(codecs_[n].pltype,
    175                                                    &my_codec));
    176       EXPECT_TRUE(CodecsEqual(codecs_[n], my_codec));
    177     } else {
    178       // Codecs with even index are not registered.
    179       EXPECT_EQ(-1, receiver_->DecoderByPayloadType(codecs_[n].pltype,
    180                                                     &my_codec));
    181     }
    182   }
    183 }
    184 
    185 TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecChangePayloadType)) {
    186   CodecInst ref_codec;
    187   const int codec_id = ACMCodecDB::kPCMA;
    188   EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &ref_codec));
    189   const int payload_type = ref_codec.pltype;
    190   EXPECT_EQ(0, receiver_->AddCodec(codec_id, ref_codec.pltype,
    191                                    ref_codec.channels, NULL));
    192   CodecInst test_codec;
    193   EXPECT_EQ(0, receiver_->DecoderByPayloadType(payload_type, &test_codec));
    194   EXPECT_EQ(true, CodecsEqual(ref_codec, test_codec));
    195 
    196   // Re-register the same codec with different payload.
    197   ref_codec.pltype = payload_type + 1;
    198   EXPECT_EQ(0, receiver_->AddCodec(codec_id, ref_codec.pltype,
    199                                    ref_codec.channels, NULL));
    200 
    201   // Payload type |payload_type| should not exist.
    202   EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &test_codec));
    203 
    204   // Payload type |payload_type + 1| should exist.
    205   EXPECT_EQ(0, receiver_->DecoderByPayloadType(payload_type + 1, &test_codec));
    206   EXPECT_TRUE(CodecsEqual(test_codec, ref_codec));
    207 }
    208 
    209 TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecRemoveCodec)) {
    210   CodecInst codec;
    211   const int codec_id = ACMCodecDB::kPCMA;
    212   EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &codec));
    213   const int payload_type = codec.pltype;
    214   EXPECT_EQ(0, receiver_->AddCodec(codec_id, codec.pltype,
    215                                    codec.channels, NULL));
    216 
    217   // Remove non-existing codec should not fail. ACM1 legacy.
    218   EXPECT_EQ(0, receiver_->RemoveCodec(payload_type + 1));
    219 
    220   // Remove an existing codec.
    221   EXPECT_EQ(0, receiver_->RemoveCodec(payload_type));
    222 
    223   // Ask for the removed codec, must fail.
    224   EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &codec));
    225 }
    226 
    227 TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(SampleRate)) {
    228   const int kCodecId[] = {
    229       ACMCodecDB::kISAC, ACMCodecDB::kISACSWB, ACMCodecDB::kISACFB,
    230       -1  // Terminator.
    231   };
    232   AddSetOfCodecs(kCodecId);
    233 
    234   AudioFrame frame;
    235   const int kOutSampleRateHz = 8000;  // Different than codec sample rate.
    236   int n = 0;
    237   while (kCodecId[n] >= 0) {
    238     const int num_10ms_frames = codecs_[kCodecId[n]].pacsize /
    239         (codecs_[kCodecId[n]].plfreq / 100);
    240     InsertOnePacketOfSilence(kCodecId[n]);
    241     for (int k = 0; k < num_10ms_frames; ++k) {
    242       EXPECT_EQ(0, receiver_->GetAudio(kOutSampleRateHz, &frame));
    243     }
    244     EXPECT_EQ(std::min(32000, codecs_[kCodecId[n]].plfreq),
    245               receiver_->current_sample_rate_hz());
    246     ++n;
    247   }
    248 }
    249 
    250 // Verify that the playout mode is set correctly.
    251 TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(PlayoutMode)) {
    252   receiver_->SetPlayoutMode(voice);
    253   EXPECT_EQ(voice, receiver_->PlayoutMode());
    254 
    255   receiver_->SetPlayoutMode(streaming);
    256   EXPECT_EQ(streaming, receiver_->PlayoutMode());
    257 
    258   receiver_->SetPlayoutMode(fax);
    259   EXPECT_EQ(fax, receiver_->PlayoutMode());
    260 
    261   receiver_->SetPlayoutMode(off);
    262   EXPECT_EQ(off, receiver_->PlayoutMode());
    263 }
    264 
    265 TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(PostdecodingVad)) {
    266   receiver_->EnableVad();
    267   EXPECT_TRUE(receiver_->vad_enabled());
    268 
    269   const int id = ACMCodecDB::kPCM16Bwb;
    270   ASSERT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels,
    271                                    NULL));
    272   const int kNumPackets = 5;
    273   const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100);
    274   AudioFrame frame;
    275   for (int n = 0; n < kNumPackets; ++n) {
    276     InsertOnePacketOfSilence(id);
    277     for (int k = 0; k < num_10ms_frames; ++k)
    278       ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
    279   }
    280   EXPECT_EQ(AudioFrame::kVadPassive, frame.vad_activity_);
    281 
    282   receiver_->DisableVad();
    283   EXPECT_FALSE(receiver_->vad_enabled());
    284 
    285   for (int n = 0; n < kNumPackets; ++n) {
    286     InsertOnePacketOfSilence(id);
    287     for (int k = 0; k < num_10ms_frames; ++k)
    288       ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
    289   }
    290   EXPECT_EQ(AudioFrame::kVadUnknown, frame.vad_activity_);
    291 }
    292 
    293 TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(LastAudioCodec)) {
    294   const int kCodecId[] = {
    295       ACMCodecDB::kISAC, ACMCodecDB::kPCMA, ACMCodecDB::kISACSWB,
    296       ACMCodecDB::kPCM16Bswb32kHz, ACMCodecDB::kG722_1C_48,
    297       -1  // Terminator.
    298   };
    299   AddSetOfCodecs(kCodecId);
    300 
    301   const int kCngId[] = {  // Not including full-band.
    302       ACMCodecDB::kCNNB, ACMCodecDB::kCNWB, ACMCodecDB::kCNSWB,
    303       -1  // Terminator.
    304   };
    305   AddSetOfCodecs(kCngId);
    306 
    307   // Register CNG at sender side.
    308   int n = 0;
    309   while (kCngId[n] > 0) {
    310     ASSERT_EQ(0, acm_->RegisterSendCodec(codecs_[kCngId[n]]));
    311     ++n;
    312   }
    313 
    314   CodecInst codec;
    315   // No audio payload is received.
    316   EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
    317 
    318   // Start with sending DTX.
    319   ASSERT_EQ(0, acm_->SetVAD(true, true, VADVeryAggr));
    320   packet_sent_ = false;
    321   InsertOnePacketOfSilence(kCodecId[0]);  // Enough to test with one codec.
    322   ASSERT_TRUE(packet_sent_);
    323   EXPECT_EQ(kAudioFrameCN, last_frame_type_);
    324 
    325   // Has received, only, DTX. Last Audio codec is undefined.
    326   EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
    327   EXPECT_EQ(-1, receiver_->last_audio_codec_id());
    328   EXPECT_EQ(-1, receiver_->last_audio_payload_type());
    329 
    330   n = 0;
    331   while (kCodecId[n] >= 0) {  // Loop over codecs.
    332     // Set DTX off to send audio payload.
    333     acm_->SetVAD(false, false, VADAggr);
    334     packet_sent_ = false;
    335     InsertOnePacketOfSilence(kCodecId[n]);
    336 
    337     // Sanity check if Actually an audio payload received, and it should be
    338     // of type "speech."
    339     ASSERT_TRUE(packet_sent_);
    340     ASSERT_EQ(kAudioFrameSpeech, last_frame_type_);
    341     EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
    342 
    343     // Set VAD on to send DTX. Then check if the "Last Audio codec" returns
    344     // the expected codec.
    345     acm_->SetVAD(true, true, VADAggr);
    346 
    347     // Do as many encoding until a DTX is sent.
    348     while (last_frame_type_ != kAudioFrameCN) {
    349       packet_sent_ = false;
    350       InsertOnePacketOfSilence(kCodecId[n]);
    351       ASSERT_TRUE(packet_sent_);
    352     }
    353     EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
    354     EXPECT_EQ(codecs_[kCodecId[n]].pltype,
    355               receiver_->last_audio_payload_type());
    356     EXPECT_EQ(0, receiver_->LastAudioCodec(&codec));
    357     EXPECT_TRUE(CodecsEqual(codecs_[kCodecId[n]], codec));
    358     ++n;
    359   }
    360 }
    361 
    362 }  // namespace acm2
    363 
    364 }  // namespace webrtc
    365