| 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 #include <string.h> | 13 #include <string.h> |
| 14 #ifdef WEBRTC_ANDROID | 14 #ifdef WEBRTC_ANDROID |
| 15 #include <sys/stat.h> | 15 #include <sys/stat.h> |
| 16 #endif | 16 #endif |
| 17 | 17 |
| 18 #include <algorithm> | 18 #include <algorithm> |
| 19 #include <memory> | 19 #include <memory> |
| 20 | 20 |
| 21 #include "webrtc/base/format_macros.h" | 21 #include "webrtc/base/format_macros.h" |
| 22 #include "webrtc/base/timeutils.h" |
| 22 #include "webrtc/common.h" | 23 #include "webrtc/common.h" |
| 23 #include "webrtc/modules/audio_processing/include/audio_processing.h" | 24 #include "webrtc/modules/audio_processing/include/audio_processing.h" |
| 24 #include "webrtc/modules/audio_processing/test/protobuf_utils.h" | 25 #include "webrtc/modules/audio_processing/test/protobuf_utils.h" |
| 25 #include "webrtc/modules/audio_processing/test/test_utils.h" | 26 #include "webrtc/modules/audio_processing/test/test_utils.h" |
| 26 #include "webrtc/modules/include/module_common_types.h" | 27 #include "webrtc/modules/include/module_common_types.h" |
| 27 #include "webrtc/system_wrappers/include/cpu_features_wrapper.h" | 28 #include "webrtc/system_wrappers/include/cpu_features_wrapper.h" |
| 28 #include "webrtc/system_wrappers/include/tick_util.h" | |
| 29 #include "webrtc/test/testsupport/fileutils.h" | 29 #include "webrtc/test/testsupport/fileutils.h" |
| 30 #include "webrtc/test/testsupport/perf_test.h" | 30 #include "webrtc/test/testsupport/perf_test.h" |
| 31 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD | 31 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD |
| 32 #include "gtest/gtest.h" | 32 #include "gtest/gtest.h" |
| 33 #include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h" | 33 #include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h" |
| 34 #else | 34 #else |
| 35 #include "testing/gtest/include/gtest/gtest.h" | 35 #include "testing/gtest/include/gtest/gtest.h" |
| 36 #include "webrtc/modules/audio_processing/debug.pb.h" | 36 #include "webrtc/modules/audio_processing/debug.pb.h" |
| 37 #endif | 37 #endif |
| 38 | 38 |
| (...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 } | 555 } |
| 556 | 556 |
| 557 if (aecm_echo_path_out_filename != NULL) { | 557 if (aecm_echo_path_out_filename != NULL) { |
| 558 aecm_echo_path_out_file = OpenFile(aecm_echo_path_out_filename, "wb"); | 558 aecm_echo_path_out_file = OpenFile(aecm_echo_path_out_filename, "wb"); |
| 559 } | 559 } |
| 560 | 560 |
| 561 size_t read_count = 0; | 561 size_t read_count = 0; |
| 562 int reverse_count = 0; | 562 int reverse_count = 0; |
| 563 int primary_count = 0; | 563 int primary_count = 0; |
| 564 int near_read_bytes = 0; | 564 int near_read_bytes = 0; |
| 565 TickInterval acc_ticks; | 565 int64_t acc_nanos = 0; |
| 566 | 566 |
| 567 AudioFrame far_frame; | 567 AudioFrame far_frame; |
| 568 AudioFrame near_frame; | 568 AudioFrame near_frame; |
| 569 | 569 |
| 570 int delay_ms = 0; | 570 int delay_ms = 0; |
| 571 int drift_samples = 0; | 571 int drift_samples = 0; |
| 572 int capture_level = 127; | 572 int capture_level = 127; |
| 573 int8_t stream_has_voice = 0; | 573 int8_t stream_has_voice = 0; |
| 574 float ns_speech_prob = 0.0f; | 574 float ns_speech_prob = 0.0f; |
| 575 | 575 |
| 576 TickTime t0 = TickTime::Now(); | 576 int64_t t0 = rtc::TimeNanos(); |
| 577 TickTime t1 = t0; | 577 int64_t t1 = t0; |
| 578 int64_t max_time_us = 0; | 578 int64_t max_time_us = 0; |
| 579 int64_t max_time_reverse_us = 0; | 579 int64_t max_time_reverse_us = 0; |
| 580 int64_t min_time_us = 1e6; | 580 int64_t min_time_us = 1e6; |
| 581 int64_t min_time_reverse_us = 1e6; | 581 int64_t min_time_reverse_us = 1e6; |
| 582 | 582 |
| 583 // TODO(ajm): Ideally we would refactor this block into separate functions, | 583 // TODO(ajm): Ideally we would refactor this block into separate functions, |
| 584 // but for now we want to share the variables. | 584 // but for now we want to share the variables. |
| 585 if (pb_file) { | 585 if (pb_file) { |
| 586 Event event_msg; | 586 Event event_msg; |
| 587 std::unique_ptr<ChannelBuffer<float> > reverse_cb; | 587 std::unique_ptr<ChannelBuffer<float> > reverse_cb; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 } else { | 669 } else { |
| 670 for (int i = 0; i < msg.channel_size(); ++i) { | 670 for (int i = 0; i < msg.channel_size(); ++i) { |
| 671 memcpy(reverse_cb->channels()[i], | 671 memcpy(reverse_cb->channels()[i], |
| 672 msg.channel(i).data(), | 672 msg.channel(i).data(), |
| 673 reverse_cb->num_frames() * | 673 reverse_cb->num_frames() * |
| 674 sizeof(reverse_cb->channels()[i][0])); | 674 sizeof(reverse_cb->channels()[i][0])); |
| 675 } | 675 } |
| 676 } | 676 } |
| 677 | 677 |
| 678 if (perf_testing) { | 678 if (perf_testing) { |
| 679 t0 = TickTime::Now(); | 679 t0 = rtc::TimeNanos(); |
| 680 } | 680 } |
| 681 | 681 |
| 682 if (msg.has_data()) { | 682 if (msg.has_data()) { |
| 683 ASSERT_EQ(apm->kNoError, | 683 ASSERT_EQ(apm->kNoError, |
| 684 apm->ProcessReverseStream(&far_frame)); | 684 apm->ProcessReverseStream(&far_frame)); |
| 685 } else { | 685 } else { |
| 686 ASSERT_EQ(apm->kNoError, | 686 ASSERT_EQ(apm->kNoError, |
| 687 apm->AnalyzeReverseStream( | 687 apm->AnalyzeReverseStream( |
| 688 reverse_cb->channels(), | 688 reverse_cb->channels(), |
| 689 far_frame.samples_per_channel_, | 689 far_frame.samples_per_channel_, |
| 690 far_frame.sample_rate_hz_, | 690 far_frame.sample_rate_hz_, |
| 691 LayoutFromChannels(far_frame.num_channels_))); | 691 LayoutFromChannels(far_frame.num_channels_))); |
| 692 } | 692 } |
| 693 | 693 |
| 694 if (perf_testing) { | 694 if (perf_testing) { |
| 695 t1 = TickTime::Now(); | 695 t1 = rtc::TimeNanos(); |
| 696 TickInterval tick_diff = t1 - t0; | 696 int64_t diff_nanos = t1 - t0; |
| 697 acc_ticks += tick_diff; | 697 acc_nanos += diff_nanos; |
| 698 if (tick_diff.Microseconds() > max_time_reverse_us) { | 698 int64_t diff_us = diff_nanos / rtc::kNumNanosecsPerMicrosec; |
| 699 max_time_reverse_us = tick_diff.Microseconds(); | 699 if (diff_us > max_time_reverse_us) { |
| 700 max_time_reverse_us = diff_us; |
| 700 } | 701 } |
| 701 if (tick_diff.Microseconds() < min_time_reverse_us) { | 702 if (diff_us < min_time_reverse_us) { |
| 702 min_time_reverse_us = tick_diff.Microseconds(); | 703 min_time_reverse_us = diff_us; |
| 703 } | 704 } |
| 704 } | 705 } |
| 705 | 706 |
| 706 } else if (event_msg.type() == Event::STREAM) { | 707 } else if (event_msg.type() == Event::STREAM) { |
| 707 ASSERT_TRUE(event_msg.has_stream()); | 708 ASSERT_TRUE(event_msg.has_stream()); |
| 708 const Stream msg = event_msg.stream(); | 709 const Stream msg = event_msg.stream(); |
| 709 primary_count++; | 710 primary_count++; |
| 710 | 711 |
| 711 // ProcessStream could have changed this for the output frame. | 712 // ProcessStream could have changed this for the output frame. |
| 712 near_frame.num_channels_ = apm->num_input_channels(); | 713 near_frame.num_channels_ = apm->num_input_channels(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 730 } | 731 } |
| 731 | 732 |
| 732 if (progress && primary_count % 100 == 0) { | 733 if (progress && primary_count % 100 == 0) { |
| 733 near_read_bytes = std::min(near_read_bytes, near_size_bytes); | 734 near_read_bytes = std::min(near_read_bytes, near_size_bytes); |
| 734 printf("%.0f%% complete\r", | 735 printf("%.0f%% complete\r", |
| 735 (near_read_bytes * 100.0) / near_size_bytes); | 736 (near_read_bytes * 100.0) / near_size_bytes); |
| 736 fflush(stdout); | 737 fflush(stdout); |
| 737 } | 738 } |
| 738 | 739 |
| 739 if (perf_testing) { | 740 if (perf_testing) { |
| 740 t0 = TickTime::Now(); | 741 t0 = rtc::TimeNanos(); |
| 741 } | 742 } |
| 742 | 743 |
| 743 ASSERT_EQ(apm->kNoError, | 744 ASSERT_EQ(apm->kNoError, |
| 744 apm->gain_control()->set_stream_analog_level(msg.level())); | 745 apm->gain_control()->set_stream_analog_level(msg.level())); |
| 745 delay_ms = msg.delay() + extra_delay_ms; | 746 delay_ms = msg.delay() + extra_delay_ms; |
| 746 if (override_delay_ms) { | 747 if (override_delay_ms) { |
| 747 delay_ms = override_delay_ms; | 748 delay_ms = override_delay_ms; |
| 748 } | 749 } |
| 749 ASSERT_EQ(apm->kNoError, | 750 ASSERT_EQ(apm->kNoError, |
| 750 apm->set_stream_delay_ms(delay_ms)); | 751 apm->set_stream_delay_ms(delay_ms)); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 788 | 789 |
| 789 if (ns_prob_file != NULL) { | 790 if (ns_prob_file != NULL) { |
| 790 ns_speech_prob = apm->noise_suppression()->speech_probability(); | 791 ns_speech_prob = apm->noise_suppression()->speech_probability(); |
| 791 ASSERT_EQ(1u, fwrite(&ns_speech_prob, | 792 ASSERT_EQ(1u, fwrite(&ns_speech_prob, |
| 792 sizeof(ns_speech_prob), | 793 sizeof(ns_speech_prob), |
| 793 1, | 794 1, |
| 794 ns_prob_file)); | 795 ns_prob_file)); |
| 795 } | 796 } |
| 796 | 797 |
| 797 if (perf_testing) { | 798 if (perf_testing) { |
| 798 t1 = TickTime::Now(); | 799 t1 = rtc::TimeNanos(); |
| 799 TickInterval tick_diff = t1 - t0; | 800 int64_t diff_nanos = t1 - t0; |
| 800 acc_ticks += tick_diff; | 801 acc_nanos += diff_nanos; |
| 801 if (tick_diff.Microseconds() > max_time_us) { | 802 int64_t diff_us = diff_nanos / rtc::kNumNanosecsPerMicrosec; |
| 802 max_time_us = tick_diff.Microseconds(); | 803 if (diff_us > max_time_us) { |
| 804 max_time_us = diff_us; |
| 803 } | 805 } |
| 804 if (tick_diff.Microseconds() < min_time_us) { | 806 if (diff_us < min_time_us) { |
| 805 min_time_us = tick_diff.Microseconds(); | 807 min_time_us = diff_us; |
| 806 } | 808 } |
| 807 } | 809 } |
| 808 | 810 |
| 809 const size_t samples_per_channel = output_sample_rate / 100; | 811 const size_t samples_per_channel = output_sample_rate / 100; |
| 810 if (msg.has_input_data()) { | 812 if (msg.has_input_data()) { |
| 811 if (raw_output && !output_raw_file) { | 813 if (raw_output && !output_raw_file) { |
| 812 output_raw_file.reset(new RawFile(out_filename + ".pcm")); | 814 output_raw_file.reset(new RawFile(out_filename + ".pcm")); |
| 813 } | 815 } |
| 814 WriteIntData(near_frame.data_, | 816 WriteIntData(near_frame.data_, |
| 815 apm->num_output_channels() * samples_per_channel, | 817 apm->num_output_channels() * samples_per_channel, |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 // not reaching end-of-file. | 920 // not reaching end-of-file. |
| 919 EXPECT_EQ(0, fseek(near_file, read_count * sizeof(int16_t), | 921 EXPECT_EQ(0, fseek(near_file, read_count * sizeof(int16_t), |
| 920 SEEK_CUR)); | 922 SEEK_CUR)); |
| 921 break; // This is expected. | 923 break; // This is expected. |
| 922 } | 924 } |
| 923 } else { | 925 } else { |
| 924 ASSERT_EQ(size, read_count); | 926 ASSERT_EQ(size, read_count); |
| 925 } | 927 } |
| 926 | 928 |
| 927 if (perf_testing) { | 929 if (perf_testing) { |
| 928 t0 = TickTime::Now(); | 930 t0 = rtc::TimeNanos(); |
| 929 } | 931 } |
| 930 | 932 |
| 931 ASSERT_EQ(apm->kNoError, | 933 ASSERT_EQ(apm->kNoError, |
| 932 apm->ProcessReverseStream(&far_frame)); | 934 apm->ProcessReverseStream(&far_frame)); |
| 933 | 935 |
| 934 if (perf_testing) { | 936 if (perf_testing) { |
| 935 t1 = TickTime::Now(); | 937 t1 = rtc::TimeNanos(); |
| 936 TickInterval tick_diff = t1 - t0; | 938 int64_t diff_nanos = t1 - t0; |
| 937 acc_ticks += tick_diff; | 939 acc_nanos += diff_nanos; |
| 938 if (tick_diff.Microseconds() > max_time_reverse_us) { | 940 int64_t diff_us = diff_nanos / rtc::kNumNanosecsPerMicrosec; |
| 939 max_time_reverse_us = tick_diff.Microseconds(); | 941 if (diff_us > max_time_reverse_us) { |
| 942 max_time_reverse_us = diff_us; |
| 940 } | 943 } |
| 941 if (tick_diff.Microseconds() < min_time_reverse_us) { | 944 if (diff_us < min_time_reverse_us) { |
| 942 min_time_reverse_us = tick_diff.Microseconds(); | 945 min_time_reverse_us = diff_us; |
| 943 } | 946 } |
| 944 } | 947 } |
| 945 | 948 |
| 946 } else if (event == kCaptureEvent) { | 949 } else if (event == kCaptureEvent) { |
| 947 primary_count++; | 950 primary_count++; |
| 948 near_frame.num_channels_ = num_capture_input_channels; | 951 near_frame.num_channels_ = num_capture_input_channels; |
| 949 | 952 |
| 950 size_t size = samples_per_channel * num_capture_input_channels; | 953 size_t size = samples_per_channel * num_capture_input_channels; |
| 951 read_count = fread(near_frame.data_, | 954 read_count = fread(near_frame.data_, |
| 952 sizeof(int16_t), | 955 sizeof(int16_t), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 975 ASSERT_EQ(1u, | 978 ASSERT_EQ(1u, |
| 976 fread(&drift_samples, sizeof(drift_samples), 1, drift_file)); | 979 fread(&drift_samples, sizeof(drift_samples), 1, drift_file)); |
| 977 } | 980 } |
| 978 | 981 |
| 979 if (apm->gain_control()->is_enabled() && | 982 if (apm->gain_control()->is_enabled() && |
| 980 apm->gain_control()->mode() == GainControl::kAdaptiveAnalog) { | 983 apm->gain_control()->mode() == GainControl::kAdaptiveAnalog) { |
| 981 SimulateMic(capture_level, &near_frame); | 984 SimulateMic(capture_level, &near_frame); |
| 982 } | 985 } |
| 983 | 986 |
| 984 if (perf_testing) { | 987 if (perf_testing) { |
| 985 t0 = TickTime::Now(); | 988 t0 = rtc::TimeNanos(); |
| 986 } | 989 } |
| 987 | 990 |
| 988 const int capture_level_in = capture_level; | 991 const int capture_level_in = capture_level; |
| 989 ASSERT_EQ(apm->kNoError, | 992 ASSERT_EQ(apm->kNoError, |
| 990 apm->gain_control()->set_stream_analog_level(capture_level)); | 993 apm->gain_control()->set_stream_analog_level(capture_level)); |
| 991 delay_ms += extra_delay_ms; | 994 delay_ms += extra_delay_ms; |
| 992 if (override_delay_ms) { | 995 if (override_delay_ms) { |
| 993 delay_ms = override_delay_ms; | 996 delay_ms = override_delay_ms; |
| 994 } | 997 } |
| 995 ASSERT_EQ(apm->kNoError, | 998 ASSERT_EQ(apm->kNoError, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1023 sizeof(ns_speech_prob), | 1026 sizeof(ns_speech_prob), |
| 1024 1, | 1027 1, |
| 1025 ns_prob_file)); | 1028 ns_prob_file)); |
| 1026 } | 1029 } |
| 1027 | 1030 |
| 1028 if (apm->gain_control()->mode() != GainControl::kAdaptiveAnalog) { | 1031 if (apm->gain_control()->mode() != GainControl::kAdaptiveAnalog) { |
| 1029 ASSERT_EQ(capture_level_in, capture_level); | 1032 ASSERT_EQ(capture_level_in, capture_level); |
| 1030 } | 1033 } |
| 1031 | 1034 |
| 1032 if (perf_testing) { | 1035 if (perf_testing) { |
| 1033 t1 = TickTime::Now(); | 1036 t1 = rtc::TimeNanos(); |
| 1034 TickInterval tick_diff = t1 - t0; | 1037 int64_t diff_nanos = t1 - t0; |
| 1035 acc_ticks += tick_diff; | 1038 acc_nanos += diff_nanos; |
| 1036 if (tick_diff.Microseconds() > max_time_us) { | 1039 int64_t diff_us = diff_nanos / rtc::kNumNanosecsPerMicrosec; |
| 1037 max_time_us = tick_diff.Microseconds(); | 1040 if (diff_us > max_time_us) { |
| 1041 max_time_us = diff_us; |
| 1038 } | 1042 } |
| 1039 if (tick_diff.Microseconds() < min_time_us) { | 1043 if (diff_us < min_time_us) { |
| 1040 min_time_us = tick_diff.Microseconds(); | 1044 min_time_us = diff_us; |
| 1041 } | 1045 } |
| 1042 } | 1046 } |
| 1043 | 1047 |
| 1044 if (raw_output && !output_raw_file) { | 1048 if (raw_output && !output_raw_file) { |
| 1045 output_raw_file.reset(new RawFile(out_filename + ".pcm")); | 1049 output_raw_file.reset(new RawFile(out_filename + ".pcm")); |
| 1046 } | 1050 } |
| 1047 if (!raw_output && !output_wav_file) { | 1051 if (!raw_output && !output_wav_file) { |
| 1048 output_wav_file.reset(new WavWriter(out_filename + ".wav", | 1052 output_wav_file.reset(new WavWriter(out_filename + ".wav", |
| 1049 sample_rate_hz, | 1053 sample_rate_hz, |
| 1050 num_capture_output_channels)); | 1054 num_capture_output_channels)); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1123 EXPECT_NE(0, feof(event_file)) << "Event file not fully processed"; | 1127 EXPECT_NE(0, feof(event_file)) << "Event file not fully processed"; |
| 1124 read_count = fread(&temp_int8, sizeof(temp_int8), 1, delay_file); | 1128 read_count = fread(&temp_int8, sizeof(temp_int8), 1, delay_file); |
| 1125 EXPECT_NE(0, feof(delay_file)) << "Delay file not fully processed"; | 1129 EXPECT_NE(0, feof(delay_file)) << "Delay file not fully processed"; |
| 1126 read_count = fread(&temp_int8, sizeof(temp_int8), 1, drift_file); | 1130 read_count = fread(&temp_int8, sizeof(temp_int8), 1, drift_file); |
| 1127 EXPECT_NE(0, feof(drift_file)) << "Drift file not fully processed"; | 1131 EXPECT_NE(0, feof(drift_file)) << "Drift file not fully processed"; |
| 1128 } | 1132 } |
| 1129 } | 1133 } |
| 1130 | 1134 |
| 1131 if (perf_testing) { | 1135 if (perf_testing) { |
| 1132 if (primary_count > 0) { | 1136 if (primary_count > 0) { |
| 1133 int64_t exec_time = acc_ticks.Milliseconds(); | 1137 int64_t exec_time = acc_nanos / rtc::kNumNanosecsPerMillisec; |
| 1134 printf("\nTotal time: %.3f s, file time: %.2f s\n", | 1138 printf("\nTotal time: %.3f s, file time: %.2f s\n", |
| 1135 exec_time * 0.001, primary_count * 0.01); | 1139 exec_time * 0.001, primary_count * 0.01); |
| 1136 printf("Time per frame: %.3f ms (average), %.3f ms (max)," | 1140 printf("Time per frame: %.3f ms (average), %.3f ms (max)," |
| 1137 " %.3f ms (min)\n", | 1141 " %.3f ms (min)\n", |
| 1138 (exec_time * 1.0) / primary_count, | 1142 (exec_time * 1.0) / primary_count, |
| 1139 (max_time_us + max_time_reverse_us) / 1000.0, | 1143 (max_time_us + max_time_reverse_us) / 1000.0, |
| 1140 (min_time_us + min_time_reverse_us) / 1000.0); | 1144 (min_time_us + min_time_reverse_us) / 1000.0); |
| 1141 // Record the results with Perf test tools. | 1145 // Record the results with Perf test tools. |
| 1142 webrtc::test::PrintResult("audioproc", "", "time_per_10ms_frame", | 1146 webrtc::test::PrintResult("audioproc", "", "time_per_10ms_frame", |
| 1143 (exec_time * 1000) / primary_count, "us", false); | 1147 (exec_time * 1000) / primary_count, "us", false); |
| 1144 } else { | 1148 } else { |
| 1145 printf("Warning: no capture frames\n"); | 1149 printf("Warning: no capture frames\n"); |
| 1146 } | 1150 } |
| 1147 } | 1151 } |
| 1148 } | 1152 } |
| 1149 | 1153 |
| 1150 } // namespace | 1154 } // namespace |
| 1151 } // namespace webrtc | 1155 } // namespace webrtc |
| 1152 | 1156 |
| 1153 int main(int argc, char* argv[]) { | 1157 int main(int argc, char* argv[]) { |
| 1154 webrtc::void_main(argc, argv); | 1158 webrtc::void_main(argc, argv); |
| 1155 | 1159 |
| 1156 // Optional, but removes memory leak noise from Valgrind. | 1160 // Optional, but removes memory leak noise from Valgrind. |
| 1157 google::protobuf::ShutdownProtobufLibrary(); | 1161 google::protobuf::ShutdownProtobufLibrary(); |
| 1158 return 0; | 1162 return 0; |
| 1159 } | 1163 } |
| OLD | NEW |