OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 <math.h> | 11 #include <math.h> |
12 #include <stdio.h> | 12 #include <stdio.h> |
13 | 13 |
14 #include <algorithm> | 14 #include <algorithm> |
15 #include <limits> | 15 #include <limits> |
16 #include <memory> | 16 #include <memory> |
17 #include <queue> | 17 #include <queue> |
18 | 18 |
19 #include "webrtc/base/arraysize.h" | 19 #include "webrtc/base/arraysize.h" |
20 #include "webrtc/base/checks.h" | 20 #include "webrtc/base/checks.h" |
21 #include "webrtc/base/gtest_prod_util.h" | 21 #include "webrtc/base/gtest_prod_util.h" |
22 #include "webrtc/base/ignore_wundef.h" | 22 #include "webrtc/base/ignore_wundef.h" |
| 23 #include "webrtc/base/task_queue.h" |
| 24 #include "webrtc/base/thread.h" |
23 #include "webrtc/common_audio/include/audio_util.h" | 25 #include "webrtc/common_audio/include/audio_util.h" |
24 #include "webrtc/common_audio/resampler/include/push_resampler.h" | 26 #include "webrtc/common_audio/resampler/include/push_resampler.h" |
25 #include "webrtc/common_audio/resampler/push_sinc_resampler.h" | 27 #include "webrtc/common_audio/resampler/push_sinc_resampler.h" |
26 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
y.h" | 28 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar
y.h" |
| 29 #include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h" |
27 #include "webrtc/modules/audio_processing/audio_processing_impl.h" | 30 #include "webrtc/modules/audio_processing/audio_processing_impl.h" |
28 #include "webrtc/modules/audio_processing/beamformer/mock_nonlinear_beamformer.h
" | 31 #include "webrtc/modules/audio_processing/beamformer/mock_nonlinear_beamformer.h
" |
29 #include "webrtc/modules/audio_processing/common.h" | 32 #include "webrtc/modules/audio_processing/common.h" |
30 #include "webrtc/modules/audio_processing/include/audio_processing.h" | 33 #include "webrtc/modules/audio_processing/include/audio_processing.h" |
31 #include "webrtc/modules/audio_processing/level_controller/level_controller_cons
tants.h" | 34 #include "webrtc/modules/audio_processing/level_controller/level_controller_cons
tants.h" |
32 #include "webrtc/modules/audio_processing/test/protobuf_utils.h" | 35 #include "webrtc/modules/audio_processing/test/protobuf_utils.h" |
33 #include "webrtc/modules/audio_processing/test/test_utils.h" | 36 #include "webrtc/modules/audio_processing/test/test_utils.h" |
34 #include "webrtc/modules/include/module_common_types.h" | 37 #include "webrtc/modules/include/module_common_types.h" |
35 #include "webrtc/system_wrappers/include/event_wrapper.h" | 38 #include "webrtc/system_wrappers/include/event_wrapper.h" |
36 #include "webrtc/system_wrappers/include/trace.h" | 39 #include "webrtc/system_wrappers/include/trace.h" |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 int output_sample_rate_hz_; | 406 int output_sample_rate_hz_; |
404 size_t num_output_channels_; | 407 size_t num_output_channels_; |
405 FILE* far_file_; | 408 FILE* far_file_; |
406 FILE* near_file_; | 409 FILE* near_file_; |
407 FILE* out_file_; | 410 FILE* out_file_; |
408 }; | 411 }; |
409 | 412 |
410 ApmTest::ApmTest() | 413 ApmTest::ApmTest() |
411 : output_path_(test::OutputPath()), | 414 : output_path_(test::OutputPath()), |
412 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) | 415 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE) |
413 ref_filename_(test::ResourcePath("audio_processing/output_data_fixed", | 416 ref_filename_( |
414 "pb")), | 417 test::ResourcePath("audio_processing/output_data_fixed", "pb")), |
415 #elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) | 418 #elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE) |
416 #if defined(WEBRTC_MAC) | 419 #if defined(WEBRTC_MAC) |
417 // A different file for Mac is needed because on this platform the AEC | 420 // A different file for Mac is needed because on this platform the AEC |
418 // constant |kFixedDelayMs| value is 20 and not 50 as it is on the rest. | 421 // constant |kFixedDelayMs| value is 20 and not 50 as it is on the rest. |
419 ref_filename_(test::ResourcePath("audio_processing/output_data_mac", | 422 ref_filename_( |
420 "pb")), | 423 test::ResourcePath("audio_processing/output_data_mac", "pb")), |
421 #else | 424 #else |
422 ref_filename_(test::ResourcePath("audio_processing/output_data_float", | 425 ref_filename_( |
423 "pb")), | 426 test::ResourcePath("audio_processing/output_data_float", "pb")), |
424 #endif | 427 #endif |
425 #endif | 428 #endif |
426 frame_(NULL), | 429 frame_(NULL), |
427 revframe_(NULL), | 430 revframe_(NULL), |
428 output_sample_rate_hz_(0), | 431 output_sample_rate_hz_(0), |
429 num_output_channels_(0), | 432 num_output_channels_(0), |
430 far_file_(NULL), | 433 far_file_(NULL), |
431 near_file_(NULL), | 434 near_file_(NULL), |
432 out_file_(NULL) { | 435 out_file_(NULL) { |
433 Config config; | 436 Config config; |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 | 577 |
575 void ApmTest::ProcessWithDefaultStreamParameters(AudioFrame* frame) { | 578 void ApmTest::ProcessWithDefaultStreamParameters(AudioFrame* frame) { |
576 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0)); | 579 EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0)); |
577 apm_->echo_cancellation()->set_stream_drift_samples(0); | 580 apm_->echo_cancellation()->set_stream_drift_samples(0); |
578 EXPECT_EQ(apm_->kNoError, | 581 EXPECT_EQ(apm_->kNoError, |
579 apm_->gain_control()->set_stream_analog_level(127)); | 582 apm_->gain_control()->set_stream_analog_level(127)); |
580 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame)); | 583 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame)); |
581 } | 584 } |
582 | 585 |
583 int ApmTest::ProcessStreamChooser(Format format) { | 586 int ApmTest::ProcessStreamChooser(Format format) { |
| 587 rtc::Thread::Current()->SleepMs(1); |
584 if (format == kIntFormat) { | 588 if (format == kIntFormat) { |
585 return apm_->ProcessStream(frame_); | 589 return apm_->ProcessStream(frame_); |
586 } | 590 } |
587 return apm_->ProcessStream(float_cb_->channels(), | 591 return apm_->ProcessStream(float_cb_->channels(), |
588 frame_->samples_per_channel_, | 592 frame_->samples_per_channel_, |
589 frame_->sample_rate_hz_, | 593 frame_->sample_rate_hz_, |
590 LayoutFromChannels(frame_->num_channels_), | 594 LayoutFromChannels(frame_->num_channels_), |
591 output_sample_rate_hz_, | 595 output_sample_rate_hz_, |
592 LayoutFromChannels(num_output_channels_), | 596 LayoutFromChannels(num_output_channels_), |
593 float_cb_->channels()); | 597 float_cb_->channels()); |
594 } | 598 } |
595 | 599 |
596 int ApmTest::AnalyzeReverseStreamChooser(Format format) { | 600 int ApmTest::AnalyzeReverseStreamChooser(Format format) { |
| 601 rtc::Thread::Current()->SleepMs(1); |
597 if (format == kIntFormat) { | 602 if (format == kIntFormat) { |
598 return apm_->ProcessReverseStream(revframe_); | 603 return apm_->ProcessReverseStream(revframe_); |
599 } | 604 } |
600 return apm_->AnalyzeReverseStream( | 605 return apm_->AnalyzeReverseStream( |
601 revfloat_cb_->channels(), | 606 revfloat_cb_->channels(), |
602 revframe_->samples_per_channel_, | 607 revframe_->samples_per_channel_, |
603 revframe_->sample_rate_hz_, | 608 revframe_->sample_rate_hz_, |
604 LayoutFromChannels(revframe_->num_channels_)); | 609 LayoutFromChannels(revframe_->num_channels_)); |
605 } | 610 } |
606 | 611 |
(...skipping 1092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1699 apm_->echo_cancellation()->set_stream_drift_samples(0); | 1704 apm_->echo_cancellation()->set_stream_drift_samples(0); |
1700 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); | 1705 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); |
1701 EXPECT_FALSE(FrameDataAreEqual(*frame_, frame_copy)); | 1706 EXPECT_FALSE(FrameDataAreEqual(*frame_, frame_copy)); |
1702 } | 1707 } |
1703 | 1708 |
1704 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP | 1709 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP |
1705 void ApmTest::ProcessDebugDump(const std::string& in_filename, | 1710 void ApmTest::ProcessDebugDump(const std::string& in_filename, |
1706 const std::string& out_filename, | 1711 const std::string& out_filename, |
1707 Format format, | 1712 Format format, |
1708 int max_size_bytes) { | 1713 int max_size_bytes) { |
| 1714 rtc::TaskQueue worker_queue("ApmTest_worker_queue"); |
1709 FILE* in_file = fopen(in_filename.c_str(), "rb"); | 1715 FILE* in_file = fopen(in_filename.c_str(), "rb"); |
1710 ASSERT_TRUE(in_file != NULL); | 1716 ASSERT_TRUE(in_file != NULL); |
1711 audioproc::Event event_msg; | 1717 audioproc::Event event_msg; |
1712 bool first_init = true; | 1718 bool first_init = true; |
1713 | 1719 |
1714 while (ReadMessageFromFile(in_file, &event_msg)) { | 1720 while (ReadMessageFromFile(in_file, &event_msg)) { |
1715 if (event_msg.type() == audioproc::Event::INIT) { | 1721 if (event_msg.type() == audioproc::Event::INIT) { |
1716 const audioproc::Init msg = event_msg.init(); | 1722 const audioproc::Init msg = event_msg.init(); |
1717 int reverse_sample_rate = msg.sample_rate(); | 1723 int reverse_sample_rate = msg.sample_rate(); |
1718 if (msg.has_reverse_sample_rate()) { | 1724 if (msg.has_reverse_sample_rate()) { |
1719 reverse_sample_rate = msg.reverse_sample_rate(); | 1725 reverse_sample_rate = msg.reverse_sample_rate(); |
1720 } | 1726 } |
1721 int output_sample_rate = msg.sample_rate(); | 1727 int output_sample_rate = msg.sample_rate(); |
1722 if (msg.has_output_sample_rate()) { | 1728 if (msg.has_output_sample_rate()) { |
1723 output_sample_rate = msg.output_sample_rate(); | 1729 output_sample_rate = msg.output_sample_rate(); |
1724 } | 1730 } |
1725 | 1731 |
1726 Init(msg.sample_rate(), | 1732 Init(msg.sample_rate(), |
1727 output_sample_rate, | 1733 output_sample_rate, |
1728 reverse_sample_rate, | 1734 reverse_sample_rate, |
1729 msg.num_input_channels(), | 1735 msg.num_input_channels(), |
1730 msg.num_output_channels(), | 1736 msg.num_output_channels(), |
1731 msg.num_reverse_channels(), | 1737 msg.num_reverse_channels(), |
1732 false); | 1738 false); |
1733 if (first_init) { | 1739 if (first_init) { |
1734 // StartDebugRecording() writes an additional init message. Don't start | 1740 // StartDebugRecording() writes an additional init message. Don't start |
1735 // recording until after the first init to avoid the extra message. | 1741 // recording until after the first init to avoid the extra message. |
1736 EXPECT_NOERR( | 1742 apm_->StartDebugRecording(AecDumpFactory::Create( |
1737 apm_->StartDebugRecording(out_filename.c_str(), max_size_bytes)); | 1743 out_filename, max_size_bytes, &worker_queue)); |
1738 first_init = false; | 1744 first_init = false; |
1739 } | 1745 } |
1740 | 1746 |
1741 } else if (event_msg.type() == audioproc::Event::REVERSE_STREAM) { | 1747 } else if (event_msg.type() == audioproc::Event::REVERSE_STREAM) { |
1742 const audioproc::ReverseStream msg = event_msg.reverse_stream(); | 1748 const audioproc::ReverseStream msg = event_msg.reverse_stream(); |
1743 | 1749 |
1744 if (msg.channel_size() > 0) { | 1750 if (msg.channel_size() > 0) { |
1745 ASSERT_EQ(revframe_->num_channels_, | 1751 ASSERT_EQ(revframe_->num_channels_, |
1746 static_cast<size_t>(msg.channel_size())); | 1752 static_cast<size_t>(msg.channel_size())); |
1747 for (int i = 0; i < msg.channel_size(); ++i) { | 1753 for (int i = 0; i < msg.channel_size(); ++i) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1783 } else { | 1789 } else { |
1784 memcpy(frame_->data_, msg.input_data().data(), msg.input_data().size()); | 1790 memcpy(frame_->data_, msg.input_data().data(), msg.input_data().size()); |
1785 if (format == kFloatFormat) { | 1791 if (format == kFloatFormat) { |
1786 // We're using an int16 input file; convert to float. | 1792 // We're using an int16 input file; convert to float. |
1787 ConvertToFloat(*frame_, float_cb_.get()); | 1793 ConvertToFloat(*frame_, float_cb_.get()); |
1788 } | 1794 } |
1789 } | 1795 } |
1790 ProcessStreamChooser(format); | 1796 ProcessStreamChooser(format); |
1791 } | 1797 } |
1792 } | 1798 } |
1793 EXPECT_NOERR(apm_->StopDebugRecording()); | 1799 apm_->StopDebugRecording(); |
1794 fclose(in_file); | 1800 fclose(in_file); |
1795 } | 1801 } |
1796 | 1802 |
1797 void ApmTest::VerifyDebugDumpTest(Format format) { | 1803 void ApmTest::VerifyDebugDumpTest(Format format) { |
1798 const std::string in_filename = test::ResourcePath("ref03", "aecdump"); | 1804 const std::string in_filename = test::ResourcePath("ref03", "aecdump"); |
1799 std::string format_string; | 1805 std::string format_string; |
1800 switch (format) { | 1806 switch (format) { |
1801 case kIntFormat: | 1807 case kIntFormat: |
1802 format_string = "_int"; | 1808 format_string = "_int"; |
1803 break; | 1809 break; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1863 VerifyDebugDumpTest(kIntFormat); | 1869 VerifyDebugDumpTest(kIntFormat); |
1864 } | 1870 } |
1865 | 1871 |
1866 TEST_F(ApmTest, VerifyDebugDumpFloat) { | 1872 TEST_F(ApmTest, VerifyDebugDumpFloat) { |
1867 VerifyDebugDumpTest(kFloatFormat); | 1873 VerifyDebugDumpTest(kFloatFormat); |
1868 } | 1874 } |
1869 #endif | 1875 #endif |
1870 | 1876 |
1871 // TODO(andrew): expand test to verify output. | 1877 // TODO(andrew): expand test to verify output. |
1872 TEST_F(ApmTest, DebugDump) { | 1878 TEST_F(ApmTest, DebugDump) { |
| 1879 rtc::TaskQueue worker_queue("ApmTest_worker_queue"); |
1873 const std::string filename = | 1880 const std::string filename = |
1874 test::TempFilename(test::OutputPath(), "debug_aec"); | 1881 test::TempFilename(test::OutputPath(), "debug_aec"); |
1875 EXPECT_EQ(apm_->kNullPointerError, | |
1876 apm_->StartDebugRecording(static_cast<const char*>(NULL), -1)); | |
1877 | 1882 |
1878 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP | 1883 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP |
1879 // Stopping without having started should be OK. | 1884 // Stopping without having started should be OK. |
1880 EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording()); | 1885 apm_->StopDebugRecording(); |
1881 | 1886 |
1882 EXPECT_EQ(apm_->kNoError, apm_->StartDebugRecording(filename.c_str(), -1)); | 1887 apm_->StartDebugRecording( |
| 1888 webrtc::AecDumpFactory::Create(filename, -1, &worker_queue)); |
1883 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); | 1889 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); |
1884 EXPECT_EQ(apm_->kNoError, apm_->ProcessReverseStream(revframe_)); | 1890 EXPECT_EQ(apm_->kNoError, apm_->ProcessReverseStream(revframe_)); |
1885 EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording()); | 1891 apm_->StopDebugRecording(); |
1886 | 1892 |
1887 // Verify the file has been written. | 1893 // Verify the file has been written. |
1888 FILE* fid = fopen(filename.c_str(), "r"); | 1894 FILE* fid = fopen(filename.c_str(), "r"); |
1889 ASSERT_TRUE(fid != NULL); | 1895 ASSERT_TRUE(fid != NULL); |
1890 | 1896 |
1891 // Clean it up. | 1897 // Clean it up. |
1892 ASSERT_EQ(0, fclose(fid)); | 1898 ASSERT_EQ(0, fclose(fid)); |
1893 ASSERT_EQ(0, remove(filename.c_str())); | 1899 ASSERT_EQ(0, remove(filename.c_str())); |
1894 #else | 1900 #else |
1895 EXPECT_EQ(apm_->kUnsupportedFunctionError, | 1901 EXPECT_EQ(apm_->kUnsupportedFunctionError, |
1896 apm_->StartDebugRecording(filename.c_str(), -1)); | 1902 apm_->StartDebugRecording(filename.c_str(), -1)); |
1897 EXPECT_EQ(apm_->kUnsupportedFunctionError, apm_->StopDebugRecording()); | 1903 EXPECT_EQ(apm_->kUnsupportedFunctionError, apm_->StopDebugRecording()); |
1898 | 1904 |
1899 // Verify the file has NOT been written. | 1905 // Verify the file has NOT been written. |
1900 ASSERT_TRUE(fopen(filename.c_str(), "r") == NULL); | 1906 ASSERT_TRUE(fopen(filename.c_str(), "r") == NULL); |
1901 #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP | 1907 #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP |
1902 } | 1908 } |
1903 | 1909 |
1904 // TODO(andrew): expand test to verify output. | 1910 // TODO(andrew): expand test to verify output. |
1905 TEST_F(ApmTest, DebugDumpFromFileHandle) { | 1911 TEST_F(ApmTest, DebugDumpFromFileHandle) { |
1906 FILE* fid = NULL; | 1912 rtc::TaskQueue worker_queue("ApmTest_worker_queue"); |
1907 EXPECT_EQ(apm_->kNullPointerError, apm_->StartDebugRecording(fid, -1)); | |
1908 const std::string filename = | 1913 const std::string filename = |
1909 test::TempFilename(test::OutputPath(), "debug_aec"); | 1914 test::TempFilename(test::OutputPath(), "debug_aec"); |
1910 fid = fopen(filename.c_str(), "w"); | 1915 FILE* fid = fopen(filename.c_str(), "w"); |
1911 ASSERT_TRUE(fid); | 1916 ASSERT_TRUE(fid); |
1912 | 1917 |
1913 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP | 1918 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP |
1914 // Stopping without having started should be OK. | 1919 // Stopping without having started should be OK. |
1915 EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording()); | 1920 apm_->StopDebugRecording(); |
1916 | 1921 |
1917 EXPECT_EQ(apm_->kNoError, apm_->StartDebugRecording(fid, -1)); | 1922 apm_->StartDebugRecording( |
| 1923 webrtc::AecDumpFactory::Create(fid, -1, &worker_queue)); |
1918 EXPECT_EQ(apm_->kNoError, apm_->ProcessReverseStream(revframe_)); | 1924 EXPECT_EQ(apm_->kNoError, apm_->ProcessReverseStream(revframe_)); |
1919 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); | 1925 EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_)); |
1920 EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording()); | 1926 apm_->StopDebugRecording(); |
1921 | 1927 |
1922 // Verify the file has been written. | 1928 // Verify the file has been written. |
1923 fid = fopen(filename.c_str(), "r"); | 1929 fid = fopen(filename.c_str(), "r"); |
1924 ASSERT_TRUE(fid != NULL); | 1930 ASSERT_TRUE(fid != NULL); |
1925 | 1931 |
1926 // Clean it up. | 1932 // Clean it up. |
1927 ASSERT_EQ(0, fclose(fid)); | 1933 ASSERT_EQ(0, fclose(fid)); |
1928 ASSERT_EQ(0, remove(filename.c_str())); | 1934 ASSERT_EQ(0, remove(filename.c_str())); |
1929 #else | 1935 #else |
1930 EXPECT_EQ(apm_->kUnsupportedFunctionError, | 1936 EXPECT_EQ(apm_->kUnsupportedFunctionError, |
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2877 // TODO(peah): Remove the testing for | 2883 // TODO(peah): Remove the testing for |
2878 // apm->capture_nonlocked_.level_controller_enabled once the value in config_ | 2884 // apm->capture_nonlocked_.level_controller_enabled once the value in config_ |
2879 // is instead used to activate the level controller. | 2885 // is instead used to activate the level controller. |
2880 EXPECT_FALSE(apm->capture_nonlocked_.level_controller_enabled); | 2886 EXPECT_FALSE(apm->capture_nonlocked_.level_controller_enabled); |
2881 EXPECT_NEAR(kTargetLcPeakLeveldBFS, | 2887 EXPECT_NEAR(kTargetLcPeakLeveldBFS, |
2882 apm->config_.level_controller.initial_peak_level_dbfs, | 2888 apm->config_.level_controller.initial_peak_level_dbfs, |
2883 std::numeric_limits<float>::epsilon()); | 2889 std::numeric_limits<float>::epsilon()); |
2884 } | 2890 } |
2885 | 2891 |
2886 } // namespace webrtc | 2892 } // namespace webrtc |
OLD | NEW |