OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2016 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 <iostream> |
| 12 |
| 13 #include "webrtc/modules/audio_processing/test/aec_dump_based_simulator.h" |
| 14 |
| 15 #include "webrtc/base/checks.h" |
| 16 #include "webrtc/modules/audio_processing/test/protobuf_utils.h" |
| 17 #include "webrtc/test/testsupport/trace_to_stderr.h" |
| 18 |
| 19 namespace webrtc { |
| 20 namespace test { |
| 21 namespace { |
| 22 |
| 23 // Verify output bitexactness for the fixed interface. |
| 24 // TODO(peah): Check whether it would make sense to add a threshold |
| 25 // to use for checking the bitexactness in a soft manner. |
| 26 bool VerifyFixedBitExactness(const webrtc::audioproc::Stream& msg, |
| 27 const AudioFrame& frame) { |
| 28 if ((sizeof(int16_t) * frame.samples_per_channel_ * frame.num_channels_) != |
| 29 msg.output_data().size()) { |
| 30 return false; |
| 31 } else { |
| 32 for (size_t k = 0; k < frame.num_channels_ * frame.samples_per_channel_; |
| 33 ++k) { |
| 34 if (msg.output_data().data()[k] != frame.data_[k]) { |
| 35 return false; |
| 36 } |
| 37 } |
| 38 } |
| 39 return true; |
| 40 } |
| 41 |
| 42 // Verify output bitexactness for the float interface. |
| 43 bool VerifyFloatBitExactness(const webrtc::audioproc::Stream& msg, |
| 44 const StreamConfig& out_config, |
| 45 const ChannelBuffer<float>& out_buf) { |
| 46 if (static_cast<size_t>(msg.output_channel_size()) != |
| 47 out_config.num_channels() || |
| 48 msg.output_channel(0).size() != out_config.num_frames()) { |
| 49 return false; |
| 50 } else { |
| 51 for (int ch = 0; ch < msg.output_channel_size(); ++ch) { |
| 52 for (size_t sample = 0; sample < out_config.num_frames(); ++sample) { |
| 53 if (msg.output_channel(ch).data()[sample] != |
| 54 out_buf.channels()[ch][sample]) { |
| 55 return false; |
| 56 } |
| 57 } |
| 58 } |
| 59 } |
| 60 return true; |
| 61 } |
| 62 |
| 63 } // namespace |
| 64 |
| 65 void AecDumpBasedSimulator::PrepareProcessStreamCall( |
| 66 const webrtc::audioproc::Stream& msg) { |
| 67 if (msg.has_input_data()) { |
| 68 // Fixed interface processing. |
| 69 // Verify interface invariance. |
| 70 RTC_CHECK(interface_used_ == InterfaceType::kFixedInterface || |
| 71 interface_used_ == InterfaceType::kNotSpecified); |
| 72 interface_used_ = InterfaceType::kFixedInterface; |
| 73 |
| 74 // ProcessStream could have changed this for the output frame. |
| 75 fwd_frame_.num_channels_ = ap_->num_input_channels(); |
| 76 |
| 77 // Populate input buffer. |
| 78 RTC_CHECK_EQ(sizeof(fwd_frame_.data_[0]) * fwd_frame_.samples_per_channel_ * |
| 79 fwd_frame_.num_channels_, |
| 80 msg.input_data().size()); |
| 81 memcpy(fwd_frame_.data_, msg.input_data().data(), msg.input_data().size()); |
| 82 } else { |
| 83 // Float interface processing. |
| 84 // Verify interface invariance. |
| 85 RTC_CHECK(interface_used_ == InterfaceType::kFloatInterface || |
| 86 interface_used_ == InterfaceType::kNotSpecified); |
| 87 interface_used_ = InterfaceType::kFloatInterface; |
| 88 |
| 89 RTC_CHECK_EQ(in_buf_->num_channels(), |
| 90 static_cast<size_t>(msg.input_channel_size())); |
| 91 |
| 92 // Populate input buffer. |
| 93 for (int i = 0; i < msg.input_channel_size(); ++i) { |
| 94 RTC_CHECK_EQ(in_buf_->num_frames() * sizeof(*in_buf_->channels()[i]), |
| 95 msg.input_channel(i).size()); |
| 96 std::memcpy(in_buf_->channels()[i], msg.input_channel(i).data(), |
| 97 msg.input_channel(i).size()); |
| 98 } |
| 99 } |
| 100 |
| 101 if (!settings_.stream_delay) { |
| 102 if (msg.has_delay()) { |
| 103 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 104 ap_->set_stream_delay_ms(msg.delay())); |
| 105 } |
| 106 } else { |
| 107 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 108 ap_->set_stream_delay_ms(*settings_.stream_delay)); |
| 109 } |
| 110 |
| 111 if (!settings_.stream_drift_samples) { |
| 112 if (msg.has_drift()) { |
| 113 ap_->echo_cancellation()->set_stream_drift_samples(msg.drift()); |
| 114 } |
| 115 } else { |
| 116 ap_->echo_cancellation()->set_stream_drift_samples( |
| 117 *settings_.stream_drift_samples); |
| 118 } |
| 119 |
| 120 if (!settings_.use_ts) { |
| 121 if (msg.has_keypress()) { |
| 122 ap_->set_stream_key_pressed(msg.keypress()); |
| 123 } |
| 124 } else { |
| 125 ap_->set_stream_key_pressed(*settings_.use_ts); |
| 126 } |
| 127 |
| 128 // TODO(peah): Add support for controlling the analog level via the |
| 129 // command-line. |
| 130 if (msg.has_level()) { |
| 131 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 132 ap_->gain_control()->set_stream_analog_level(msg.level())); |
| 133 } |
| 134 } |
| 135 |
| 136 void AecDumpBasedSimulator::VerifyProcessStreamBitExactness( |
| 137 const webrtc::audioproc::Stream& msg) { |
| 138 if (bitexact_output_) { |
| 139 if (interface_used_ == InterfaceType::kFixedInterface) { |
| 140 bitexact_output_ = VerifyFixedBitExactness(msg, fwd_frame_); |
| 141 } else { |
| 142 bitexact_output_ = VerifyFloatBitExactness(msg, out_config_, *out_buf_); |
| 143 } |
| 144 } |
| 145 } |
| 146 |
| 147 void AecDumpBasedSimulator::PrepareReverseProcessStreamCall( |
| 148 const webrtc::audioproc::ReverseStream& msg) { |
| 149 if (msg.has_data()) { |
| 150 // Fixed interface processing. |
| 151 // Verify interface invariance. |
| 152 RTC_CHECK(interface_used_ == InterfaceType::kFixedInterface || |
| 153 interface_used_ == InterfaceType::kNotSpecified); |
| 154 interface_used_ = InterfaceType::kFixedInterface; |
| 155 |
| 156 // Populate input buffer. |
| 157 RTC_CHECK_EQ(sizeof(int16_t) * rev_frame_.samples_per_channel_ * |
| 158 rev_frame_.num_channels_, |
| 159 msg.data().size()); |
| 160 memcpy(rev_frame_.data_, msg.data().data(), msg.data().size()); |
| 161 } else { |
| 162 // Float interface processing. |
| 163 // Verify interface invariance. |
| 164 RTC_CHECK(interface_used_ == InterfaceType::kFloatInterface || |
| 165 interface_used_ == InterfaceType::kNotSpecified); |
| 166 interface_used_ = InterfaceType::kFloatInterface; |
| 167 |
| 168 RTC_CHECK_EQ(reverse_in_buf_->num_channels(), |
| 169 static_cast<size_t>(msg.channel_size())); |
| 170 |
| 171 // Populate input buffer. |
| 172 for (int i = 0; i < msg.channel_size(); ++i) { |
| 173 RTC_CHECK_EQ(reverse_in_buf_->num_frames() * |
| 174 sizeof(*reverse_in_buf_->channels()[i]), |
| 175 msg.channel(i).size()); |
| 176 std::memcpy(reverse_in_buf_->channels()[i], msg.channel(i).data(), |
| 177 msg.channel(i).size()); |
| 178 } |
| 179 } |
| 180 } |
| 181 |
| 182 void AecDumpBasedSimulator::Process() { |
| 183 std::unique_ptr<test::TraceToStderr> trace_to_stderr; |
| 184 if (settings_.use_verbose_logging) { |
| 185 trace_to_stderr.reset(new test::TraceToStderr(true)); |
| 186 } |
| 187 |
| 188 CreateAudioProcessor(); |
| 189 dump_input_file_ = OpenFile(settings_.aec_dump_input_filename->c_str(), "rb"); |
| 190 |
| 191 webrtc::audioproc::Event event_msg; |
| 192 int num_forward_chunks_processed = 0; |
| 193 const float kOneBykChunksPerSecond = |
| 194 1.f / AudioProcessingSimulator::kChunksPerSecond; |
| 195 while (ReadMessageFromFile(dump_input_file_, &event_msg)) { |
| 196 switch (event_msg.type()) { |
| 197 case webrtc::audioproc::Event::INIT: |
| 198 RTC_CHECK(event_msg.has_init()); |
| 199 HandleMessage(event_msg.init()); |
| 200 break; |
| 201 case webrtc::audioproc::Event::STREAM: |
| 202 RTC_CHECK(event_msg.has_stream()); |
| 203 HandleMessage(event_msg.stream()); |
| 204 ++num_forward_chunks_processed; |
| 205 break; |
| 206 case webrtc::audioproc::Event::REVERSE_STREAM: |
| 207 RTC_CHECK(event_msg.has_reverse_stream()); |
| 208 HandleMessage(event_msg.reverse_stream()); |
| 209 break; |
| 210 case webrtc::audioproc::Event::CONFIG: |
| 211 RTC_CHECK(event_msg.has_config()); |
| 212 HandleMessage(event_msg.config()); |
| 213 break; |
| 214 default: |
| 215 RTC_CHECK(false); |
| 216 } |
| 217 if (trace_to_stderr) { |
| 218 trace_to_stderr->SetTimeSeconds(num_forward_chunks_processed * |
| 219 kOneBykChunksPerSecond); |
| 220 } |
| 221 } |
| 222 |
| 223 fclose(dump_input_file_); |
| 224 |
| 225 DestroyAudioProcessor(); |
| 226 } |
| 227 |
| 228 void AecDumpBasedSimulator::HandleMessage( |
| 229 const webrtc::audioproc::Config& msg) { |
| 230 if (settings_.use_verbose_logging) { |
| 231 std::cout << "Config at frame:" << std::endl; |
| 232 std::cout << " Forward: " << get_num_process_stream_calls() << std::endl; |
| 233 std::cout << " Reverse: " << get_num_reverse_process_stream_calls() |
| 234 << std::endl; |
| 235 } |
| 236 |
| 237 if (!settings_.discard_all_settings_in_aecdump) { |
| 238 if (settings_.use_verbose_logging) { |
| 239 std::cout << "Setting used in config:" << std::endl; |
| 240 } |
| 241 Config config; |
| 242 |
| 243 if (msg.has_aec_enabled() || settings_.use_aec) { |
| 244 bool enable = settings_.use_aec ? *settings_.use_aec : msg.aec_enabled(); |
| 245 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 246 ap_->echo_cancellation()->Enable(enable)); |
| 247 if (settings_.use_verbose_logging) { |
| 248 std::cout << " aec_enabled: " << (enable ? "true" : "false") |
| 249 << std::endl; |
| 250 } |
| 251 } |
| 252 |
| 253 if (msg.has_aec_delay_agnostic_enabled() || settings_.use_delay_agnostic) { |
| 254 bool enable = settings_.use_delay_agnostic |
| 255 ? *settings_.use_delay_agnostic |
| 256 : msg.aec_delay_agnostic_enabled(); |
| 257 config.Set<DelayAgnostic>(new DelayAgnostic(enable)); |
| 258 if (settings_.use_verbose_logging) { |
| 259 std::cout << " aec_delay_agnostic_enabled: " |
| 260 << (enable ? "true" : "false") << std::endl; |
| 261 } |
| 262 } |
| 263 |
| 264 if (msg.has_aec_drift_compensation_enabled() || |
| 265 settings_.use_drift_compensation) { |
| 266 bool enable = settings_.use_drift_compensation |
| 267 ? *settings_.use_drift_compensation |
| 268 : msg.aec_drift_compensation_enabled(); |
| 269 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 270 ap_->echo_cancellation()->enable_drift_compensation(enable)); |
| 271 if (settings_.use_verbose_logging) { |
| 272 std::cout << " aec_drift_compensation_enabled: " |
| 273 << (enable ? "true" : "false") << std::endl; |
| 274 } |
| 275 } |
| 276 |
| 277 if (msg.has_aec_extended_filter_enabled() || |
| 278 settings_.use_extended_filter) { |
| 279 bool enable = settings_.use_extended_filter |
| 280 ? *settings_.use_extended_filter |
| 281 : msg.aec_extended_filter_enabled(); |
| 282 config.Set<ExtendedFilter>(new ExtendedFilter(enable)); |
| 283 if (settings_.use_verbose_logging) { |
| 284 std::cout << " aec_extended_filter_enabled: " |
| 285 << (enable ? "true" : "false") << std::endl; |
| 286 } |
| 287 } |
| 288 |
| 289 if (msg.has_aec_suppression_level() || settings_.aec_suppression_level) { |
| 290 int level = settings_.aec_suppression_level |
| 291 ? *settings_.aec_suppression_level |
| 292 : msg.aec_suppression_level(); |
| 293 RTC_CHECK_EQ( |
| 294 AudioProcessing::kNoError, |
| 295 ap_->echo_cancellation()->set_suppression_level( |
| 296 static_cast<webrtc::EchoCancellation::SuppressionLevel>(level))); |
| 297 if (settings_.use_verbose_logging) { |
| 298 std::cout << " aec_suppression_level: " << level << std::endl; |
| 299 } |
| 300 } |
| 301 |
| 302 if (msg.has_aecm_enabled() || settings_.use_aecm) { |
| 303 bool enable = |
| 304 settings_.use_aecm ? *settings_.use_aecm : msg.aecm_enabled(); |
| 305 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 306 ap_->echo_control_mobile()->Enable(enable)); |
| 307 if (settings_.use_verbose_logging) { |
| 308 std::cout << " aecm_enabled: " << (enable ? "true" : "false") |
| 309 << std::endl; |
| 310 } |
| 311 } |
| 312 |
| 313 if (msg.has_aecm_comfort_noise_enabled() || |
| 314 settings_.use_aecm_comfort_noise) { |
| 315 bool enable = settings_.use_aecm_comfort_noise |
| 316 ? *settings_.use_aecm_comfort_noise |
| 317 : msg.aecm_comfort_noise_enabled(); |
| 318 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 319 ap_->echo_control_mobile()->enable_comfort_noise(enable)); |
| 320 if (settings_.use_verbose_logging) { |
| 321 std::cout << " aecm_comfort_noise_enabled: " |
| 322 << (enable ? "true" : "false") << std::endl; |
| 323 } |
| 324 } |
| 325 |
| 326 if (msg.has_aecm_routing_mode() || settings_.aecm_routing_mode) { |
| 327 int routing_mode = settings_.aecm_routing_mode |
| 328 ? *settings_.aecm_routing_mode |
| 329 : msg.aecm_routing_mode(); |
| 330 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 331 ap_->echo_control_mobile()->set_routing_mode( |
| 332 static_cast<webrtc::EchoControlMobile::RoutingMode>( |
| 333 routing_mode))); |
| 334 if (settings_.use_verbose_logging) { |
| 335 std::cout << " aecm_routing_mode: " << routing_mode << std::endl; |
| 336 } |
| 337 } |
| 338 |
| 339 if (msg.has_agc_enabled() || settings_.use_agc) { |
| 340 bool enable = settings_.use_agc ? *settings_.use_agc : msg.agc_enabled(); |
| 341 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 342 ap_->gain_control()->Enable(enable)); |
| 343 if (settings_.use_verbose_logging) { |
| 344 std::cout << " agc_enabled: " << (enable ? "true" : "false") |
| 345 << std::endl; |
| 346 } |
| 347 } |
| 348 |
| 349 if (msg.has_agc_mode() || settings_.agc_mode) { |
| 350 int mode = settings_.agc_mode ? *settings_.agc_mode : msg.agc_mode(); |
| 351 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 352 ap_->gain_control()->set_mode( |
| 353 static_cast<webrtc::GainControl::Mode>(mode))); |
| 354 if (settings_.use_verbose_logging) { |
| 355 std::cout << " agc_mode: " << mode << std::endl; |
| 356 } |
| 357 } |
| 358 |
| 359 if (msg.has_agc_limiter_enabled() || settings_.use_agc_limiter) { |
| 360 bool enable = settings_.use_agc_limiter ? *settings_.use_agc_limiter |
| 361 : msg.agc_limiter_enabled(); |
| 362 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 363 ap_->gain_control()->enable_limiter(enable)); |
| 364 if (settings_.use_verbose_logging) { |
| 365 std::cout << " agc_limiter_enabled: " << (enable ? "true" : "false") |
| 366 << std::endl; |
| 367 } |
| 368 } |
| 369 |
| 370 // TODO(peah): Add support for controlling the Experimental AGC from the |
| 371 // command line. |
| 372 if (msg.has_noise_robust_agc_enabled()) { |
| 373 config.Set<ExperimentalAgc>( |
| 374 new ExperimentalAgc(msg.noise_robust_agc_enabled())); |
| 375 if (settings_.use_verbose_logging) { |
| 376 std::cout << " noise_robust_agc_enabled: " |
| 377 << (msg.noise_robust_agc_enabled() ? "true" : "false") |
| 378 << std::endl; |
| 379 } |
| 380 } |
| 381 |
| 382 if (msg.has_transient_suppression_enabled() || settings_.use_ts) { |
| 383 bool enable = settings_.use_ts ? *settings_.use_ts |
| 384 : msg.transient_suppression_enabled(); |
| 385 config.Set<ExperimentalNs>(new ExperimentalNs(enable)); |
| 386 if (settings_.use_verbose_logging) { |
| 387 std::cout << " transient_suppression_enabled: " |
| 388 << (enable ? "true" : "false") << std::endl; |
| 389 } |
| 390 } |
| 391 |
| 392 if (msg.has_hpf_enabled() || settings_.use_hpf) { |
| 393 bool enable = settings_.use_hpf ? *settings_.use_hpf : msg.hpf_enabled(); |
| 394 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 395 ap_->high_pass_filter()->Enable(enable)); |
| 396 if (settings_.use_verbose_logging) { |
| 397 std::cout << " hpf_enabled: " << (enable ? "true" : "false") |
| 398 << std::endl; |
| 399 } |
| 400 } |
| 401 |
| 402 if (msg.has_ns_enabled() || settings_.use_ns) { |
| 403 bool enable = settings_.use_ns ? *settings_.use_ns : msg.ns_enabled(); |
| 404 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 405 ap_->noise_suppression()->Enable(enable)); |
| 406 if (settings_.use_verbose_logging) { |
| 407 std::cout << " ns_enabled: " << (enable ? "true" : "false") |
| 408 << std::endl; |
| 409 } |
| 410 } |
| 411 |
| 412 if (msg.has_ns_level() || settings_.ns_level) { |
| 413 int level = settings_.ns_level ? *settings_.ns_level : msg.ns_level(); |
| 414 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 415 ap_->noise_suppression()->set_level( |
| 416 static_cast<NoiseSuppression::Level>(level))); |
| 417 if (settings_.use_verbose_logging) { |
| 418 std::cout << " ns_level: " << level << std::endl; |
| 419 } |
| 420 } |
| 421 |
| 422 if (settings_.use_verbose_logging && msg.has_experiments_description() && |
| 423 msg.experiments_description().size() > 0) { |
| 424 std::cout << " experiments not included by default in the simulation: " |
| 425 << msg.experiments_description() << std::endl; |
| 426 } |
| 427 |
| 428 if (settings_.use_refined_adaptive_filter) { |
| 429 config.Set<RefinedAdaptiveFilter>( |
| 430 new RefinedAdaptiveFilter(*settings_.use_refined_adaptive_filter)); |
| 431 } |
| 432 |
| 433 if (settings_.use_aec3) { |
| 434 config.Set<EchoCanceller3>(new EchoCanceller3(*settings_.use_aec3)); |
| 435 } |
| 436 |
| 437 ap_->SetExtraOptions(config); |
| 438 } |
| 439 } |
| 440 |
| 441 void AecDumpBasedSimulator::HandleMessage(const webrtc::audioproc::Init& msg) { |
| 442 RTC_CHECK(msg.has_sample_rate()); |
| 443 RTC_CHECK(msg.has_num_input_channels()); |
| 444 RTC_CHECK(msg.has_num_reverse_channels()); |
| 445 RTC_CHECK(msg.has_reverse_sample_rate()); |
| 446 |
| 447 if (settings_.use_verbose_logging) { |
| 448 std::cout << "Init at frame:" << std::endl; |
| 449 std::cout << " Forward: " << get_num_process_stream_calls() << std::endl; |
| 450 std::cout << " Reverse: " << get_num_reverse_process_stream_calls() |
| 451 << std::endl; |
| 452 } |
| 453 |
| 454 int num_output_channels; |
| 455 if (settings_.output_num_channels) { |
| 456 num_output_channels = *settings_.output_num_channels; |
| 457 } else { |
| 458 num_output_channels = msg.has_num_output_channels() |
| 459 ? msg.num_output_channels() |
| 460 : msg.num_input_channels(); |
| 461 } |
| 462 |
| 463 int output_sample_rate; |
| 464 if (settings_.output_sample_rate_hz) { |
| 465 output_sample_rate = *settings_.output_sample_rate_hz; |
| 466 } else { |
| 467 output_sample_rate = msg.has_output_sample_rate() ? msg.output_sample_rate() |
| 468 : msg.sample_rate(); |
| 469 } |
| 470 |
| 471 int num_reverse_output_channels; |
| 472 if (settings_.reverse_output_num_channels) { |
| 473 num_reverse_output_channels = *settings_.reverse_output_num_channels; |
| 474 } else { |
| 475 num_reverse_output_channels = msg.has_num_reverse_output_channels() |
| 476 ? msg.num_reverse_output_channels() |
| 477 : msg.num_reverse_channels(); |
| 478 } |
| 479 |
| 480 int reverse_output_sample_rate; |
| 481 if (settings_.reverse_output_sample_rate_hz) { |
| 482 reverse_output_sample_rate = *settings_.reverse_output_sample_rate_hz; |
| 483 } else { |
| 484 reverse_output_sample_rate = msg.has_reverse_output_sample_rate() |
| 485 ? msg.reverse_output_sample_rate() |
| 486 : msg.reverse_sample_rate(); |
| 487 } |
| 488 |
| 489 SetupBuffersConfigsOutputs( |
| 490 msg.sample_rate(), output_sample_rate, msg.reverse_sample_rate(), |
| 491 reverse_output_sample_rate, msg.num_input_channels(), num_output_channels, |
| 492 msg.num_reverse_channels(), num_reverse_output_channels); |
| 493 } |
| 494 |
| 495 void AecDumpBasedSimulator::HandleMessage( |
| 496 const webrtc::audioproc::Stream& msg) { |
| 497 PrepareProcessStreamCall(msg); |
| 498 ProcessStream(interface_used_ == InterfaceType::kFixedInterface); |
| 499 VerifyProcessStreamBitExactness(msg); |
| 500 } |
| 501 |
| 502 void AecDumpBasedSimulator::HandleMessage( |
| 503 const webrtc::audioproc::ReverseStream& msg) { |
| 504 PrepareReverseProcessStreamCall(msg); |
| 505 ProcessReverseStream(interface_used_ == InterfaceType::kFixedInterface); |
| 506 } |
| 507 |
| 508 } // namespace test |
| 509 } // namespace webrtc |
OLD | NEW |