1 /* 2 * Copyright (c) 2015 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 "testing/gtest/include/gtest/gtest.h" 12 #include "webrtc/base/arraysize.h" 13 #include "webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h" 14 #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" 15 16 namespace webrtc { 17 namespace acm2 { 18 19 using ::testing::Return; 20 21 namespace { 22 const int kDataLengthSamples = 80; 23 const int kPacketSizeSamples = 2 * kDataLengthSamples; 24 const int16_t kZeroData[kDataLengthSamples] = {0}; 25 const CodecInst kDefaultCodecInst = {0, "pcmu", 8000, kPacketSizeSamples, 26 1, 64000}; 27 const int kCngPt = 13; 28 } // namespace 29 30 class RentACodecTestF : public ::testing::Test { 31 protected: 32 void CreateCodec() { 33 speech_encoder_ = rent_a_codec_.RentEncoder(kDefaultCodecInst); 34 ASSERT_TRUE(speech_encoder_); 35 RentACodec::StackParameters param; 36 param.use_cng = true; 37 param.speech_encoder = speech_encoder_; 38 encoder_ = rent_a_codec_.RentEncoderStack(¶m); 39 } 40 41 void EncodeAndVerify(size_t expected_out_length, 42 uint32_t expected_timestamp, 43 int expected_payload_type, 44 int expected_send_even_if_empty) { 45 uint8_t out[kPacketSizeSamples]; 46 AudioEncoder::EncodedInfo encoded_info; 47 encoded_info = 48 encoder_->Encode(timestamp_, kZeroData, kPacketSizeSamples, out); 49 timestamp_ += kDataLengthSamples; 50 EXPECT_TRUE(encoded_info.redundant.empty()); 51 EXPECT_EQ(expected_out_length, encoded_info.encoded_bytes); 52 EXPECT_EQ(expected_timestamp, encoded_info.encoded_timestamp); 53 if (expected_payload_type >= 0) 54 EXPECT_EQ(expected_payload_type, encoded_info.payload_type); 55 if (expected_send_even_if_empty >= 0) 56 EXPECT_EQ(static_cast<bool>(expected_send_even_if_empty), 57 encoded_info.send_even_if_empty); 58 } 59 60 RentACodec rent_a_codec_; 61 AudioEncoder* speech_encoder_ = nullptr; 62 AudioEncoder* encoder_ = nullptr; 63 uint32_t timestamp_ = 0; 64 }; 65 66 // This test verifies that CNG frames are delivered as expected. Since the frame 67 // size is set to 20 ms, we expect the first encode call to produce no output 68 // (which is signaled as 0 bytes output of type kNoEncoding). The next encode 69 // call should produce one SID frame of 9 bytes. The third call should not 70 // result in any output (just like the first one). The fourth and final encode 71 // call should produce an "empty frame", which is like no output, but with 72 // AudioEncoder::EncodedInfo::send_even_if_empty set to true. (The reason to 73 // produce an empty frame is to drive sending of DTMF packets in the RTP/RTCP 74 // module.) 75 TEST_F(RentACodecTestF, VerifyCngFrames) { 76 CreateCodec(); 77 uint32_t expected_timestamp = timestamp_; 78 // Verify no frame. 79 { 80 SCOPED_TRACE("First encoding"); 81 EncodeAndVerify(0, expected_timestamp, -1, -1); 82 } 83 84 // Verify SID frame delivered. 85 { 86 SCOPED_TRACE("Second encoding"); 87 EncodeAndVerify(9, expected_timestamp, kCngPt, 1); 88 } 89 90 // Verify no frame. 91 { 92 SCOPED_TRACE("Third encoding"); 93 EncodeAndVerify(0, expected_timestamp, -1, -1); 94 } 95 96 // Verify NoEncoding. 97 expected_timestamp += 2 * kDataLengthSamples; 98 { 99 SCOPED_TRACE("Fourth encoding"); 100 EncodeAndVerify(0, expected_timestamp, kCngPt, 1); 101 } 102 } 103 104 TEST(RentACodecTest, ExternalEncoder) { 105 const int kSampleRateHz = 8000; 106 MockAudioEncoder external_encoder; 107 EXPECT_CALL(external_encoder, SampleRateHz()) 108 .WillRepeatedly(Return(kSampleRateHz)); 109 EXPECT_CALL(external_encoder, NumChannels()).WillRepeatedly(Return(1)); 110 EXPECT_CALL(external_encoder, SetFec(false)).WillRepeatedly(Return(true)); 111 112 RentACodec rac; 113 RentACodec::StackParameters param; 114 param.speech_encoder = &external_encoder; 115 EXPECT_EQ(&external_encoder, rac.RentEncoderStack(¶m)); 116 const int kPacketSizeSamples = kSampleRateHz / 100; 117 int16_t audio[kPacketSizeSamples] = {0}; 118 uint8_t encoded[kPacketSizeSamples]; 119 AudioEncoder::EncodedInfo info; 120 121 { 122 ::testing::InSequence s; 123 info.encoded_timestamp = 0; 124 EXPECT_CALL(external_encoder, 125 EncodeInternal(0, rtc::ArrayView<const int16_t>(audio), 126 arraysize(encoded), encoded)) 127 .WillOnce(Return(info)); 128 EXPECT_CALL(external_encoder, Mark("A")); 129 EXPECT_CALL(external_encoder, Mark("B")); 130 info.encoded_timestamp = 2; 131 EXPECT_CALL(external_encoder, 132 EncodeInternal(2, rtc::ArrayView<const int16_t>(audio), 133 arraysize(encoded), encoded)) 134 .WillOnce(Return(info)); 135 EXPECT_CALL(external_encoder, Die()); 136 } 137 138 info = rac.GetEncoderStack()->Encode(0, audio, arraysize(encoded), encoded); 139 EXPECT_EQ(0u, info.encoded_timestamp); 140 external_encoder.Mark("A"); 141 142 // Change to internal encoder. 143 CodecInst codec_inst = kDefaultCodecInst; 144 codec_inst.pacsize = kPacketSizeSamples; 145 param.speech_encoder = rac.RentEncoder(codec_inst); 146 ASSERT_TRUE(param.speech_encoder); 147 EXPECT_EQ(param.speech_encoder, rac.RentEncoderStack(¶m)); 148 149 // Don't expect any more calls to the external encoder. 150 info = rac.GetEncoderStack()->Encode(1, audio, arraysize(encoded), encoded); 151 external_encoder.Mark("B"); 152 153 // Change back to external encoder again. 154 param.speech_encoder = &external_encoder; 155 EXPECT_EQ(&external_encoder, rac.RentEncoderStack(¶m)); 156 info = rac.GetEncoderStack()->Encode(2, audio, arraysize(encoded), encoded); 157 EXPECT_EQ(2u, info.encoded_timestamp); 158 } 159 160 // Verify that the speech encoder's Reset method is called when CNG or RED 161 // (or both) are switched on, but not when they're switched off. 162 void TestCngAndRedResetSpeechEncoder(bool use_cng, bool use_red) { 163 MockAudioEncoder speech_encoder; 164 EXPECT_CALL(speech_encoder, NumChannels()).WillRepeatedly(Return(1)); 165 EXPECT_CALL(speech_encoder, Max10MsFramesInAPacket()) 166 .WillRepeatedly(Return(2)); 167 EXPECT_CALL(speech_encoder, SampleRateHz()).WillRepeatedly(Return(8000)); 168 EXPECT_CALL(speech_encoder, SetFec(false)).WillRepeatedly(Return(true)); 169 { 170 ::testing::InSequence s; 171 EXPECT_CALL(speech_encoder, Mark("disabled")); 172 EXPECT_CALL(speech_encoder, Mark("enabled")); 173 if (use_cng || use_red) 174 EXPECT_CALL(speech_encoder, Reset()); 175 EXPECT_CALL(speech_encoder, Die()); 176 } 177 178 RentACodec::StackParameters param1, param2; 179 param1.speech_encoder = &speech_encoder; 180 param2.speech_encoder = &speech_encoder; 181 param2.use_cng = use_cng; 182 param2.use_red = use_red; 183 speech_encoder.Mark("disabled"); 184 RentACodec rac; 185 rac.RentEncoderStack(¶m1); 186 speech_encoder.Mark("enabled"); 187 rac.RentEncoderStack(¶m2); 188 } 189 190 TEST(RentACodecTest, CngResetsSpeechEncoder) { 191 TestCngAndRedResetSpeechEncoder(true, false); 192 } 193 194 TEST(RentACodecTest, RedResetsSpeechEncoder) { 195 TestCngAndRedResetSpeechEncoder(false, true); 196 } 197 198 TEST(RentACodecTest, CngAndRedResetsSpeechEncoder) { 199 TestCngAndRedResetSpeechEncoder(true, true); 200 } 201 202 TEST(RentACodecTest, NoCngAndRedNoSpeechEncoderReset) { 203 TestCngAndRedResetSpeechEncoder(false, false); 204 } 205 206 TEST(RentACodecTest, RentEncoderError) { 207 const CodecInst codec_inst = { 208 0, "Robert'); DROP TABLE Students;", 8000, 160, 1, 64000}; 209 RentACodec rent_a_codec; 210 EXPECT_FALSE(rent_a_codec.RentEncoder(codec_inst)); 211 } 212 213 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 214 TEST(RentACodecTest, RentEncoderStackWithoutSpeechEncoder) { 215 RentACodec::StackParameters sp; 216 EXPECT_EQ(nullptr, sp.speech_encoder); 217 EXPECT_DEATH(RentACodec().RentEncoderStack(&sp), ""); 218 } 219 #endif 220 221 } // namespace acm2 222 } // namespace webrtc 223