OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 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 |
(...skipping 29 matching lines...) Expand all Loading... |
40 AudioEncoderCopyRed::Config config; | 40 AudioEncoderCopyRed::Config config; |
41 config.payload_type = red_payload_type_; | 41 config.payload_type = red_payload_type_; |
42 config.speech_encoder = &mock_encoder_; | 42 config.speech_encoder = &mock_encoder_; |
43 red_.reset(new AudioEncoderCopyRed(config)); | 43 red_.reset(new AudioEncoderCopyRed(config)); |
44 memset(audio_, 0, sizeof(audio_)); | 44 memset(audio_, 0, sizeof(audio_)); |
45 EXPECT_CALL(mock_encoder_, NumChannels()).WillRepeatedly(Return(1U)); | 45 EXPECT_CALL(mock_encoder_, NumChannels()).WillRepeatedly(Return(1U)); |
46 EXPECT_CALL(mock_encoder_, SampleRateHz()) | 46 EXPECT_CALL(mock_encoder_, SampleRateHz()) |
47 .WillRepeatedly(Return(sample_rate_hz_)); | 47 .WillRepeatedly(Return(sample_rate_hz_)); |
48 EXPECT_CALL(mock_encoder_, MaxEncodedBytes()) | 48 EXPECT_CALL(mock_encoder_, MaxEncodedBytes()) |
49 .WillRepeatedly(Return(kMockMaxEncodedBytes)); | 49 .WillRepeatedly(Return(kMockMaxEncodedBytes)); |
50 encoded_.resize(red_->MaxEncodedBytes(), 0); | |
51 } | 50 } |
52 | 51 |
53 void TearDown() override { | 52 void TearDown() override { |
54 red_.reset(); | 53 red_.reset(); |
55 // Don't expect the red_ object to delete the AudioEncoder object. But it | 54 // Don't expect the red_ object to delete the AudioEncoder object. But it |
56 // will be deleted with the test fixture. This is why we explicitly delete | 55 // will be deleted with the test fixture. This is why we explicitly delete |
57 // the red_ object above, and set expectations on mock_encoder_ afterwards. | 56 // the red_ object above, and set expectations on mock_encoder_ afterwards. |
58 EXPECT_CALL(mock_encoder_, Die()).Times(1); | 57 EXPECT_CALL(mock_encoder_, Die()).Times(1); |
59 } | 58 } |
60 | 59 |
61 void Encode() { | 60 void Encode() { |
62 ASSERT_TRUE(red_.get() != NULL); | 61 ASSERT_TRUE(red_.get() != NULL); |
| 62 encoded_.Clear(); |
63 encoded_info_ = red_->Encode( | 63 encoded_info_ = red_->Encode( |
64 timestamp_, | 64 timestamp_, |
65 rtc::ArrayView<const int16_t>(audio_, num_audio_samples_10ms), | 65 rtc::ArrayView<const int16_t>(audio_, num_audio_samples_10ms), |
66 encoded_.size(), &encoded_[0]); | 66 &encoded_); |
67 timestamp_ += num_audio_samples_10ms; | 67 timestamp_ += num_audio_samples_10ms; |
68 } | 68 } |
69 | 69 |
70 MockAudioEncoder mock_encoder_; | 70 MockAudioEncoder mock_encoder_; |
71 std::unique_ptr<AudioEncoderCopyRed> red_; | 71 std::unique_ptr<AudioEncoderCopyRed> red_; |
72 uint32_t timestamp_; | 72 uint32_t timestamp_; |
73 int16_t audio_[kMaxNumSamples]; | 73 int16_t audio_[kMaxNumSamples]; |
74 const int sample_rate_hz_; | 74 const int sample_rate_hz_; |
75 size_t num_audio_samples_10ms; | 75 size_t num_audio_samples_10ms; |
76 std::vector<uint8_t> encoded_; | 76 rtc::Buffer encoded_; |
77 AudioEncoder::EncodedInfo encoded_info_; | 77 AudioEncoder::EncodedInfo encoded_info_; |
78 const int red_payload_type_; | 78 const int red_payload_type_; |
79 }; | 79 }; |
80 | 80 |
81 class MockEncodeHelper { | |
82 public: | |
83 MockEncodeHelper() : write_payload_(false), payload_(NULL) { | |
84 memset(&info_, 0, sizeof(info_)); | |
85 } | |
86 | |
87 AudioEncoder::EncodedInfo Encode(uint32_t timestamp, | |
88 rtc::ArrayView<const int16_t> audio, | |
89 size_t max_encoded_bytes, | |
90 uint8_t* encoded) { | |
91 if (write_payload_) { | |
92 RTC_CHECK(encoded); | |
93 RTC_CHECK_LE(info_.encoded_bytes, max_encoded_bytes); | |
94 memcpy(encoded, payload_, info_.encoded_bytes); | |
95 } | |
96 return info_; | |
97 } | |
98 | |
99 AudioEncoder::EncodedInfo info_; | |
100 bool write_payload_; | |
101 uint8_t* payload_; | |
102 }; | |
103 | |
104 TEST_F(AudioEncoderCopyRedTest, CreateAndDestroy) { | 81 TEST_F(AudioEncoderCopyRedTest, CreateAndDestroy) { |
105 } | 82 } |
106 | 83 |
107 TEST_F(AudioEncoderCopyRedTest, CheckSampleRatePropagation) { | 84 TEST_F(AudioEncoderCopyRedTest, CheckSampleRatePropagation) { |
108 EXPECT_CALL(mock_encoder_, SampleRateHz()).WillOnce(Return(17)); | 85 EXPECT_CALL(mock_encoder_, SampleRateHz()).WillOnce(Return(17)); |
109 EXPECT_EQ(17, red_->SampleRateHz()); | 86 EXPECT_EQ(17, red_->SampleRateHz()); |
110 } | 87 } |
111 | 88 |
112 TEST_F(AudioEncoderCopyRedTest, CheckNumChannelsPropagation) { | 89 TEST_F(AudioEncoderCopyRedTest, CheckNumChannelsPropagation) { |
113 EXPECT_CALL(mock_encoder_, NumChannels()).WillOnce(Return(17U)); | 90 EXPECT_CALL(mock_encoder_, NumChannels()).WillOnce(Return(17U)); |
(...skipping 22 matching lines...) Expand all Loading... |
136 | 113 |
137 // Checks that the an Encode() call is immediately propagated to the speech | 114 // Checks that the an Encode() call is immediately propagated to the speech |
138 // encoder. | 115 // encoder. |
139 TEST_F(AudioEncoderCopyRedTest, CheckImmediateEncode) { | 116 TEST_F(AudioEncoderCopyRedTest, CheckImmediateEncode) { |
140 // Interleaving the EXPECT_CALL sequence with expectations on the MockFunction | 117 // Interleaving the EXPECT_CALL sequence with expectations on the MockFunction |
141 // check ensures that exactly one call to EncodeInternal happens in each | 118 // check ensures that exactly one call to EncodeInternal happens in each |
142 // Encode call. | 119 // Encode call. |
143 InSequence s; | 120 InSequence s; |
144 MockFunction<void(int check_point_id)> check; | 121 MockFunction<void(int check_point_id)> check; |
145 for (int i = 1; i <= 6; ++i) { | 122 for (int i = 1; i <= 6; ++i) { |
146 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) | 123 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)) |
147 .WillRepeatedly(Return(AudioEncoder::EncodedInfo())); | 124 .WillRepeatedly(Return(AudioEncoder::EncodedInfo())); |
148 EXPECT_CALL(check, Call(i)); | 125 EXPECT_CALL(check, Call(i)); |
149 Encode(); | 126 Encode(); |
150 check.Call(i); | 127 check.Call(i); |
151 } | 128 } |
152 } | 129 } |
153 | 130 |
154 // Checks that no output is produced if the underlying codec doesn't emit any | 131 // Checks that no output is produced if the underlying codec doesn't emit any |
155 // new data, even if the RED codec is loaded with a secondary encoding. | 132 // new data, even if the RED codec is loaded with a secondary encoding. |
156 TEST_F(AudioEncoderCopyRedTest, CheckNoOutput) { | 133 TEST_F(AudioEncoderCopyRedTest, CheckNoOutput) { |
157 // Start with one Encode() call that will produce output. | 134 // Start with one Encode() call that will produce output. |
158 static const size_t kEncodedSize = 17; | 135 static const size_t kEncodedSize = 17; |
159 AudioEncoder::EncodedInfo info; | 136 MockAudioEncoderHelper helper; |
160 info.encoded_bytes = kEncodedSize; | 137 helper.info_.encoded_bytes = kEncodedSize; |
161 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) | 138 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)) |
162 .WillOnce(Return(info)); | 139 .WillRepeatedly(Invoke(&helper, &MockAudioEncoderHelper::Encode)); |
163 Encode(); | 140 Encode(); |
164 // First call is a special case, since it does not include a secondary | 141 // First call is a special case, since it does not include a secondary |
165 // payload. | 142 // payload. |
166 EXPECT_EQ(1u, encoded_info_.redundant.size()); | 143 EXPECT_EQ(1u, encoded_info_.redundant.size()); |
167 EXPECT_EQ(kEncodedSize, encoded_info_.encoded_bytes); | 144 EXPECT_EQ(kEncodedSize, encoded_info_.encoded_bytes); |
168 | 145 |
169 // Next call to the speech encoder will not produce any output. | 146 // Next call to the speech encoder will not produce any output. |
170 info.encoded_bytes = 0; | 147 helper.info_.encoded_bytes = 0; |
171 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) | |
172 .WillOnce(Return(info)); | |
173 Encode(); | 148 Encode(); |
174 EXPECT_EQ(0u, encoded_info_.encoded_bytes); | 149 EXPECT_EQ(0u, encoded_info_.encoded_bytes); |
175 | 150 |
176 // Final call to the speech encoder will produce output. | 151 // Final call to the speech encoder will produce output. |
177 info.encoded_bytes = kEncodedSize; | 152 helper.info_.encoded_bytes = kEncodedSize; |
178 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) | |
179 .WillOnce(Return(info)); | |
180 Encode(); | 153 Encode(); |
181 EXPECT_EQ(2 * kEncodedSize, encoded_info_.encoded_bytes); | 154 EXPECT_EQ(2 * kEncodedSize, encoded_info_.encoded_bytes); |
182 ASSERT_EQ(2u, encoded_info_.redundant.size()); | 155 ASSERT_EQ(2u, encoded_info_.redundant.size()); |
183 } | 156 } |
184 | 157 |
185 // Checks that the correct payload sizes are populated into the redundancy | 158 // Checks that the correct payload sizes are populated into the redundancy |
186 // information. | 159 // information. |
187 TEST_F(AudioEncoderCopyRedTest, CheckPayloadSizes) { | 160 TEST_F(AudioEncoderCopyRedTest, CheckPayloadSizes) { |
188 // Let the mock encoder return payload sizes 1, 2, 3, ..., 10 for the sequence | 161 // Let the mock encoder return payload sizes 1, 2, 3, ..., 10 for the sequence |
189 // of calls. | 162 // of calls. |
190 static const int kNumPackets = 10; | 163 static const int kNumPackets = 10; |
191 InSequence s; | 164 InSequence s; |
| 165 MockAudioEncoderHelper helpers[kNumPackets]; |
| 166 |
192 for (int encode_size = 1; encode_size <= kNumPackets; ++encode_size) { | 167 for (int encode_size = 1; encode_size <= kNumPackets; ++encode_size) { |
193 AudioEncoder::EncodedInfo info; | 168 helpers[encode_size - 1].info_.encoded_bytes = encode_size; |
194 info.encoded_bytes = encode_size; | 169 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)) |
195 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) | 170 .WillOnce(Invoke(&helpers[encode_size - 1], |
196 .WillOnce(Return(info)); | 171 &MockAudioEncoderHelper::Encode)); |
197 } | 172 } |
198 | 173 |
199 // First call is a special case, since it does not include a secondary | 174 // First call is a special case, since it does not include a secondary |
200 // payload. | 175 // payload. |
201 Encode(); | 176 Encode(); |
202 EXPECT_EQ(1u, encoded_info_.redundant.size()); | 177 EXPECT_EQ(1u, encoded_info_.redundant.size()); |
203 EXPECT_EQ(1u, encoded_info_.encoded_bytes); | 178 EXPECT_EQ(1u, encoded_info_.encoded_bytes); |
204 | 179 |
205 for (size_t i = 2; i <= kNumPackets; ++i) { | 180 for (size_t i = 2; i <= kNumPackets; ++i) { |
206 Encode(); | 181 Encode(); |
207 ASSERT_EQ(2u, encoded_info_.redundant.size()); | 182 ASSERT_EQ(2u, encoded_info_.redundant.size()); |
208 EXPECT_EQ(i, encoded_info_.redundant[0].encoded_bytes); | 183 EXPECT_EQ(i, encoded_info_.redundant[0].encoded_bytes); |
209 EXPECT_EQ(i - 1, encoded_info_.redundant[1].encoded_bytes); | 184 EXPECT_EQ(i - 1, encoded_info_.redundant[1].encoded_bytes); |
210 EXPECT_EQ(i + i - 1, encoded_info_.encoded_bytes); | 185 EXPECT_EQ(i + i - 1, encoded_info_.encoded_bytes); |
211 } | 186 } |
212 } | 187 } |
213 | 188 |
214 // Checks that the correct timestamps are returned. | 189 // Checks that the correct timestamps are returned. |
215 TEST_F(AudioEncoderCopyRedTest, CheckTimestamps) { | 190 TEST_F(AudioEncoderCopyRedTest, CheckTimestamps) { |
216 MockEncodeHelper helper; | 191 MockAudioEncoderHelper helper; |
217 | 192 |
218 helper.info_.encoded_bytes = 17; | 193 helper.info_.encoded_bytes = 17; |
219 helper.info_.encoded_timestamp = timestamp_; | 194 helper.info_.encoded_timestamp = timestamp_; |
220 uint32_t primary_timestamp = timestamp_; | 195 uint32_t primary_timestamp = timestamp_; |
221 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) | 196 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)) |
222 .WillRepeatedly(Invoke(&helper, &MockEncodeHelper::Encode)); | 197 .WillRepeatedly(Invoke(&helper, &MockAudioEncoderHelper::Encode)); |
223 | 198 |
224 // First call is a special case, since it does not include a secondary | 199 // First call is a special case, since it does not include a secondary |
225 // payload. | 200 // payload. |
226 Encode(); | 201 Encode(); |
227 EXPECT_EQ(primary_timestamp, encoded_info_.encoded_timestamp); | 202 EXPECT_EQ(primary_timestamp, encoded_info_.encoded_timestamp); |
228 | 203 |
229 uint32_t secondary_timestamp = primary_timestamp; | 204 uint32_t secondary_timestamp = primary_timestamp; |
230 primary_timestamp = timestamp_; | 205 primary_timestamp = timestamp_; |
231 helper.info_.encoded_timestamp = timestamp_; | 206 helper.info_.encoded_timestamp = timestamp_; |
232 Encode(); | 207 Encode(); |
233 ASSERT_EQ(2u, encoded_info_.redundant.size()); | 208 ASSERT_EQ(2u, encoded_info_.redundant.size()); |
234 EXPECT_EQ(primary_timestamp, encoded_info_.redundant[0].encoded_timestamp); | 209 EXPECT_EQ(primary_timestamp, encoded_info_.redundant[0].encoded_timestamp); |
235 EXPECT_EQ(secondary_timestamp, encoded_info_.redundant[1].encoded_timestamp); | 210 EXPECT_EQ(secondary_timestamp, encoded_info_.redundant[1].encoded_timestamp); |
236 EXPECT_EQ(primary_timestamp, encoded_info_.encoded_timestamp); | 211 EXPECT_EQ(primary_timestamp, encoded_info_.encoded_timestamp); |
237 } | 212 } |
238 | 213 |
239 // Checks that the primary and secondary payloads are written correctly. | 214 // Checks that the primary and secondary payloads are written correctly. |
240 TEST_F(AudioEncoderCopyRedTest, CheckPayloads) { | 215 TEST_F(AudioEncoderCopyRedTest, CheckPayloads) { |
241 // Let the mock encoder write payloads with increasing values. The first | 216 // Let the mock encoder write payloads with increasing values. The first |
242 // payload will have values 0, 1, 2, ..., kPayloadLenBytes - 1. | 217 // payload will have values 0, 1, 2, ..., kPayloadLenBytes - 1. |
243 MockEncodeHelper helper; | 218 MockAudioEncoderHelper helper; |
244 static const size_t kPayloadLenBytes = 5; | 219 static const size_t kPayloadLenBytes = 5; |
245 helper.info_.encoded_bytes = kPayloadLenBytes; | 220 helper.info_.encoded_bytes = kPayloadLenBytes; |
246 helper.write_payload_ = true; | 221 helper.write_payload_ = true; |
247 uint8_t payload[kPayloadLenBytes]; | 222 uint8_t payload[kPayloadLenBytes]; |
248 for (uint8_t i = 0; i < kPayloadLenBytes; ++i) { | 223 for (uint8_t i = 0; i < kPayloadLenBytes; ++i) { |
249 payload[i] = i; | 224 payload[i] = i; |
250 } | 225 } |
251 helper.payload_ = payload; | 226 helper.payload_ = payload; |
252 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) | 227 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)) |
253 .WillRepeatedly(Invoke(&helper, &MockEncodeHelper::Encode)); | 228 .WillRepeatedly(Invoke(&helper, &MockAudioEncoderHelper::Encode)); |
254 | 229 |
255 // First call is a special case, since it does not include a secondary | 230 // First call is a special case, since it does not include a secondary |
256 // payload. | 231 // payload. |
257 Encode(); | 232 Encode(); |
258 EXPECT_EQ(kPayloadLenBytes, encoded_info_.encoded_bytes); | 233 EXPECT_EQ(kPayloadLenBytes, encoded_info_.encoded_bytes); |
259 for (size_t i = 0; i < kPayloadLenBytes; ++i) { | 234 for (size_t i = 0; i < kPayloadLenBytes; ++i) { |
260 EXPECT_EQ(i, encoded_[i]); | 235 EXPECT_EQ(i, encoded_.data()[i]); |
261 } | 236 } |
262 | 237 |
263 for (int j = 0; j < 5; ++j) { | 238 for (int j = 0; j < 5; ++j) { |
264 // Increment all values of the payload by 10. | 239 // Increment all values of the payload by 10. |
265 for (size_t i = 0; i < kPayloadLenBytes; ++i) | 240 for (size_t i = 0; i < kPayloadLenBytes; ++i) |
266 helper.payload_[i] += 10; | 241 payload[i] += 10; |
267 | 242 |
268 Encode(); | 243 Encode(); |
269 ASSERT_EQ(2u, encoded_info_.redundant.size()); | 244 ASSERT_EQ(2u, encoded_info_.redundant.size()); |
270 EXPECT_EQ(kPayloadLenBytes, encoded_info_.redundant[0].encoded_bytes); | 245 EXPECT_EQ(kPayloadLenBytes, encoded_info_.redundant[0].encoded_bytes); |
271 EXPECT_EQ(kPayloadLenBytes, encoded_info_.redundant[1].encoded_bytes); | 246 EXPECT_EQ(kPayloadLenBytes, encoded_info_.redundant[1].encoded_bytes); |
272 for (size_t i = 0; i < kPayloadLenBytes; ++i) { | 247 for (size_t i = 0; i < kPayloadLenBytes; ++i) { |
273 // Check primary payload. | 248 // Check primary payload. |
274 EXPECT_EQ((j + 1) * 10 + i, encoded_[i]); | 249 EXPECT_EQ((j + 1) * 10 + i, encoded_.data()[i]); |
275 // Check secondary payload. | 250 // Check secondary payload. |
276 EXPECT_EQ(j * 10 + i, encoded_[i + kPayloadLenBytes]); | 251 EXPECT_EQ(j * 10 + i, encoded_.data()[i + kPayloadLenBytes]); |
277 } | 252 } |
278 } | 253 } |
279 } | 254 } |
280 | 255 |
281 // Checks correct propagation of payload type. | 256 // Checks correct propagation of payload type. |
282 // Checks that the correct timestamps are returned. | 257 // Checks that the correct timestamps are returned. |
283 TEST_F(AudioEncoderCopyRedTest, CheckPayloadType) { | 258 TEST_F(AudioEncoderCopyRedTest, CheckPayloadType) { |
284 MockEncodeHelper helper; | 259 MockAudioEncoderHelper helper; |
285 | 260 |
286 helper.info_.encoded_bytes = 17; | 261 helper.info_.encoded_bytes = 17; |
287 const int primary_payload_type = red_payload_type_ + 1; | 262 const int primary_payload_type = red_payload_type_ + 1; |
288 helper.info_.payload_type = primary_payload_type; | 263 helper.info_.payload_type = primary_payload_type; |
289 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) | 264 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _)) |
290 .WillRepeatedly(Invoke(&helper, &MockEncodeHelper::Encode)); | 265 .WillRepeatedly(Invoke(&helper, &MockAudioEncoderHelper::Encode)); |
291 | 266 |
292 // First call is a special case, since it does not include a secondary | 267 // First call is a special case, since it does not include a secondary |
293 // payload. | 268 // payload. |
294 Encode(); | 269 Encode(); |
295 ASSERT_EQ(1u, encoded_info_.redundant.size()); | 270 ASSERT_EQ(1u, encoded_info_.redundant.size()); |
296 EXPECT_EQ(primary_payload_type, encoded_info_.redundant[0].payload_type); | 271 EXPECT_EQ(primary_payload_type, encoded_info_.redundant[0].payload_type); |
297 EXPECT_EQ(red_payload_type_, encoded_info_.payload_type); | 272 EXPECT_EQ(red_payload_type_, encoded_info_.payload_type); |
298 | 273 |
299 const int secondary_payload_type = red_payload_type_ + 2; | 274 const int secondary_payload_type = red_payload_type_ + 2; |
300 helper.info_.payload_type = secondary_payload_type; | 275 helper.info_.payload_type = secondary_payload_type; |
(...skipping 26 matching lines...) Expand all Loading... |
327 config.speech_encoder = NULL; | 302 config.speech_encoder = NULL; |
328 EXPECT_DEATH(red = new AudioEncoderCopyRed(config), | 303 EXPECT_DEATH(red = new AudioEncoderCopyRed(config), |
329 "Speech encoder not provided."); | 304 "Speech encoder not provided."); |
330 // The delete operation is needed to avoid leak reports from memcheck. | 305 // The delete operation is needed to avoid leak reports from memcheck. |
331 delete red; | 306 delete red; |
332 } | 307 } |
333 | 308 |
334 #endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) | 309 #endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) |
335 | 310 |
336 } // namespace webrtc | 311 } // namespace webrtc |
OLD | NEW |