From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- third_party/libwebrtc/rtc_tools/BUILD.gn | 600 + third_party/libwebrtc/rtc_tools/DEPS | 36 + third_party/libwebrtc/rtc_tools/OWNERS | 4 + .../rtc_tools/audioproc_f/audioproc_float_main.cc | 19 + .../libwebrtc/rtc_tools/author_line_count.sh | 28 + third_party/libwebrtc/rtc_tools/class_usage.sh | 22 + third_party/libwebrtc/rtc_tools/compare_videos.py | 210 + .../rtc_tools/data_channel_benchmark/BUILD.gn | 63 + .../data_channel_benchmark.cc | 322 + .../data_channel_benchmark/grpc_signaling.cc | 267 + .../data_channel_benchmark/grpc_signaling.h | 64 + .../peer_connection_client.cc | 300 + .../peer_connection_client.h | 107 + .../peer_connection_signaling.proto | 29 + .../data_channel_benchmark/signaling_interface.h | 42 + .../rtc_tools/frame_analyzer/frame_analyzer.cc | 197 + .../frame_analyzer/linear_least_squares.cc | 206 + .../frame_analyzer/linear_least_squares.h | 56 + .../linear_least_squares_unittest.cc | 93 + .../reference_less_video_analysis.cc | 41 + .../reference_less_video_analysis_lib.cc | 139 + .../reference_less_video_analysis_lib.h | 48 + .../reference_less_video_analysis_unittest.cc | 49 + .../frame_analyzer/video_color_aligner.cc | 237 + .../rtc_tools/frame_analyzer/video_color_aligner.h | 51 + .../frame_analyzer/video_color_aligner_unittest.cc | 176 + .../frame_analyzer/video_geometry_aligner.cc | 178 + .../frame_analyzer/video_geometry_aligner.h | 57 + .../video_geometry_aligner_unittest.cc | 153 + .../frame_analyzer/video_quality_analysis.cc | 160 + .../frame_analyzer/video_quality_analysis.h | 103 + .../video_quality_analysis_unittest.cc | 249 + .../frame_analyzer/video_temporal_aligner.cc | 238 + .../frame_analyzer/video_temporal_aligner.h | 61 + .../video_temporal_aligner_unittest.cc | 129 + third_party/libwebrtc/rtc_tools/header_usage.sh | 37 + third_party/libwebrtc/rtc_tools/metrics_plotter.py | 98 + .../libwebrtc/rtc_tools/network_tester/BUILD.gn | 184 + .../libwebrtc/rtc_tools/network_tester/README | 35 + .../network_tester/androidapp/AndroidManifest.xml | 24 + .../androidapp/res/layout/activity_main.xml | 28 + .../androidapp/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3418 bytes .../androidapp/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2206 bytes .../androidapp/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4842 bytes .../androidapp/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7718 bytes .../androidapp/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 10486 bytes .../androidapp/res/values-v17/styles.xml | 8 + .../androidapp/res/values-w820dp/dimens.xml | 6 + .../androidapp/res/values/colors.xml | 6 + .../androidapp/res/values/dimens.xml | 5 + .../androidapp/res/values/strings.xml | 6 + .../google/media/networktester/MainActivity.java | 62 + .../google/media/networktester/NetworkTester.java | 32 + .../rtc_tools/network_tester/config_reader.cc | 54 + .../rtc_tools/network_tester/config_reader.h | 53 + .../network_tester/create_network_tester_config.py | 30 + .../libwebrtc/rtc_tools/network_tester/jni.cc | 68 + .../network_tester/network_tester_config.proto | 14 + .../network_tester/network_tester_packet.proto | 18 + .../network_tester/network_tester_unittest.cc | 37 + .../rtc_tools/network_tester/packet_logger.cc | 44 + .../rtc_tools/network_tester/packet_logger.h | 46 + .../rtc_tools/network_tester/packet_sender.cc | 133 + .../rtc_tools/network_tester/packet_sender.h | 71 + .../rtc_tools/network_tester/parse_packet_log.py | 150 + .../libwebrtc/rtc_tools/network_tester/server.cc | 23 + .../rtc_tools/network_tester/test_controller.cc | 158 + .../rtc_tools/network_tester/test_controller.h | 95 + .../psnr_ssim_analyzer/psnr_ssim_analyzer.cc | 108 + .../rtc_tools/py_event_log_analyzer/README.md | 26 + .../rtc_tools/py_event_log_analyzer/misc.py | 85 + .../rtc_tools/py_event_log_analyzer/misc_test.py | 74 + .../rtc_tools/py_event_log_analyzer/pb_parse.py | 51 + .../py_event_log_analyzer/rtp_analyzer.py | 340 + .../py_event_log_analyzer/rtp_analyzer.sh | 10 + .../py_event_log_analyzer/rtp_analyzer_test.py | 62 + .../rtc_tools/rtc_event_log_to_text/OWNERS | 1 + .../rtc_tools/rtc_event_log_to_text/converter.cc | 525 + .../rtc_tools/rtc_event_log_to_text/converter.h | 36 + .../rtc_tools/rtc_event_log_to_text/main.cc | 78 + .../rtc_tools/rtc_event_log_visualizer/OWNERS | 1 + .../rtc_tools/rtc_event_log_visualizer/alerts.cc | 236 + .../rtc_tools/rtc_event_log_visualizer/alerts.h | 89 + .../rtc_event_log_visualizer/analyze_audio.cc | 499 + .../rtc_event_log_visualizer/analyze_audio.h | 75 + .../rtc_tools/rtc_event_log_visualizer/analyzer.cc | 1831 + .../rtc_tools/rtc_event_log_visualizer/analyzer.h | 115 + .../rtc_event_log_visualizer/analyzer_common.cc | 83 + .../rtc_event_log_visualizer/analyzer_common.h | 196 + .../conversational_speech_en.h | 169459 ++++++++++++++++++ .../rtc_event_log_visualizer/log_simulation.cc | 209 + .../rtc_event_log_visualizer/log_simulation.h | 64 + .../rtc_tools/rtc_event_log_visualizer/main.cc | 653 + .../rtc_event_log_visualizer/plot_base.cc | 324 + .../rtc_tools/rtc_event_log_visualizer/plot_base.h | 215 + .../rtc_event_log_visualizer/plot_protobuf.cc | 45 + .../rtc_event_log_visualizer/plot_protobuf.h | 40 + .../rtc_event_log_visualizer/plot_python.cc | 46 + .../rtc_event_log_visualizer/plot_python.h | 39 + .../rtc_event_log_visualizer/proto/chart.proto | 40 + .../proto/chart_enums.proto | 13 + .../rtc_tools/rtp_generator/configs/vp8.json | 13 + .../rtc_tools/rtp_generator/configs/vp9.json | 13 + .../libwebrtc/rtc_tools/rtp_generator/main.cc | 48 + .../rtc_tools/rtp_generator/rtp_generator.cc | 330 + .../rtc_tools/rtp_generator/rtp_generator.h | 124 + .../libwebrtc/rtc_tools/sanitizers_unittest.cc | 125 + third_party/libwebrtc/rtc_tools/testing/README.md | 44 + .../libwebrtc/rtc_tools/testing/build_apprtc.py | 67 + .../libwebrtc/rtc_tools/testing/download_apprtc.py | 56 + .../rtc_tools/testing/golang/linux/go.tar.gz.sha1 | 1 + .../rtc_tools/testing/golang/mac/go.tar.gz.sha1 | 1 + .../rtc_tools/testing/golang/win/go.zip.sha1 | 1 + .../rtc_tools/testing/prebuilt_apprtc.zip.sha1 | 1 + .../libwebrtc/rtc_tools/testing/setup_apprtc.py | 43 + third_party/libwebrtc/rtc_tools/testing/utils.py | 129 + .../libwebrtc/rtc_tools/unpack_aecdump/OWNERS | 3 + .../libwebrtc/rtc_tools/unpack_aecdump/unpack.cc | 621 + .../libwebrtc/rtc_tools/video_file_reader.cc | 288 + .../libwebrtc/rtc_tools/video_file_reader.h | 82 + .../rtc_tools/video_file_reader_unittest.cc | 127 + .../libwebrtc/rtc_tools/video_file_writer.cc | 93 + .../libwebrtc/rtc_tools/video_file_writer.h | 39 + .../rtc_tools/video_file_writer_unittest.cc | 151 + third_party/libwebrtc/rtc_tools/video_replay.cc | 717 + 125 files changed, 185044 insertions(+) create mode 100644 third_party/libwebrtc/rtc_tools/BUILD.gn create mode 100644 third_party/libwebrtc/rtc_tools/DEPS create mode 100644 third_party/libwebrtc/rtc_tools/OWNERS create mode 100644 third_party/libwebrtc/rtc_tools/audioproc_f/audioproc_float_main.cc create mode 100755 third_party/libwebrtc/rtc_tools/author_line_count.sh create mode 100755 third_party/libwebrtc/rtc_tools/class_usage.sh create mode 100755 third_party/libwebrtc/rtc_tools/compare_videos.py create mode 100644 third_party/libwebrtc/rtc_tools/data_channel_benchmark/BUILD.gn create mode 100644 third_party/libwebrtc/rtc_tools/data_channel_benchmark/data_channel_benchmark.cc create mode 100644 third_party/libwebrtc/rtc_tools/data_channel_benchmark/grpc_signaling.cc create mode 100644 third_party/libwebrtc/rtc_tools/data_channel_benchmark/grpc_signaling.h create mode 100644 third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_client.cc create mode 100644 third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_client.h create mode 100644 third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_signaling.proto create mode 100644 third_party/libwebrtc/rtc_tools/data_channel_benchmark/signaling_interface.h create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/frame_analyzer.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/linear_least_squares.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/linear_least_squares.h create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/linear_least_squares_unittest.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/reference_less_video_analysis.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/reference_less_video_analysis_lib.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/reference_less_video_analysis_lib.h create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/reference_less_video_analysis_unittest.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_color_aligner.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_color_aligner.h create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_color_aligner_unittest.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_geometry_aligner.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_geometry_aligner.h create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_geometry_aligner_unittest.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_quality_analysis.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_quality_analysis.h create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_quality_analysis_unittest.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_temporal_aligner.cc create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_temporal_aligner.h create mode 100644 third_party/libwebrtc/rtc_tools/frame_analyzer/video_temporal_aligner_unittest.cc create mode 100755 third_party/libwebrtc/rtc_tools/header_usage.sh create mode 100644 third_party/libwebrtc/rtc_tools/metrics_plotter.py create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/BUILD.gn create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/README create mode 100755 third_party/libwebrtc/rtc_tools/network_tester/androidapp/AndroidManifest.xml create mode 100755 third_party/libwebrtc/rtc_tools/network_tester/androidapp/res/layout/activity_main.xml create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/androidapp/res/mipmap-hdpi/ic_launcher.png create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/androidapp/res/mipmap-mdpi/ic_launcher.png create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/androidapp/res/mipmap-xhdpi/ic_launcher.png create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/androidapp/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/androidapp/res/mipmap-xxxhdpi/ic_launcher.png create mode 100755 third_party/libwebrtc/rtc_tools/network_tester/androidapp/res/values-v17/styles.xml create mode 100755 third_party/libwebrtc/rtc_tools/network_tester/androidapp/res/values-w820dp/dimens.xml create mode 100755 third_party/libwebrtc/rtc_tools/network_tester/androidapp/res/values/colors.xml create mode 100755 third_party/libwebrtc/rtc_tools/network_tester/androidapp/res/values/dimens.xml create mode 100755 third_party/libwebrtc/rtc_tools/network_tester/androidapp/res/values/strings.xml create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/androidapp/src/com/google/media/networktester/MainActivity.java create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/androidapp/src/com/google/media/networktester/NetworkTester.java create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/config_reader.cc create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/config_reader.h create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/create_network_tester_config.py create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/jni.cc create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/network_tester_config.proto create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/network_tester_packet.proto create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/network_tester_unittest.cc create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/packet_logger.cc create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/packet_logger.h create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/packet_sender.cc create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/packet_sender.h create mode 100755 third_party/libwebrtc/rtc_tools/network_tester/parse_packet_log.py create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/server.cc create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/test_controller.cc create mode 100644 third_party/libwebrtc/rtc_tools/network_tester/test_controller.h create mode 100644 third_party/libwebrtc/rtc_tools/psnr_ssim_analyzer/psnr_ssim_analyzer.cc create mode 100644 third_party/libwebrtc/rtc_tools/py_event_log_analyzer/README.md create mode 100644 third_party/libwebrtc/rtc_tools/py_event_log_analyzer/misc.py create mode 100755 third_party/libwebrtc/rtc_tools/py_event_log_analyzer/misc_test.py create mode 100644 third_party/libwebrtc/rtc_tools/py_event_log_analyzer/pb_parse.py create mode 100644 third_party/libwebrtc/rtc_tools/py_event_log_analyzer/rtp_analyzer.py create mode 100755 third_party/libwebrtc/rtc_tools/py_event_log_analyzer/rtp_analyzer.sh create mode 100755 third_party/libwebrtc/rtc_tools/py_event_log_analyzer/rtp_analyzer_test.py create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_to_text/OWNERS create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_to_text/converter.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_to_text/converter.h create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_to_text/main.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/OWNERS create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/alerts.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/alerts.h create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/analyze_audio.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/analyze_audio.h create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/analyzer.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/analyzer.h create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/analyzer_common.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/analyzer_common.h create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/conversational_speech_en.h create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/log_simulation.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/log_simulation.h create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/main.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/plot_base.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/plot_base.h create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/plot_protobuf.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/plot_protobuf.h create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/plot_python.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/plot_python.h create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/proto/chart.proto create mode 100644 third_party/libwebrtc/rtc_tools/rtc_event_log_visualizer/proto/chart_enums.proto create mode 100644 third_party/libwebrtc/rtc_tools/rtp_generator/configs/vp8.json create mode 100644 third_party/libwebrtc/rtc_tools/rtp_generator/configs/vp9.json create mode 100644 third_party/libwebrtc/rtc_tools/rtp_generator/main.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtp_generator/rtp_generator.cc create mode 100644 third_party/libwebrtc/rtc_tools/rtp_generator/rtp_generator.h create mode 100644 third_party/libwebrtc/rtc_tools/sanitizers_unittest.cc create mode 100644 third_party/libwebrtc/rtc_tools/testing/README.md create mode 100755 third_party/libwebrtc/rtc_tools/testing/build_apprtc.py create mode 100755 third_party/libwebrtc/rtc_tools/testing/download_apprtc.py create mode 100644 third_party/libwebrtc/rtc_tools/testing/golang/linux/go.tar.gz.sha1 create mode 100644 third_party/libwebrtc/rtc_tools/testing/golang/mac/go.tar.gz.sha1 create mode 100644 third_party/libwebrtc/rtc_tools/testing/golang/win/go.zip.sha1 create mode 100644 third_party/libwebrtc/rtc_tools/testing/prebuilt_apprtc.zip.sha1 create mode 100755 third_party/libwebrtc/rtc_tools/testing/setup_apprtc.py create mode 100755 third_party/libwebrtc/rtc_tools/testing/utils.py create mode 100644 third_party/libwebrtc/rtc_tools/unpack_aecdump/OWNERS create mode 100644 third_party/libwebrtc/rtc_tools/unpack_aecdump/unpack.cc create mode 100644 third_party/libwebrtc/rtc_tools/video_file_reader.cc create mode 100644 third_party/libwebrtc/rtc_tools/video_file_reader.h create mode 100644 third_party/libwebrtc/rtc_tools/video_file_reader_unittest.cc create mode 100644 third_party/libwebrtc/rtc_tools/video_file_writer.cc create mode 100644 third_party/libwebrtc/rtc_tools/video_file_writer.h create mode 100644 third_party/libwebrtc/rtc_tools/video_file_writer_unittest.cc create mode 100644 third_party/libwebrtc/rtc_tools/video_replay.cc (limited to 'third_party/libwebrtc/rtc_tools') diff --git a/third_party/libwebrtc/rtc_tools/BUILD.gn b/third_party/libwebrtc/rtc_tools/BUILD.gn new file mode 100644 index 0000000000..9b1f1fecda --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/BUILD.gn @@ -0,0 +1,600 @@ +# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. +import("../webrtc.gni") +if (rtc_enable_protobuf) { + import("//third_party/protobuf/proto_library.gni") +} + +group("rtc_tools") { + # This target shall build all targets in tools/. + testonly = true + + deps = [ ":video_file_reader" ] + if (!build_with_chromium) { + deps += [ + ":frame_analyzer", + ":psnr_ssim_analyzer", + ":video_quality_analysis", + ] + } + if (!build_with_chromium && rtc_enable_protobuf) { + deps += [ ":chart_proto" ] + } + if (!build_with_chromium && rtc_include_tests) { + deps += [ ":tools_unittests" ] + } + if (rtc_include_tests && rtc_enable_protobuf) { + deps += [ + ":rtp_analyzer", + "network_tester", + ] + } + if (rtc_include_tests && rtc_enable_protobuf && !build_with_chromium) { + deps += [ + ":audioproc_f", + ":event_log_visualizer", + ":rtc_event_log_to_text", + ":unpack_aecdump", + ] + } + if (!build_with_chromium && rtc_enable_grpc) { + deps += [ "data_channel_benchmark" ] + } +} + +rtc_library("video_file_reader") { + sources = [ + "video_file_reader.cc", + "video_file_reader.h", + ] + deps = [ + "../api:make_ref_counted", + "../api:scoped_refptr", + "../api/video:video_frame", + "../api/video:video_rtp_headers", + "../rtc_base:checks", + "../rtc_base:logging", + "../rtc_base:refcount", + "../rtc_base:stringutils", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("video_file_writer") { + sources = [ + "video_file_writer.cc", + "video_file_writer.h", + ] + deps = [ + ":video_file_reader", + "../api:scoped_refptr", + "../api/video:video_frame", + "../api/video:video_rtp_headers", + "../rtc_base:logging", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("video_quality_analysis") { + testonly = true + sources = [ + "frame_analyzer/linear_least_squares.cc", + "frame_analyzer/linear_least_squares.h", + "frame_analyzer/video_color_aligner.cc", + "frame_analyzer/video_color_aligner.h", + "frame_analyzer/video_geometry_aligner.cc", + "frame_analyzer/video_geometry_aligner.h", + "frame_analyzer/video_quality_analysis.cc", + "frame_analyzer/video_quality_analysis.h", + "frame_analyzer/video_temporal_aligner.cc", + "frame_analyzer/video_temporal_aligner.h", + ] + deps = [ + ":video_file_reader", + "../api:array_view", + "../api:make_ref_counted", + "../api:scoped_refptr", + "../api/numerics", + "../api/test/metrics:metric", + "../api/test/metrics:metrics_logger", + "../api/video:video_frame", + "../api/video:video_rtp_headers", + "../common_video", + "../rtc_base:checks", + "../rtc_base:logging", + "//third_party/libyuv", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +# TODO(bugs.webrtc.org/11474): Enable this on win if needed. For now it +# is only required for Linux and Android. +if (!build_with_chromium && !build_with_mozilla && !is_win && !is_ios) { + action("frame_analyzer_host") { + script = "//tools_webrtc/executable_host_build.py" + outputs = [ "${root_out_dir}/frame_analyzer_host" ] + args = [ + "--executable_name", + "frame_analyzer", + ] + } +} + +if (!is_component_build) { + # This target can be built from Chromium but it doesn't support + # is_component_build=true because it depends on WebRTC testonly code + # which is not part of //third_party/webrtc_overrides:webrtc_component. + + # Abseil dependencies are not moved to the absl_deps field deliberately. + # If build_with_chromium is true, the absl_deps replaces the dependencies with + # the "//third_party/abseil-cpp:absl" target. Which doesn't include absl/flags + # (and some others) because they cannot be used in Chromiums. Special exception + # for the "frame_analyzer" target in "third_party/abseil-cpp/absl.gni" allows + # it to be build in chromium. + rtc_executable("frame_analyzer") { + visibility = [ "*" ] + testonly = true + sources = [ "frame_analyzer/frame_analyzer.cc" ] + + deps = [ + ":video_file_reader", + ":video_file_writer", + ":video_quality_analysis", + "../api:make_ref_counted", + "../api:scoped_refptr", + "../api/test/metrics:chrome_perf_dashboard_metrics_exporter", + "../api/test/metrics:global_metrics_logger_and_exporter", + "../api/test/metrics:metrics_exporter", + "../api/test/metrics:stdout_metrics_exporter", + "../rtc_base:stringutils", + "//third_party/abseil-cpp/absl/flags:flag", + "//third_party/abseil-cpp/absl/flags:parse", + "//third_party/abseil-cpp/absl/strings", + ] + + if (build_with_chromium) { + # When building from Chromium, WebRTC's metrics and field trial + # implementations need to be replaced by the Chromium ones. + deps += [ "//third_party/webrtc_overrides:webrtc_component" ] + } + } + + # This target can be built from Chromium but it doesn't support + # is_component_build=true because it depends on WebRTC testonly code + # which is not part of //third_party/webrtc_overrides:webrtc_component. + + # Abseil dependencies are not moved to the absl_deps field deliberately. + # If build_with_chromium is true, the absl_deps replaces the dependencies with + # the "//third_party/abseil-cpp:absl" target. Which doesn't include absl/flags + # (and some others) because they cannot be used in Chromiums. Special exception + # for the "rtp_generator" target in "third_party/abseil-cpp/absl.gni" allows + # it to be build in chromium. + rtc_executable("rtp_generator") { + visibility = [ "*" ] + testonly = true + sources = [ + "rtp_generator/main.cc", + "rtp_generator/rtp_generator.cc", + "rtp_generator/rtp_generator.h", + ] + + deps = [ + "../api:create_frame_generator", + "../api:rtp_parameters", + "../api:transport_api", + "../api/rtc_event_log", + "../api/task_queue:default_task_queue_factory", + "../api/task_queue:task_queue", + "../api/video:builtin_video_bitrate_allocator_factory", + "../api/video_codecs:builtin_video_decoder_factory", + "../api/video_codecs:builtin_video_encoder_factory", + "../api/video_codecs:video_codecs_api", + "../call", + "../call:call_interfaces", + "../call:fake_network", + "../call:rtp_interfaces", + "../call:rtp_sender", + "../call:simulated_network", + "../call:simulated_packet_receiver", + "../call:video_stream_api", + "../media:media_constants", + "../media:rtc_audio_video", + "../media:rtc_media_base", + "../rtc_base:rtc_json", + "../rtc_base:threading", + "../rtc_base/system:file_wrapper", + "../test:fileutils", + "../test:rtp_test_utils", + "../test:video_test_common", + "../video/config:encoder_config", + "../video/config:streams_config", + "//third_party/abseil-cpp/absl/flags:flag", + "//third_party/abseil-cpp/absl/flags:parse", + "//third_party/abseil-cpp/absl/flags:usage", + "//third_party/abseil-cpp/absl/strings", + ] + if (build_with_chromium) { + # When building from Chromium, WebRTC's metrics and field trial + # implementations need to be replaced by the Chromium ones. + deps += [ "//third_party/webrtc_overrides:webrtc_component" ] + } + } + + # This target can be built from Chromium but it doesn't support + # is_component_build=true because it depends on WebRTC testonly code + # which is not part of //third_party/webrtc_overrides:webrtc_component. + + # Abseil dependencies are not moved to the absl_deps field deliberately. + # If build_with_chromium is true, the absl_deps replaces the dependencies with + # the "//third_party/abseil-cpp:absl" target. Which doesn't include absl/flags + # (and some others) because they cannot be used in Chromiums. Special exception + # for the "video_replay" target in "third_party/abseil-cpp/absl.gni" allows + # it to be build in chromium. + rtc_executable("video_replay") { + visibility = [ "*" ] + testonly = true + sources = [ "video_replay.cc" ] + deps = [ + "../api:field_trials", + "../api:rtp_parameters", + "../api/rtc_event_log", + "../api/task_queue:default_task_queue_factory", + "../api/test/video:function_video_factory", + "../api/transport:field_trial_based_config", + "../api/units:timestamp", + "../api/video:video_frame", + "../api/video_codecs:video_codecs_api", + "../call", + "../call:call_interfaces", + "../common_video", + "../media:rtc_internal_video_codecs", + "../modules/rtp_rtcp:rtp_rtcp_format", + "../modules/video_coding:video_coding_utility", + "../rtc_base:checks", + "../rtc_base:rtc_json", + "../rtc_base:stringutils", + "../rtc_base:timeutils", + "../system_wrappers", + "../test:call_config_utils", + "../test:encoder_settings", + "../test:fake_video_codecs", + "../test:null_transport", + "../test:rtp_test_utils", + "../test:run_loop", + "../test:run_test", + "../test:run_test_interface", + "../test:test_common", + "../test:test_renderer", + "../test:test_support", + "../test:video_test_common", + "../test:video_test_support", + "../test/time_controller:time_controller", + "//third_party/abseil-cpp/absl/flags:flag", + "//third_party/abseil-cpp/absl/flags:parse", + ] + if (build_with_chromium) { + # When building from Chromium, WebRTC's metrics and field trial + # implementations need to be replaced by the Chromium ones. + deps += [ "//third_party/webrtc_overrides:webrtc_component" ] + } + } +} + +# Only expose the targets needed by Chromium (e.g. frame_analyzer) to avoid +# building a lot of redundant code as part of Chromium builds. +if (!build_with_chromium) { + rtc_executable("psnr_ssim_analyzer") { + testonly = true + sources = [ "psnr_ssim_analyzer/psnr_ssim_analyzer.cc" ] + + deps = [ + ":video_file_reader", + ":video_quality_analysis", + "../api:scoped_refptr", + "../api/video:video_frame", + "../api/video:video_rtp_headers", + "//third_party/abseil-cpp/absl/flags:flag", + "//third_party/abseil-cpp/absl/flags:parse", + "//third_party/abseil-cpp/absl/flags:usage", + ] + } + + rtc_library("reference_less_video_analysis_lib") { + testonly = true + sources = [ + "frame_analyzer/reference_less_video_analysis_lib.cc", + "frame_analyzer/reference_less_video_analysis_lib.h", + ] + + deps = [ + ":video_file_reader", + ":video_quality_analysis", + "../api:scoped_refptr", + "../api/video:video_frame", + "../api/video:video_rtp_headers", + ] + } + + rtc_executable("reference_less_video_analysis") { + testonly = true + sources = [ "frame_analyzer/reference_less_video_analysis.cc" ] + + deps = [ + ":reference_less_video_analysis_lib", + "//third_party/abseil-cpp/absl/flags:flag", + "//third_party/abseil-cpp/absl/flags:parse", + "//third_party/abseil-cpp/absl/flags:usage", + ] + } + + if (rtc_enable_protobuf) { + proto_library("chart_proto") { + visibility = [ "*" ] + sources = [ + "rtc_event_log_visualizer/proto/chart.proto", + "rtc_event_log_visualizer/proto/chart_enums.proto", + ] + proto_out_dir = "rtc_tools/rtc_event_log_visualizer/proto" + } + + rtc_library("event_log_visualizer_utils") { + visibility = [ "*" ] + sources = [ + "rtc_event_log_visualizer/alerts.cc", + "rtc_event_log_visualizer/alerts.h", + "rtc_event_log_visualizer/analyze_audio.cc", + "rtc_event_log_visualizer/analyze_audio.h", + "rtc_event_log_visualizer/analyzer.cc", + "rtc_event_log_visualizer/analyzer.h", + "rtc_event_log_visualizer/analyzer_common.cc", + "rtc_event_log_visualizer/analyzer_common.h", + "rtc_event_log_visualizer/log_simulation.cc", + "rtc_event_log_visualizer/log_simulation.h", + "rtc_event_log_visualizer/plot_base.cc", + "rtc_event_log_visualizer/plot_base.h", + "rtc_event_log_visualizer/plot_protobuf.cc", + "rtc_event_log_visualizer/plot_protobuf.h", + "rtc_event_log_visualizer/plot_python.cc", + "rtc_event_log_visualizer/plot_python.h", + ] + deps = [ + ":chart_proto", + "../api:function_view", + "../api:network_state_predictor_api", + "../modules/audio_coding:neteq_input_audio_tools", + "../modules/audio_coding:neteq_tools_minimal", + "../rtc_base:ignore_wundef", + "../rtc_base:logging", + "../rtc_base:macromagic", + "../rtc_base:rate_statistics", + "../rtc_base:refcount", + + # TODO(kwiberg): Remove this dependency. + "../api/audio_codecs:audio_codecs_api", + "../api/transport:field_trial_based_config", + "../api/transport:goog_cc", + "../api/transport:network_control", + "../call:call_interfaces", + "../call:video_stream_api", + "../logging:rtc_event_log_parser", + "../logging:rtc_stream_config", + "../modules/audio_coding:ana_debug_dump_proto", + "../modules/audio_coding:audio_network_adaptor", + "../modules/audio_coding:neteq_tools", + "../modules/congestion_controller", + "../modules/congestion_controller/goog_cc:delay_based_bwe", + "../modules/congestion_controller/goog_cc:estimators", + "../modules/congestion_controller/rtp:transport_feedback", + "../modules/pacing", + "../modules/remote_bitrate_estimator", + "../modules/rtp_rtcp", + "../modules/rtp_rtcp:rtp_rtcp_format", + "../rtc_base:checks", + "../rtc_base:rtc_numerics", + "../rtc_base:stringutils", + "../system_wrappers", + "../test:explicit_key_value_config", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/functional:bind_front", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] + } + } +} + +if (rtc_include_tests) { + if (!build_with_chromium) { + if (rtc_enable_protobuf) { + rtc_executable("event_log_visualizer") { + # TODO(bugs.webrtc.org/14248): Remove once usage of std::tmpnam + # is removed (in favor of in memory InputAudioFile. + cflags_cc = [ "-Wno-deprecated-declarations" ] + sources = [ + "rtc_event_log_visualizer/conversational_speech_en.h", + "rtc_event_log_visualizer/main.cc", + ] + deps = [ + ":event_log_visualizer_utils", + "../api/neteq:neteq_api", + "../api/rtc_event_log", + "../logging:rtc_event_log_parser", + "../modules/audio_coding:neteq", + "../modules/rtp_rtcp:rtp_rtcp_format", + "../rtc_base:checks", + "../rtc_base:logging", + "../rtc_base:protobuf_utils", + "../system_wrappers:field_trial", + "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/flags:config", + "//third_party/abseil-cpp/absl/flags:flag", + "//third_party/abseil-cpp/absl/flags:parse", + "//third_party/abseil-cpp/absl/flags:usage", + "//third_party/abseil-cpp/absl/strings", + ] + } + + rtc_executable("rtc_event_log_to_text") { + testonly = true + sources = [ + "rtc_event_log_to_text/converter.cc", + "rtc_event_log_to_text/converter.h", + "rtc_event_log_to_text/main.cc", + ] + deps = [ + "../api/rtc_event_log", + "../logging:ice_log", + "../logging:rtc_event_audio", + "../logging:rtc_event_begin_end", + "../logging:rtc_event_bwe", + "../logging:rtc_event_frame_events", + "../logging:rtc_event_generic_packet_events", + "../logging:rtc_event_log2_proto", + "../logging:rtc_event_log_impl_encoder", + "../logging:rtc_event_log_parser", + "../logging:rtc_event_log_proto", + "../logging:rtc_event_pacing", + "../logging:rtc_event_rtp_rtcp", + "../logging:rtc_event_video", + "../logging:rtc_stream_config", + "../rtc_base:checks", + "../rtc_base:logging", + "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/flags:flag", + "//third_party/abseil-cpp/absl/flags:parse", + "//third_party/abseil-cpp/absl/flags:usage", + "//third_party/abseil-cpp/absl/strings", + ] + } + } + + tools_unittests_resources = [ + "../resources/foreman_128x96.yuv", + "../resources/foreman_cif.yuv", + "../resources/reference_less_video_test_file.y4m", + ] + + if (is_ios) { + bundle_data("tools_unittests_bundle_data") { + testonly = true + sources = tools_unittests_resources + outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ] + } + } + + rtc_test("tools_unittests") { + testonly = true + + sources = [ + "frame_analyzer/linear_least_squares_unittest.cc", + "frame_analyzer/reference_less_video_analysis_unittest.cc", + "frame_analyzer/video_color_aligner_unittest.cc", + "frame_analyzer/video_geometry_aligner_unittest.cc", + "frame_analyzer/video_quality_analysis_unittest.cc", + "frame_analyzer/video_temporal_aligner_unittest.cc", + "sanitizers_unittest.cc", + "video_file_reader_unittest.cc", + "video_file_writer_unittest.cc", + ] + + deps = [ + ":video_file_reader", + ":video_file_writer", + ":video_quality_analysis", + "../api:scoped_refptr", + "../api/test/metrics:metric", + "../api/test/metrics:metrics_logger", + "../api/video:video_frame", + "../api/video:video_rtp_headers", + "../common_video", + "../rtc_base:checks", + "../rtc_base:null_socket_server", + "../rtc_base:threading", + "../system_wrappers", + "../test:fileutils", + "../test:test_main", + "../test:test_support", + "//testing/gtest", + "//third_party/libyuv", + ] + + if (!build_with_chromium) { + deps += [ ":reference_less_video_analysis_lib" ] + } + + if (rtc_enable_protobuf) { + deps += [ "network_tester:network_tester_unittests" ] + } + + data = tools_unittests_resources + if (is_android) { + deps += [ "//testing/android/native_test:native_test_support" ] + shard_timeout = 900 + } + if (is_ios) { + deps += [ ":tools_unittests_bundle_data" ] + } + } + + if (rtc_enable_protobuf) { + rtc_executable("audioproc_f") { + testonly = true + sources = [ "audioproc_f/audioproc_float_main.cc" ] + deps = [ + "../api:audioproc_f_api", + "../modules/audio_processing", + "../modules/audio_processing:api", + ] + } + + rtc_executable("unpack_aecdump") { + visibility = [ "*" ] + sources = [ "unpack_aecdump/unpack.cc" ] + + deps = [ + "../api:function_view", + "../common_audio", + "../modules/audio_processing", + "../modules/audio_processing:audioproc_debug_proto", + "../modules/audio_processing:audioproc_debug_proto", + "../modules/audio_processing:audioproc_protobuf_utils", + "../rtc_base:checks", + "../rtc_base:ignore_wundef", + "../rtc_base:macromagic", + "../rtc_base:protobuf_utils", + "../rtc_base:stringutils", + "../rtc_base/system:arch", + "//third_party/abseil-cpp/absl/flags:flag", + "//third_party/abseil-cpp/absl/flags:parse", + ] + } # unpack_aecdump + } + } + + if (rtc_enable_protobuf) { + copy("rtp_analyzer") { + sources = [ + "py_event_log_analyzer/misc.py", + "py_event_log_analyzer/pb_parse.py", + "py_event_log_analyzer/rtp_analyzer.py", + "py_event_log_analyzer/rtp_analyzer.sh", + ] + outputs = [ "$root_build_dir/{{source_file_part}}" ] + deps = [ "../logging:rtc_event_log_proto" ] + } # rtp_analyzer + } +} diff --git a/third_party/libwebrtc/rtc_tools/DEPS b/third_party/libwebrtc/rtc_tools/DEPS new file mode 100644 index 0000000000..4d99061b8d --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/DEPS @@ -0,0 +1,36 @@ +include_rules = [ + "+call", + "+common_audio", + "+common_video", + "+logging/rtc_event_log", + "+media", + "+modules/audio_device", + "+modules/audio_coding/audio_network_adaptor", + "+modules/audio_coding/neteq/include", + "+modules/audio_coding/neteq/tools", + "+modules/audio_processing", + "+modules/bitrate_controller", + "+modules/remote_bitrate_estimator", + "+modules/congestion_controller", + "+modules/pacing", + "+modules/rtp_rtcp", + "+system_wrappers", + "+p2p", + "+third_party/libyuv", + "+video/config", +] + +specific_include_rules = { + ".*ivf_converter\.cc": [ + "+absl/debugging/failure_signal_handler.h", + "+absl/debugging/symbolize.h", + "+modules/video_coding/codecs/vp8/include/vp8.h", + "+modules/video_coding/codecs/vp9/include/vp9.h", + "+modules/video_coding/include/video_error_codes.h", + "+modules/video_coding/utility/ivf_file_writer.h", + "+modules/video_coding/codecs/h264/include/h264.h", + ], + ".*video_replay\.cc": [ + "+modules/video_coding/utility/ivf_file_writer.h", + ], +} diff --git a/third_party/libwebrtc/rtc_tools/OWNERS b/third_party/libwebrtc/rtc_tools/OWNERS new file mode 100644 index 0000000000..c2f49200e7 --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/OWNERS @@ -0,0 +1,4 @@ +mbonadei@webrtc.org + +# For video analysis tools +magjed@webrtc.org diff --git a/third_party/libwebrtc/rtc_tools/audioproc_f/audioproc_float_main.cc b/third_party/libwebrtc/rtc_tools/audioproc_f/audioproc_float_main.cc new file mode 100644 index 0000000000..3cc6d4323b --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/audioproc_f/audioproc_float_main.cc @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include "api/test/audioproc_float.h" +#include "modules/audio_processing/include/audio_processing.h" + +int main(int argc, char* argv[]) { + return webrtc::test::AudioprocFloat( + std::make_unique(), argc, argv); +} diff --git a/third_party/libwebrtc/rtc_tools/author_line_count.sh b/third_party/libwebrtc/rtc_tools/author_line_count.sh new file mode 100755 index 0000000000..1e463e4723 --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/author_line_count.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. + +# This script counts net line count contributions by author. Besides +# amusement, the value of these stats are of course questionable. + +git log --pretty=format:%ae --shortstat "$@" \ + | sed '/^ /s/,/\n/g' \ + | gawk ' +/^[^ ]/ { + /* Some author "email addresses" have a trailing @svn-id, strip that out. */ + author = gensub(/^([^@]*@[^@]*).*/, "\\1", "g", $1); +} +/^ .*insertion/ { total[author] += $1 } +/^ .*deletion/ { total[author] -= $1 } +END { for (author in total) { + print total[author], author + } +} +' \ + | sort -nr diff --git a/third_party/libwebrtc/rtc_tools/class_usage.sh b/third_party/libwebrtc/rtc_tools/class_usage.sh new file mode 100755 index 0000000000..02b80c2599 --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/class_usage.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. + +# This script is run in a git repository. It lists all classes defined +# in header files, sorted by the number of other files where the name +# of the class occurs. It is intentionally not limited to only source +# files. Classes close to the top of the list are candidates for +# removal. + +git grep -h '^class .*[:{]' -- '*.h' '*.hpp' \ + | sed -e 's/WEBRTC_DLL_EXPORT// ' -e 's/^class *\([^ :{(<]*\).*/\1/' \ + | sort | uniq | while read class ; do + count="$(git grep -l -w -F "${class}" | wc -l)" + echo "${count}" "${class}" +done | sort -n diff --git a/third_party/libwebrtc/rtc_tools/compare_videos.py b/third_party/libwebrtc/rtc_tools/compare_videos.py new file mode 100755 index 0000000000..a54eb42979 --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/compare_videos.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python +# Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +import json +import optparse +import os +import shutil +import subprocess +import sys +import tempfile + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Chrome browsertests will throw away stderr; avoid that output gets lost. +sys.stderr = sys.stdout + + +def _ParseArgs(): + """Registers the command-line options.""" + usage = 'usage: %prog [options]' + parser = optparse.OptionParser(usage=usage) + + parser.add_option('--label', + type='string', + default='MY_TEST', + help=('Label of the test, used to identify different ' + 'tests. Default: %default')) + parser.add_option('--ref_video', + type='string', + help='Reference video to compare with (YUV).') + parser.add_option('--test_video', + type='string', + help=('Test video to be compared with the reference ' + 'video (YUV).')) + parser.add_option('--frame_analyzer', + type='string', + help='Path to the frame analyzer executable.') + parser.add_option('--aligned_output_file', + type='string', + help='Path for output aligned YUV or Y4M file.') + parser.add_option('--vmaf', type='string', help='Path to VMAF executable.') + parser.add_option('--vmaf_model', + type='string', + help='Path to VMAF model.') + parser.add_option('--vmaf_phone_model', + action='store_true', + help='Whether to use phone model in VMAF.') + parser.add_option( + '--yuv_frame_width', + type='int', + default=640, + help='Width of the YUV file\'s frames. Default: %default') + parser.add_option( + '--yuv_frame_height', + type='int', + default=480, + help='Height of the YUV file\'s frames. Default: %default') + parser.add_option('--chartjson_result_file', + type='str', + default=None, + help='Where to store perf results in chartjson format.') + options, _ = parser.parse_args() + + if not options.ref_video: + parser.error('You must provide a path to the reference video!') + if not os.path.exists(options.ref_video): + parser.error('Cannot find the reference video at %s' % + options.ref_video) + + if not options.test_video: + parser.error('You must provide a path to the test video!') + if not os.path.exists(options.test_video): + parser.error('Cannot find the test video at %s' % options.test_video) + + if not options.frame_analyzer: + parser.error( + 'You must provide the path to the frame analyzer executable!') + if not os.path.exists(options.frame_analyzer): + parser.error('Cannot find frame analyzer executable at %s!' % + options.frame_analyzer) + + if options.vmaf and not options.vmaf_model: + parser.error('You must provide a path to a VMAF model to use VMAF.') + + return options + + +def _DevNull(): + """On Windows, sometimes the inherited stdin handle from the parent process + fails. Workaround this by passing null to stdin to the subprocesses commands. + This function can be used to create the null file handler. + """ + return open(os.devnull, 'r') + + +def _RunFrameAnalyzer(options, yuv_directory=None): + """Run frame analyzer to compare the videos and print output.""" + cmd = [ + options.frame_analyzer, + '--label=%s' % options.label, + '--reference_file=%s' % options.ref_video, + '--test_file=%s' % options.test_video, + '--width=%d' % options.yuv_frame_width, + '--height=%d' % options.yuv_frame_height, + ] + if options.chartjson_result_file: + cmd.append('--chartjson_result_file=%s' % + options.chartjson_result_file) + if options.aligned_output_file: + cmd.append('--aligned_output_file=%s' % options.aligned_output_file) + if yuv_directory: + cmd.append('--yuv_directory=%s' % yuv_directory) + frame_analyzer = subprocess.Popen(cmd, + stdin=_DevNull(), + stdout=sys.stdout, + stderr=sys.stderr) + frame_analyzer.wait() + if frame_analyzer.returncode != 0: + print('Failed to run frame analyzer.') + return frame_analyzer.returncode + + +def _RunVmaf(options, yuv_directory, logfile): + """ Run VMAF to compare videos and print output. + + The yuv_directory is assumed to have been populated with a reference and test + video in .yuv format, with names according to the label. + """ + cmd = [ + options.vmaf, + 'yuv420p', + str(options.yuv_frame_width), + str(options.yuv_frame_height), + os.path.join(yuv_directory, "ref.yuv"), + os.path.join(yuv_directory, "test.yuv"), + options.vmaf_model, + '--log', + logfile, + '--log-fmt', + 'json', + ] + if options.vmaf_phone_model: + cmd.append('--phone-model') + + vmaf = subprocess.Popen(cmd, + stdin=_DevNull(), + stdout=sys.stdout, + stderr=sys.stderr) + vmaf.wait() + if vmaf.returncode != 0: + print('Failed to run VMAF.') + return 1 + + # Read per-frame scores from VMAF output and print. + with open(logfile) as f: + vmaf_data = json.load(f) + vmaf_scores = [] + for frame in vmaf_data['frames']: + vmaf_scores.append(frame['metrics']['vmaf']) + print('RESULT VMAF: %s=' % options.label, vmaf_scores) + + return 0 + + +def main(): + """The main function. + + A simple invocation is: + ./webrtc/rtc_tools/compare_videos.py + --ref_video= + --test_video= + --frame_analyzer= + + Running vmaf requires the following arguments: + --vmaf, --vmaf_model, --yuv_frame_width, --yuv_frame_height + """ + options = _ParseArgs() + + if options.vmaf: + try: + # Directory to save temporary YUV files for VMAF in frame_analyzer. + yuv_directory = tempfile.mkdtemp() + _, vmaf_logfile = tempfile.mkstemp() + + # Run frame analyzer to compare the videos and print output. + if _RunFrameAnalyzer(options, yuv_directory=yuv_directory) != 0: + return 1 + + # Run VMAF for further video comparison and print output. + return _RunVmaf(options, yuv_directory, vmaf_logfile) + finally: + shutil.rmtree(yuv_directory) + os.remove(vmaf_logfile) + else: + return _RunFrameAnalyzer(options) + + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/third_party/libwebrtc/rtc_tools/data_channel_benchmark/BUILD.gn b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/BUILD.gn new file mode 100644 index 0000000000..040061b3e8 --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright 2021 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/grpc/grpc_library.gni") +import("../../webrtc.gni") + +grpc_library("signaling_grpc_proto") { + testonly = true + sources = [ "peer_connection_signaling.proto" ] +} + +rtc_library("signaling_interface") { + sources = [ "signaling_interface.h" ] + deps = [ "../../api:libjingle_peerconnection_api" ] +} + +rtc_library("grpc_signaling") { + testonly = true + sources = [ + "grpc_signaling.cc", + "grpc_signaling.h", + ] + deps = [ + ":signaling_grpc_proto", + ":signaling_interface", + "../../api:libjingle_peerconnection_api", + "../../rtc_base:threading", + "//third_party/grpc:grpc++", + ] + + defines = [ "GPR_FORBID_UNREACHABLE_CODE=0" ] +} + +rtc_executable("data_channel_benchmark") { + testonly = true + sources = [ + "data_channel_benchmark.cc", + "peer_connection_client.cc", + "peer_connection_client.h", + ] + deps = [ + ":grpc_signaling", + ":signaling_interface", + "../../api:create_peerconnection_factory", + "../../api:libjingle_peerconnection_api", + "../../api:rtc_error", + "../../api:scoped_refptr", + "../../api/audio_codecs:builtin_audio_decoder_factory", + "../../api/audio_codecs:builtin_audio_encoder_factory", + "../../api/video_codecs:builtin_video_decoder_factory", + "../../api/video_codecs:builtin_video_encoder_factory", + "../../rtc_base:logging", + "../../rtc_base:refcount", + "../../rtc_base:rtc_event", + "../../rtc_base:ssl", + "../../rtc_base:threading", + "../../system_wrappers:field_trial", + "//third_party/abseil-cpp/absl/cleanup:cleanup", + "//third_party/abseil-cpp/absl/flags:flag", + "//third_party/abseil-cpp/absl/flags:parse", + ] +} diff --git a/third_party/libwebrtc/rtc_tools/data_channel_benchmark/data_channel_benchmark.cc b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/data_channel_benchmark.cc new file mode 100644 index 0000000000..33776f37aa --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/data_channel_benchmark.cc @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + * Data Channel Benchmarking tool. + * + * Create a server using: ./data_channel_benchmark --server --port 12345 + * Start the flow of data from the server to a client using: + * ./data_channel_benchmark --port 12345 --transfer_size 100 --packet_size 8196 + * The throughput is reported on the server console. + * + * The negotiation does not require a 3rd party server and is done over a gRPC + * transport. No TURN server is configured, so both peers need to be reachable + * using STUN only. + */ +#include + +#include + +#include "absl/cleanup/cleanup.h" +#include "absl/flags/flag.h" +#include "absl/flags/parse.h" +#include "rtc_base/event.h" +#include "rtc_base/ssl_adapter.h" +#include "rtc_base/thread.h" +#include "rtc_tools/data_channel_benchmark/grpc_signaling.h" +#include "rtc_tools/data_channel_benchmark/peer_connection_client.h" +#include "system_wrappers/include/field_trial.h" + +ABSL_FLAG(int, verbose, 0, "verbosity level (0-5)"); +ABSL_FLAG(bool, server, false, "Server mode"); +ABSL_FLAG(bool, oneshot, true, "Terminate after serving a client"); +ABSL_FLAG(std::string, address, "localhost", "Connect to server address"); +ABSL_FLAG(uint16_t, port, 0, "Connect to port (0 for random)"); +ABSL_FLAG(uint64_t, transfer_size, 2, "Transfer size (MiB)"); +ABSL_FLAG(uint64_t, packet_size, 256 * 1024, "Packet size"); +ABSL_FLAG(std::string, + force_fieldtrials, + "", + "Field trials control experimental feature code which can be forced. " + "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/" + " will assign the group Enable to field trial WebRTC-FooFeature."); + +struct SetupMessage { + size_t packet_size; + size_t transfer_size; + + std::string ToString() { + char buffer[64]; + rtc::SimpleStringBuilder sb(buffer); + sb << packet_size << "," << transfer_size; + + return sb.str(); + } + + static SetupMessage FromString(absl::string_view sv) { + SetupMessage result; + auto parameters = rtc::split(sv, ','); + std::from_chars(parameters[0].data(), + parameters[0].data() + parameters[0].size(), + result.packet_size, 10); + std::from_chars(parameters[1].data(), + parameters[1].data() + parameters[1].size(), + result.transfer_size, 10); + return result; + } +}; + +class DataChannelObserverImpl : public webrtc::DataChannelObserver { + public: + explicit DataChannelObserverImpl(webrtc::DataChannelInterface* dc) + : dc_(dc), bytes_received_(0) {} + void OnStateChange() override { + RTC_LOG(LS_INFO) << "State changed to " << dc_->state(); + switch (dc_->state()) { + case webrtc::DataChannelInterface::DataState::kOpen: + open_event_.Set(); + break; + case webrtc::DataChannelInterface::DataState::kClosed: + closed_event_.Set(); + break; + default: + break; + } + } + void OnMessage(const webrtc::DataBuffer& buffer) override { + bytes_received_ += buffer.data.size(); + if (bytes_received_threshold_ && + bytes_received_ >= bytes_received_threshold_) { + bytes_received_event_.Set(); + } + + if (setup_message_.empty() && !buffer.binary) { + setup_message_.assign(buffer.data.cdata(), buffer.data.size()); + setup_message_event_.Set(); + } + } + void OnBufferedAmountChange(uint64_t sent_data_size) override { + if (dc_->buffered_amount() < + webrtc::DataChannelInterface::MaxSendQueueSize() / 2) + low_buffered_threshold_event_.Set(); + else + low_buffered_threshold_event_.Reset(); + } + + bool WaitForOpenState() { + return dc_->state() == webrtc::DataChannelInterface::DataState::kOpen || + open_event_.Wait(rtc::Event::kForever); + } + bool WaitForClosedState() { + return dc_->state() == webrtc::DataChannelInterface::DataState::kClosed || + closed_event_.Wait(rtc::Event::kForever); + } + + // Set how many received bytes are required until + // WaitForBytesReceivedThreshold return true. + void SetBytesReceivedThreshold(uint64_t bytes_received_threshold) { + bytes_received_threshold_ = bytes_received_threshold; + if (bytes_received_ >= bytes_received_threshold_) + bytes_received_event_.Set(); + } + // Wait until the received byte count reaches the desired value. + bool WaitForBytesReceivedThreshold() { + return (bytes_received_threshold_ && + bytes_received_ >= bytes_received_threshold_) || + bytes_received_event_.Wait(rtc::Event::kForever); + } + + bool WaitForLowbufferedThreshold() { + return low_buffered_threshold_event_.Wait(rtc::Event::kForever); + } + std::string SetupMessage() { return setup_message_; } + bool WaitForSetupMessage() { + return setup_message_event_.Wait(rtc::Event::kForever); + } + + private: + webrtc::DataChannelInterface* dc_; + rtc::Event open_event_; + rtc::Event closed_event_; + rtc::Event bytes_received_event_; + absl::optional bytes_received_threshold_; + uint64_t bytes_received_; + rtc::Event low_buffered_threshold_event_; + std::string setup_message_; + rtc::Event setup_message_event_; +}; + +int RunServer() { + bool oneshot = absl::GetFlag(FLAGS_oneshot); + uint16_t port = absl::GetFlag(FLAGS_port); + + auto signaling_thread = rtc::Thread::Create(); + signaling_thread->Start(); + { + auto factory = webrtc::PeerConnectionClient::CreateDefaultFactory( + signaling_thread.get()); + + auto grpc_server = webrtc::GrpcSignalingServerInterface::Create( + [factory = rtc::scoped_refptr( + factory)](webrtc::SignalingInterface* signaling) { + webrtc::PeerConnectionClient client(factory.get(), signaling); + client.StartPeerConnection(); + auto peer_connection = client.peerConnection(); + + // Set up the data channel + auto dc_or_error = + peer_connection->CreateDataChannelOrError("benchmark", nullptr); + auto data_channel = dc_or_error.MoveValue(); + auto data_channel_observer = + std::make_unique(data_channel.get()); + data_channel->RegisterObserver(data_channel_observer.get()); + absl::Cleanup unregister_observer( + [data_channel] { data_channel->UnregisterObserver(); }); + + // Wait for a first message from the remote peer. + // It configures how much data should be sent and how big the packets + // should be. + // First message is "packet_size,transfer_size". + data_channel_observer->WaitForSetupMessage(); + auto parameters = + SetupMessage::FromString(data_channel_observer->SetupMessage()); + + // Wait for the sender and receiver peers to stabilize (send all ACKs) + // This makes it easier to isolate the sending part when profiling. + absl::SleepFor(absl::Seconds(1)); + + std::string data(parameters.packet_size, '0'); + size_t remaining_data = parameters.transfer_size; + + auto begin_time = webrtc::Clock::GetRealTimeClock()->CurrentTime(); + + while (remaining_data) { + if (remaining_data < data.size()) + data.resize(remaining_data); + + rtc::CopyOnWriteBuffer buffer(data); + webrtc::DataBuffer data_buffer(buffer, true); + if (!data_channel->Send(data_buffer)) { + // If the send() call failed, the buffers are full. + // We wait until there's more room. + data_channel_observer->WaitForLowbufferedThreshold(); + continue; + } + remaining_data -= buffer.size(); + fprintf(stderr, "Progress: %zu / %zu (%zu%%)\n", + (parameters.transfer_size - remaining_data), + parameters.transfer_size, + (100 - remaining_data * 100 / parameters.transfer_size)); + } + + // Receiver signals the data channel close event when it has received + // all the data it requested. + data_channel_observer->WaitForClosedState(); + + auto end_time = webrtc::Clock::GetRealTimeClock()->CurrentTime(); + auto duration_ms = (end_time - begin_time).ms(); + double throughput = (parameters.transfer_size / 1024. / 1024.) / + (duration_ms / 1000.); + printf("Elapsed time: %zums %gMiB/s\n", duration_ms, throughput); + }, + port, oneshot); + grpc_server->Start(); + + printf("Server listening on port %d\n", grpc_server->SelectedPort()); + grpc_server->Wait(); + } + + signaling_thread->Quit(); + return 0; +} + +int RunClient() { + uint16_t port = absl::GetFlag(FLAGS_port); + std::string server_address = absl::GetFlag(FLAGS_address); + size_t transfer_size = absl::GetFlag(FLAGS_transfer_size) * 1024 * 1024; + size_t packet_size = absl::GetFlag(FLAGS_packet_size); + + auto signaling_thread = rtc::Thread::Create(); + signaling_thread->Start(); + { + auto factory = webrtc::PeerConnectionClient::CreateDefaultFactory( + signaling_thread.get()); + auto grpc_client = webrtc::GrpcSignalingClientInterface::Create( + server_address + ":" + std::to_string(port)); + webrtc::PeerConnectionClient client(factory.get(), + grpc_client->signaling_client()); + + // Set up the callback to receive the data channel from the sender. + rtc::scoped_refptr data_channel; + rtc::Event got_data_channel; + client.SetOnDataChannel( + [&data_channel, &got_data_channel]( + rtc::scoped_refptr channel) { + data_channel = channel; + got_data_channel.Set(); + }); + + // Connect to the server. + if (!grpc_client->Start()) { + fprintf(stderr, "Failed to connect to server\n"); + return 1; + } + + // Wait for the data channel to be received + got_data_channel.Wait(rtc::Event::kForever); + + // DataChannel needs an observer to start draining the read queue + DataChannelObserverImpl observer(data_channel.get()); + observer.SetBytesReceivedThreshold(transfer_size); + data_channel->RegisterObserver(&observer); + absl::Cleanup unregister_observer( + [data_channel] { data_channel->UnregisterObserver(); }); + + // Send a configuration string to the server to tell it to send + // 'packet_size' bytes packets and send a total of 'transfer_size' MB. + observer.WaitForOpenState(); + SetupMessage setup_message = { + .packet_size = packet_size, + .transfer_size = transfer_size, + }; + if (!data_channel->Send(webrtc::DataBuffer(setup_message.ToString()))) { + fprintf(stderr, "Failed to send parameter string\n"); + return 1; + } + + // Wait until we have received all the data + observer.WaitForBytesReceivedThreshold(); + + // Close the data channel, signaling to the server we have received + // all the requested data. + data_channel->Close(); + } + + signaling_thread->Quit(); + + return 0; +} + +int main(int argc, char** argv) { + rtc::InitializeSSL(); + absl::ParseCommandLine(argc, argv); + + // Make sure that higher severity number means more logs by reversing the + // rtc::LoggingSeverity values. + auto logging_severity = + std::max(0, rtc::LS_NONE - absl::GetFlag(FLAGS_verbose)); + rtc::LogMessage::LogToDebug( + static_cast(logging_severity)); + + bool is_server = absl::GetFlag(FLAGS_server); + std::string field_trials = absl::GetFlag(FLAGS_force_fieldtrials); + + webrtc::field_trial::InitFieldTrialsFromString(field_trials.c_str()); + + return is_server ? RunServer() : RunClient(); +} diff --git a/third_party/libwebrtc/rtc_tools/data_channel_benchmark/grpc_signaling.cc b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/grpc_signaling.cc new file mode 100644 index 0000000000..8db717fc71 --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/grpc_signaling.cc @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "rtc_tools/data_channel_benchmark/grpc_signaling.h" + +#include +#include + +#include +#include + +#include "api/jsep.h" +#include "api/jsep_ice_candidate.h" +#include "rtc_base/thread.h" +#include "rtc_tools/data_channel_benchmark/peer_connection_signaling.grpc.pb.h" + +namespace webrtc { +namespace { + +using GrpcSignaling::IceCandidate; +using GrpcSignaling::PeerConnectionSignaling; +using GrpcSignaling::SessionDescription; +using GrpcSignaling::SignalingMessage; + +template +class SessionData : public webrtc::SignalingInterface { + public: + SessionData() {} + explicit SessionData(T* stream) : stream_(stream) {} + void SetStream(T* stream) { stream_ = stream; } + + void SendIceCandidate(const IceCandidateInterface* candidate) override { + RTC_LOG(LS_INFO) << "SendIceCandidate"; + std::string serialized_candidate; + if (!candidate->ToString(&serialized_candidate)) { + RTC_LOG(LS_ERROR) << "Failed to serialize ICE candidate"; + return; + } + + SignalingMessage message; + IceCandidate* proto_candidate = message.mutable_candidate(); + proto_candidate->set_description(serialized_candidate); + proto_candidate->set_mid(candidate->sdp_mid()); + proto_candidate->set_mline_index(candidate->sdp_mline_index()); + + stream_->Write(message); + } + + void SendDescription(const SessionDescriptionInterface* sdp) override { + RTC_LOG(LS_INFO) << "SendDescription"; + + std::string serialized_sdp; + sdp->ToString(&serialized_sdp); + + SignalingMessage message; + if (sdp->GetType() == SdpType::kOffer) + message.mutable_description()->set_type(SessionDescription::OFFER); + else if (sdp->GetType() == SdpType::kAnswer) + message.mutable_description()->set_type(SessionDescription::ANSWER); + message.mutable_description()->set_content(serialized_sdp); + + stream_->Write(message); + } + + void OnRemoteDescription( + std::function sdp)> + callback) override { + RTC_LOG(LS_INFO) << "OnRemoteDescription"; + remote_description_callback_ = callback; + } + + void OnIceCandidate( + std::function candidate)> + callback) override { + RTC_LOG(LS_INFO) << "OnIceCandidate"; + ice_candidate_callback_ = callback; + } + + T* stream_; + + std::function)> + ice_candidate_callback_; + std::function)> + remote_description_callback_; +}; + +using ServerSessionData = + SessionData>; +using ClientSessionData = + SessionData>; + +template +void ProcessMessages(StreamReader* stream, SessionData* session) { + MessageType message; + + while (stream->Read(&message)) { + switch (message.Content_case()) { + case SignalingMessage::ContentCase::kCandidate: { + webrtc::SdpParseError error; + auto jsep_candidate = std::make_unique( + message.candidate().mid(), message.candidate().mline_index()); + if (!jsep_candidate->Initialize(message.candidate().description(), + &error)) { + RTC_LOG(LS_ERROR) << "Failed to deserialize ICE candidate '" + << message.candidate().description() << "'"; + RTC_LOG(LS_ERROR) + << "Error at line " << error.line << ":" << error.description; + continue; + } + + session->ice_candidate_callback_(std::move(jsep_candidate)); + break; + } + case SignalingMessage::ContentCase::kDescription: { + auto& description = message.description(); + auto content = description.content(); + + auto sdp = webrtc::CreateSessionDescription( + description.type() == SessionDescription::OFFER + ? webrtc::SdpType::kOffer + : webrtc::SdpType::kAnswer, + description.content()); + session->remote_description_callback_(std::move(sdp)); + break; + } + default: + RTC_DCHECK_NOTREACHED(); + } + } +} + +class GrpcNegotiationServer : public GrpcSignalingServerInterface, + public PeerConnectionSignaling::Service { + public: + GrpcNegotiationServer( + std::function callback, + int port, + bool oneshot) + : connect_callback_(std::move(callback)), + requested_port_(port), + oneshot_(oneshot) {} + ~GrpcNegotiationServer() override { + Stop(); + if (server_stop_thread_) + server_stop_thread_->Stop(); + } + + void Start() override { + std::string server_address = "[::]"; + + grpc::ServerBuilder builder; + builder.AddListeningPort( + server_address + ":" + std::to_string(requested_port_), + grpc::InsecureServerCredentials(), &selected_port_); + builder.RegisterService(this); + server_ = builder.BuildAndStart(); + } + + void Wait() override { server_->Wait(); } + + void Stop() override { server_->Shutdown(); } + + int SelectedPort() override { return selected_port_; } + + grpc::Status Connect( + grpc::ServerContext* context, + grpc::ServerReaderWriter* stream) + override { + if (oneshot_) { + // Request the termination of the server early so we don't serve another + // client in parallel. + server_stop_thread_ = rtc::Thread::Create(); + server_stop_thread_->Start(); + server_stop_thread_->PostTask([this] { Stop(); }); + } + + ServerSessionData session(stream); + + auto reading_thread = rtc::Thread::Create(); + reading_thread->Start(); + reading_thread->PostTask([&session, &stream] { + ProcessMessages(stream, &session); + }); + + connect_callback_(&session); + + reading_thread->Stop(); + + return grpc::Status::OK; + } + + private: + std::function connect_callback_; + int requested_port_; + int selected_port_; + bool oneshot_; + + std::unique_ptr server_; + std::unique_ptr server_stop_thread_; +}; + +class GrpcNegotiationClient : public GrpcSignalingClientInterface { + public: + explicit GrpcNegotiationClient(const std::string& server) { + channel_ = grpc::CreateChannel(server, grpc::InsecureChannelCredentials()); + stub_ = PeerConnectionSignaling::NewStub(channel_); + } + + ~GrpcNegotiationClient() override { + context_.TryCancel(); + if (reading_thread_) + reading_thread_->Stop(); + } + + bool Start() override { + if (!channel_->WaitForConnected( + absl::ToChronoTime(absl::Now() + absl::Seconds(3)))) { + return false; + } + + stream_ = stub_->Connect(&context_); + session_.SetStream(stream_.get()); + + reading_thread_ = rtc::Thread::Create(); + reading_thread_->Start(); + reading_thread_->PostTask([this] { + ProcessMessages(stream_.get(), &session_); + }); + + return true; + } + + webrtc::SignalingInterface* signaling_client() override { return &session_; } + + private: + std::shared_ptr channel_; + std::unique_ptr stub_; + std::unique_ptr reading_thread_; + grpc::ClientContext context_; + std::unique_ptr< + ::grpc::ClientReaderWriter> + stream_; + ClientSessionData session_; +}; +} // namespace + +std::unique_ptr +GrpcSignalingServerInterface::Create( + std::function callback, + int port, + bool oneshot) { + return std::make_unique(std::move(callback), port, + oneshot); +} + +std::unique_ptr +GrpcSignalingClientInterface::Create(const std::string& server) { + return std::make_unique(server); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_tools/data_channel_benchmark/grpc_signaling.h b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/grpc_signaling.h new file mode 100644 index 0000000000..15799d22b7 --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/grpc_signaling.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef RTC_TOOLS_DATA_CHANNEL_BENCHMARK_GRPC_SIGNALING_H_ +#define RTC_TOOLS_DATA_CHANNEL_BENCHMARK_GRPC_SIGNALING_H_ + +#include +#include + +#include "api/jsep.h" +#include "rtc_tools/data_channel_benchmark/signaling_interface.h" + +namespace webrtc { + +// This class defines a server enabling clients to perform a PeerConnection +// negotiation directly over gRPC. +// When a client connects, a callback is run to handle the request. +class GrpcSignalingServerInterface { + public: + virtual ~GrpcSignalingServerInterface() = default; + + // Start listening for connections. + virtual void Start() = 0; + + // Wait for the gRPC server to terminate. + virtual void Wait() = 0; + + // Stop the gRPC server instance. + virtual void Stop() = 0; + + // The port the server is listening on. + virtual int SelectedPort() = 0; + + // Create a gRPC server listening on |port| that will run |callback| on each + // request. If |oneshot| is true, it will terminate after serving one request. + static std::unique_ptr Create( + std::function callback, + int port, + bool oneshot); +}; + +// This class defines a client that can connect to a server and perform a +// PeerConnection negotiation directly over gRPC. +class GrpcSignalingClientInterface { + public: + virtual ~GrpcSignalingClientInterface() = default; + + // Connect the client to the gRPC server. + virtual bool Start() = 0; + virtual webrtc::SignalingInterface* signaling_client() = 0; + + // Create a client to connnect to a server at |server_address|. + static std::unique_ptr Create( + const std::string& server_address); +}; + +} // namespace webrtc +#endif // RTC_TOOLS_DATA_CHANNEL_BENCHMARK_GRPC_SIGNALING_H_ diff --git a/third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_client.cc b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_client.cc new file mode 100644 index 0000000000..cd02e7118a --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_client.cc @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "rtc_tools/data_channel_benchmark/peer_connection_client.h" + +#include +#include +#include + +#include "api/audio_codecs/builtin_audio_decoder_factory.h" +#include "api/audio_codecs/builtin_audio_encoder_factory.h" +#include "api/create_peerconnection_factory.h" +#include "api/jsep.h" +#include "api/peer_connection_interface.h" +#include "api/rtc_error.h" +#include "api/scoped_refptr.h" +#include "api/set_remote_description_observer_interface.h" +#include "api/video_codecs/builtin_video_decoder_factory.h" +#include "api/video_codecs/builtin_video_encoder_factory.h" +#include "rtc_base/logging.h" +#include "rtc_base/thread.h" + +namespace { + +constexpr char kStunServer[] = "stun:stun.l.google.com:19302"; + +class SetLocalDescriptionObserverAdapter + : public webrtc::SetLocalDescriptionObserverInterface { + public: + using Callback = std::function; + static rtc::scoped_refptr Create( + Callback callback) { + return rtc::scoped_refptr( + new rtc::RefCountedObject( + std::move(callback))); + } + + explicit SetLocalDescriptionObserverAdapter(Callback callback) + : callback_(std::move(callback)) {} + ~SetLocalDescriptionObserverAdapter() override = default; + + private: + void OnSetLocalDescriptionComplete(webrtc::RTCError error) override { + callback_(std::move(error)); + } + + Callback callback_; +}; + +class SetRemoteDescriptionObserverAdapter + : public webrtc::SetRemoteDescriptionObserverInterface { + public: + using Callback = std::function; + static rtc::scoped_refptr Create( + Callback callback) { + return rtc::scoped_refptr( + new rtc::RefCountedObject( + std::move(callback))); + } + + explicit SetRemoteDescriptionObserverAdapter(Callback callback) + : callback_(std::move(callback)) {} + ~SetRemoteDescriptionObserverAdapter() override = default; + + private: + void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override { + callback_(std::move(error)); + } + + Callback callback_; +}; + +class CreateSessionDescriptionObserverAdapter + : public webrtc::CreateSessionDescriptionObserver { + public: + using Success = std::function; + using Failure = std::function; + + static rtc::scoped_refptr Create( + Success success, + Failure failure) { + return rtc::scoped_refptr( + new rtc::RefCountedObject( + std::move(success), std::move(failure))); + } + + CreateSessionDescriptionObserverAdapter(Success success, Failure failure) + : success_(std::move(success)), failure_(std::move(failure)) {} + ~CreateSessionDescriptionObserverAdapter() override = default; + + private: + void OnSuccess(webrtc::SessionDescriptionInterface* desc) override { + success_(desc); + } + + void OnFailure(webrtc::RTCError error) override { + failure_(std::move(error)); + } + + Success success_; + Failure failure_; +}; + +} // namespace + +namespace webrtc { + +PeerConnectionClient::PeerConnectionClient( + webrtc::PeerConnectionFactoryInterface* factory, + webrtc::SignalingInterface* signaling) + : signaling_(signaling) { + signaling_->OnIceCandidate( + [&](std::unique_ptr candidate) { + AddIceCandidate(std::move(candidate)); + }); + signaling_->OnRemoteDescription( + [&](std::unique_ptr sdp) { + SetRemoteDescription(std::move(sdp)); + }); + InitializePeerConnection(factory); +} + +PeerConnectionClient::~PeerConnectionClient() { + Disconnect(); +} + +rtc::scoped_refptr +PeerConnectionClient::CreateDefaultFactory(rtc::Thread* signaling_thread) { + auto factory = webrtc::CreatePeerConnectionFactory( + /*network_thread=*/nullptr, /*worker_thread=*/nullptr, + /*signaling_thread*/ signaling_thread, + /*default_adm=*/nullptr, webrtc::CreateBuiltinAudioEncoderFactory(), + webrtc::CreateBuiltinAudioDecoderFactory(), + webrtc::CreateBuiltinVideoEncoderFactory(), + webrtc::CreateBuiltinVideoDecoderFactory(), + /*audio_mixer=*/nullptr, /*audio_processing=*/nullptr); + + if (!factory) { + RTC_LOG(LS_ERROR) << "Failed to initialize PeerConnectionFactory"; + return nullptr; + } + + return factory; +} + +bool PeerConnectionClient::InitializePeerConnection( + webrtc::PeerConnectionFactoryInterface* factory) { + RTC_CHECK(factory) + << "Must call InitializeFactory before InitializePeerConnection"; + + webrtc::PeerConnectionInterface::RTCConfiguration config; + webrtc::PeerConnectionInterface::IceServer server; + server.urls.push_back(kStunServer); + config.servers.push_back(server); + config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; + + webrtc::PeerConnectionDependencies dependencies(this); + auto result = + factory->CreatePeerConnectionOrError(config, std::move(dependencies)); + + if (!result.ok()) { + RTC_LOG(LS_ERROR) << "Failed to create PeerConnection: " + << result.error().message(); + DeletePeerConnection(); + return false; + } + peer_connection_ = result.MoveValue(); + RTC_LOG(LS_INFO) << "PeerConnection created successfully"; + return true; +} + +bool PeerConnectionClient::StartPeerConnection() { + RTC_LOG(LS_INFO) << "Creating offer"; + + peer_connection_->SetLocalDescription( + SetLocalDescriptionObserverAdapter::Create([this]( + webrtc::RTCError error) { + if (error.ok()) + signaling_->SendDescription(peer_connection_->local_description()); + })); + + return true; +} + +bool PeerConnectionClient::IsConnected() { + return peer_connection_->peer_connection_state() == + webrtc::PeerConnectionInterface::PeerConnectionState::kConnected; +} + +// Disconnect from the call. +void PeerConnectionClient::Disconnect() { + for (auto& data_channel : data_channels_) { + data_channel->Close(); + data_channel.release(); + } + data_channels_.clear(); + DeletePeerConnection(); +} + +// Delete the WebRTC PeerConnection. +void PeerConnectionClient::DeletePeerConnection() { + RTC_LOG(LS_INFO); + + if (peer_connection_) { + peer_connection_->Close(); + } + peer_connection_.release(); +} + +void PeerConnectionClient::OnIceConnectionChange( + webrtc::PeerConnectionInterface::IceConnectionState new_state) { + if (new_state == webrtc::PeerConnectionInterface::IceConnectionState:: + kIceConnectionCompleted) { + RTC_LOG(LS_INFO) << "State is updating to connected"; + } else if (new_state == webrtc::PeerConnectionInterface::IceConnectionState:: + kIceConnectionDisconnected) { + RTC_LOG(LS_INFO) << "Disconnecting from peer"; + Disconnect(); + } +} + +void PeerConnectionClient::OnIceGatheringChange( + webrtc::PeerConnectionInterface::IceGatheringState new_state) { + if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) { + RTC_LOG(LS_INFO) << "Client is ready to receive remote SDP"; + } +} + +void PeerConnectionClient::OnIceCandidate( + const webrtc::IceCandidateInterface* candidate) { + signaling_->SendIceCandidate(candidate); +} + +void PeerConnectionClient::OnDataChannel( + rtc::scoped_refptr channel) { + RTC_LOG(LS_INFO) << __FUNCTION__ << " remote datachannel created"; + if (on_data_channel_callback_) + on_data_channel_callback_(channel); + data_channels_.push_back(channel); +} + +void PeerConnectionClient::SetOnDataChannel( + std::function)> + callback) { + on_data_channel_callback_ = callback; +} + +void PeerConnectionClient::OnNegotiationNeededEvent(uint32_t event_id) { + RTC_LOG(LS_INFO) << "OnNegotiationNeededEvent"; + + peer_connection_->SetLocalDescription( + SetLocalDescriptionObserverAdapter::Create([this]( + webrtc::RTCError error) { + if (error.ok()) + signaling_->SendDescription(peer_connection_->local_description()); + })); +} + +bool PeerConnectionClient::SetRemoteDescription( + std::unique_ptr desc) { + RTC_LOG(LS_INFO) << "SetRemoteDescription"; + auto type = desc->GetType(); + + peer_connection_->SetRemoteDescription( + std::move(desc), + SetRemoteDescriptionObserverAdapter::Create([&](webrtc::RTCError) { + RTC_LOG(LS_INFO) << "SetRemoteDescription done"; + + if (type == webrtc::SdpType::kOffer) { + // Got an offer from the remote, need to set an answer and send it. + peer_connection_->SetLocalDescription( + SetLocalDescriptionObserverAdapter::Create( + [this](webrtc::RTCError error) { + if (error.ok()) + signaling_->SendDescription( + peer_connection_->local_description()); + })); + } + })); + + return true; +} + +void PeerConnectionClient::AddIceCandidate( + std::unique_ptr candidate) { + RTC_LOG(LS_INFO) << "AddIceCandidate"; + + peer_connection_->AddIceCandidate( + std::move(candidate), [](const webrtc::RTCError& error) { + RTC_LOG(LS_INFO) << "Failed to add candidate: " << error.message(); + }); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_client.h b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_client.h new file mode 100644 index 0000000000..62b205c2ed --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_client.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef RTC_TOOLS_DATA_CHANNEL_BENCHMARK_PEER_CONNECTION_CLIENT_H_ +#define RTC_TOOLS_DATA_CHANNEL_BENCHMARK_PEER_CONNECTION_CLIENT_H_ + +#include + +#include +#include +#include + +#include "api/jsep.h" +#include "api/peer_connection_interface.h" +#include "api/rtp_receiver_interface.h" +#include "api/scoped_refptr.h" +#include "api/set_local_description_observer_interface.h" +#include "rtc_base/logging.h" +#include "rtc_base/thread.h" +#include "rtc_tools/data_channel_benchmark/signaling_interface.h" + +namespace webrtc { + +// Handles all the details for creating a PeerConnection and negotiation using a +// SignalingInterface object. +class PeerConnectionClient : public webrtc::PeerConnectionObserver { + public: + explicit PeerConnectionClient(webrtc::PeerConnectionFactoryInterface* factory, + webrtc::SignalingInterface* signaling); + + ~PeerConnectionClient() override; + + PeerConnectionClient(const PeerConnectionClient&) = delete; + PeerConnectionClient& operator=(const PeerConnectionClient&) = delete; + + // Set the local description and send offer using the SignalingInterface, + // initiating the negotiation process. + bool StartPeerConnection(); + + // Whether the peer connection is connected to the remote peer. + bool IsConnected(); + + // Disconnect from the call. + void Disconnect(); + + rtc::scoped_refptr peerConnection() { + return peer_connection_; + } + + // Set a callback to run when a DataChannel is created by the remote peer. + void SetOnDataChannel( + std::function)> + callback); + + std::vector>& + dataChannels() { + return data_channels_; + } + + // Creates a default PeerConnectionFactory object. + static rtc::scoped_refptr + CreateDefaultFactory(rtc::Thread* signaling_thread); + + private: + void AddIceCandidate( + std::unique_ptr candidate); + bool SetRemoteDescription( + std::unique_ptr desc); + + // Initialize the PeerConnection with a given PeerConnectionFactory. + bool InitializePeerConnection( + webrtc::PeerConnectionFactoryInterface* factory); + void DeletePeerConnection(); + + // PeerConnectionObserver implementation. + void OnSignalingChange( + webrtc::PeerConnectionInterface::SignalingState new_state) override { + RTC_LOG(LS_INFO) << __FUNCTION__ << " new state: " << new_state; + } + void OnDataChannel( + rtc::scoped_refptr channel) override; + void OnNegotiationNeededEvent(uint32_t event_id) override; + void OnIceConnectionChange( + webrtc::PeerConnectionInterface::IceConnectionState new_state) override; + void OnIceGatheringChange( + webrtc::PeerConnectionInterface::IceGatheringState new_state) override; + void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override; + void OnIceConnectionReceivingChange(bool receiving) override { + RTC_LOG(LS_INFO) << __FUNCTION__ << " receiving? " << receiving; + } + + rtc::scoped_refptr peer_connection_; + std::function)> + on_data_channel_callback_; + std::vector> data_channels_; + webrtc::SignalingInterface* signaling_; +}; + +} // namespace webrtc + +#endif // RTC_TOOLS_DATA_CHANNEL_BENCHMARK_PEER_CONNECTION_CLIENT_H_ diff --git a/third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_signaling.proto b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_signaling.proto new file mode 100644 index 0000000000..9bd0aae912 --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/peer_connection_signaling.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; + +package webrtc.GrpcSignaling; + +service PeerConnectionSignaling { + rpc Connect(stream SignalingMessage) returns (stream SignalingMessage) {} +} + +message SignalingMessage { + oneof Content { + SessionDescription description = 1; + IceCandidate candidate = 2; + } +} + +message SessionDescription { + enum SessionDescriptionType { + OFFER = 0; + ANSWER = 1; + } + SessionDescriptionType type = 1; + string content = 2; +} + +message IceCandidate { + string mid = 1; + int32 mline_index = 2; + string description = 3; +} \ No newline at end of file diff --git a/third_party/libwebrtc/rtc_tools/data_channel_benchmark/signaling_interface.h b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/signaling_interface.h new file mode 100644 index 0000000000..77c811acb3 --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/data_channel_benchmark/signaling_interface.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef RTC_TOOLS_DATA_CHANNEL_BENCHMARK_SIGNALING_INTERFACE_H_ +#define RTC_TOOLS_DATA_CHANNEL_BENCHMARK_SIGNALING_INTERFACE_H_ + +#include + +#include "api/jsep.h" + +namespace webrtc { +class SignalingInterface { + public: + virtual ~SignalingInterface() = default; + + // Send an ICE candidate over the transport. + virtual void SendIceCandidate( + const webrtc::IceCandidateInterface* candidate) = 0; + + // Send a local description over the transport. + virtual void SendDescription( + const webrtc::SessionDescriptionInterface* sdp) = 0; + + // Set a callback when receiving a description from the transport. + virtual void OnRemoteDescription( + std::function + sdp)> callback) = 0; + + // Set a callback when receiving an ICE candidate from the transport. + virtual void OnIceCandidate( + std::function + candidate)> callback) = 0; +}; +} // namespace webrtc + +#endif // RTC_TOOLS_DATA_CHANNEL_BENCHMARK_SIGNALING_INTERFACE_H_ diff --git a/third_party/libwebrtc/rtc_tools/frame_analyzer/frame_analyzer.cc b/third_party/libwebrtc/rtc_tools/frame_analyzer/frame_analyzer.cc new file mode 100644 index 0000000000..501a6142a8 --- /dev/null +++ b/third_party/libwebrtc/rtc_tools/frame_analyzer/frame_analyzer.cc @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include +#include + +#include +#include +#include + +#include "absl/flags/flag.h" +#include "absl/flags/parse.h" +#include "absl/strings/match.h" +#include "api/scoped_refptr.h" +#include "api/test/metrics/chrome_perf_dashboard_metrics_exporter.h" +#include "api/test/metrics/global_metrics_logger_and_exporter.h" +#include "api/test/metrics/metrics_exporter.h" +#include "api/test/metrics/stdout_metrics_exporter.h" +#include "rtc_base/strings/string_builder.h" +#include "rtc_tools/frame_analyzer/video_color_aligner.h" +#include "rtc_tools/frame_analyzer/video_geometry_aligner.h" +#include "rtc_tools/frame_analyzer/video_quality_analysis.h" +#include "rtc_tools/frame_analyzer/video_temporal_aligner.h" +#include "rtc_tools/video_file_reader.h" +#include "rtc_tools/video_file_writer.h" + +ABSL_FLAG(int32_t, width, -1, "The width of the reference and test files"); +ABSL_FLAG(int32_t, height, -1, "The height of the reference and test files"); +ABSL_FLAG(std::string, + label, + "MY_TEST", + "The label to use for the perf output"); +ABSL_FLAG(std::string, + reference_file, + "ref.yuv", + "The reference YUV file to run the analysis against"); +ABSL_FLAG(std::string, + test_file, + "test.yuv", + "The test YUV file to run the analysis for"); +ABSL_FLAG(std::string, + aligned_output_file, + "", + "Where to write aligned YUV/Y4M output file, f not present, no files " + "will be written"); +ABSL_FLAG(std::string, + yuv_directory, + "", + "Where to write aligned YUV ref+test output files, if not present, " + "no files will be written"); +ABSL_FLAG(std::string, + chartjson_result_file, + "", + "Where to store perf result in chartjson format, if not present, no " + "perf result will be stored"); + +namespace { + +#ifdef WIN32 +const char* const kPathDelimiter = "\\"; +#else +const char* const kPathDelimiter = "/"; +#endif + +std::string JoinFilename(std::string directory, std::string filename) { + return directory + kPathDelimiter + filename; +} + +} // namespace + +/* + * A command line tool running PSNR and SSIM on a reference video and a test + * video. The test video is a record of the reference video which can start at + * an arbitrary point. It is possible that there will be repeated frames or + * skipped frames as well. The video files should be I420 .y4m or .yuv videos. + * If both files are .y4m, it's not needed to specify width/height. The tool + * prints the result to standard output in the Chromium perf format: + * RESULT :