Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc

Issue 1725143003: Changed AudioEncoder::Encode to take an rtc::Buffer* instead of uint8_t* and a maximum size. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Added more fixes for override hiding in AudioEncoder implementations. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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) {
134 static const size_t kEncodedSize = 17;
135 {
136 InSequence s;
137 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _))
138 .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(kEncodedSize)))
139 .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(0)))
140 .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(kEncodedSize)));
141 }
142
157 // Start with one Encode() call that will produce output. 143 // Start with one Encode() call that will produce output.
158 static const size_t kEncodedSize = 17;
159 AudioEncoder::EncodedInfo info;
160 info.encoded_bytes = kEncodedSize;
161 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
162 .WillOnce(Return(info));
163 Encode(); 144 Encode();
164 // First call is a special case, since it does not include a secondary 145 // First call is a special case, since it does not include a secondary
165 // payload. 146 // payload.
166 EXPECT_EQ(1u, encoded_info_.redundant.size()); 147 EXPECT_EQ(1u, encoded_info_.redundant.size());
167 EXPECT_EQ(kEncodedSize, encoded_info_.encoded_bytes); 148 EXPECT_EQ(kEncodedSize, encoded_info_.encoded_bytes);
168 149
169 // Next call to the speech encoder will not produce any output. 150 // Next call to the speech encoder will not produce any output.
170 info.encoded_bytes = 0;
171 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
172 .WillOnce(Return(info));
173 Encode(); 151 Encode();
174 EXPECT_EQ(0u, encoded_info_.encoded_bytes); 152 EXPECT_EQ(0u, encoded_info_.encoded_bytes);
175 153
176 // Final call to the speech encoder will produce output. 154 // Final call to the speech encoder will produce output.
177 info.encoded_bytes = kEncodedSize;
178 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
179 .WillOnce(Return(info));
180 Encode(); 155 Encode();
181 EXPECT_EQ(2 * kEncodedSize, encoded_info_.encoded_bytes); 156 EXPECT_EQ(2 * kEncodedSize, encoded_info_.encoded_bytes);
182 ASSERT_EQ(2u, encoded_info_.redundant.size()); 157 ASSERT_EQ(2u, encoded_info_.redundant.size());
183 } 158 }
184 159
185 // Checks that the correct payload sizes are populated into the redundancy 160 // Checks that the correct payload sizes are populated into the redundancy
186 // information. 161 // information.
187 TEST_F(AudioEncoderCopyRedTest, CheckPayloadSizes) { 162 TEST_F(AudioEncoderCopyRedTest, CheckPayloadSizes) {
188 // Let the mock encoder return payload sizes 1, 2, 3, ..., 10 for the sequence 163 // Let the mock encoder return payload sizes 1, 2, 3, ..., 10 for the sequence
189 // of calls. 164 // of calls.
190 static const int kNumPackets = 10; 165 static const int kNumPackets = 10;
191 InSequence s; 166 InSequence s;
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 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _))
194 info.encoded_bytes = encode_size; 169 .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(encode_size)));
195 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
196 .WillOnce(Return(info));
197 } 170 }
198 171
199 // First call is a special case, since it does not include a secondary 172 // First call is a special case, since it does not include a secondary
200 // payload. 173 // payload.
201 Encode(); 174 Encode();
202 EXPECT_EQ(1u, encoded_info_.redundant.size()); 175 EXPECT_EQ(1u, encoded_info_.redundant.size());
203 EXPECT_EQ(1u, encoded_info_.encoded_bytes); 176 EXPECT_EQ(1u, encoded_info_.encoded_bytes);
204 177
205 for (size_t i = 2; i <= kNumPackets; ++i) { 178 for (size_t i = 2; i <= kNumPackets; ++i) {
206 Encode(); 179 Encode();
207 ASSERT_EQ(2u, encoded_info_.redundant.size()); 180 ASSERT_EQ(2u, encoded_info_.redundant.size());
208 EXPECT_EQ(i, encoded_info_.redundant[0].encoded_bytes); 181 EXPECT_EQ(i, encoded_info_.redundant[0].encoded_bytes);
209 EXPECT_EQ(i - 1, encoded_info_.redundant[1].encoded_bytes); 182 EXPECT_EQ(i - 1, encoded_info_.redundant[1].encoded_bytes);
210 EXPECT_EQ(i + i - 1, encoded_info_.encoded_bytes); 183 EXPECT_EQ(i + i - 1, encoded_info_.encoded_bytes);
211 } 184 }
212 } 185 }
213 186
214 // Checks that the correct timestamps are returned. 187 // Checks that the correct timestamps are returned.
215 TEST_F(AudioEncoderCopyRedTest, CheckTimestamps) { 188 TEST_F(AudioEncoderCopyRedTest, CheckTimestamps) {
216 MockEncodeHelper helper; 189 uint32_t primary_timestamp = timestamp_;
190 AudioEncoder::EncodedInfo info;
191 info.encoded_bytes = 17;
192 info.encoded_timestamp = timestamp_;
217 193
218 helper.info_.encoded_bytes = 17; 194 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _))
219 helper.info_.encoded_timestamp = timestamp_; 195 .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
220 uint32_t primary_timestamp = timestamp_;
221 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _))
222 .WillRepeatedly(Invoke(&helper, &MockEncodeHelper::Encode));
223 196
224 // First call is a special case, since it does not include a secondary 197 // First call is a special case, since it does not include a secondary
225 // payload. 198 // payload.
226 Encode(); 199 Encode();
227 EXPECT_EQ(primary_timestamp, encoded_info_.encoded_timestamp); 200 EXPECT_EQ(primary_timestamp, encoded_info_.encoded_timestamp);
228 201
229 uint32_t secondary_timestamp = primary_timestamp; 202 uint32_t secondary_timestamp = primary_timestamp;
230 primary_timestamp = timestamp_; 203 primary_timestamp = timestamp_;
231 helper.info_.encoded_timestamp = timestamp_; 204 info.encoded_timestamp = timestamp_;
205 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _))
206 .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
207
232 Encode(); 208 Encode();
233 ASSERT_EQ(2u, encoded_info_.redundant.size()); 209 ASSERT_EQ(2u, encoded_info_.redundant.size());
234 EXPECT_EQ(primary_timestamp, encoded_info_.redundant[0].encoded_timestamp); 210 EXPECT_EQ(primary_timestamp, encoded_info_.redundant[0].encoded_timestamp);
235 EXPECT_EQ(secondary_timestamp, encoded_info_.redundant[1].encoded_timestamp); 211 EXPECT_EQ(secondary_timestamp, encoded_info_.redundant[1].encoded_timestamp);
236 EXPECT_EQ(primary_timestamp, encoded_info_.encoded_timestamp); 212 EXPECT_EQ(primary_timestamp, encoded_info_.encoded_timestamp);
237 } 213 }
238 214
239 // Checks that the primary and secondary payloads are written correctly. 215 // Checks that the primary and secondary payloads are written correctly.
240 TEST_F(AudioEncoderCopyRedTest, CheckPayloads) { 216 TEST_F(AudioEncoderCopyRedTest, CheckPayloads) {
241 // Let the mock encoder write payloads with increasing values. The first 217 // Let the mock encoder write payloads with increasing values. The first
242 // payload will have values 0, 1, 2, ..., kPayloadLenBytes - 1. 218 // payload will have values 0, 1, 2, ..., kPayloadLenBytes - 1.
243 MockEncodeHelper helper;
244 static const size_t kPayloadLenBytes = 5; 219 static const size_t kPayloadLenBytes = 5;
245 helper.info_.encoded_bytes = kPayloadLenBytes;
246 helper.write_payload_ = true;
247 uint8_t payload[kPayloadLenBytes]; 220 uint8_t payload[kPayloadLenBytes];
248 for (uint8_t i = 0; i < kPayloadLenBytes; ++i) { 221 for (uint8_t i = 0; i < kPayloadLenBytes; ++i) {
249 payload[i] = i; 222 payload[i] = i;
250 } 223 }
251 helper.payload_ = payload; 224 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _))
252 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) 225 .WillRepeatedly(Invoke(MockAudioEncoder::CopyEncoding(payload)));
253 .WillRepeatedly(Invoke(&helper, &MockEncodeHelper::Encode));
254 226
255 // First call is a special case, since it does not include a secondary 227 // First call is a special case, since it does not include a secondary
256 // payload. 228 // payload.
257 Encode(); 229 Encode();
258 EXPECT_EQ(kPayloadLenBytes, encoded_info_.encoded_bytes); 230 EXPECT_EQ(kPayloadLenBytes, encoded_info_.encoded_bytes);
259 for (size_t i = 0; i < kPayloadLenBytes; ++i) { 231 for (size_t i = 0; i < kPayloadLenBytes; ++i) {
260 EXPECT_EQ(i, encoded_[i]); 232 EXPECT_EQ(i, encoded_.data()[i]);
261 } 233 }
262 234
263 for (int j = 0; j < 5; ++j) { 235 for (int j = 0; j < 5; ++j) {
264 // Increment all values of the payload by 10. 236 // Increment all values of the payload by 10.
265 for (size_t i = 0; i < kPayloadLenBytes; ++i) 237 for (size_t i = 0; i < kPayloadLenBytes; ++i)
266 helper.payload_[i] += 10; 238 payload[i] += 10;
267 239
268 Encode(); 240 Encode();
269 ASSERT_EQ(2u, encoded_info_.redundant.size()); 241 ASSERT_EQ(2u, encoded_info_.redundant.size());
270 EXPECT_EQ(kPayloadLenBytes, encoded_info_.redundant[0].encoded_bytes); 242 EXPECT_EQ(kPayloadLenBytes, encoded_info_.redundant[0].encoded_bytes);
271 EXPECT_EQ(kPayloadLenBytes, encoded_info_.redundant[1].encoded_bytes); 243 EXPECT_EQ(kPayloadLenBytes, encoded_info_.redundant[1].encoded_bytes);
272 for (size_t i = 0; i < kPayloadLenBytes; ++i) { 244 for (size_t i = 0; i < kPayloadLenBytes; ++i) {
273 // Check primary payload. 245 // Check primary payload.
274 EXPECT_EQ((j + 1) * 10 + i, encoded_[i]); 246 EXPECT_EQ((j + 1) * 10 + i, encoded_.data()[i]);
275 // Check secondary payload. 247 // Check secondary payload.
276 EXPECT_EQ(j * 10 + i, encoded_[i + kPayloadLenBytes]); 248 EXPECT_EQ(j * 10 + i, encoded_.data()[i + kPayloadLenBytes]);
277 } 249 }
278 } 250 }
279 } 251 }
280 252
281 // Checks correct propagation of payload type. 253 // Checks correct propagation of payload type.
282 // Checks that the correct timestamps are returned. 254 // Checks that the correct timestamps are returned.
283 TEST_F(AudioEncoderCopyRedTest, CheckPayloadType) { 255 TEST_F(AudioEncoderCopyRedTest, CheckPayloadType) {
284 MockEncodeHelper helper;
285
286 helper.info_.encoded_bytes = 17;
287 const int primary_payload_type = red_payload_type_ + 1; 256 const int primary_payload_type = red_payload_type_ + 1;
288 helper.info_.payload_type = primary_payload_type; 257 AudioEncoder::EncodedInfo info;
289 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _, _)) 258 info.encoded_bytes = 17;
290 .WillRepeatedly(Invoke(&helper, &MockEncodeHelper::Encode)); 259 info.payload_type = primary_payload_type;
260 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _))
261 .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
291 262
292 // First call is a special case, since it does not include a secondary 263 // First call is a special case, since it does not include a secondary
293 // payload. 264 // payload.
294 Encode(); 265 Encode();
295 ASSERT_EQ(1u, encoded_info_.redundant.size()); 266 ASSERT_EQ(1u, encoded_info_.redundant.size());
296 EXPECT_EQ(primary_payload_type, encoded_info_.redundant[0].payload_type); 267 EXPECT_EQ(primary_payload_type, encoded_info_.redundant[0].payload_type);
297 EXPECT_EQ(red_payload_type_, encoded_info_.payload_type); 268 EXPECT_EQ(red_payload_type_, encoded_info_.payload_type);
298 269
299 const int secondary_payload_type = red_payload_type_ + 2; 270 const int secondary_payload_type = red_payload_type_ + 2;
300 helper.info_.payload_type = secondary_payload_type; 271 info.payload_type = secondary_payload_type;
272 EXPECT_CALL(mock_encoder_, EncodeInternal(_, _, _))
273 .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info)));
274
301 Encode(); 275 Encode();
302 ASSERT_EQ(2u, encoded_info_.redundant.size()); 276 ASSERT_EQ(2u, encoded_info_.redundant.size());
303 EXPECT_EQ(secondary_payload_type, encoded_info_.redundant[0].payload_type); 277 EXPECT_EQ(secondary_payload_type, encoded_info_.redundant[0].payload_type);
304 EXPECT_EQ(primary_payload_type, encoded_info_.redundant[1].payload_type); 278 EXPECT_EQ(primary_payload_type, encoded_info_.redundant[1].payload_type);
305 EXPECT_EQ(red_payload_type_, encoded_info_.payload_type); 279 EXPECT_EQ(red_payload_type_, encoded_info_.payload_type);
306 } 280 }
307 281
308 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 282 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
309 283
310 // This test fixture tests various error conditions that makes the 284 // This test fixture tests various error conditions that makes the
(...skipping 16 matching lines...) Expand all
327 config.speech_encoder = NULL; 301 config.speech_encoder = NULL;
328 EXPECT_DEATH(red = new AudioEncoderCopyRed(config), 302 EXPECT_DEATH(red = new AudioEncoderCopyRed(config),
329 "Speech encoder not provided."); 303 "Speech encoder not provided.");
330 // The delete operation is needed to avoid leak reports from memcheck. 304 // The delete operation is needed to avoid leak reports from memcheck.
331 delete red; 305 delete red;
332 } 306 }
333 307
334 #endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 308 #endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
335 309
336 } // namespace webrtc 310 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698