OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
12 #include "webrtc/base/arraysize.h" | 12 #include "webrtc/base/arraysize.h" |
13 #include "webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h" | 13 #include "webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h" |
14 #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" | 14 #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" |
15 | 15 |
16 namespace webrtc { | 16 namespace webrtc { |
17 namespace acm2 { | 17 namespace acm2 { |
18 | 18 |
19 using ::testing::Return; | 19 using ::testing::Return; |
20 | 20 |
21 namespace { | 21 namespace { |
| 22 |
22 const int kDataLengthSamples = 80; | 23 const int kDataLengthSamples = 80; |
23 const int kPacketSizeSamples = 2 * kDataLengthSamples; | 24 const int kPacketSizeSamples = 2 * kDataLengthSamples; |
24 const int16_t kZeroData[kDataLengthSamples] = {0}; | 25 const int16_t kZeroData[kDataLengthSamples] = {0}; |
25 const CodecInst kDefaultCodecInst = {0, "pcmu", 8000, kPacketSizeSamples, | 26 const CodecInst kDefaultCodecInst = {0, "pcmu", 8000, kPacketSizeSamples, |
26 1, 64000}; | 27 1, 64000}; |
27 const int kCngPt = 13; | 28 const int kCngPt = 13; |
| 29 |
| 30 class Marker final { |
| 31 public: |
| 32 MOCK_METHOD1(Mark, void(std::string desc)); |
| 33 }; |
| 34 |
28 } // namespace | 35 } // namespace |
29 | 36 |
30 class RentACodecTestF : public ::testing::Test { | 37 class RentACodecTestF : public ::testing::Test { |
31 protected: | 38 protected: |
32 void CreateCodec() { | 39 void CreateCodec() { |
33 speech_encoder_ = rent_a_codec_.RentEncoder(kDefaultCodecInst); | 40 auto speech_encoder = rent_a_codec_.RentEncoder(kDefaultCodecInst); |
34 ASSERT_TRUE(speech_encoder_); | 41 ASSERT_TRUE(speech_encoder); |
35 RentACodec::StackParameters param; | 42 RentACodec::StackParameters param; |
36 param.use_cng = true; | 43 param.use_cng = true; |
37 param.speech_encoder = speech_encoder_; | 44 param.speech_encoder = std::move(speech_encoder); |
38 encoder_ = rent_a_codec_.RentEncoderStack(¶m); | 45 encoder_ = rent_a_codec_.RentEncoderStack(¶m); |
39 } | 46 } |
40 | 47 |
41 void EncodeAndVerify(size_t expected_out_length, | 48 void EncodeAndVerify(size_t expected_out_length, |
42 uint32_t expected_timestamp, | 49 uint32_t expected_timestamp, |
43 int expected_payload_type, | 50 int expected_payload_type, |
44 int expected_send_even_if_empty) { | 51 int expected_send_even_if_empty) { |
45 rtc::Buffer out; | 52 rtc::Buffer out; |
46 AudioEncoder::EncodedInfo encoded_info; | 53 AudioEncoder::EncodedInfo encoded_info; |
47 encoded_info = | 54 encoded_info = |
48 encoder_->Encode(timestamp_, kZeroData, &out); | 55 encoder_->Encode(timestamp_, kZeroData, &out); |
49 timestamp_ += kDataLengthSamples; | 56 timestamp_ += kDataLengthSamples; |
50 EXPECT_TRUE(encoded_info.redundant.empty()); | 57 EXPECT_TRUE(encoded_info.redundant.empty()); |
51 EXPECT_EQ(expected_out_length, encoded_info.encoded_bytes); | 58 EXPECT_EQ(expected_out_length, encoded_info.encoded_bytes); |
52 EXPECT_EQ(expected_timestamp, encoded_info.encoded_timestamp); | 59 EXPECT_EQ(expected_timestamp, encoded_info.encoded_timestamp); |
53 if (expected_payload_type >= 0) | 60 if (expected_payload_type >= 0) |
54 EXPECT_EQ(expected_payload_type, encoded_info.payload_type); | 61 EXPECT_EQ(expected_payload_type, encoded_info.payload_type); |
55 if (expected_send_even_if_empty >= 0) | 62 if (expected_send_even_if_empty >= 0) |
56 EXPECT_EQ(static_cast<bool>(expected_send_even_if_empty), | 63 EXPECT_EQ(static_cast<bool>(expected_send_even_if_empty), |
57 encoded_info.send_even_if_empty); | 64 encoded_info.send_even_if_empty); |
58 } | 65 } |
59 | 66 |
60 RentACodec rent_a_codec_; | 67 RentACodec rent_a_codec_; |
61 AudioEncoder* speech_encoder_ = nullptr; | 68 std::unique_ptr<AudioEncoder> encoder_; |
62 AudioEncoder* encoder_ = nullptr; | |
63 uint32_t timestamp_ = 0; | 69 uint32_t timestamp_ = 0; |
64 }; | 70 }; |
65 | 71 |
66 // This test verifies that CNG frames are delivered as expected. Since the frame | 72 // 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 | 73 // 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 | 74 // (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 | 75 // 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 | 76 // 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 | 77 // 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 | 78 // AudioEncoder::EncodedInfo::send_even_if_empty set to true. (The reason to |
(...skipping 23 matching lines...) Expand all Loading... |
96 // Verify NoEncoding. | 102 // Verify NoEncoding. |
97 expected_timestamp += 2 * kDataLengthSamples; | 103 expected_timestamp += 2 * kDataLengthSamples; |
98 { | 104 { |
99 SCOPED_TRACE("Fourth encoding"); | 105 SCOPED_TRACE("Fourth encoding"); |
100 EncodeAndVerify(0, expected_timestamp, kCngPt, 1); | 106 EncodeAndVerify(0, expected_timestamp, kCngPt, 1); |
101 } | 107 } |
102 } | 108 } |
103 | 109 |
104 TEST(RentACodecTest, ExternalEncoder) { | 110 TEST(RentACodecTest, ExternalEncoder) { |
105 const int kSampleRateHz = 8000; | 111 const int kSampleRateHz = 8000; |
106 MockAudioEncoder external_encoder; | 112 auto* external_encoder = new MockAudioEncoder; |
107 EXPECT_CALL(external_encoder, SampleRateHz()) | 113 EXPECT_CALL(*external_encoder, SampleRateHz()) |
108 .WillRepeatedly(Return(kSampleRateHz)); | 114 .WillRepeatedly(Return(kSampleRateHz)); |
109 EXPECT_CALL(external_encoder, NumChannels()).WillRepeatedly(Return(1)); | 115 EXPECT_CALL(*external_encoder, NumChannels()).WillRepeatedly(Return(1)); |
110 EXPECT_CALL(external_encoder, SetFec(false)).WillRepeatedly(Return(true)); | 116 EXPECT_CALL(*external_encoder, SetFec(false)).WillRepeatedly(Return(true)); |
111 | 117 |
112 RentACodec rac; | 118 RentACodec rac; |
113 RentACodec::StackParameters param; | 119 RentACodec::StackParameters param; |
114 param.speech_encoder = &external_encoder; | 120 param.speech_encoder = std::unique_ptr<AudioEncoder>(external_encoder); |
115 EXPECT_EQ(&external_encoder, rac.RentEncoderStack(¶m)); | 121 std::unique_ptr<AudioEncoder> encoder_stack = rac.RentEncoderStack(¶m); |
| 122 EXPECT_EQ(external_encoder, encoder_stack.get()); |
116 const int kPacketSizeSamples = kSampleRateHz / 100; | 123 const int kPacketSizeSamples = kSampleRateHz / 100; |
117 int16_t audio[kPacketSizeSamples] = {0}; | 124 int16_t audio[kPacketSizeSamples] = {0}; |
118 rtc::Buffer encoded; | 125 rtc::Buffer encoded; |
119 AudioEncoder::EncodedInfo info; | 126 AudioEncoder::EncodedInfo info; |
120 | 127 |
| 128 Marker marker; |
121 { | 129 { |
122 ::testing::InSequence s; | 130 ::testing::InSequence s; |
123 info.encoded_timestamp = 0; | 131 info.encoded_timestamp = 0; |
124 EXPECT_CALL(external_encoder, | 132 EXPECT_CALL( |
125 EncodeImpl(0, rtc::ArrayView<const int16_t>(audio), | 133 *external_encoder, |
126 &encoded)) | 134 EncodeImpl(0, rtc::ArrayView<const int16_t>(audio), &encoded)) |
127 .WillOnce(Return(info)); | 135 .WillOnce(Return(info)); |
128 EXPECT_CALL(external_encoder, Mark("A")); | 136 EXPECT_CALL(marker, Mark("A")); |
129 EXPECT_CALL(external_encoder, Mark("B")); | 137 EXPECT_CALL(marker, Mark("B")); |
130 info.encoded_timestamp = 2; | 138 EXPECT_CALL(*external_encoder, Die()); |
131 EXPECT_CALL(external_encoder, | 139 EXPECT_CALL(marker, Mark("C")); |
132 EncodeImpl(2, rtc::ArrayView<const int16_t>(audio), | |
133 &encoded)) | |
134 .WillOnce(Return(info)); | |
135 EXPECT_CALL(external_encoder, Die()); | |
136 } | 140 } |
137 | 141 |
138 info = external_encoder.Encode(0, audio, &encoded); | 142 info = encoder_stack->Encode(0, audio, &encoded); |
139 EXPECT_EQ(0u, info.encoded_timestamp); | 143 EXPECT_EQ(0u, info.encoded_timestamp); |
140 external_encoder.Mark("A"); | 144 marker.Mark("A"); |
141 | 145 |
142 // Change to internal encoder. | 146 // Change to internal encoder. |
143 CodecInst codec_inst = kDefaultCodecInst; | 147 CodecInst codec_inst = kDefaultCodecInst; |
144 codec_inst.pacsize = kPacketSizeSamples; | 148 codec_inst.pacsize = kPacketSizeSamples; |
145 param.speech_encoder = rac.RentEncoder(codec_inst); | 149 param.speech_encoder = rac.RentEncoder(codec_inst); |
146 ASSERT_TRUE(param.speech_encoder); | 150 ASSERT_TRUE(param.speech_encoder); |
147 EXPECT_EQ(param.speech_encoder, rac.RentEncoderStack(¶m)); | 151 AudioEncoder* enc = param.speech_encoder.get(); |
| 152 std::unique_ptr<AudioEncoder> stack = rac.RentEncoderStack(¶m); |
| 153 EXPECT_EQ(enc, stack.get()); |
148 | 154 |
149 // Don't expect any more calls to the external encoder. | 155 // Don't expect any more calls to the external encoder. |
150 info = param.speech_encoder->Encode(1, audio, &encoded); | 156 info = stack->Encode(1, audio, &encoded); |
151 external_encoder.Mark("B"); | 157 marker.Mark("B"); |
152 | 158 encoder_stack.reset(); |
153 // Change back to external encoder again. | 159 marker.Mark("C"); |
154 param.speech_encoder = &external_encoder; | |
155 EXPECT_EQ(&external_encoder, rac.RentEncoderStack(¶m)); | |
156 info = external_encoder.Encode(2, audio, &encoded); | |
157 EXPECT_EQ(2u, info.encoded_timestamp); | |
158 } | 160 } |
159 | 161 |
160 // Verify that the speech encoder's Reset method is called when CNG or RED | 162 // 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. | 163 // (or both) are switched on, but not when they're switched off. |
162 void TestCngAndRedResetSpeechEncoder(bool use_cng, bool use_red) { | 164 void TestCngAndRedResetSpeechEncoder(bool use_cng, bool use_red) { |
163 MockAudioEncoder speech_encoder; | 165 auto make_enc = [] { |
164 EXPECT_CALL(speech_encoder, NumChannels()).WillRepeatedly(Return(1)); | 166 auto speech_encoder = |
165 EXPECT_CALL(speech_encoder, Max10MsFramesInAPacket()) | 167 std::unique_ptr<MockAudioEncoder>(new MockAudioEncoder); |
166 .WillRepeatedly(Return(2)); | 168 EXPECT_CALL(*speech_encoder, NumChannels()).WillRepeatedly(Return(1)); |
167 EXPECT_CALL(speech_encoder, SampleRateHz()).WillRepeatedly(Return(8000)); | 169 EXPECT_CALL(*speech_encoder, Max10MsFramesInAPacket()) |
168 EXPECT_CALL(speech_encoder, SetFec(false)).WillRepeatedly(Return(true)); | 170 .WillRepeatedly(Return(2)); |
| 171 EXPECT_CALL(*speech_encoder, SampleRateHz()).WillRepeatedly(Return(8000)); |
| 172 EXPECT_CALL(*speech_encoder, SetFec(false)).WillRepeatedly(Return(true)); |
| 173 return speech_encoder; |
| 174 }; |
| 175 auto speech_encoder1 = make_enc(); |
| 176 auto speech_encoder2 = make_enc(); |
| 177 Marker marker; |
169 { | 178 { |
170 ::testing::InSequence s; | 179 ::testing::InSequence s; |
171 EXPECT_CALL(speech_encoder, Mark("disabled")); | 180 EXPECT_CALL(marker, Mark("disabled")); |
172 EXPECT_CALL(speech_encoder, Mark("enabled")); | 181 EXPECT_CALL(*speech_encoder1, Die()); |
| 182 EXPECT_CALL(marker, Mark("enabled")); |
173 if (use_cng || use_red) | 183 if (use_cng || use_red) |
174 EXPECT_CALL(speech_encoder, Reset()); | 184 EXPECT_CALL(*speech_encoder2, Reset()); |
175 EXPECT_CALL(speech_encoder, Die()); | 185 EXPECT_CALL(*speech_encoder2, Die()); |
176 } | 186 } |
177 | 187 |
178 RentACodec::StackParameters param1, param2; | 188 RentACodec::StackParameters param1, param2; |
179 param1.speech_encoder = &speech_encoder; | 189 param1.speech_encoder = std::move(speech_encoder1); |
180 param2.speech_encoder = &speech_encoder; | 190 param2.speech_encoder = std::move(speech_encoder2); |
181 param2.use_cng = use_cng; | 191 param2.use_cng = use_cng; |
182 param2.use_red = use_red; | 192 param2.use_red = use_red; |
183 speech_encoder.Mark("disabled"); | 193 marker.Mark("disabled"); |
184 RentACodec rac; | 194 RentACodec rac; |
185 rac.RentEncoderStack(¶m1); | 195 rac.RentEncoderStack(¶m1); |
186 speech_encoder.Mark("enabled"); | 196 marker.Mark("enabled"); |
187 rac.RentEncoderStack(¶m2); | 197 rac.RentEncoderStack(¶m2); |
188 } | 198 } |
189 | 199 |
190 TEST(RentACodecTest, CngResetsSpeechEncoder) { | 200 TEST(RentACodecTest, CngResetsSpeechEncoder) { |
191 TestCngAndRedResetSpeechEncoder(true, false); | 201 TestCngAndRedResetSpeechEncoder(true, false); |
192 } | 202 } |
193 | 203 |
194 TEST(RentACodecTest, RedResetsSpeechEncoder) { | 204 TEST(RentACodecTest, RedResetsSpeechEncoder) { |
195 TestCngAndRedResetSpeechEncoder(false, true); | 205 TestCngAndRedResetSpeechEncoder(false, true); |
196 } | 206 } |
(...skipping 16 matching lines...) Expand all Loading... |
213 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) | 223 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) |
214 TEST(RentACodecTest, RentEncoderStackWithoutSpeechEncoder) { | 224 TEST(RentACodecTest, RentEncoderStackWithoutSpeechEncoder) { |
215 RentACodec::StackParameters sp; | 225 RentACodec::StackParameters sp; |
216 EXPECT_EQ(nullptr, sp.speech_encoder); | 226 EXPECT_EQ(nullptr, sp.speech_encoder); |
217 EXPECT_DEATH(RentACodec().RentEncoderStack(&sp), ""); | 227 EXPECT_DEATH(RentACodec().RentEncoderStack(&sp), ""); |
218 } | 228 } |
219 #endif | 229 #endif |
220 | 230 |
221 } // namespace acm2 | 231 } // namespace acm2 |
222 } // namespace webrtc | 232 } // namespace webrtc |
OLD | NEW |