diff options
Diffstat (limited to 'third_party/libwebrtc/api')
675 files changed, 88073 insertions, 0 deletions
diff --git a/third_party/libwebrtc/api/BUILD.gn b/third_party/libwebrtc/api/BUILD.gn new file mode 100644 index 0000000000..7c16b45e05 --- /dev/null +++ b/third_party/libwebrtc/api/BUILD.gn @@ -0,0 +1,1559 @@ +# Copyright (c) 2015 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 (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +group("api") { + visibility = [ "*" ] + deps = [] + + if (!build_with_mozilla) { + deps += [ ":libjingle_peerconnection_api" ] + } +} + +rtc_source_set("call_api") { + visibility = [ "*" ] + sources = [ "call/audio_sink.h" ] +} + +rtc_source_set("callfactory_api") { + visibility = [ "*" ] + sources = [ "call/call_factory_interface.h" ] + deps = [ + "../call:rtp_interfaces", + "../rtc_base/system:rtc_export", + ] +} + +if (!build_with_chromium && !build_with_mozilla) { + rtc_library("create_peerconnection_factory") { + visibility = [ "*" ] + allow_poison = [ "default_task_queue" ] + sources = [ + "create_peerconnection_factory.cc", + "create_peerconnection_factory.h", + ] + deps = [ + ":callfactory_api", + ":libjingle_peerconnection_api", + ":scoped_refptr", + "../api/rtc_event_log:rtc_event_log_factory", + "../media:rtc_audio_video", + "../media:rtc_media_base", + "../modules/audio_device:audio_device_api", + "../modules/audio_processing:api", + "../pc:peer_connection_factory", + "../pc:webrtc_sdp", + "../rtc_base:threading", + "../stats:rtc_stats", + "audio:audio_mixer_api", + "audio_codecs:audio_codecs_api", + "task_queue:default_task_queue_factory", + "transport:field_trial_based_config", + "video_codecs:video_codecs_api", + ] + } +} + +rtc_library("rtp_headers") { + visibility = [ "*" ] + sources = [ + "rtp_headers.cc", + "rtp_headers.h", + ] + deps = [ + ":array_view", + "units:timestamp", + "video:video_rtp_headers", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("rtp_packet_info") { + visibility = [ "*" ] + sources = [ + "rtp_packet_info.cc", + "rtp_packet_info.h", + "rtp_packet_infos.h", + ] + deps = [ + ":array_view", + ":make_ref_counted", + ":refcountedbase", + ":rtp_headers", + ":scoped_refptr", + "../rtc_base/system:rtc_export", + "units:time_delta", + "units:timestamp", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_source_set("video_track_source_constraints") { + visibility = [ "*" ] + sources = [ "video_track_source_constraints.h" ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("media_stream_interface") { + visibility = [ "*" ] + sources = [ + "media_stream_interface.cc", + "media_stream_interface.h", + "media_stream_track.h", + "notifier.h", + ] + deps = [ + ":audio_options_api", + ":make_ref_counted", + ":rtp_parameters", + ":scoped_refptr", + ":sequence_checker", + ":video_track_source_constraints", + "../modules/audio_processing:audio_processing_statistics", + "../rtc_base:checks", + "../rtc_base:refcount", + "../rtc_base/system:no_unique_address", + "../rtc_base/system:rtc_export", + "video:recordable_encoded_frame", + "video:video_frame", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("candidate") { + visibility = [ "*" ] + + sources = [ + "candidate.cc", + "candidate.h", + ] + deps = [ + "../rtc_base:checks", + "../rtc_base:ip_address", + "../rtc_base:logging", + "../rtc_base:network_constants", + "../rtc_base:socket_address", + "../rtc_base:ssl", + "../rtc_base:stringutils", + "../rtc_base/system:rtc_export", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} + +rtc_source_set("turn_customizer") { + visibility = [ "*" ] + sources = [ "turn_customizer.h" ] + deps = [ "transport:stun_types" ] +} + +rtc_source_set("ice_transport_interface") { + visibility = [ "*" ] + + sources = [ "ice_transport_interface.h" ] + deps = [ + ":async_dns_resolver", + ":packet_socket_factory", + ":rtc_error", + ":scoped_refptr", + "../rtc_base:refcount", + "rtc_event_log:rtc_event_log", + ] +} + +rtc_library("dtls_transport_interface") { +# Previously, Mozilla has tried to limit including this dep, but as +# upstream changes, it requires whack-a-mole. Making it an empty +# definition has the same effect, but only requires one change. +if (!build_with_mozilla) { + visibility = [ "*" ] + + sources = [ + "dtls_transport_interface.cc", + "dtls_transport_interface.h", + ] + deps = [ + ":ice_transport_interface", + ":rtc_error", + ":scoped_refptr", + "../rtc_base:refcount", + "../rtc_base:ssl", + "../rtc_base/system:rtc_export", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} +} + +rtc_library("dtmf_sender_interface") { + visibility = [ "*" ] + + sources = [ "dtmf_sender_interface.h" ] + deps = [ + ":media_stream_interface", + "../rtc_base:refcount", + ] +} + +rtc_library("rtp_sender_interface") { +# Previously, Mozilla has tried to limit including this dep, but as +# upstream changes, it requires whack-a-mole. Making it an empty +# definition has the same effect, but only requires one change. +if (!build_with_mozilla) { + visibility = [ "*" ] + + sources = [ + "rtp_sender_interface.cc", + "rtp_sender_interface.h", + ] + deps = [ + ":dtls_transport_interface", + ":dtmf_sender_interface", + ":frame_transformer_interface", + ":media_stream_interface", + ":rtp_parameters", + ":rtp_sender_setparameters_callback", + ":scoped_refptr", + "../rtc_base:checks", + "../rtc_base:refcount", + "../rtc_base/system:rtc_export", + "crypto:frame_encryptor_interface", + "video_codecs:video_codecs_api", + ] +} +} + +rtc_library("rtp_sender_setparameters_callback") { + visibility = [ "*" ] + + sources = [ + "rtp_sender_setparameters_callback.cc", + "rtp_sender_setparameters_callback.h", + ] + deps = [ + ":rtc_error", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/functional:any_invocable" ] +} + +rtc_library("libjingle_peerconnection_api") { +if (!build_with_mozilla) { + visibility = [ "*" ] + cflags = [] + sources = [ + "crypto_params.h", + "data_channel_interface.cc", + "data_channel_interface.h", + "jsep.cc", + "jsep.h", + "jsep_ice_candidate.cc", + "jsep_ice_candidate.h", + "jsep_session_description.h", + "legacy_stats_types.cc", + "legacy_stats_types.h", + "peer_connection_interface.cc", + "peer_connection_interface.h", + "rtp_receiver_interface.cc", + "rtp_receiver_interface.h", + "rtp_transceiver_interface.cc", + "rtp_transceiver_interface.h", + "sctp_transport_interface.cc", + "sctp_transport_interface.h", + "set_local_description_observer_interface.h", + "set_remote_description_observer_interface.h", + "uma_metrics.h", + "video_track_source_proxy_factory.h", + + # Remove when downstream has been updated + "dtmf_sender_interface.h", + "rtp_sender_interface.h", + ] + public_deps = [ # no-presubmit-check TODO(webrtc:8603) + # Remove when downstream has been updated + ":dtmf_sender_interface", + ":rtp_sender_interface", + ] + deps = [ + ":array_view", + ":async_dns_resolver", + ":audio_options_api", + ":callfactory_api", + ":candidate", + ":dtls_transport_interface", + ":fec_controller_api", + ":field_trials", + ":field_trials_view", + ":frame_transformer_interface", + ":ice_transport_interface", + ":libjingle_logging_api", + ":make_ref_counted", + ":media_stream_interface", + ":network_state_predictor_api", + ":packet_socket_factory", + ":priority", + ":rtc_error", + ":rtc_stats_api", + ":rtp_packet_info", + ":rtp_parameters", + ":rtp_sender_interface", + ":rtp_transceiver_direction", + ":scoped_refptr", + ":sequence_checker", + ":turn_customizer", + "../call:rtp_interfaces", + "../p2p:rtc_p2p", + "../rtc_base:copy_on_write_buffer", + "../rtc_base:logging", + "../rtc_base:network", + "../rtc_base:network_constants", + "../rtc_base:refcount", + "../rtc_base:rtc_certificate_generator", + "../rtc_base:ssl", + "../rtc_base:stringutils", + "adaptation:resource_adaptation_api", + "audio:audio_mixer_api", + "audio_codecs:audio_codecs_api", + "crypto:frame_decryptor_interface", + "crypto:frame_encryptor_interface", + "crypto:options", + "metronome", + "neteq:neteq_api", + "rtc_event_log", + "task_queue", + "transport:bitrate_settings", + "transport:enums", + "transport:network_control", + "transport:sctp_transport_factory_interface", + "transport/rtp:rtp_source", + "units:data_rate", + "units:timestamp", + "video:encoded_image", + "video:video_bitrate_allocator_factory", + "video:video_frame", + "video:video_rtp_headers", + "video_codecs:video_codecs_api", + + # Basically, don't add stuff here. You might break sensitive downstream + # targets like pnacl. API should not depend on anything outside of this + # file, really. All these should arguably go away in time. + "../media:rtc_media_base", + "../media:rtc_media_config", + "../modules/audio_processing:audio_processing_statistics", + "../rtc_base:checks", + "../rtc_base:ip_address", + "../rtc_base:socket_address", + "../rtc_base:threading", + "../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/functional:any_invocable", + "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} +} + +rtc_source_set("frame_transformer_interface") { + visibility = [ "*" ] + sources = [ "frame_transformer_interface.h" ] + deps = [ + ":make_ref_counted", + ":scoped_refptr", + "../rtc_base:refcount", + "video:encoded_frame", + "video:video_frame_metadata", + ] +} + +rtc_library("rtc_error") { + visibility = [ "*" ] + sources = [ + "rtc_error.cc", + "rtc_error.h", + ] + deps = [ + "../rtc_base:checks", + "../rtc_base:logging", + "../rtc_base:macromagic", + "../rtc_base/system:rtc_export", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_source_set("packet_socket_factory") { + visibility = [ "*" ] + sources = [ + "async_resolver_factory.h", + "packet_socket_factory.h", + ] + deps = [ + ":async_dns_resolver", + ":wrapping_async_dns_resolver", + "../rtc_base:async_packet_socket", + "../rtc_base:async_resolver_interface", + "../rtc_base:proxy_info", + "../rtc_base:socket_address", + "../rtc_base/system:rtc_export", + ] +} + +rtc_source_set("async_dns_resolver") { + visibility = [ "*" ] + sources = [ "async_dns_resolver.h" ] + deps = [ + "../rtc_base:checks", + "../rtc_base:socket_address", + "../rtc_base/system:rtc_export", + ] +} + +rtc_source_set("wrapping_async_dns_resolver") { + visibility = [ + ":*", + "../p2p:rtc_p2p", + ] + sources = [ + "wrapping_async_dns_resolver.cc", + "wrapping_async_dns_resolver.h", + ] + deps = [ + ":async_dns_resolver", + ":sequence_checker", + "../rtc_base:async_resolver_interface", + "../rtc_base:checks", + "../rtc_base:macromagic", + "../rtc_base:socket_address", + "../rtc_base:threading", + "../rtc_base/third_party/sigslot", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/memory" ] +} + +rtc_source_set("scoped_refptr") { + visibility = [ "*" ] + sources = [ "scoped_refptr.h" ] +} + +rtc_source_set("make_ref_counted") { + visibility = [ "*" ] + sources = [ "make_ref_counted.h" ] + deps = [ "../rtc_base:refcount" ] +} + +rtc_source_set("video_quality_test_fixture_api") { + visibility = [ "*" ] + testonly = true + sources = [ "test/video_quality_test_fixture.h" ] + deps = [ + ":fec_controller_api", + ":libjingle_peerconnection_api", + ":network_state_predictor_api", + ":rtp_parameters", + ":simulated_network_api", + "../call:fake_network", + "../call:rtp_interfaces", + "../test:test_common", + "../test:video_test_common", + "../video/config:encoder_config", + "transport:bitrate_settings", + "transport:network_control", + "video_codecs:video_codecs_api", + ] +} + +rtc_source_set("video_quality_analyzer_api") { + visibility = [ "*" ] + testonly = true + sources = [ "test/video_quality_analyzer_interface.h" ] + + deps = [ + ":array_view", + ":stats_observer_interface", + "video:encoded_image", + "video:video_frame", + "video:video_rtp_headers", + "video_codecs:video_codecs_api", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_source_set("track_id_stream_info_map") { + visibility = [ "*" ] + sources = [ "test/track_id_stream_info_map.h" ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} + +rtc_source_set("rtp_transceiver_direction") { + visibility = [ "*" ] + sources = [ "rtp_transceiver_direction.h" ] +} + +rtc_source_set("priority") { + visibility = [ "*" ] + sources = [ "priority.h" ] +} + +rtc_library("rtp_parameters") { + visibility = [ "*" ] + sources = [ + "media_types.cc", + "media_types.h", + "rtp_parameters.cc", + "rtp_parameters.h", + ] + deps = [ + ":array_view", + ":priority", + ":rtp_transceiver_direction", + "../rtc_base:checks", + "../rtc_base:stringutils", + "../rtc_base/system:rtc_export", + "video:resolution", + "video_codecs:scalability_mode", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/container:inlined_vector", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +if (is_android) { + java_cpp_enum("priority_enums") { + sources = [ "priority.h" ] + } +} + +rtc_source_set("audio_quality_analyzer_api") { + visibility = [ "*" ] + testonly = true + sources = [ "test/audio_quality_analyzer_interface.h" ] + + deps = [ + ":stats_observer_interface", + ":track_id_stream_info_map", + ] +} + +rtc_source_set("stats_observer_interface") { + visibility = [ "*" ] + testonly = true + sources = [ "test/stats_observer_interface.h" ] + + deps = [ ":rtc_stats_api" ] + + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} + +rtc_source_set("peer_network_dependencies") { + visibility = [ "*" ] + sources = [ "test/peer_network_dependencies.h" ] + deps = [ + ":packet_socket_factory", + "../rtc_base:network", + "../rtc_base:threading", + ] +} + +rtc_source_set("peer_connection_quality_test_fixture_api") { +if (!build_with_mozilla) { + visibility = [ "*" ] + testonly = true + sources = [ "test/peerconnection_quality_test_fixture.h" ] + + deps = [ + ":array_view", + ":audio_quality_analyzer_api", + ":callfactory_api", + ":fec_controller_api", + ":frame_generator_api", + ":function_view", + ":libjingle_peerconnection_api", + ":media_stream_interface", + ":network_state_predictor_api", + ":packet_socket_factory", + ":peer_network_dependencies", + ":rtp_parameters", + ":simulated_network_api", + ":stats_observer_interface", + ":track_id_stream_info_map", + ":video_quality_analyzer_api", + "../media:media_constants", + "../media:rtc_media_base", + "../modules/audio_processing:api", + "../rtc_base:checks", + "../rtc_base:network", + "../rtc_base:rtc_certificate_generator", + "../rtc_base:ssl", + "../rtc_base:stringutils", + "../rtc_base:threading", + "../test:fileutils", + "audio:audio_mixer_api", + "rtc_event_log", + "task_queue", + "test/pclf:media_configuration", + "test/pclf:media_quality_test_params", + "test/pclf:peer_configurer", + "test/video:video_frame_writer", + "transport:network_control", + "units:time_delta", + "video:video_frame", + "video_codecs:video_codecs_api", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} +} + +rtc_source_set("frame_generator_api") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/frame_generator_interface.cc", + "test/frame_generator_interface.h", + ] + + deps = [ + ":scoped_refptr", + "video:video_frame", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("test_dependency_factory") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/test_dependency_factory.cc", + "test/test_dependency_factory.h", + ] + deps = [ + ":video_quality_test_fixture_api", + "../rtc_base:checks", + "../rtc_base:platform_thread_types", + ] +} + +if (rtc_include_tests) { + # TODO(srte): Move to network_emulation sub directory. + rtc_library("create_network_emulation_manager") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/create_network_emulation_manager.cc", + "test/create_network_emulation_manager.h", + ] + deps = [ + ":network_emulation_manager_api", + "../test/network:emulated_network", + ] + } + + if (!build_with_chromium) { + rtc_library("create_video_quality_test_fixture_api") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/create_video_quality_test_fixture.cc", + "test/create_video_quality_test_fixture.h", + ] + deps = [ + ":fec_controller_api", + ":network_state_predictor_api", + ":scoped_refptr", + ":video_quality_test_fixture_api", + "../video:video_quality_test", + ] + } + + rtc_library("create_peerconnection_quality_test_fixture") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/create_peerconnection_quality_test_fixture.cc", + "test/create_peerconnection_quality_test_fixture.h", + ] + + deps = [ + ":audio_quality_analyzer_api", + ":peer_connection_quality_test_fixture_api", + ":time_controller", + ":video_quality_analyzer_api", + "../test/pc/e2e:peerconnection_quality_test", + "test/metrics:global_metrics_logger_and_exporter", + ] + } + } +} + +rtc_library("create_frame_generator") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/create_frame_generator.cc", + "test/create_frame_generator.h", + ] + deps = [ + ":frame_generator_api", + "../rtc_base:checks", + "../system_wrappers", + "../test:frame_generator_impl", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +if (!build_with_mozilla) { +rtc_library("create_peer_connection_quality_test_frame_generator") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/create_peer_connection_quality_test_frame_generator.cc", + "test/create_peer_connection_quality_test_frame_generator.h", + ] + deps = [ + ":create_frame_generator", + ":frame_generator_api", + "../rtc_base:checks", + "../test:fileutils", + "test/pclf:media_configuration", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} +} + +rtc_source_set("libjingle_logging_api") { + visibility = [ "*" ] + sources = [ "rtc_event_log_output.h" ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings:strings" ] +} + +rtc_library("rtc_event_log_output_file") { + visibility = [ "*" ] + sources = [ + "rtc_event_log_output_file.cc", + "rtc_event_log_output_file.h", + ] + + deps = [ + ":libjingle_logging_api", + "../rtc_base:checks", + "../rtc_base:logging", + "../rtc_base/system:file_wrapper", + "rtc_event_log", + ] +} + +rtc_source_set("rtc_stats_api") { + visibility = [ "*" ] + cflags = [] + sources = [ + "stats/rtc_stats.h", + "stats/rtc_stats_collector_callback.h", + "stats/rtc_stats_report.h", + "stats/rtcstats_objects.h", + ] + + deps = [ + ":make_ref_counted", + ":scoped_refptr", + "../api:refcountedbase", + "../rtc_base:checks", + "../rtc_base:refcount", + "../rtc_base/system:rtc_export", + "units:timestamp", + ] + + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("audio_options_api") { + visibility = [ "*" ] + sources = [ + "audio_options.cc", + "audio_options.h", + ] + + deps = [ + ":array_view", + "../rtc_base:stringutils", + "../rtc_base/system:rtc_export", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("transport_api") { + visibility = [ "*" ] + sources = [ + "call/transport.cc", + "call/transport.h", + ] + deps = [ + ":refcountedbase", + ":scoped_refptr", + ] +} + +rtc_source_set("bitrate_allocation") { + visibility = [ "*" ] + sources = [ "call/bitrate_allocation.h" ] + deps = [ + "units:data_rate", + "units:time_delta", + ] +} + +# TODO(srte): Move to network_emulation sub directory. +rtc_source_set("simulated_network_api") { + visibility = [ "*" ] + sources = [ "test/simulated_network.h" ] + deps = [ + "../rtc_base:macromagic", + "../rtc_base:random", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +# TODO(srte): Move to network_emulation sub directory. +rtc_source_set("network_emulation_manager_api") { + visibility = [ "*" ] + sources = [ + "test/network_emulation_manager.cc", + "test/network_emulation_manager.h", + ] + deps = [ + ":array_view", + ":packet_socket_factory", + ":peer_network_dependencies", + ":simulated_network_api", + ":time_controller", + "../call:simulated_network", + "../rtc_base:checks", + "../rtc_base:network", + "../rtc_base:network_constants", + "../rtc_base:threading", + "test/network_emulation", + "units:data_rate", + "units:data_size", + "units:timestamp", + ] +} + +rtc_source_set("time_controller") { + visibility = [ "*" ] + sources = [ + "test/time_controller.cc", + "test/time_controller.h", + ] + + deps = [ + "../rtc_base:threading", + "../rtc_base/synchronization:yield_policy", + "../system_wrappers", + "task_queue", + "units:time_delta", + "units:timestamp", + ] +} + +rtc_source_set("fec_controller_api") { + visibility = [ "*" ] + sources = [ + "fec_controller.h", + "fec_controller_override.h", + ] + + deps = [ + "../modules:module_fec_api", + "video:video_frame_type", + ] +} + +rtc_source_set("network_state_predictor_api") { + visibility = [ "*" ] + sources = [ "network_state_predictor.h" ] +} + +rtc_source_set("array_view") { + visibility = [ "*" ] + sources = [ "array_view.h" ] + deps = [ + "../rtc_base:checks", + "../rtc_base:type_traits", + ] +} + +rtc_source_set("refcountedbase") { + visibility = [ "*" ] + sources = [ "ref_counted_base.h" ] + deps = [ + "../rtc_base:macromagic", + "../rtc_base:refcount", + ] +} + +if (!build_with_mozilla) { +rtc_library("ice_transport_factory") { + visibility = [ "*" ] + sources = [ + "ice_transport_factory.cc", + "ice_transport_factory.h", + ] + deps = [ + ":ice_transport_interface", + ":libjingle_peerconnection_api", + ":make_ref_counted", + ":packet_socket_factory", + ":scoped_refptr", + "../p2p:rtc_p2p", + "../rtc_base:threading", + "../rtc_base/system:rtc_export", + "rtc_event_log:rtc_event_log", + ] +} +} + +rtc_library("neteq_simulator_api") { + visibility = [ "*" ] + sources = [ + "test/neteq_simulator.cc", + "test/neteq_simulator.h", + ] +} + +rtc_source_set("function_view") { + visibility = [ "*" ] + sources = [ "function_view.h" ] + deps = [ "../rtc_base:checks" ] +} + +rtc_source_set("sequence_checker") { + visibility = [ "*" ] + sources = [ "sequence_checker.h" ] + deps = [ + "../rtc_base:checks", + "../rtc_base:macromagic", + "../rtc_base/synchronization:sequence_checker_internal", + ] +} + +if (rtc_include_tests) { + if (rtc_enable_protobuf && !build_with_chromium) { + rtc_library("audioproc_f_api") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/audioproc_float.cc", + "test/audioproc_float.h", + ] + + deps = [ + "../modules/audio_processing", + "../modules/audio_processing:api", + "../modules/audio_processing:audioproc_f_impl", + ] + } + + rtc_library("neteq_simulator_factory") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/neteq_simulator_factory.cc", + "test/neteq_simulator_factory.h", + ] + deps = [ + ":neteq_simulator_api", + "../modules/audio_coding:neteq_test_factory", + "../rtc_base:checks", + "neteq:neteq_api", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/flags:flag", + "//third_party/abseil-cpp/absl/flags:parse", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] + } + } + + rtc_source_set("simulcast_test_fixture_api") { + visibility = [ "*" ] + testonly = true + sources = [ "test/simulcast_test_fixture.h" ] + } + + rtc_library("create_simulcast_test_fixture_api") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/create_simulcast_test_fixture.cc", + "test/create_simulcast_test_fixture.h", + ] + deps = [ + ":simulcast_test_fixture_api", + "../modules/video_coding:simulcast_test_fixture_impl", + "video_codecs:video_codecs_api", + ] + } + + rtc_library("videocodec_test_stats_api") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/videocodec_test_stats.cc", + "test/videocodec_test_stats.h", + ] + deps = [ + "../api/units:data_rate", + "../api/units:frequency", + "../rtc_base:stringutils", + "video:video_frame_type", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + } + + rtc_library("videocodec_test_fixture_api") { + visibility = [ "*" ] + testonly = true + sources = [ "test/videocodec_test_fixture.h" ] + deps = [ + ":videocodec_test_stats_api", + "../modules/video_coding:video_codec_interface", + "video_codecs:video_codecs_api", + ] + } + + rtc_library("video_codec_tester_api") { + visibility = [ "*" ] + testonly = true + sources = [ "test/video_codec_tester.h" ] + deps = [ + ":videocodec_test_stats_api", + "../modules/video_coding/svc:scalability_mode_util", + "video:encoded_image", + "video:resolution", + "video:video_frame", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/functional:any_invocable", + "//third_party/abseil-cpp/absl/types:optional", + ] + } + + rtc_library("create_videocodec_test_fixture_api") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/create_videocodec_test_fixture.cc", + "test/create_videocodec_test_fixture.h", + ] + deps = [ + ":videocodec_test_fixture_api", + "../modules/video_coding:video_codecs_test_framework", + "../modules/video_coding:videocodec_test_impl", + "video_codecs:video_codecs_api", + ] + } + + rtc_library("create_video_codec_tester_api") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/create_video_codec_tester.cc", + "test/create_video_codec_tester.h", + ] + deps = [ + ":video_codec_tester_api", + "../modules/video_coding:videocodec_test_impl", + ] + } + + rtc_source_set("mock_audio_mixer") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_audio_mixer.h" ] + + deps = [ + "../test:test_support", + "audio:audio_mixer_api", + ] + } + + rtc_source_set("mock_audio_sink") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_audio_sink.h" ] + + deps = [ + "../api:media_stream_interface", + "../test:test_support", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + } + + rtc_source_set("mock_data_channel") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_data_channel.h" ] + + deps = [ + ":libjingle_peerconnection_api", + "../test:test_support", + ] + } + + rtc_source_set("mock_dtmf_sender") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_dtmf_sender.h" ] + + deps = [ + ":dtmf_sender_interface", + ":libjingle_peerconnection_api", + "../test:test_support", + ] + } + + rtc_source_set("mock_fec_controller_override") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_fec_controller_override.h" ] + deps = [ + ":fec_controller_api", + "../test:test_support", + ] + } + + rtc_library("mock_frame_encryptor") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_frame_encryptor.h" ] + deps = [ + # For api/crypto/frame_encryptor_interface.h + ":libjingle_peerconnection_api", + "../test:test_support", + "crypto:frame_encryptor_interface", + ] + } + + rtc_library("mock_frame_decryptor") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_frame_decryptor.h" ] + deps = [ + ":libjingle_peerconnection_api", + "../test:test_support", + "crypto:frame_decryptor_interface", + ] + } + + rtc_library("mock_encoder_selector") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_encoder_selector.h" ] + deps = [ + ":libjingle_peerconnection_api", + "../api/video_codecs:video_codecs_api", + "../test:test_support", + ] + } + + rtc_library("fake_frame_encryptor") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/fake_frame_encryptor.cc", + "test/fake_frame_encryptor.h", + ] + deps = [ + ":array_view", + ":libjingle_peerconnection_api", + ":make_ref_counted", + ":rtp_parameters", + "../rtc_base:checks", + "../rtc_base:refcount", + "crypto:frame_encryptor_interface", + ] + } + + rtc_library("fake_frame_decryptor") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/fake_frame_decryptor.cc", + "test/fake_frame_decryptor.h", + ] + deps = [ + ":array_view", + ":libjingle_peerconnection_api", + ":make_ref_counted", + ":rtp_parameters", + "../rtc_base:checks", + "crypto:frame_decryptor_interface", + ] + } + + rtc_source_set("mock_media_stream_interface") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_media_stream_interface.h" ] + + deps = [ + ":media_stream_interface", + "../test:test_support", + ] + } + + rtc_source_set("mock_packet_socket_factory") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_packet_socket_factory.h" ] + + deps = [ + ":packet_socket_factory", + "../test:test_support", + ] + } + + rtc_source_set("mock_peerconnectioninterface") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_peerconnectioninterface.h" ] + + deps = [ + ":libjingle_peerconnection_api", + "../api:scoped_refptr", + "../rtc_base:refcount", + "../test:test_support", + ] + } + + rtc_source_set("mock_peer_connection_factory_interface") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_peer_connection_factory_interface.h" ] + + deps = [ + ":libjingle_peerconnection_api", + "../test:test_support", + ] + } + + rtc_source_set("mock_session_description_interface") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_session_description_interface.h" ] + deps = [ + ":libjingle_peerconnection_api", + "../test:test_support", + ] + } + + rtc_source_set("mock_async_dns_resolver") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_async_dns_resolver.h" ] + deps = [ + ":async_dns_resolver", + "../test:test_support", + ] + } + + rtc_source_set("mock_rtp") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/mock_rtp_transceiver.h", + "test/mock_rtpreceiver.h", + "test/mock_rtpsender.h", + ] + + deps = [ + ":libjingle_peerconnection_api", + ":rtp_sender_interface", + "../api/crypto:frame_decryptor_interface", + "../test:test_support", + ] + } + + rtc_source_set("mock_transformable_video_frame") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_transformable_video_frame.h" ] + + deps = [ + ":frame_transformer_interface", + "../test:test_support", + ] + } + + rtc_source_set("mock_video_bitrate_allocator") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_video_bitrate_allocator.h" ] + + deps = [ + "../api/video:video_bitrate_allocator", + "../test:test_support", + ] + } + + rtc_source_set("mock_video_bitrate_allocator_factory") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_video_bitrate_allocator_factory.h" ] + + deps = [ + "../api/video:video_bitrate_allocator_factory", + "../test:test_support", + ] + } + + rtc_source_set("mock_video_codec_factory") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/mock_video_decoder_factory.h", + "test/mock_video_encoder_factory.h", + ] + + deps = [ + "../api/video_codecs:video_codecs_api", + "../test:test_support", + ] + } + + rtc_library("mock_video_decoder") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_video_decoder.h" ] + + deps = [ + "../api/video_codecs:video_codecs_api", + "../test:test_support", + ] + } + + rtc_library("mock_video_encoder") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_video_encoder.h" ] + + deps = [ + "../api/video_codecs:video_codecs_api", + "../test:test_support", + ] + } + + rtc_library("mock_video_track") { + visibility = [ "*" ] + testonly = true + sources = [ "test/mock_video_track.h" ] + + deps = [ + "../api:media_stream_interface", + "../api:scoped_refptr", + "../rtc_base:refcount", + "../test:test_support", + ] + } + + rtc_library("create_time_controller") { + visibility = [ "*" ] + testonly = true + sources = [ + "test/create_time_controller.cc", + "test/create_time_controller.h", + ] + + deps = [ + ":callfactory_api", + ":time_controller", + "../call", + "../call:call_interfaces", + "../call:rtp_interfaces", + "../test/time_controller", + ] + } + + rtc_library("rtc_api_unittests") { + testonly = true + + sources = [ + "array_view_unittest.cc", + "field_trials_unittest.cc", + "function_view_unittest.cc", + "rtc_error_unittest.cc", + "rtc_event_log_output_file_unittest.cc", + "rtp_packet_info_unittest.cc", + "rtp_packet_infos_unittest.cc", + "rtp_parameters_unittest.cc", + "scoped_refptr_unittest.cc", + "sequence_checker_unittest.cc", + "test/create_time_controller_unittest.cc", + "test/peerconnection_quality_test_fixture_unittest.cc", + ] + + deps = [ + ":array_view", + ":create_time_controller", + ":field_trials", + ":field_trials_view", + ":function_view", + ":libjingle_peerconnection_api", + ":peer_connection_quality_test_fixture_api", + ":rtc_error", + ":rtc_event_log_output_file", + ":rtp_packet_info", + ":rtp_parameters", + ":scoped_refptr", + ":sequence_checker", + ":time_controller", + "../rtc_base:buffer", + "../rtc_base:checks", + "../rtc_base:gunit_helpers", + "../rtc_base:platform_thread", + "../rtc_base:rtc_event", + "../rtc_base:rtc_task_queue", + "../rtc_base:task_queue_for_test", + "../rtc_base/containers:flat_set", + "../rtc_base/task_utils:repeating_task", + "../system_wrappers:field_trial", + "../test:field_trial", + "../test:fileutils", + "../test:rtc_expect_death", + "../test:test_support", + "task_queue:task_queue_default_factory_unittests", + "test/pclf:media_configuration", + "test/video:video_frame_writer", + "transport:field_trial_based_config", + "units:time_delta", + "units:timestamp", + "units:units_unittests", + "video:frame_buffer_unittest", + "video:rtp_video_frame_assembler_unittests", + "video:video_unittests", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] + } + + rtc_library("compile_all_headers") { + testonly = true + + sources = [ "test/compile_all_headers.cc" ] + + deps = [ + ":fake_frame_decryptor", + ":fake_frame_encryptor", + ":mock_async_dns_resolver", + ":mock_audio_mixer", + ":mock_audio_sink", + ":mock_data_channel", + ":mock_dtmf_sender", + ":mock_frame_decryptor", + ":mock_frame_encryptor", + ":mock_media_stream_interface", + ":mock_packet_socket_factory", + ":mock_peer_connection_factory_interface", + ":mock_peerconnectioninterface", + ":mock_rtp", + ":mock_session_description_interface", + ":mock_transformable_video_frame", + ":mock_video_bitrate_allocator", + ":mock_video_bitrate_allocator_factory", + ":mock_video_codec_factory", + ":mock_video_decoder", + ":mock_video_encoder", + ":mock_video_track", + ":rtc_api_unittests", + "units:units_unittests", + ] + } +} + +rtc_source_set("field_trials_registry") { + visibility = [ "*" ] + sources = [ + "field_trials_registry.cc", + "field_trials_registry.h", + ] + deps = [ + ":field_trials_view", + "../experiments:registered_field_trials", + "../rtc_base:checks", + "../rtc_base/containers:flat_set", + "../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/strings", + ] +} + +rtc_source_set("field_trials_view") { + visibility = [ "*" ] + sources = [ "field_trials_view.h" ] + deps = [ "../rtc_base/system:rtc_export" ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} + +rtc_source_set("webrtc_key_value_config") { + visibility = [ "*" ] + sources = [ "webrtc_key_value_config.h" ] + deps = [ ":field_trials_view" ] +} + +rtc_library("field_trials") { + visibility = [ "*" ] + sources = [ + "field_trials.cc", + "field_trials.h", + ] + deps = [ + ":field_trials_registry", + "../rtc_base:checks", + "../rtc_base/containers:flat_map", + "../system_wrappers:field_trial", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} + +rtc_library("frame_transformer_factory") { + visibility = [ "*" ] + sources = [ + "frame_transformer_factory.cc", + "frame_transformer_factory.h", + ] + deps = [ + ":frame_transformer_interface", + ":scoped_refptr", + "../modules/rtp_rtcp", + "../rtc_base:refcount", + "video:encoded_frame", + "video:video_frame_metadata", + ] +} diff --git a/third_party/libwebrtc/api/DEPS b/third_party/libwebrtc/api/DEPS new file mode 100644 index 0000000000..bcfd705741 --- /dev/null +++ b/third_party/libwebrtc/api/DEPS @@ -0,0 +1,346 @@ +# This is supposed to be a complete list of top-level directories, +# excepting only api/ itself. +include_rules = [ + "-audio", + "-base", + "-build", + "-buildtools", + "-build_overrides", + "-call", + "-common_audio", + "-common_video", + "-data", + "-examples", + "-experiments", + "-g3doc", + "-ios", + "-infra", + "-logging", + "-media", + "-net", + "-modules", + "-out", + "-p2p", + "-pc", + "-resources", + "-rtc_base", + "-rtc_tools", + "-sdk", + "-stats", + "-style-guide", + "-system_wrappers", + "-test", + "-testing", + "-third_party", + "-tools", + "-tools_webrtc", + "-video", + "-external/webrtc/webrtc", # Android platform build. + "-libyuv", + "-common_types.h", + "-WebRTC", +] + +specific_include_rules = { + # Some internal headers are allowed even in API headers: + + "call_factory_interface\.h": [ + "+call/rtp_transport_controller_send_factory_interface.h", + ], + + ".*\.h": [ + "+rtc_base/checks.h", + "+rtc_base/system/rtc_export.h", + "+rtc_base/system/rtc_export_template.h", + "+rtc_base/units/unit_base.h", + ], + + "array_view\.h": [ + "+rtc_base/type_traits.h", + ], + + # Needed because AudioEncoderOpus is in the wrong place for + # backwards compatibilty reasons. See + # https://bugs.chromium.org/p/webrtc/issues/detail?id=7847 + "audio_encoder_opus\.h": [ + "+modules/audio_coding/codecs/opus/audio_encoder_opus.h", + ], + + "async_resolver_factory\.h": [ + "+rtc_base/async_resolver_interface.h", + ], + + "async_dns_resolver\.h": [ + "+rtc_base/socket_address.h", + ], + + "candidate\.h": [ + "+rtc_base/network_constants.h", + "+rtc_base/socket_address.h", + ], + + "data_channel_interface\.h": [ + "+rtc_base/copy_on_write_buffer.h", + "+rtc_base/ref_count.h", + ], + + "data_channel_transport_interface\.h": [ + "+rtc_base/copy_on_write_buffer.h", + ], + + "dtls_transport_interface\.h": [ + "+rtc_base/ref_count.h", + "+rtc_base/ssl_certificate.h", + ], + + "dtmf_sender_interface\.h": [ + "+rtc_base/ref_count.h", + ], + + "fec_controller\.h": [ + "+modules/include/module_fec_types.h", + ], + + "frame_transformer_interface\.h": [ + "+rtc_base/ref_count.h", + ], + + "ice_transport_interface\.h": [ + "+rtc_base/ref_count.h", + ], + + "jsep\.h": [ + "+rtc_base/ref_count.h", + ], + + "media_stream_interface\.h": [ + "+modules/audio_processing/include/audio_processing_statistics.h", + "+rtc_base/ref_count.h", + ], + + "packet_socket_factory\.h": [ + "+rtc_base/proxy_info.h", + "+rtc_base/async_packet_socket.h", + ], + + "peer_connection_interface\.h": [ + "+call/rtp_transport_controller_send_factory_interface.h", + "+media/base/media_config.h", + "+media/base/media_engine.h", + "+p2p/base/port.h", + "+p2p/base/port_allocator.h", + "+rtc_base/network.h", + "+rtc_base/network_constants.h", + "+rtc_base/network_monitor_factory.h", + "+rtc_base/ref_count.h", + "+rtc_base/rtc_certificate.h", + "+rtc_base/rtc_certificate_generator.h", + "+rtc_base/socket_address.h", + "+rtc_base/ssl_certificate.h", + "+rtc_base/ssl_stream_adapter.h", + "+rtc_base/thread.h", + ], + + "proxy\.h": [ + "+rtc_base/event.h", + "+rtc_base/message_handler.h", # Inherits from it. + "+rtc_base/thread.h", + ], + + "ref_counted_base\.h": [ + "+rtc_base/ref_count.h", + "+rtc_base/ref_counter.h", + ], + + "rtc_error\.h": [ + "+rtc_base/logging.h", + ], + "rtc_event_log_output_file.h": [ + # For private member and constructor. + "+rtc_base/system/file_wrapper.h", + ], + "rtp_receiver_interface\.h": [ + "+rtc_base/ref_count.h", + ], + + "rtp_sender_interface\.h": [ + "+rtc_base/ref_count.h", + ], + + "rtp_transceiver_interface\.h": [ + "+rtc_base/ref_count.h", + ], + + "sctp_transport_interface\.h": [ + "+rtc_base/ref_count.h", + ], + + "set_local_description_observer_interface\.h": [ + "+rtc_base/ref_count.h", + ], + "set_remote_description_observer_interface\.h": [ + "+rtc_base/ref_count.h", + ], + + "legacy_stats_types\.h": [ + "+rtc_base/ref_count.h", + "+rtc_base/thread_checker.h", + ], + + "uma_metrics\.h": [ + "+rtc_base/ref_count.h", + ], + + "audio_mixer\.h": [ + "+rtc_base/ref_count.h", + ], + + "audio_decoder\.h": [ + "+rtc_base/buffer.h", + ], + + "audio_decoder_factory\.h": [ + "+rtc_base/ref_count.h", + ], + + "audio_encoder\.h": [ + "+rtc_base/buffer.h", + ], + + "audio_encoder_factory\.h": [ + "+rtc_base/ref_count.h", + ], + + "frame_decryptor_interface\.h": [ + "+rtc_base/ref_count.h", + ], + + "frame_encryptor_interface\.h": [ + "+rtc_base/ref_count.h", + ], + + "rtc_stats_collector_callback\.h": [ + "+rtc_base/ref_count.h", + ], + + "rtc_stats_report\.h": [ + "+rtc_base/ref_count.h", + ], + + "audioproc_float\.h": [ + "+modules/audio_processing/include/audio_processing.h", + ], + + "echo_detector_creator\.h": [ + "+modules/audio_processing/include/audio_processing.h", + ], + + "fake_metronome\.h": [ + "+rtc_base/synchronization/mutex.h", + "+rtc_base/task_queue.h", + "+rtc_base/task_utils/repeating_task.h", + "+rtc_base/thread_annotations.h", + ], + + "make_ref_counted\.h": [ + "+rtc_base/ref_counted_object.h", + ], + + "mock.*\.h": [ + "+test/gmock.h", + ], + + "mock_peerconnectioninterface\.h": [ + "+rtc_base/ref_counted_object.h", + ], + + "mock_video_track\.h": [ + "+rtc_base/ref_counted_object.h", + ], + + "notifier\.h": [ + "+rtc_base/system/no_unique_address.h", + ], + + "simulated_network\.h": [ + "+rtc_base/random.h", + "+rtc_base/thread_annotations.h", + ], + + "test_dependency_factory\.h": [ + "+rtc_base/thread_checker.h", + ], + + "time_controller\.h": [ + "+rtc_base/thread.h", + ], + + "videocodec_test_fixture\.h": [ + "+modules/video_coding/include/video_codec_interface.h" + ], + + "video_encoder_config\.h": [ + "+rtc_base/ref_count.h", + ], + + "sequence_checker\.h": [ + "+rtc_base/synchronization/sequence_checker_internal.h", + "+rtc_base/thread_annotations.h", + ], + + "wrapping_async_dns_resolver\.h": [ + "+rtc_base/async_resolver.h", + "+rtc_base/async_resolver_interface.h", + "+rtc_base/socket_address.h", + "+rtc_base/third_party/sigslot/sigslot.h", + "+rtc_base/thread_annotations.h", + ], + + "video_encoder_factory_template.*\.h": [ + "+modules/video_coding", + ], + + "video_decoder_factory_template.*\.h": [ + "+modules/video_coding", + ], + + "field_trials\.h": [ + "+rtc_base/containers/flat_map.h", + ], + + "video_track_source_proxy_factory.h": [ + "+rtc_base/thread.h", + ], + + "field_trials_registry\.h": [ + "+rtc_base/containers/flat_set.h", + ], + + # .cc files in api/ should not be restricted in what they can #include, + # so we re-add all the top-level directories here. (That's because .h + # files leak their #includes to whoever's #including them, but .cc files + # do not since no one #includes them.) + ".*\.cc": [ + "+audio", + "+call", + "+common_audio", + "+common_video", + "+examples", + "+experiments", + "+logging", + "+media", + "+modules", + "+p2p", + "+pc", + "+rtc_base", + "+rtc_tools", + "+sdk", + "+stats", + "+system_wrappers", + "+test", + "+tools", + "+tools_webrtc", + "+video", + "+third_party", + ], +} diff --git a/third_party/libwebrtc/api/OWNERS b/third_party/libwebrtc/api/OWNERS new file mode 100644 index 0000000000..383ac8a3ed --- /dev/null +++ b/third_party/libwebrtc/api/OWNERS @@ -0,0 +1,14 @@ +hta@webrtc.org +magjed@webrtc.org +perkj@webrtc.org +tommi@webrtc.org + +# For approvals that absolutely must be done on US Pacific time +deadbeef@webrtc.org +tkchin@webrtc.org + +per-file peer_connection*=hbos@webrtc.org + +per-file DEPS=mbonadei@webrtc.org + +per-file uma_metrics.h=kron@webrtc.org diff --git a/third_party/libwebrtc/api/README.md b/third_party/libwebrtc/api/README.md new file mode 100644 index 0000000000..7153cb57c4 --- /dev/null +++ b/third_party/libwebrtc/api/README.md @@ -0,0 +1,27 @@ +<!-- go/cmark --> +<!--* freshness: {owner: 'hta' reviewed: '2021-01-01'} *--> + +# How to write code in the `api/` directory + +Mostly, just follow the regular [style guide](/g3doc/style-guide.md), but: + +* Note that `api/` code is not exempt from the “`.h` and `.cc` files come in + pairs” rule, so if you declare something in `api/path/to/foo.h`, it should be + defined in `api/path/to/foo.cc`. +* Headers in `api/` should, if possible, not `#include` headers outside `api/`. + It’s not always possible to avoid this, but be aware that it adds to a small + mountain of technical debt that we’re trying to shrink. +* `.cc` files in `api/`, on the other hand, are free to `#include` headers + outside `api/`. + +That is, the preferred way for `api/` code to access non-`api/` code is to call +it from a `.cc` file, so that users of our API headers won’t transitively +`#include` non-public headers. + +For headers in `api/` that need to refer to non-public types, forward +declarations are often a lesser evil than including non-public header files. The +usual [rules](/g3doc/style-guide.md#forward-declarations) still apply, though. + +`.cc` files in `api/` should preferably be kept reasonably small. If a +substantial implementation is needed, consider putting it with our non-public +code, and just call it from the `api/` `.cc` file. diff --git a/third_party/libwebrtc/api/adaptation/BUILD.gn b/third_party/libwebrtc/api/adaptation/BUILD.gn new file mode 100644 index 0000000000..839ad2c24b --- /dev/null +++ b/third_party/libwebrtc/api/adaptation/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright(c) 2020 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") + +rtc_source_set("resource_adaptation_api") { + visibility = [ "*" ] + sources = [ + "resource.cc", + "resource.h", + ] + deps = [ + "../../api:scoped_refptr", + "../../rtc_base:checks", + "../../rtc_base:refcount", + "../../rtc_base/system:rtc_export", + ] +} diff --git a/third_party/libwebrtc/api/adaptation/DEPS b/third_party/libwebrtc/api/adaptation/DEPS new file mode 100644 index 0000000000..734e152497 --- /dev/null +++ b/third_party/libwebrtc/api/adaptation/DEPS @@ -0,0 +1,7 @@ +specific_include_rules = { + "resource\.h": [ + # ref_count.h is a public_deps of rtc_base:refcount. Necessary because of + # rtc::RefCountInterface. + "+rtc_base/ref_count.h", + ], +}
\ No newline at end of file diff --git a/third_party/libwebrtc/api/adaptation/resource.cc b/third_party/libwebrtc/api/adaptation/resource.cc new file mode 100644 index 0000000000..dac03fe019 --- /dev/null +++ b/third_party/libwebrtc/api/adaptation/resource.cc @@ -0,0 +1,33 @@ +/* + * Copyright 2019 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 "api/adaptation/resource.h" + +#include "rtc_base/checks.h" + +namespace webrtc { + +const char* ResourceUsageStateToString(ResourceUsageState usage_state) { + switch (usage_state) { + case ResourceUsageState::kOveruse: + return "kOveruse"; + case ResourceUsageState::kUnderuse: + return "kUnderuse"; + } + RTC_CHECK_NOTREACHED(); +} + +ResourceListener::~ResourceListener() {} + +Resource::Resource() {} + +Resource::~Resource() {} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/adaptation/resource.h b/third_party/libwebrtc/api/adaptation/resource.h new file mode 100644 index 0000000000..7d7c70b3eb --- /dev/null +++ b/third_party/libwebrtc/api/adaptation/resource.h @@ -0,0 +1,67 @@ +/* + * Copyright 2019 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 API_ADAPTATION_RESOURCE_H_ +#define API_ADAPTATION_RESOURCE_H_ + +#include <string> + +#include "api/scoped_refptr.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +class Resource; + +enum class ResourceUsageState { + // Action is needed to minimze the load on this resource. + kOveruse, + // Increasing the load on this resource is desired, if possible. + kUnderuse, +}; + +RTC_EXPORT const char* ResourceUsageStateToString( + ResourceUsageState usage_state); + +class RTC_EXPORT ResourceListener { + public: + virtual ~ResourceListener(); + + virtual void OnResourceUsageStateMeasured( + rtc::scoped_refptr<Resource> resource, + ResourceUsageState usage_state) = 0; +}; + +// A Resource monitors an implementation-specific resource. It may report +// kOveruse or kUnderuse when resource usage is high or low enough that we +// should perform some sort of mitigation to fulfil the resource's constraints. +// +// The methods on this interface are invoked on the adaptation task queue. +// Resource usage measurements may be performed on an any task queue. +// +// The Resource is reference counted to prevent use-after-free when posting +// between task queues. As such, the implementation MUST NOT make any +// assumptions about which task queue Resource is destructed on. +class RTC_EXPORT Resource : public rtc::RefCountInterface { + public: + Resource(); + // Destruction may happen on any task queue. + ~Resource() override; + + virtual std::string Name() const = 0; + // The `listener` may be informed of resource usage measurements on any task + // queue, but not after this method is invoked with the null argument. + virtual void SetResourceListener(ResourceListener* listener) = 0; +}; + +} // namespace webrtc + +#endif // API_ADAPTATION_RESOURCE_H_ diff --git a/third_party/libwebrtc/api/adaptation/resource_adaptation_api_gn/moz.build b/third_party/libwebrtc/api/adaptation/resource_adaptation_api_gn/moz.build new file mode 100644 index 0000000000..aa958f7042 --- /dev/null +++ b/third_party/libwebrtc/api/adaptation/resource_adaptation_api_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/adaptation/resource.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("resource_adaptation_api_gn") diff --git a/third_party/libwebrtc/api/array_view.h b/third_party/libwebrtc/api/array_view.h new file mode 100644 index 0000000000..2d68f1650f --- /dev/null +++ b/third_party/libwebrtc/api/array_view.h @@ -0,0 +1,330 @@ +/* + * Copyright 2015 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 API_ARRAY_VIEW_H_ +#define API_ARRAY_VIEW_H_ + +#include <algorithm> +#include <array> +#include <iterator> +#include <type_traits> + +#include "rtc_base/checks.h" +#include "rtc_base/type_traits.h" + +namespace rtc { + +// tl;dr: rtc::ArrayView is the same thing as gsl::span from the Guideline +// Support Library. +// +// Many functions read from or write to arrays. The obvious way to do this is +// to use two arguments, a pointer to the first element and an element count: +// +// bool Contains17(const int* arr, size_t size) { +// for (size_t i = 0; i < size; ++i) { +// if (arr[i] == 17) +// return true; +// } +// return false; +// } +// +// This is flexible, since it doesn't matter how the array is stored (C array, +// std::vector, rtc::Buffer, ...), but it's error-prone because the caller has +// to correctly specify the array length: +// +// Contains17(arr, arraysize(arr)); // C array +// Contains17(arr.data(), arr.size()); // std::vector +// Contains17(arr, size); // pointer + size +// ... +// +// It's also kind of messy to have two separate arguments for what is +// conceptually a single thing. +// +// Enter rtc::ArrayView<T>. It contains a T pointer (to an array it doesn't +// own) and a count, and supports the basic things you'd expect, such as +// indexing and iteration. It allows us to write our function like this: +// +// bool Contains17(rtc::ArrayView<const int> arr) { +// for (auto e : arr) { +// if (e == 17) +// return true; +// } +// return false; +// } +// +// And even better, because a bunch of things will implicitly convert to +// ArrayView, we can call it like this: +// +// Contains17(arr); // C array +// Contains17(arr); // std::vector +// Contains17(rtc::ArrayView<int>(arr, size)); // pointer + size +// Contains17(nullptr); // nullptr -> empty ArrayView +// ... +// +// ArrayView<T> stores both a pointer and a size, but you may also use +// ArrayView<T, N>, which has a size that's fixed at compile time (which means +// it only has to store the pointer). +// +// One important point is that ArrayView<T> and ArrayView<const T> are +// different types, which allow and don't allow mutation of the array elements, +// respectively. The implicit conversions work just like you'd hope, so that +// e.g. vector<int> will convert to either ArrayView<int> or ArrayView<const +// int>, but const vector<int> will convert only to ArrayView<const int>. +// (ArrayView itself can be the source type in such conversions, so +// ArrayView<int> will convert to ArrayView<const int>.) +// +// Note: ArrayView is tiny (just a pointer and a count if variable-sized, just +// a pointer if fix-sized) and trivially copyable, so it's probably cheaper to +// pass it by value than by const reference. + +namespace array_view_internal { + +// Magic constant for indicating that the size of an ArrayView is variable +// instead of fixed. +enum : std::ptrdiff_t { kArrayViewVarSize = -4711 }; + +// Base class for ArrayViews of fixed nonzero size. +template <typename T, std::ptrdiff_t Size> +class ArrayViewBase { + static_assert(Size > 0, "ArrayView size must be variable or non-negative"); + + public: + ArrayViewBase(T* data, size_t size) : data_(data) {} + + static constexpr size_t size() { return Size; } + static constexpr bool empty() { return false; } + T* data() const { return data_; } + + protected: + static constexpr bool fixed_size() { return true; } + + private: + T* data_; +}; + +// Specialized base class for ArrayViews of fixed zero size. +template <typename T> +class ArrayViewBase<T, 0> { + public: + explicit ArrayViewBase(T* data, size_t size) {} + + static constexpr size_t size() { return 0; } + static constexpr bool empty() { return true; } + T* data() const { return nullptr; } + + protected: + static constexpr bool fixed_size() { return true; } +}; + +// Specialized base class for ArrayViews of variable size. +template <typename T> +class ArrayViewBase<T, array_view_internal::kArrayViewVarSize> { + public: + ArrayViewBase(T* data, size_t size) + : data_(size == 0 ? nullptr : data), size_(size) {} + + size_t size() const { return size_; } + bool empty() const { return size_ == 0; } + T* data() const { return data_; } + + protected: + static constexpr bool fixed_size() { return false; } + + private: + T* data_; + size_t size_; +}; + +} // namespace array_view_internal + +template <typename T, + std::ptrdiff_t Size = array_view_internal::kArrayViewVarSize> +class ArrayView final : public array_view_internal::ArrayViewBase<T, Size> { + public: + using value_type = T; + using const_iterator = const T*; + + // Construct an ArrayView from a pointer and a length. + template <typename U> + ArrayView(U* data, size_t size) + : array_view_internal::ArrayViewBase<T, Size>::ArrayViewBase(data, size) { + RTC_DCHECK_EQ(size == 0 ? nullptr : data, this->data()); + RTC_DCHECK_EQ(size, this->size()); + RTC_DCHECK_EQ(!this->data(), + this->size() == 0); // data is null iff size == 0. + } + + // Construct an empty ArrayView. Note that fixed-size ArrayViews of size > 0 + // cannot be empty. + ArrayView() : ArrayView(nullptr, 0) {} + ArrayView(std::nullptr_t) // NOLINT + : ArrayView() {} + ArrayView(std::nullptr_t, size_t size) + : ArrayView(static_cast<T*>(nullptr), size) { + static_assert(Size == 0 || Size == array_view_internal::kArrayViewVarSize, + ""); + RTC_DCHECK_EQ(0, size); + } + + // Construct an ArrayView from a C-style array. + template <typename U, size_t N> + ArrayView(U (&array)[N]) // NOLINT + : ArrayView(array, N) { + static_assert(Size == N || Size == array_view_internal::kArrayViewVarSize, + "Array size must match ArrayView size"); + } + + // (Only if size is fixed.) Construct a fixed size ArrayView<T, N> from a + // non-const std::array instance. For an ArrayView with variable size, the + // used ctor is ArrayView(U& u) instead. + template <typename U, + size_t N, + typename std::enable_if< + Size == static_cast<std::ptrdiff_t>(N)>::type* = nullptr> + ArrayView(std::array<U, N>& u) // NOLINT + : ArrayView(u.data(), u.size()) {} + + // (Only if size is fixed.) Construct a fixed size ArrayView<T, N> where T is + // const from a const(expr) std::array instance. For an ArrayView with + // variable size, the used ctor is ArrayView(U& u) instead. + template <typename U, + size_t N, + typename std::enable_if< + Size == static_cast<std::ptrdiff_t>(N)>::type* = nullptr> + ArrayView(const std::array<U, N>& u) // NOLINT + : ArrayView(u.data(), u.size()) {} + + // (Only if size is fixed.) Construct an ArrayView from any type U that has a + // static constexpr size() method whose return value is equal to Size, and a + // data() method whose return value converts implicitly to T*. In particular, + // this means we allow conversion from ArrayView<T, N> to ArrayView<const T, + // N>, but not the other way around. We also don't allow conversion from + // ArrayView<T> to ArrayView<T, N>, or from ArrayView<T, M> to ArrayView<T, + // N> when M != N. + template < + typename U, + typename std::enable_if<Size != array_view_internal::kArrayViewVarSize && + HasDataAndSize<U, T>::value>::type* = nullptr> + ArrayView(U& u) // NOLINT + : ArrayView(u.data(), u.size()) { + static_assert(U::size() == Size, "Sizes must match exactly"); + } + template < + typename U, + typename std::enable_if<Size != array_view_internal::kArrayViewVarSize && + HasDataAndSize<U, T>::value>::type* = nullptr> + ArrayView(const U& u) // NOLINT(runtime/explicit) + : ArrayView(u.data(), u.size()) { + static_assert(U::size() == Size, "Sizes must match exactly"); + } + + // (Only if size is variable.) Construct an ArrayView from any type U that + // has a size() method whose return value converts implicitly to size_t, and + // a data() method whose return value converts implicitly to T*. In + // particular, this means we allow conversion from ArrayView<T> to + // ArrayView<const T>, but not the other way around. Other allowed + // conversions include + // ArrayView<T, N> to ArrayView<T> or ArrayView<const T>, + // std::vector<T> to ArrayView<T> or ArrayView<const T>, + // const std::vector<T> to ArrayView<const T>, + // rtc::Buffer to ArrayView<uint8_t> or ArrayView<const uint8_t>, and + // const rtc::Buffer to ArrayView<const uint8_t>. + template < + typename U, + typename std::enable_if<Size == array_view_internal::kArrayViewVarSize && + HasDataAndSize<U, T>::value>::type* = nullptr> + ArrayView(U& u) // NOLINT + : ArrayView(u.data(), u.size()) {} + template < + typename U, + typename std::enable_if<Size == array_view_internal::kArrayViewVarSize && + HasDataAndSize<U, T>::value>::type* = nullptr> + ArrayView(const U& u) // NOLINT(runtime/explicit) + : ArrayView(u.data(), u.size()) {} + + // Indexing and iteration. These allow mutation even if the ArrayView is + // const, because the ArrayView doesn't own the array. (To prevent mutation, + // use a const element type.) + T& operator[](size_t idx) const { + RTC_DCHECK_LT(idx, this->size()); + RTC_DCHECK(this->data()); + return this->data()[idx]; + } + T* begin() const { return this->data(); } + T* end() const { return this->data() + this->size(); } + const T* cbegin() const { return this->data(); } + const T* cend() const { return this->data() + this->size(); } + std::reverse_iterator<T*> rbegin() const { + return std::make_reverse_iterator(end()); + } + std::reverse_iterator<T*> rend() const { + return std::make_reverse_iterator(begin()); + } + std::reverse_iterator<const T*> crbegin() const { + return std::make_reverse_iterator(cend()); + } + std::reverse_iterator<const T*> crend() const { + return std::make_reverse_iterator(cbegin()); + } + + ArrayView<T> subview(size_t offset, size_t size) const { + return offset < this->size() + ? ArrayView<T>(this->data() + offset, + std::min(size, this->size() - offset)) + : ArrayView<T>(); + } + ArrayView<T> subview(size_t offset) const { + return subview(offset, this->size()); + } +}; + +// Comparing two ArrayViews compares their (pointer,size) pairs; it does *not* +// dereference the pointers. +template <typename T, std::ptrdiff_t Size1, std::ptrdiff_t Size2> +bool operator==(const ArrayView<T, Size1>& a, const ArrayView<T, Size2>& b) { + return a.data() == b.data() && a.size() == b.size(); +} +template <typename T, std::ptrdiff_t Size1, std::ptrdiff_t Size2> +bool operator!=(const ArrayView<T, Size1>& a, const ArrayView<T, Size2>& b) { + return !(a == b); +} + +// Variable-size ArrayViews are the size of two pointers; fixed-size ArrayViews +// are the size of one pointer. (And as a special case, fixed-size ArrayViews +// of size 0 require no storage.) +static_assert(sizeof(ArrayView<int>) == 2 * sizeof(int*), ""); +static_assert(sizeof(ArrayView<int, 17>) == sizeof(int*), ""); +static_assert(std::is_empty<ArrayView<int, 0>>::value, ""); + +template <typename T> +inline ArrayView<T> MakeArrayView(T* data, size_t size) { + return ArrayView<T>(data, size); +} + +// Only for primitive types that have the same size and aligment. +// Allow reinterpret cast of the array view to another primitive type of the +// same size. +// Template arguments order is (U, T, Size) to allow deduction of the template +// arguments in client calls: reinterpret_array_view<target_type>(array_view). +template <typename U, typename T, std::ptrdiff_t Size> +inline ArrayView<U, Size> reinterpret_array_view(ArrayView<T, Size> view) { + static_assert(sizeof(U) == sizeof(T) && alignof(U) == alignof(T), + "ArrayView reinterpret_cast is only supported for casting " + "between views that represent the same chunk of memory."); + static_assert( + std::is_fundamental<T>::value && std::is_fundamental<U>::value, + "ArrayView reinterpret_cast is only supported for casting between " + "fundamental types."); + return ArrayView<U, Size>(reinterpret_cast<U*>(view.data()), view.size()); +} + +} // namespace rtc + +#endif // API_ARRAY_VIEW_H_ diff --git a/third_party/libwebrtc/api/array_view_gn/moz.build b/third_party/libwebrtc/api/array_view_gn/moz.build new file mode 100644 index 0000000000..e453cb8585 --- /dev/null +++ b/third_party/libwebrtc/api/array_view_gn/moz.build @@ -0,0 +1,205 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("array_view_gn") diff --git a/third_party/libwebrtc/api/array_view_unittest.cc b/third_party/libwebrtc/api/array_view_unittest.cc new file mode 100644 index 0000000000..97267df006 --- /dev/null +++ b/third_party/libwebrtc/api/array_view_unittest.cc @@ -0,0 +1,630 @@ +/* + * Copyright 2015 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 "api/array_view.h" + +#include <algorithm> +#include <array> +#include <string> +#include <utility> +#include <vector> + +#include "rtc_base/buffer.h" +#include "rtc_base/checks.h" +#include "rtc_base/gunit.h" +#include "test/gmock.h" + +namespace rtc { + +namespace { + +using ::testing::ElementsAre; +using ::testing::IsEmpty; + +template <typename T> +size_t Call(ArrayView<T> av) { + return av.size(); +} + +template <typename T, size_t N> +void CallFixed(ArrayView<T, N> av) {} + +} // namespace + +TEST(ArrayViewDeathTest, TestConstructFromPtrAndArray) { + char arr[] = "Arrr!"; + const char carr[] = "Carrr!"; + EXPECT_EQ(6u, Call<const char>(arr)); + EXPECT_EQ(7u, Call<const char>(carr)); + EXPECT_EQ(6u, Call<char>(arr)); + // Call<char>(carr); // Compile error, because can't drop const. + // Call<int>(arr); // Compile error, because incompatible types. + ArrayView<int*> x; + EXPECT_EQ(0u, x.size()); + EXPECT_EQ(nullptr, x.data()); + ArrayView<char> y = arr; + EXPECT_EQ(6u, y.size()); + EXPECT_EQ(arr, y.data()); + ArrayView<char, 6> yf = arr; + static_assert(yf.size() == 6, ""); + EXPECT_EQ(arr, yf.data()); + ArrayView<const char> z(arr + 1, 3); + EXPECT_EQ(3u, z.size()); + EXPECT_EQ(arr + 1, z.data()); + ArrayView<const char, 3> zf(arr + 1, 3); + static_assert(zf.size() == 3, ""); + EXPECT_EQ(arr + 1, zf.data()); + ArrayView<const char> w(arr, 2); + EXPECT_EQ(2u, w.size()); + EXPECT_EQ(arr, w.data()); + ArrayView<const char, 2> wf(arr, 2); + static_assert(wf.size() == 2, ""); + EXPECT_EQ(arr, wf.data()); + ArrayView<char> q(arr, 0); + EXPECT_EQ(0u, q.size()); + EXPECT_EQ(nullptr, q.data()); + ArrayView<char, 0> qf(arr, 0); + static_assert(qf.size() == 0, ""); + EXPECT_EQ(nullptr, qf.data()); +#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) + // DCHECK error (nullptr with nonzero size). + EXPECT_DEATH(ArrayView<int>(static_cast<int*>(nullptr), 5), ""); +#endif + // These are compile errors, because incompatible types. + // ArrayView<int> m = arr; + // ArrayView<float> n(arr + 2, 2); +} + +TEST(ArrayViewTest, TestCopyConstructorVariableLvalue) { + char arr[] = "Arrr!"; + ArrayView<char> x = arr; + EXPECT_EQ(6u, x.size()); + EXPECT_EQ(arr, x.data()); + ArrayView<char> y = x; // Copy non-const -> non-const. + EXPECT_EQ(6u, y.size()); + EXPECT_EQ(arr, y.data()); + ArrayView<const char> z = x; // Copy non-const -> const. + EXPECT_EQ(6u, z.size()); + EXPECT_EQ(arr, z.data()); + ArrayView<const char> w = z; // Copy const -> const. + EXPECT_EQ(6u, w.size()); + EXPECT_EQ(arr, w.data()); + // ArrayView<char> v = z; // Compile error, because can't drop const. +} + +TEST(ArrayViewTest, TestCopyConstructorVariableRvalue) { + char arr[] = "Arrr!"; + ArrayView<char> x = arr; + EXPECT_EQ(6u, x.size()); + EXPECT_EQ(arr, x.data()); + ArrayView<char> y = std::move(x); // Copy non-const -> non-const. + EXPECT_EQ(6u, y.size()); + EXPECT_EQ(arr, y.data()); + ArrayView<const char> z = std::move(x); // Copy non-const -> const. + EXPECT_EQ(6u, z.size()); + EXPECT_EQ(arr, z.data()); + ArrayView<const char> w = std::move(z); // Copy const -> const. + EXPECT_EQ(6u, w.size()); + EXPECT_EQ(arr, w.data()); + // ArrayView<char> v = std::move(z); // Error, because can't drop const. +} + +TEST(ArrayViewTest, TestCopyConstructorFixedLvalue) { + char arr[] = "Arrr!"; + ArrayView<char, 6> x = arr; + static_assert(x.size() == 6, ""); + EXPECT_EQ(arr, x.data()); + + // Copy fixed -> fixed. + ArrayView<char, 6> y = x; // Copy non-const -> non-const. + static_assert(y.size() == 6, ""); + EXPECT_EQ(arr, y.data()); + ArrayView<const char, 6> z = x; // Copy non-const -> const. + static_assert(z.size() == 6, ""); + EXPECT_EQ(arr, z.data()); + ArrayView<const char, 6> w = z; // Copy const -> const. + static_assert(w.size() == 6, ""); + EXPECT_EQ(arr, w.data()); + // ArrayView<char, 6> v = z; // Compile error, because can't drop const. + + // Copy fixed -> variable. + ArrayView<char> yv = x; // Copy non-const -> non-const. + EXPECT_EQ(6u, yv.size()); + EXPECT_EQ(arr, yv.data()); + ArrayView<const char> zv = x; // Copy non-const -> const. + EXPECT_EQ(6u, zv.size()); + EXPECT_EQ(arr, zv.data()); + ArrayView<const char> wv = z; // Copy const -> const. + EXPECT_EQ(6u, wv.size()); + EXPECT_EQ(arr, wv.data()); + // ArrayView<char> vv = z; // Compile error, because can't drop const. +} + +TEST(ArrayViewTest, TestCopyConstructorFixedRvalue) { + char arr[] = "Arrr!"; + ArrayView<char, 6> x = arr; + static_assert(x.size() == 6, ""); + EXPECT_EQ(arr, x.data()); + + // Copy fixed -> fixed. + ArrayView<char, 6> y = std::move(x); // Copy non-const -> non-const. + static_assert(y.size() == 6, ""); + EXPECT_EQ(arr, y.data()); + ArrayView<const char, 6> z = std::move(x); // Copy non-const -> const. + static_assert(z.size() == 6, ""); + EXPECT_EQ(arr, z.data()); + ArrayView<const char, 6> w = std::move(z); // Copy const -> const. + static_assert(w.size() == 6, ""); + EXPECT_EQ(arr, w.data()); + // ArrayView<char, 6> v = std::move(z); // Error, because can't drop const. + + // Copy fixed -> variable. + ArrayView<char> yv = std::move(x); // Copy non-const -> non-const. + EXPECT_EQ(6u, yv.size()); + EXPECT_EQ(arr, yv.data()); + ArrayView<const char> zv = std::move(x); // Copy non-const -> const. + EXPECT_EQ(6u, zv.size()); + EXPECT_EQ(arr, zv.data()); + ArrayView<const char> wv = std::move(z); // Copy const -> const. + EXPECT_EQ(6u, wv.size()); + EXPECT_EQ(arr, wv.data()); + // ArrayView<char> vv = std::move(z); // Error, because can't drop const. +} + +TEST(ArrayViewTest, TestCopyAssignmentVariableLvalue) { + char arr[] = "Arrr!"; + ArrayView<char> x(arr); + EXPECT_EQ(6u, x.size()); + EXPECT_EQ(arr, x.data()); + ArrayView<char> y; + y = x; // Copy non-const -> non-const. + EXPECT_EQ(6u, y.size()); + EXPECT_EQ(arr, y.data()); + ArrayView<const char> z; + z = x; // Copy non-const -> const. + EXPECT_EQ(6u, z.size()); + EXPECT_EQ(arr, z.data()); + ArrayView<const char> w; + w = z; // Copy const -> const. + EXPECT_EQ(6u, w.size()); + EXPECT_EQ(arr, w.data()); + // ArrayView<char> v; + // v = z; // Compile error, because can't drop const. +} + +TEST(ArrayViewTest, TestCopyAssignmentVariableRvalue) { + char arr[] = "Arrr!"; + ArrayView<char> x(arr); + EXPECT_EQ(6u, x.size()); + EXPECT_EQ(arr, x.data()); + ArrayView<char> y; + y = std::move(x); // Copy non-const -> non-const. + EXPECT_EQ(6u, y.size()); + EXPECT_EQ(arr, y.data()); + ArrayView<const char> z; + z = std::move(x); // Copy non-const -> const. + EXPECT_EQ(6u, z.size()); + EXPECT_EQ(arr, z.data()); + ArrayView<const char> w; + w = std::move(z); // Copy const -> const. + EXPECT_EQ(6u, w.size()); + EXPECT_EQ(arr, w.data()); + // ArrayView<char> v; + // v = std::move(z); // Compile error, because can't drop const. +} + +TEST(ArrayViewTest, TestCopyAssignmentFixedLvalue) { + char arr[] = "Arrr!"; + char init[] = "Init!"; + ArrayView<char, 6> x(arr); + EXPECT_EQ(arr, x.data()); + + // Copy fixed -> fixed. + ArrayView<char, 6> y(init); + y = x; // Copy non-const -> non-const. + EXPECT_EQ(arr, y.data()); + ArrayView<const char, 6> z(init); + z = x; // Copy non-const -> const. + EXPECT_EQ(arr, z.data()); + ArrayView<const char, 6> w(init); + w = z; // Copy const -> const. + EXPECT_EQ(arr, w.data()); + // ArrayView<char, 6> v(init); + // v = z; // Compile error, because can't drop const. + + // Copy fixed -> variable. + ArrayView<char> yv; + yv = x; // Copy non-const -> non-const. + EXPECT_EQ(6u, yv.size()); + EXPECT_EQ(arr, yv.data()); + ArrayView<const char> zv; + zv = x; // Copy non-const -> const. + EXPECT_EQ(6u, zv.size()); + EXPECT_EQ(arr, zv.data()); + ArrayView<const char> wv; + wv = z; // Copy const -> const. + EXPECT_EQ(6u, wv.size()); + EXPECT_EQ(arr, wv.data()); + // ArrayView<char> v; + // v = z; // Compile error, because can't drop const. +} + +TEST(ArrayViewTest, TestCopyAssignmentFixedRvalue) { + char arr[] = "Arrr!"; + char init[] = "Init!"; + ArrayView<char, 6> x(arr); + EXPECT_EQ(arr, x.data()); + + // Copy fixed -> fixed. + ArrayView<char, 6> y(init); + y = std::move(x); // Copy non-const -> non-const. + EXPECT_EQ(arr, y.data()); + ArrayView<const char, 6> z(init); + z = std::move(x); // Copy non-const -> const. + EXPECT_EQ(arr, z.data()); + ArrayView<const char, 6> w(init); + w = std::move(z); // Copy const -> const. + EXPECT_EQ(arr, w.data()); + // ArrayView<char, 6> v(init); + // v = std::move(z); // Compile error, because can't drop const. + + // Copy fixed -> variable. + ArrayView<char> yv; + yv = std::move(x); // Copy non-const -> non-const. + EXPECT_EQ(6u, yv.size()); + EXPECT_EQ(arr, yv.data()); + ArrayView<const char> zv; + zv = std::move(x); // Copy non-const -> const. + EXPECT_EQ(6u, zv.size()); + EXPECT_EQ(arr, zv.data()); + ArrayView<const char> wv; + wv = std::move(z); // Copy const -> const. + EXPECT_EQ(6u, wv.size()); + EXPECT_EQ(arr, wv.data()); + // ArrayView<char> v; + // v = std::move(z); // Compile error, because can't drop const. +} + +TEST(ArrayViewTest, TestStdArray) { + EXPECT_EQ(4u, Call<const int>(std::array<int, 4>{1, 2, 3, 4})); + CallFixed<const int, 3>(std::array<int, 3>{2, 3, 4}); + constexpr size_t size = 5; + std::array<float, size> arr{}; + // Fixed size view. + rtc::ArrayView<float, size> arr_view_fixed(arr); + EXPECT_EQ(arr.data(), arr_view_fixed.data()); + static_assert(size == arr_view_fixed.size(), ""); + // Variable size view. + rtc::ArrayView<float> arr_view(arr); + EXPECT_EQ(arr.data(), arr_view.data()); + EXPECT_EQ(size, arr_view.size()); +} + +TEST(ArrayViewTest, TestConstStdArray) { + constexpr size_t size = 5; + + constexpr std::array<float, size> constexpr_arr{}; + rtc::ArrayView<const float, size> constexpr_arr_view(constexpr_arr); + EXPECT_EQ(constexpr_arr.data(), constexpr_arr_view.data()); + static_assert(constexpr_arr.size() == constexpr_arr_view.size(), ""); + + const std::array<float, size> const_arr{}; + rtc::ArrayView<const float, size> const_arr_view(const_arr); + EXPECT_EQ(const_arr.data(), const_arr_view.data()); + static_assert(const_arr.size() == const_arr_view.size(), ""); + + std::array<float, size> non_const_arr{}; + rtc::ArrayView<const float, size> non_const_arr_view(non_const_arr); + EXPECT_EQ(non_const_arr.data(), non_const_arr_view.data()); + static_assert(non_const_arr.size() == non_const_arr_view.size(), ""); +} + +TEST(ArrayViewTest, TestStdVector) { + EXPECT_EQ(3u, Call<const int>(std::vector<int>{4, 5, 6})); + std::vector<int> v; + v.push_back(3); + v.push_back(11); + EXPECT_EQ(2u, Call<const int>(v)); + EXPECT_EQ(2u, Call<int>(v)); + // Call<unsigned int>(v); // Compile error, because incompatible types. + ArrayView<int> x = v; + EXPECT_EQ(2u, x.size()); + EXPECT_EQ(v.data(), x.data()); + ArrayView<const int> y; + y = v; + EXPECT_EQ(2u, y.size()); + EXPECT_EQ(v.data(), y.data()); + // ArrayView<double> d = v; // Compile error, because incompatible types. + const std::vector<int> cv; + EXPECT_EQ(0u, Call<const int>(cv)); + // Call<int>(cv); // Compile error, because can't drop const. + ArrayView<const int> z = cv; + EXPECT_EQ(0u, z.size()); + EXPECT_EQ(nullptr, z.data()); + // ArrayView<int> w = cv; // Compile error, because can't drop const. +} + +TEST(ArrayViewTest, TestRtcBuffer) { + rtc::Buffer b = "so buffer"; + EXPECT_EQ(10u, Call<const uint8_t>(b)); + EXPECT_EQ(10u, Call<uint8_t>(b)); + // Call<int8_t>(b); // Compile error, because incompatible types. + ArrayView<uint8_t> x = b; + EXPECT_EQ(10u, x.size()); + EXPECT_EQ(b.data(), x.data()); + ArrayView<const uint8_t> y; + y = b; + EXPECT_EQ(10u, y.size()); + EXPECT_EQ(b.data(), y.data()); + // ArrayView<char> d = b; // Compile error, because incompatible types. + const rtc::Buffer cb = "very const"; + EXPECT_EQ(11u, Call<const uint8_t>(cb)); + // Call<uint8_t>(cb); // Compile error, because can't drop const. + ArrayView<const uint8_t> z = cb; + EXPECT_EQ(11u, z.size()); + EXPECT_EQ(cb.data(), z.data()); + // ArrayView<uint8_t> w = cb; // Compile error, because can't drop const. +} + +TEST(ArrayViewTest, TestSwapVariable) { + const char arr[] = "Arrr!"; + const char aye[] = "Aye, Cap'n!"; + ArrayView<const char> x(arr); + EXPECT_EQ(6u, x.size()); + EXPECT_EQ(arr, x.data()); + ArrayView<const char> y(aye); + EXPECT_EQ(12u, y.size()); + EXPECT_EQ(aye, y.data()); + using std::swap; + swap(x, y); + EXPECT_EQ(12u, x.size()); + EXPECT_EQ(aye, x.data()); + EXPECT_EQ(6u, y.size()); + EXPECT_EQ(arr, y.data()); + // ArrayView<char> z; + // swap(x, z); // Compile error, because can't drop const. +} + +TEST(FixArrayViewTest, TestSwapFixed) { + const char arr[] = "Arr!"; + char aye[] = "Aye!"; + ArrayView<const char, 5> x(arr); + EXPECT_EQ(arr, x.data()); + ArrayView<const char, 5> y(aye); + EXPECT_EQ(aye, y.data()); + using std::swap; + swap(x, y); + EXPECT_EQ(aye, x.data()); + EXPECT_EQ(arr, y.data()); + // ArrayView<char, 5> z(aye); + // swap(x, z); // Compile error, because can't drop const. + // ArrayView<const char, 4> w(aye, 4); + // swap(x, w); // Compile error, because different sizes. +} + +TEST(ArrayViewDeathTest, TestIndexing) { + char arr[] = "abcdefg"; + ArrayView<char> x(arr); + const ArrayView<char> y(arr); + ArrayView<const char, 8> z(arr); + EXPECT_EQ(8u, x.size()); + EXPECT_EQ(8u, y.size()); + EXPECT_EQ(8u, z.size()); + EXPECT_EQ('b', x[1]); + EXPECT_EQ('c', y[2]); + EXPECT_EQ('d', z[3]); + x[3] = 'X'; + y[2] = 'Y'; + // z[1] = 'Z'; // Compile error, because z's element type is const char. + EXPECT_EQ('b', x[1]); + EXPECT_EQ('Y', y[2]); + EXPECT_EQ('X', z[3]); +#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) + EXPECT_DEATH(z[8], ""); // DCHECK error (index out of bounds). +#endif +} + +TEST(ArrayViewTest, TestIterationEmpty) { + // Variable-size. + ArrayView<std::vector<std::vector<std::vector<std::string>>>> av; + EXPECT_EQ(av.begin(), av.end()); + EXPECT_EQ(av.cbegin(), av.cend()); + for (auto& e : av) { + EXPECT_TRUE(false); + EXPECT_EQ(42u, e.size()); // Dummy use of e to prevent unused var warning. + } + + // Fixed-size. + ArrayView<std::vector<std::vector<std::vector<std::string>>>, 0> af; + EXPECT_EQ(af.begin(), af.end()); + EXPECT_EQ(af.cbegin(), af.cend()); + for (auto& e : af) { + EXPECT_TRUE(false); + EXPECT_EQ(42u, e.size()); // Dummy use of e to prevent unused var warning. + } +} + +TEST(ArrayViewTest, TestReverseIterationEmpty) { + // Variable-size. + ArrayView<std::vector<std::vector<std::vector<std::string>>>> av; + EXPECT_EQ(av.rbegin(), av.rend()); + EXPECT_EQ(av.crbegin(), av.crend()); + EXPECT_TRUE(av.empty()); + + // Fixed-size. + ArrayView<std::vector<std::vector<std::vector<std::string>>>, 0> af; + EXPECT_EQ(af.begin(), af.end()); + EXPECT_EQ(af.cbegin(), af.cend()); + EXPECT_TRUE(af.empty()); +} + +TEST(ArrayViewTest, TestIterationVariable) { + char arr[] = "Arrr!"; + ArrayView<char> av(arr); + EXPECT_EQ('A', *av.begin()); + EXPECT_EQ('A', *av.cbegin()); + EXPECT_EQ('\0', *(av.end() - 1)); + EXPECT_EQ('\0', *(av.cend() - 1)); + char i = 0; + for (auto& e : av) { + EXPECT_EQ(arr + i, &e); + e = 's' + i; + ++i; + } + i = 0; + for (auto& e : ArrayView<const char>(av)) { + EXPECT_EQ(arr + i, &e); + // e = 'q' + i; // Compile error, because e is a const char&. + ++i; + } +} + +TEST(ArrayViewTest, TestReverseIterationVariable) { + char arr[] = "Arrr!"; + ArrayView<char> av(arr); + EXPECT_EQ('\0', *av.rbegin()); + EXPECT_EQ('\0', *av.crbegin()); + EXPECT_EQ('A', *(av.rend() - 1)); + EXPECT_EQ('A', *(av.crend() - 1)); + + const char* cit = av.cend() - 1; + for (auto crit = av.crbegin(); crit != av.crend(); ++crit, --cit) { + EXPECT_EQ(*cit, *crit); + } + + char* it = av.end() - 1; + for (auto rit = av.rbegin(); rit != av.rend(); ++rit, --it) { + EXPECT_EQ(*it, *rit); + } +} + +TEST(ArrayViewTest, TestIterationFixed) { + char arr[] = "Arrr!"; + ArrayView<char, 6> av(arr); + EXPECT_EQ('A', *av.begin()); + EXPECT_EQ('A', *av.cbegin()); + EXPECT_EQ('\0', *(av.end() - 1)); + EXPECT_EQ('\0', *(av.cend() - 1)); + char i = 0; + for (auto& e : av) { + EXPECT_EQ(arr + i, &e); + e = 's' + i; + ++i; + } + i = 0; + for (auto& e : ArrayView<const char, 6>(av)) { + EXPECT_EQ(arr + i, &e); + // e = 'q' + i; // Compile error, because e is a const char&. + ++i; + } +} + +TEST(ArrayViewTest, TestReverseIterationFixed) { + char arr[] = "Arrr!"; + ArrayView<char, 6> av(arr); + EXPECT_EQ('\0', *av.rbegin()); + EXPECT_EQ('\0', *av.crbegin()); + EXPECT_EQ('A', *(av.rend() - 1)); + EXPECT_EQ('A', *(av.crend() - 1)); + + const char* cit = av.cend() - 1; + for (auto crit = av.crbegin(); crit != av.crend(); ++crit, --cit) { + EXPECT_EQ(*cit, *crit); + } + + char* it = av.end() - 1; + for (auto rit = av.rbegin(); rit != av.rend(); ++rit, --it) { + EXPECT_EQ(*it, *rit); + } +} + +TEST(ArrayViewTest, TestEmpty) { + EXPECT_TRUE(ArrayView<int>().empty()); + const int a[] = {1, 2, 3}; + EXPECT_FALSE(ArrayView<const int>(a).empty()); + + static_assert(ArrayView<int, 0>::empty(), ""); + static_assert(!ArrayView<int, 3>::empty(), ""); +} + +TEST(ArrayViewTest, TestCompare) { + int a[] = {1, 2, 3}; + int b[] = {1, 2, 3}; + + EXPECT_EQ(ArrayView<int>(a), ArrayView<int>(a)); + EXPECT_EQ((ArrayView<int, 3>(a)), (ArrayView<int, 3>(a))); + EXPECT_EQ(ArrayView<int>(a), (ArrayView<int, 3>(a))); + EXPECT_EQ(ArrayView<int>(), ArrayView<int>()); + EXPECT_EQ(ArrayView<int>(), ArrayView<int>(a, 0)); + EXPECT_EQ(ArrayView<int>(a, 0), ArrayView<int>(b, 0)); + EXPECT_EQ((ArrayView<int, 0>(a, 0)), ArrayView<int>()); + + EXPECT_NE(ArrayView<int>(a), ArrayView<int>(b)); + EXPECT_NE((ArrayView<int, 3>(a)), (ArrayView<int, 3>(b))); + EXPECT_NE((ArrayView<int, 3>(a)), ArrayView<int>(b)); + EXPECT_NE(ArrayView<int>(a), ArrayView<int>()); + EXPECT_NE(ArrayView<int>(a), ArrayView<int>(a, 2)); + EXPECT_NE((ArrayView<int, 3>(a)), (ArrayView<int, 2>(a, 2))); +} + +TEST(ArrayViewTest, TestSubViewVariable) { + int a[] = {1, 2, 3}; + ArrayView<int> av(a); + + EXPECT_EQ(av.subview(0), av); + + EXPECT_THAT(av.subview(1), ElementsAre(2, 3)); + EXPECT_THAT(av.subview(2), ElementsAre(3)); + EXPECT_THAT(av.subview(3), IsEmpty()); + EXPECT_THAT(av.subview(4), IsEmpty()); + + EXPECT_THAT(av.subview(1, 0), IsEmpty()); + EXPECT_THAT(av.subview(1, 1), ElementsAre(2)); + EXPECT_THAT(av.subview(1, 2), ElementsAre(2, 3)); + EXPECT_THAT(av.subview(1, 3), ElementsAre(2, 3)); +} + +TEST(ArrayViewTest, TestSubViewFixed) { + int a[] = {1, 2, 3}; + ArrayView<int, 3> av(a); + + EXPECT_EQ(av.subview(0), av); + + EXPECT_THAT(av.subview(1), ElementsAre(2, 3)); + EXPECT_THAT(av.subview(2), ElementsAre(3)); + EXPECT_THAT(av.subview(3), IsEmpty()); + EXPECT_THAT(av.subview(4), IsEmpty()); + + EXPECT_THAT(av.subview(1, 0), IsEmpty()); + EXPECT_THAT(av.subview(1, 1), ElementsAre(2)); + EXPECT_THAT(av.subview(1, 2), ElementsAre(2, 3)); + EXPECT_THAT(av.subview(1, 3), ElementsAre(2, 3)); +} + +TEST(ArrayViewTest, TestReinterpretCastFixedSize) { + uint8_t bytes[] = {1, 2, 3}; + ArrayView<uint8_t, 3> uint8_av(bytes); + ArrayView<int8_t, 3> int8_av = reinterpret_array_view<int8_t>(uint8_av); + EXPECT_EQ(int8_av.size(), uint8_av.size()); + EXPECT_EQ(int8_av[0], 1); + EXPECT_EQ(int8_av[1], 2); + EXPECT_EQ(int8_av[2], 3); +} + +TEST(ArrayViewTest, TestReinterpretCastVariableSize) { + std::vector<int8_t> v = {1, 2, 3}; + ArrayView<int8_t> int8_av(v); + ArrayView<uint8_t> uint8_av = reinterpret_array_view<uint8_t>(int8_av); + EXPECT_EQ(int8_av.size(), uint8_av.size()); + EXPECT_EQ(uint8_av[0], 1); + EXPECT_EQ(uint8_av[1], 2); + EXPECT_EQ(uint8_av[2], 3); +} +} // namespace rtc diff --git a/third_party/libwebrtc/api/async_dns_resolver.h b/third_party/libwebrtc/api/async_dns_resolver.h new file mode 100644 index 0000000000..82d80de2c3 --- /dev/null +++ b/third_party/libwebrtc/api/async_dns_resolver.h @@ -0,0 +1,104 @@ +/* + * Copyright 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 API_ASYNC_DNS_RESOLVER_H_ +#define API_ASYNC_DNS_RESOLVER_H_ + +#include <functional> +#include <memory> + +#include "rtc_base/checks.h" +#include "rtc_base/socket_address.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// This interface defines the methods to resolve a hostname asynchronously. +// The AsyncDnsResolverInterface class encapsulates a single name query. +// +// Usage: +// std::unique_ptr<AsyncDnsResolverInterface> resolver = +// factory->Create(address-to-be-resolved, [r = resolver.get()]() { +// if (r->result.GetResolvedAddress(AF_INET, &addr) { +// // success +// } else { +// // failure +// error = r->result().GetError(); +// } +// // Release resolver. +// resolver_list.erase(std::remove_if(resolver_list.begin(), +// resolver_list.end(), +// [](refptr) { refptr.get() == r; }); +// }); +// resolver_list.push_back(std::move(resolver)); + +class AsyncDnsResolverResult { + public: + virtual ~AsyncDnsResolverResult() = default; + // Returns true iff the address from `Start` was successfully resolved. + // If the address was successfully resolved, sets `addr` to a copy of the + // address from `Start` with the IP address set to the top most resolved + // address of `family` (`addr` will have both hostname and the resolved ip). + virtual bool GetResolvedAddress(int family, + rtc::SocketAddress* addr) const = 0; + // Returns error from resolver. + virtual int GetError() const = 0; +}; + +// The API for a single name query. +// The constructor, destructor and all functions must be called from +// the same sequence, and the callback will also be called on that sequence. +// The class guarantees that the callback will not be called if the +// resolver's destructor has been called. +class RTC_EXPORT AsyncDnsResolverInterface { + public: + virtual ~AsyncDnsResolverInterface() = default; + + // Start address resolution of the hostname in `addr`. + virtual void Start(const rtc::SocketAddress& addr, + std::function<void()> callback) = 0; + // Start address resolution of the hostname in `addr` matching `family`. + virtual void Start(const rtc::SocketAddress& addr, + int family, + std::function<void()> callback) = 0; + virtual const AsyncDnsResolverResult& result() const = 0; +}; + +// An abstract factory for creating AsyncDnsResolverInterfaces. This allows +// client applications to provide WebRTC with their own mechanism for +// performing DNS resolution. +class AsyncDnsResolverFactoryInterface { + public: + virtual ~AsyncDnsResolverFactoryInterface() = default; + + // Creates an AsyncDnsResolver and starts resolving the name. The callback + // will be called when resolution is finished. + // The callback will be called on the sequence that the caller runs on. + virtual std::unique_ptr<webrtc::AsyncDnsResolverInterface> CreateAndResolve( + const rtc::SocketAddress& addr, + std::function<void()> callback) = 0; + // Creates an AsyncDnsResolver and starts resolving the name to an address + // matching the specified family. The callback will be called when resolution + // is finished. The callback will be called on the sequence that the caller + // runs on. + virtual std::unique_ptr<webrtc::AsyncDnsResolverInterface> CreateAndResolve( + const rtc::SocketAddress& addr, + int family, + std::function<void()> callback) = 0; + // Creates an AsyncDnsResolver and does not start it. + // For backwards compatibility, will be deprecated and removed. + // One has to do a separate Start() call on the + // resolver to start name resolution. + virtual std::unique_ptr<webrtc::AsyncDnsResolverInterface> Create() = 0; +}; + +} // namespace webrtc + +#endif // API_ASYNC_DNS_RESOLVER_H_ diff --git a/third_party/libwebrtc/api/async_resolver_factory.h b/third_party/libwebrtc/api/async_resolver_factory.h new file mode 100644 index 0000000000..93d3f7934b --- /dev/null +++ b/third_party/libwebrtc/api/async_resolver_factory.h @@ -0,0 +1,32 @@ +/* + * Copyright 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. + */ + +#ifndef API_ASYNC_RESOLVER_FACTORY_H_ +#define API_ASYNC_RESOLVER_FACTORY_H_ + +#include "rtc_base/async_resolver_interface.h" + +namespace webrtc { + +// An abstract factory for creating AsyncResolverInterfaces. This allows +// client applications to provide WebRTC with their own mechanism for +// performing DNS resolution. +class AsyncResolverFactory { + public: + AsyncResolverFactory() = default; + virtual ~AsyncResolverFactory() = default; + + // The caller should call Destroy on the returned object to delete it. + virtual rtc::AsyncResolverInterface* Create() = 0; +}; + +} // namespace webrtc + +#endif // API_ASYNC_RESOLVER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/audio/BUILD.gn b/third_party/libwebrtc/api/audio/BUILD.gn new file mode 100644 index 0000000000..4832751b5f --- /dev/null +++ b/third_party/libwebrtc/api/audio/BUILD.gn @@ -0,0 +1,111 @@ +# 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. + +import("../../webrtc.gni") + +rtc_library("audio_frame_api") { + visibility = [ "*" ] + sources = [ + "audio_frame.cc", + "audio_frame.h", + "channel_layout.cc", + "channel_layout.h", + ] + + deps = [ + "..:rtp_packet_info", + "../../rtc_base:checks", + "../../rtc_base:logging", + "../../rtc_base:macromagic", + "../../rtc_base:timeutils", + ] +} + +rtc_source_set("audio_frame_processor") { + visibility = [ "*" ] + sources = [ "audio_frame_processor.h" ] +} + +rtc_source_set("audio_mixer_api") { + visibility = [ "*" ] + sources = [ "audio_mixer.h" ] + + deps = [ + ":audio_frame_api", + "..:make_ref_counted", + "../../rtc_base:refcount", + ] +} + +rtc_library("aec3_config") { + visibility = [ "*" ] + sources = [ + "echo_canceller3_config.cc", + "echo_canceller3_config.h", + ] + deps = [ + "../../rtc_base:checks", + "../../rtc_base:safe_minmax", + "../../rtc_base/system:rtc_export", + ] +} + +rtc_library("aec3_config_json") { + visibility = [ "*" ] + allow_poison = [ "rtc_json" ] + sources = [ + "echo_canceller3_config_json.cc", + "echo_canceller3_config_json.h", + ] + deps = [ + ":aec3_config", + "../../rtc_base:checks", + "../../rtc_base:logging", + "../../rtc_base:rtc_json", + "../../rtc_base:stringutils", + "../../rtc_base/system:rtc_export", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} + +rtc_library("aec3_factory") { + visibility = [ "*" ] + configs += [ "../../modules/audio_processing:apm_debug_dump" ] + sources = [ + "echo_canceller3_factory.cc", + "echo_canceller3_factory.h", + ] + + deps = [ + ":aec3_config", + ":echo_control", + "../../modules/audio_processing/aec3", + "../../rtc_base/system:rtc_export", + ] +} + +rtc_source_set("echo_control") { + visibility = [ "*" ] + sources = [ "echo_control.h" ] + deps = [ "../../rtc_base:checks" ] +} + +rtc_source_set("echo_detector_creator") { + visibility = [ "*" ] + allow_poison = [ "default_echo_detector" ] + sources = [ + "echo_detector_creator.cc", + "echo_detector_creator.h", + ] + deps = [ + "..:make_ref_counted", + "../../api:scoped_refptr", + "../../modules/audio_processing:api", + "../../modules/audio_processing:residual_echo_detector", + ] +} diff --git a/third_party/libwebrtc/api/audio/OWNERS b/third_party/libwebrtc/api/audio/OWNERS new file mode 100644 index 0000000000..bb499b450f --- /dev/null +++ b/third_party/libwebrtc/api/audio/OWNERS @@ -0,0 +1,2 @@ +gustaf@webrtc.org +peah@webrtc.org diff --git a/third_party/libwebrtc/api/audio/aec3_config_gn/moz.build b/third_party/libwebrtc/api/audio/aec3_config_gn/moz.build new file mode 100644 index 0000000000..c2d256488d --- /dev/null +++ b/third_party/libwebrtc/api/audio/aec3_config_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio/echo_canceller3_config.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("aec3_config_gn") diff --git a/third_party/libwebrtc/api/audio/aec3_factory_gn/moz.build b/third_party/libwebrtc/api/audio/aec3_factory_gn/moz.build new file mode 100644 index 0000000000..ecd28a7006 --- /dev/null +++ b/third_party/libwebrtc/api/audio/aec3_factory_gn/moz.build @@ -0,0 +1,233 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_APM_DEBUG_DUMP"] = "0" +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio/echo_canceller3_factory.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("aec3_factory_gn") diff --git a/third_party/libwebrtc/api/audio/audio_frame.cc b/third_party/libwebrtc/api/audio/audio_frame.cc new file mode 100644 index 0000000000..3e12006386 --- /dev/null +++ b/third_party/libwebrtc/api/audio/audio_frame.cc @@ -0,0 +1,140 @@ +/* + * 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 "api/audio/audio_frame.h" + +#include <string.h> + +#include "rtc_base/checks.h" +#include "rtc_base/time_utils.h" + +namespace webrtc { + +AudioFrame::AudioFrame() { + // Visual Studio doesn't like this in the class definition. + static_assert(sizeof(data_) == kMaxDataSizeBytes, "kMaxDataSizeBytes"); +} + +void AudioFrame::Reset() { + ResetWithoutMuting(); + muted_ = true; +} + +void AudioFrame::ResetWithoutMuting() { + // TODO(wu): Zero is a valid value for `timestamp_`. We should initialize + // to an invalid value, or add a new member to indicate invalidity. + timestamp_ = 0; + elapsed_time_ms_ = -1; + ntp_time_ms_ = -1; + samples_per_channel_ = 0; + sample_rate_hz_ = 0; + num_channels_ = 0; + channel_layout_ = CHANNEL_LAYOUT_NONE; + speech_type_ = kUndefined; + vad_activity_ = kVadUnknown; + profile_timestamp_ms_ = 0; + packet_infos_ = RtpPacketInfos(); + absolute_capture_timestamp_ms_ = absl::nullopt; +} + +void AudioFrame::UpdateFrame(uint32_t timestamp, + const int16_t* data, + size_t samples_per_channel, + int sample_rate_hz, + SpeechType speech_type, + VADActivity vad_activity, + size_t num_channels) { + timestamp_ = timestamp; + samples_per_channel_ = samples_per_channel; + sample_rate_hz_ = sample_rate_hz; + speech_type_ = speech_type; + vad_activity_ = vad_activity; + num_channels_ = num_channels; + channel_layout_ = GuessChannelLayout(num_channels); + if (channel_layout_ != CHANNEL_LAYOUT_UNSUPPORTED) { + RTC_DCHECK_EQ(num_channels, ChannelLayoutToChannelCount(channel_layout_)); + } + + const size_t length = samples_per_channel * num_channels; + RTC_CHECK_LE(length, kMaxDataSizeSamples); + if (data != nullptr) { + memcpy(data_, data, sizeof(int16_t) * length); + muted_ = false; + } else { + muted_ = true; + } +} + +void AudioFrame::CopyFrom(const AudioFrame& src) { + if (this == &src) + return; + + timestamp_ = src.timestamp_; + elapsed_time_ms_ = src.elapsed_time_ms_; + ntp_time_ms_ = src.ntp_time_ms_; + packet_infos_ = src.packet_infos_; + muted_ = src.muted(); + samples_per_channel_ = src.samples_per_channel_; + sample_rate_hz_ = src.sample_rate_hz_; + speech_type_ = src.speech_type_; + vad_activity_ = src.vad_activity_; + num_channels_ = src.num_channels_; + channel_layout_ = src.channel_layout_; + absolute_capture_timestamp_ms_ = src.absolute_capture_timestamp_ms(); + + const size_t length = samples_per_channel_ * num_channels_; + RTC_CHECK_LE(length, kMaxDataSizeSamples); + if (!src.muted()) { + memcpy(data_, src.data(), sizeof(int16_t) * length); + muted_ = false; + } +} + +void AudioFrame::UpdateProfileTimeStamp() { + profile_timestamp_ms_ = rtc::TimeMillis(); +} + +int64_t AudioFrame::ElapsedProfileTimeMs() const { + if (profile_timestamp_ms_ == 0) { + // Profiling has not been activated. + return -1; + } + return rtc::TimeSince(profile_timestamp_ms_); +} + +const int16_t* AudioFrame::data() const { + return muted_ ? empty_data() : data_; +} + +// TODO(henrik.lundin) Can we skip zeroing the buffer? +// See https://bugs.chromium.org/p/webrtc/issues/detail?id=5647. +int16_t* AudioFrame::mutable_data() { + if (muted_) { + memset(data_, 0, kMaxDataSizeBytes); + muted_ = false; + } + return data_; +} + +void AudioFrame::Mute() { + muted_ = true; +} + +bool AudioFrame::muted() const { + return muted_; +} + +// static +const int16_t* AudioFrame::empty_data() { + static int16_t* null_data = new int16_t[kMaxDataSizeSamples](); + return &null_data[0]; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio/audio_frame.h b/third_party/libwebrtc/api/audio/audio_frame.h new file mode 100644 index 0000000000..d5dcb5f788 --- /dev/null +++ b/third_party/libwebrtc/api/audio/audio_frame.h @@ -0,0 +1,173 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_AUDIO_FRAME_H_ +#define API_AUDIO_AUDIO_FRAME_H_ + +#include <stddef.h> +#include <stdint.h> + +#include "api/audio/channel_layout.h" +#include "api/rtp_packet_infos.h" + +namespace webrtc { + +/* This class holds up to 120 ms of super-wideband (32 kHz) stereo audio. It + * allows for adding and subtracting frames while keeping track of the resulting + * states. + * + * Notes + * - This is a de-facto api, not designed for external use. The AudioFrame class + * is in need of overhaul or even replacement, and anyone depending on it + * should be prepared for that. + * - The total number of samples is samples_per_channel_ * num_channels_. + * - Stereo data is interleaved starting with the left channel. + */ +class AudioFrame { + public: + // Using constexpr here causes linker errors unless the variable also has an + // out-of-class definition, which is impractical in this header-only class. + // (This makes no sense because it compiles as an enum value, which we most + // certainly cannot take the address of, just fine.) C++17 introduces inline + // variables which should allow us to switch to constexpr and keep this a + // header-only class. + enum : size_t { + // Stereo, 32 kHz, 120 ms (2 * 32 * 120) + // Stereo, 192 kHz, 20 ms (2 * 192 * 20) + kMaxDataSizeSamples = 7680, + kMaxDataSizeBytes = kMaxDataSizeSamples * sizeof(int16_t), + }; + + enum VADActivity { kVadActive = 0, kVadPassive = 1, kVadUnknown = 2 }; + enum SpeechType { + kNormalSpeech = 0, + kPLC = 1, + kCNG = 2, + kPLCCNG = 3, + kCodecPLC = 5, + kUndefined = 4 + }; + + AudioFrame(); + + AudioFrame(const AudioFrame&) = delete; + AudioFrame& operator=(const AudioFrame&) = delete; + + // Resets all members to their default state. + void Reset(); + // Same as Reset(), but leaves mute state unchanged. Muting a frame requires + // the buffer to be zeroed on the next call to mutable_data(). Callers + // intending to write to the buffer immediately after Reset() can instead use + // ResetWithoutMuting() to skip this wasteful zeroing. + void ResetWithoutMuting(); + + void UpdateFrame(uint32_t timestamp, + const int16_t* data, + size_t samples_per_channel, + int sample_rate_hz, + SpeechType speech_type, + VADActivity vad_activity, + size_t num_channels = 1); + + void CopyFrom(const AudioFrame& src); + + // Sets a wall-time clock timestamp in milliseconds to be used for profiling + // of time between two points in the audio chain. + // Example: + // t0: UpdateProfileTimeStamp() + // t1: ElapsedProfileTimeMs() => t1 - t0 [msec] + void UpdateProfileTimeStamp(); + // Returns the time difference between now and when UpdateProfileTimeStamp() + // was last called. Returns -1 if UpdateProfileTimeStamp() has not yet been + // called. + int64_t ElapsedProfileTimeMs() const; + + // data() returns a zeroed static buffer if the frame is muted. + // mutable_frame() always returns a non-static buffer; the first call to + // mutable_frame() zeros the non-static buffer and marks the frame unmuted. + const int16_t* data() const; + int16_t* mutable_data(); + + // Prefer to mute frames using AudioFrameOperations::Mute. + void Mute(); + // Frame is muted by default. + bool muted() const; + + size_t max_16bit_samples() const { return kMaxDataSizeSamples; } + size_t samples_per_channel() const { return samples_per_channel_; } + size_t num_channels() const { return num_channels_; } + ChannelLayout channel_layout() const { return channel_layout_; } + int sample_rate_hz() const { return sample_rate_hz_; } + + void set_absolute_capture_timestamp_ms( + int64_t absolute_capture_time_stamp_ms) { + absolute_capture_timestamp_ms_ = absolute_capture_time_stamp_ms; + } + + absl::optional<int64_t> absolute_capture_timestamp_ms() const { + return absolute_capture_timestamp_ms_; + } + + // RTP timestamp of the first sample in the AudioFrame. + uint32_t timestamp_ = 0; + // Time since the first frame in milliseconds. + // -1 represents an uninitialized value. + int64_t elapsed_time_ms_ = -1; + // NTP time of the estimated capture time in local timebase in milliseconds. + // -1 represents an uninitialized value. + int64_t ntp_time_ms_ = -1; + size_t samples_per_channel_ = 0; + int sample_rate_hz_ = 0; + size_t num_channels_ = 0; + ChannelLayout channel_layout_ = CHANNEL_LAYOUT_NONE; + SpeechType speech_type_ = kUndefined; + VADActivity vad_activity_ = kVadUnknown; + // Monotonically increasing timestamp intended for profiling of audio frames. + // Typically used for measuring elapsed time between two different points in + // the audio path. No lock is used to save resources and we are thread safe + // by design. + // TODO(nisse@webrtc.org): consider using absl::optional. + int64_t profile_timestamp_ms_ = 0; + + // Information about packets used to assemble this audio frame. This is needed + // by `SourceTracker` when the frame is delivered to the RTCRtpReceiver's + // MediaStreamTrack, in order to implement getContributingSources(). See: + // https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-getcontributingsources + // + // TODO(bugs.webrtc.org/10757): + // Note that this information might not be fully accurate since we currently + // don't have a proper way to track it across the audio sync buffer. The + // sync buffer is the small sample-holding buffer located after the audio + // decoder and before where samples are assembled into output frames. + // + // `RtpPacketInfos` may also be empty if the audio samples did not come from + // RTP packets. E.g. if the audio were locally generated by packet loss + // concealment, comfort noise generation, etc. + RtpPacketInfos packet_infos_; + + private: + // A permanently zeroed out buffer to represent muted frames. This is a + // header-only class, so the only way to avoid creating a separate empty + // buffer per translation unit is to wrap a static in an inline function. + static const int16_t* empty_data(); + + int16_t data_[kMaxDataSizeSamples]; + bool muted_ = true; + + // Absolute capture timestamp when this audio frame was originally captured. + // This is only valid for audio frames captured on this machine. The absolute + // capture timestamp of a received frame is found in `packet_infos_`. + // This timestamp MUST be based on the same clock as rtc::TimeMillis(). + absl::optional<int64_t> absolute_capture_timestamp_ms_; +}; + +} // namespace webrtc + +#endif // API_AUDIO_AUDIO_FRAME_H_ diff --git a/third_party/libwebrtc/api/audio/audio_frame_api_gn/moz.build b/third_party/libwebrtc/api/audio/audio_frame_api_gn/moz.build new file mode 100644 index 0000000000..6fac266c73 --- /dev/null +++ b/third_party/libwebrtc/api/audio/audio_frame_api_gn/moz.build @@ -0,0 +1,226 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio/audio_frame.cc", + "/third_party/libwebrtc/api/audio/channel_layout.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_frame_api_gn") diff --git a/third_party/libwebrtc/api/audio/audio_frame_processor.h b/third_party/libwebrtc/api/audio/audio_frame_processor.h new file mode 100644 index 0000000000..cb65c4817e --- /dev/null +++ b/third_party/libwebrtc/api/audio/audio_frame_processor.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020 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 API_AUDIO_AUDIO_FRAME_PROCESSOR_H_ +#define API_AUDIO_AUDIO_FRAME_PROCESSOR_H_ + +#include <functional> +#include <memory> + +namespace webrtc { + +class AudioFrame; + +// If passed into PeerConnectionFactory, will be used for additional +// processing of captured audio frames, performed before encoding. +// Implementations must be thread-safe. +class AudioFrameProcessor { + public: + using OnAudioFrameCallback = std::function<void(std::unique_ptr<AudioFrame>)>; + virtual ~AudioFrameProcessor() = default; + + // Processes the frame received from WebRTC, is called by WebRTC off the + // realtime audio capturing path. AudioFrameProcessor must reply with + // processed frames by calling `sink_callback` if it was provided in SetSink() + // call. `sink_callback` can be called in the context of Process(). + virtual void Process(std::unique_ptr<AudioFrame> frame) = 0; + + // Atomically replaces the current sink with the new one. Before the + // first call to this function, or if the provided `sink_callback` is nullptr, + // processed frames are simply discarded. + virtual void SetSink(OnAudioFrameCallback sink_callback) = 0; +}; + +} // namespace webrtc + +#endif // API_AUDIO_AUDIO_FRAME_PROCESSOR_H_ diff --git a/third_party/libwebrtc/api/audio/audio_frame_processor_gn/moz.build b/third_party/libwebrtc/api/audio/audio_frame_processor_gn/moz.build new file mode 100644 index 0000000000..1732aa7d0c --- /dev/null +++ b/third_party/libwebrtc/api/audio/audio_frame_processor_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_frame_processor_gn") diff --git a/third_party/libwebrtc/api/audio/audio_mixer.h b/third_party/libwebrtc/api/audio/audio_mixer.h new file mode 100644 index 0000000000..3483df22bc --- /dev/null +++ b/third_party/libwebrtc/api/audio/audio_mixer.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011 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 API_AUDIO_AUDIO_MIXER_H_ +#define API_AUDIO_AUDIO_MIXER_H_ + +#include <memory> + +#include "api/audio/audio_frame.h" +#include "rtc_base/ref_count.h" + +namespace webrtc { + +// WORK IN PROGRESS +// This class is under development and is not yet intended for for use outside +// of WebRtc/Libjingle. +class AudioMixer : public rtc::RefCountInterface { + public: + // A callback class that all mixer participants must inherit from/implement. + class Source { + public: + enum class AudioFrameInfo { + kNormal, // The samples in audio_frame are valid and should be used. + kMuted, // The samples in audio_frame should not be used, but + // should be implicitly interpreted as zero. Other + // fields in audio_frame may be read and should + // contain meaningful values. + kError, // The audio_frame will not be used. + }; + + // Overwrites `audio_frame`. The data_ field is overwritten with + // 10 ms of new audio (either 1 or 2 interleaved channels) at + // `sample_rate_hz`. All fields in `audio_frame` must be updated. + virtual AudioFrameInfo GetAudioFrameWithInfo(int sample_rate_hz, + AudioFrame* audio_frame) = 0; + + // A way for a mixer implementation to distinguish participants. + virtual int Ssrc() const = 0; + + // A way for this source to say that GetAudioFrameWithInfo called + // with this sample rate or higher will not cause quality loss. + virtual int PreferredSampleRate() const = 0; + + virtual ~Source() {} + }; + + // Returns true if adding was successful. A source is never added + // twice. Addition and removal can happen on different threads. + virtual bool AddSource(Source* audio_source) = 0; + + // Removal is never attempted if a source has not been successfully + // added to the mixer. + virtual void RemoveSource(Source* audio_source) = 0; + + // Performs mixing by asking registered audio sources for audio. The + // mixed result is placed in the provided AudioFrame. This method + // will only be called from a single thread. The channels argument + // specifies the number of channels of the mix result. The mixer + // should mix at a rate that doesn't cause quality loss of the + // sources' audio. The mixing rate is one of the rates listed in + // AudioProcessing::NativeRate. All fields in + // `audio_frame_for_mixing` must be updated. + virtual void Mix(size_t number_of_channels, + AudioFrame* audio_frame_for_mixing) = 0; + + protected: + // Since the mixer is reference counted, the destructor may be + // called from any thread. + ~AudioMixer() override {} +}; +} // namespace webrtc + +#endif // API_AUDIO_AUDIO_MIXER_H_ diff --git a/third_party/libwebrtc/api/audio/audio_mixer_api_gn/moz.build b/third_party/libwebrtc/api/audio/audio_mixer_api_gn/moz.build new file mode 100644 index 0000000000..4eac2aa4b4 --- /dev/null +++ b/third_party/libwebrtc/api/audio/audio_mixer_api_gn/moz.build @@ -0,0 +1,209 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_mixer_api_gn") diff --git a/third_party/libwebrtc/api/audio/channel_layout.cc b/third_party/libwebrtc/api/audio/channel_layout.cc new file mode 100644 index 0000000000..e4ae356fab --- /dev/null +++ b/third_party/libwebrtc/api/audio/channel_layout.cc @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2019 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 "api/audio/channel_layout.h" + +#include <stddef.h> + +#include "rtc_base/arraysize.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" + +namespace webrtc { + +static const int kLayoutToChannels[] = { + 0, // CHANNEL_LAYOUT_NONE + 0, // CHANNEL_LAYOUT_UNSUPPORTED + 1, // CHANNEL_LAYOUT_MONO + 2, // CHANNEL_LAYOUT_STEREO + 3, // CHANNEL_LAYOUT_2_1 + 3, // CHANNEL_LAYOUT_SURROUND + 4, // CHANNEL_LAYOUT_4_0 + 4, // CHANNEL_LAYOUT_2_2 + 4, // CHANNEL_LAYOUT_QUAD + 5, // CHANNEL_LAYOUT_5_0 + 6, // CHANNEL_LAYOUT_5_1 + 5, // CHANNEL_LAYOUT_5_0_BACK + 6, // CHANNEL_LAYOUT_5_1_BACK + 7, // CHANNEL_LAYOUT_7_0 + 8, // CHANNEL_LAYOUT_7_1 + 8, // CHANNEL_LAYOUT_7_1_WIDE + 2, // CHANNEL_LAYOUT_STEREO_DOWNMIX + 3, // CHANNEL_LAYOUT_2POINT1 + 4, // CHANNEL_LAYOUT_3_1 + 5, // CHANNEL_LAYOUT_4_1 + 6, // CHANNEL_LAYOUT_6_0 + 6, // CHANNEL_LAYOUT_6_0_FRONT + 6, // CHANNEL_LAYOUT_HEXAGONAL + 7, // CHANNEL_LAYOUT_6_1 + 7, // CHANNEL_LAYOUT_6_1_BACK + 7, // CHANNEL_LAYOUT_6_1_FRONT + 7, // CHANNEL_LAYOUT_7_0_FRONT + 8, // CHANNEL_LAYOUT_7_1_WIDE_BACK + 8, // CHANNEL_LAYOUT_OCTAGONAL + 0, // CHANNEL_LAYOUT_DISCRETE + 3, // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC + 5, // CHANNEL_LAYOUT_4_1_QUAD_SIDE + 0, // CHANNEL_LAYOUT_BITSTREAM +}; + +// The channel orderings for each layout as specified by FFmpeg. Each value +// represents the index of each channel in each layout. Values of -1 mean the +// channel at that index is not used for that layout. For example, the left side +// surround sound channel in FFmpeg's 5.1 layout is in the 5th position (because +// the order is L, R, C, LFE, LS, RS), so +// kChannelOrderings[CHANNEL_LAYOUT_5_1][SIDE_LEFT] = 4; +static const int kChannelOrderings[CHANNEL_LAYOUT_MAX + 1][CHANNELS_MAX + 1] = { + // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR + + // CHANNEL_LAYOUT_NONE + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_UNSUPPORTED + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_MONO + {-1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_STEREO + {0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_2_1 + {0, 1, -1, -1, -1, -1, -1, -1, 2, -1, -1}, + + // CHANNEL_LAYOUT_SURROUND + {0, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_4_0 + {0, 1, 2, -1, -1, -1, -1, -1, 3, -1, -1}, + + // CHANNEL_LAYOUT_2_2 + {0, 1, -1, -1, -1, -1, -1, -1, -1, 2, 3}, + + // CHANNEL_LAYOUT_QUAD + {0, 1, -1, -1, 2, 3, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_5_0 + {0, 1, 2, -1, -1, -1, -1, -1, -1, 3, 4}, + + // CHANNEL_LAYOUT_5_1 + {0, 1, 2, 3, -1, -1, -1, -1, -1, 4, 5}, + + // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR + + // CHANNEL_LAYOUT_5_0_BACK + {0, 1, 2, -1, 3, 4, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_5_1_BACK + {0, 1, 2, 3, 4, 5, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_7_0 + {0, 1, 2, -1, 5, 6, -1, -1, -1, 3, 4}, + + // CHANNEL_LAYOUT_7_1 + {0, 1, 2, 3, 6, 7, -1, -1, -1, 4, 5}, + + // CHANNEL_LAYOUT_7_1_WIDE + {0, 1, 2, 3, -1, -1, 6, 7, -1, 4, 5}, + + // CHANNEL_LAYOUT_STEREO_DOWNMIX + {0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_2POINT1 + {0, 1, -1, 2, -1, -1, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_3_1 + {0, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_4_1 + {0, 1, 2, 4, -1, -1, -1, -1, 3, -1, -1}, + + // CHANNEL_LAYOUT_6_0 + {0, 1, 2, -1, -1, -1, -1, -1, 5, 3, 4}, + + // CHANNEL_LAYOUT_6_0_FRONT + {0, 1, -1, -1, -1, -1, 4, 5, -1, 2, 3}, + + // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR + + // CHANNEL_LAYOUT_HEXAGONAL + {0, 1, 2, -1, 3, 4, -1, -1, 5, -1, -1}, + + // CHANNEL_LAYOUT_6_1 + {0, 1, 2, 3, -1, -1, -1, -1, 6, 4, 5}, + + // CHANNEL_LAYOUT_6_1_BACK + {0, 1, 2, 3, 4, 5, -1, -1, 6, -1, -1}, + + // CHANNEL_LAYOUT_6_1_FRONT + {0, 1, -1, 6, -1, -1, 4, 5, -1, 2, 3}, + + // CHANNEL_LAYOUT_7_0_FRONT + {0, 1, 2, -1, -1, -1, 5, 6, -1, 3, 4}, + + // CHANNEL_LAYOUT_7_1_WIDE_BACK + {0, 1, 2, 3, 4, 5, 6, 7, -1, -1, -1}, + + // CHANNEL_LAYOUT_OCTAGONAL + {0, 1, 2, -1, 5, 6, -1, -1, 7, 3, 4}, + + // CHANNEL_LAYOUT_DISCRETE + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC + {0, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1}, + + // CHANNEL_LAYOUT_4_1_QUAD_SIDE + {0, 1, -1, 4, -1, -1, -1, -1, -1, 2, 3}, + + // CHANNEL_LAYOUT_BITSTREAM + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + + // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR +}; + +int ChannelLayoutToChannelCount(ChannelLayout layout) { + RTC_DCHECK_LT(static_cast<size_t>(layout), arraysize(kLayoutToChannels)); + RTC_DCHECK_LE(kLayoutToChannels[layout], kMaxConcurrentChannels); + return kLayoutToChannels[layout]; +} + +// Converts a channel count into a channel layout. +ChannelLayout GuessChannelLayout(int channels) { + switch (channels) { + case 1: + return CHANNEL_LAYOUT_MONO; + case 2: + return CHANNEL_LAYOUT_STEREO; + case 3: + return CHANNEL_LAYOUT_SURROUND; + case 4: + return CHANNEL_LAYOUT_QUAD; + case 5: + return CHANNEL_LAYOUT_5_0; + case 6: + return CHANNEL_LAYOUT_5_1; + case 7: + return CHANNEL_LAYOUT_6_1; + case 8: + return CHANNEL_LAYOUT_7_1; + default: + RTC_DLOG(LS_WARNING) << "Unsupported channel count: " << channels; + } + return CHANNEL_LAYOUT_UNSUPPORTED; +} + +int ChannelOrder(ChannelLayout layout, Channels channel) { + RTC_DCHECK_LT(static_cast<size_t>(layout), arraysize(kChannelOrderings)); + RTC_DCHECK_LT(static_cast<size_t>(channel), arraysize(kChannelOrderings[0])); + return kChannelOrderings[layout][channel]; +} + +const char* ChannelLayoutToString(ChannelLayout layout) { + switch (layout) { + case CHANNEL_LAYOUT_NONE: + return "NONE"; + case CHANNEL_LAYOUT_UNSUPPORTED: + return "UNSUPPORTED"; + case CHANNEL_LAYOUT_MONO: + return "MONO"; + case CHANNEL_LAYOUT_STEREO: + return "STEREO"; + case CHANNEL_LAYOUT_2_1: + return "2.1"; + case CHANNEL_LAYOUT_SURROUND: + return "SURROUND"; + case CHANNEL_LAYOUT_4_0: + return "4.0"; + case CHANNEL_LAYOUT_2_2: + return "QUAD_SIDE"; + case CHANNEL_LAYOUT_QUAD: + return "QUAD"; + case CHANNEL_LAYOUT_5_0: + return "5.0"; + case CHANNEL_LAYOUT_5_1: + return "5.1"; + case CHANNEL_LAYOUT_5_0_BACK: + return "5.0_BACK"; + case CHANNEL_LAYOUT_5_1_BACK: + return "5.1_BACK"; + case CHANNEL_LAYOUT_7_0: + return "7.0"; + case CHANNEL_LAYOUT_7_1: + return "7.1"; + case CHANNEL_LAYOUT_7_1_WIDE: + return "7.1_WIDE"; + case CHANNEL_LAYOUT_STEREO_DOWNMIX: + return "STEREO_DOWNMIX"; + case CHANNEL_LAYOUT_2POINT1: + return "2POINT1"; + case CHANNEL_LAYOUT_3_1: + return "3.1"; + case CHANNEL_LAYOUT_4_1: + return "4.1"; + case CHANNEL_LAYOUT_6_0: + return "6.0"; + case CHANNEL_LAYOUT_6_0_FRONT: + return "6.0_FRONT"; + case CHANNEL_LAYOUT_HEXAGONAL: + return "HEXAGONAL"; + case CHANNEL_LAYOUT_6_1: + return "6.1"; + case CHANNEL_LAYOUT_6_1_BACK: + return "6.1_BACK"; + case CHANNEL_LAYOUT_6_1_FRONT: + return "6.1_FRONT"; + case CHANNEL_LAYOUT_7_0_FRONT: + return "7.0_FRONT"; + case CHANNEL_LAYOUT_7_1_WIDE_BACK: + return "7.1_WIDE_BACK"; + case CHANNEL_LAYOUT_OCTAGONAL: + return "OCTAGONAL"; + case CHANNEL_LAYOUT_DISCRETE: + return "DISCRETE"; + case CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC: + return "STEREO_AND_KEYBOARD_MIC"; + case CHANNEL_LAYOUT_4_1_QUAD_SIDE: + return "4.1_QUAD_SIDE"; + case CHANNEL_LAYOUT_BITSTREAM: + return "BITSTREAM"; + } + RTC_DCHECK_NOTREACHED() << "Invalid channel layout provided: " << layout; + return ""; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio/channel_layout.h b/third_party/libwebrtc/api/audio/channel_layout.h new file mode 100644 index 0000000000..175aee71e5 --- /dev/null +++ b/third_party/libwebrtc/api/audio/channel_layout.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2019 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 API_AUDIO_CHANNEL_LAYOUT_H_ +#define API_AUDIO_CHANNEL_LAYOUT_H_ + +namespace webrtc { + +// This file is derived from Chromium's base/channel_layout.h. + +// Enumerates the various representations of the ordering of audio channels. +// Logged to UMA, so never reuse a value, always add new/greater ones! +enum ChannelLayout { + CHANNEL_LAYOUT_NONE = 0, + CHANNEL_LAYOUT_UNSUPPORTED = 1, + + // Front C + CHANNEL_LAYOUT_MONO = 2, + + // Front L, Front R + CHANNEL_LAYOUT_STEREO = 3, + + // Front L, Front R, Back C + CHANNEL_LAYOUT_2_1 = 4, + + // Front L, Front R, Front C + CHANNEL_LAYOUT_SURROUND = 5, + + // Front L, Front R, Front C, Back C + CHANNEL_LAYOUT_4_0 = 6, + + // Front L, Front R, Side L, Side R + CHANNEL_LAYOUT_2_2 = 7, + + // Front L, Front R, Back L, Back R + CHANNEL_LAYOUT_QUAD = 8, + + // Front L, Front R, Front C, Side L, Side R + CHANNEL_LAYOUT_5_0 = 9, + + // Front L, Front R, Front C, LFE, Side L, Side R + CHANNEL_LAYOUT_5_1 = 10, + + // Front L, Front R, Front C, Back L, Back R + CHANNEL_LAYOUT_5_0_BACK = 11, + + // Front L, Front R, Front C, LFE, Back L, Back R + CHANNEL_LAYOUT_5_1_BACK = 12, + + // Front L, Front R, Front C, Side L, Side R, Back L, Back R + CHANNEL_LAYOUT_7_0 = 13, + + // Front L, Front R, Front C, LFE, Side L, Side R, Back L, Back R + CHANNEL_LAYOUT_7_1 = 14, + + // Front L, Front R, Front C, LFE, Side L, Side R, Front LofC, Front RofC + CHANNEL_LAYOUT_7_1_WIDE = 15, + + // Stereo L, Stereo R + CHANNEL_LAYOUT_STEREO_DOWNMIX = 16, + + // Stereo L, Stereo R, LFE + CHANNEL_LAYOUT_2POINT1 = 17, + + // Stereo L, Stereo R, Front C, LFE + CHANNEL_LAYOUT_3_1 = 18, + + // Stereo L, Stereo R, Front C, Rear C, LFE + CHANNEL_LAYOUT_4_1 = 19, + + // Stereo L, Stereo R, Front C, Side L, Side R, Back C + CHANNEL_LAYOUT_6_0 = 20, + + // Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC + CHANNEL_LAYOUT_6_0_FRONT = 21, + + // Stereo L, Stereo R, Front C, Rear L, Rear R, Rear C + CHANNEL_LAYOUT_HEXAGONAL = 22, + + // Stereo L, Stereo R, Front C, LFE, Side L, Side R, Rear Center + CHANNEL_LAYOUT_6_1 = 23, + + // Stereo L, Stereo R, Front C, LFE, Back L, Back R, Rear Center + CHANNEL_LAYOUT_6_1_BACK = 24, + + // Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC, LFE + CHANNEL_LAYOUT_6_1_FRONT = 25, + + // Front L, Front R, Front C, Side L, Side R, Front LofC, Front RofC + CHANNEL_LAYOUT_7_0_FRONT = 26, + + // Front L, Front R, Front C, LFE, Back L, Back R, Front LofC, Front RofC + CHANNEL_LAYOUT_7_1_WIDE_BACK = 27, + + // Front L, Front R, Front C, Side L, Side R, Rear L, Back R, Back C. + CHANNEL_LAYOUT_OCTAGONAL = 28, + + // Channels are not explicitly mapped to speakers. + CHANNEL_LAYOUT_DISCRETE = 29, + + // Front L, Front R, Front C. Front C contains the keyboard mic audio. This + // layout is only intended for input for WebRTC. The Front C channel + // is stripped away in the WebRTC audio input pipeline and never seen outside + // of that. + CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC = 30, + + // Front L, Front R, Side L, Side R, LFE + CHANNEL_LAYOUT_4_1_QUAD_SIDE = 31, + + // Actual channel layout is specified in the bitstream and the actual channel + // count is unknown at Chromium media pipeline level (useful for audio + // pass-through mode). + CHANNEL_LAYOUT_BITSTREAM = 32, + + // Max value, must always equal the largest entry ever logged. + CHANNEL_LAYOUT_MAX = CHANNEL_LAYOUT_BITSTREAM +}; + +// Note: Do not reorder or reassign these values; other code depends on their +// ordering to operate correctly. E.g., CoreAudio channel layout computations. +enum Channels { + LEFT = 0, + RIGHT, + CENTER, + LFE, + BACK_LEFT, + BACK_RIGHT, + LEFT_OF_CENTER, + RIGHT_OF_CENTER, + BACK_CENTER, + SIDE_LEFT, + SIDE_RIGHT, + CHANNELS_MAX = + SIDE_RIGHT, // Must always equal the largest value ever logged. +}; + +// The maximum number of concurrently active channels for all possible layouts. +// ChannelLayoutToChannelCount() will never return a value higher than this. +constexpr int kMaxConcurrentChannels = 8; + +// Returns the expected channel position in an interleaved stream. Values of -1 +// mean the channel at that index is not used for that layout. Values range +// from 0 to ChannelLayoutToChannelCount(layout) - 1. +int ChannelOrder(ChannelLayout layout, Channels channel); + +// Returns the number of channels in a given ChannelLayout. +int ChannelLayoutToChannelCount(ChannelLayout layout); + +// Given the number of channels, return the best layout, +// or return CHANNEL_LAYOUT_UNSUPPORTED if there is no good match. +ChannelLayout GuessChannelLayout(int channels); + +// Returns a string representation of the channel layout. +const char* ChannelLayoutToString(ChannelLayout layout); + +} // namespace webrtc + +#endif // API_AUDIO_CHANNEL_LAYOUT_H_ diff --git a/third_party/libwebrtc/api/audio/echo_canceller3_config.cc b/third_party/libwebrtc/api/audio/echo_canceller3_config.cc new file mode 100644 index 0000000000..0224c712b4 --- /dev/null +++ b/third_party/libwebrtc/api/audio/echo_canceller3_config.cc @@ -0,0 +1,278 @@ +/* + * 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 "api/audio/echo_canceller3_config.h" + +#include <algorithm> +#include <cmath> + +#include "rtc_base/checks.h" +#include "rtc_base/numerics/safe_minmax.h" + +namespace webrtc { +namespace { +bool Limit(float* value, float min, float max) { + float clamped = rtc::SafeClamp(*value, min, max); + clamped = std::isfinite(clamped) ? clamped : min; + bool res = *value == clamped; + *value = clamped; + return res; +} + +bool Limit(size_t* value, size_t min, size_t max) { + size_t clamped = rtc::SafeClamp(*value, min, max); + bool res = *value == clamped; + *value = clamped; + return res; +} + +bool Limit(int* value, int min, int max) { + int clamped = rtc::SafeClamp(*value, min, max); + bool res = *value == clamped; + *value = clamped; + return res; +} + +bool FloorLimit(size_t* value, size_t min) { + size_t clamped = *value >= min ? *value : min; + bool res = *value == clamped; + *value = clamped; + return res; +} + +} // namespace + +EchoCanceller3Config::EchoCanceller3Config() = default; +EchoCanceller3Config::EchoCanceller3Config(const EchoCanceller3Config& e) = + default; +EchoCanceller3Config& EchoCanceller3Config::operator=( + const EchoCanceller3Config& e) = default; +EchoCanceller3Config::Delay::Delay() = default; +EchoCanceller3Config::Delay::Delay(const EchoCanceller3Config::Delay& e) = + default; +EchoCanceller3Config::Delay& EchoCanceller3Config::Delay::operator=( + const Delay& e) = default; + +EchoCanceller3Config::EchoModel::EchoModel() = default; +EchoCanceller3Config::EchoModel::EchoModel( + const EchoCanceller3Config::EchoModel& e) = default; +EchoCanceller3Config::EchoModel& EchoCanceller3Config::EchoModel::operator=( + const EchoModel& e) = default; + +EchoCanceller3Config::Suppressor::Suppressor() = default; +EchoCanceller3Config::Suppressor::Suppressor( + const EchoCanceller3Config::Suppressor& e) = default; +EchoCanceller3Config::Suppressor& EchoCanceller3Config::Suppressor::operator=( + const Suppressor& e) = default; + +EchoCanceller3Config::Suppressor::MaskingThresholds::MaskingThresholds( + float enr_transparent, + float enr_suppress, + float emr_transparent) + : enr_transparent(enr_transparent), + enr_suppress(enr_suppress), + emr_transparent(emr_transparent) {} +EchoCanceller3Config::Suppressor::MaskingThresholds::MaskingThresholds( + const EchoCanceller3Config::Suppressor::MaskingThresholds& e) = default; +EchoCanceller3Config::Suppressor::MaskingThresholds& +EchoCanceller3Config::Suppressor::MaskingThresholds::operator=( + const MaskingThresholds& e) = default; + +EchoCanceller3Config::Suppressor::Tuning::Tuning(MaskingThresholds mask_lf, + MaskingThresholds mask_hf, + float max_inc_factor, + float max_dec_factor_lf) + : mask_lf(mask_lf), + mask_hf(mask_hf), + max_inc_factor(max_inc_factor), + max_dec_factor_lf(max_dec_factor_lf) {} +EchoCanceller3Config::Suppressor::Tuning::Tuning( + const EchoCanceller3Config::Suppressor::Tuning& e) = default; +EchoCanceller3Config::Suppressor::Tuning& +EchoCanceller3Config::Suppressor::Tuning::operator=(const Tuning& e) = default; + +bool EchoCanceller3Config::Validate(EchoCanceller3Config* config) { + RTC_DCHECK(config); + EchoCanceller3Config* c = config; + bool res = true; + + if (c->delay.down_sampling_factor != 4 && + c->delay.down_sampling_factor != 8) { + c->delay.down_sampling_factor = 4; + res = false; + } + + res = res & Limit(&c->delay.default_delay, 0, 5000); + res = res & Limit(&c->delay.num_filters, 0, 5000); + res = res & Limit(&c->delay.delay_headroom_samples, 0, 5000); + res = res & Limit(&c->delay.hysteresis_limit_blocks, 0, 5000); + res = res & Limit(&c->delay.fixed_capture_delay_samples, 0, 5000); + res = res & Limit(&c->delay.delay_estimate_smoothing, 0.f, 1.f); + res = res & Limit(&c->delay.delay_candidate_detection_threshold, 0.f, 1.f); + res = res & Limit(&c->delay.delay_selection_thresholds.initial, 1, 250); + res = res & Limit(&c->delay.delay_selection_thresholds.converged, 1, 250); + + res = res & FloorLimit(&c->filter.refined.length_blocks, 1); + res = res & Limit(&c->filter.refined.leakage_converged, 0.f, 1000.f); + res = res & Limit(&c->filter.refined.leakage_diverged, 0.f, 1000.f); + res = res & Limit(&c->filter.refined.error_floor, 0.f, 1000.f); + res = res & Limit(&c->filter.refined.error_ceil, 0.f, 100000000.f); + res = res & Limit(&c->filter.refined.noise_gate, 0.f, 100000000.f); + + res = res & FloorLimit(&c->filter.refined_initial.length_blocks, 1); + res = res & Limit(&c->filter.refined_initial.leakage_converged, 0.f, 1000.f); + res = res & Limit(&c->filter.refined_initial.leakage_diverged, 0.f, 1000.f); + res = res & Limit(&c->filter.refined_initial.error_floor, 0.f, 1000.f); + res = res & Limit(&c->filter.refined_initial.error_ceil, 0.f, 100000000.f); + res = res & Limit(&c->filter.refined_initial.noise_gate, 0.f, 100000000.f); + + if (c->filter.refined.length_blocks < + c->filter.refined_initial.length_blocks) { + c->filter.refined_initial.length_blocks = c->filter.refined.length_blocks; + res = false; + } + + res = res & FloorLimit(&c->filter.coarse.length_blocks, 1); + res = res & Limit(&c->filter.coarse.rate, 0.f, 1.f); + res = res & Limit(&c->filter.coarse.noise_gate, 0.f, 100000000.f); + + res = res & FloorLimit(&c->filter.coarse_initial.length_blocks, 1); + res = res & Limit(&c->filter.coarse_initial.rate, 0.f, 1.f); + res = res & Limit(&c->filter.coarse_initial.noise_gate, 0.f, 100000000.f); + + if (c->filter.coarse.length_blocks < c->filter.coarse_initial.length_blocks) { + c->filter.coarse_initial.length_blocks = c->filter.coarse.length_blocks; + res = false; + } + + res = res & Limit(&c->filter.config_change_duration_blocks, 0, 100000); + res = res & Limit(&c->filter.initial_state_seconds, 0.f, 100.f); + res = res & Limit(&c->filter.coarse_reset_hangover_blocks, 0, 250000); + + res = res & Limit(&c->erle.min, 1.f, 100000.f); + res = res & Limit(&c->erle.max_l, 1.f, 100000.f); + res = res & Limit(&c->erle.max_h, 1.f, 100000.f); + if (c->erle.min > c->erle.max_l || c->erle.min > c->erle.max_h) { + c->erle.min = std::min(c->erle.max_l, c->erle.max_h); + res = false; + } + res = res & Limit(&c->erle.num_sections, 1, c->filter.refined.length_blocks); + + res = res & Limit(&c->ep_strength.default_gain, 0.f, 1000000.f); + res = res & Limit(&c->ep_strength.default_len, -1.f, 1.f); + res = res & Limit(&c->ep_strength.nearend_len, -1.0f, 1.0f); + + res = + res & Limit(&c->echo_audibility.low_render_limit, 0.f, 32768.f * 32768.f); + res = res & + Limit(&c->echo_audibility.normal_render_limit, 0.f, 32768.f * 32768.f); + res = res & Limit(&c->echo_audibility.floor_power, 0.f, 32768.f * 32768.f); + res = res & Limit(&c->echo_audibility.audibility_threshold_lf, 0.f, + 32768.f * 32768.f); + res = res & Limit(&c->echo_audibility.audibility_threshold_mf, 0.f, + 32768.f * 32768.f); + res = res & Limit(&c->echo_audibility.audibility_threshold_hf, 0.f, + 32768.f * 32768.f); + + res = res & + Limit(&c->render_levels.active_render_limit, 0.f, 32768.f * 32768.f); + res = res & Limit(&c->render_levels.poor_excitation_render_limit, 0.f, + 32768.f * 32768.f); + res = res & Limit(&c->render_levels.poor_excitation_render_limit_ds8, 0.f, + 32768.f * 32768.f); + + res = res & Limit(&c->echo_model.noise_floor_hold, 0, 1000); + res = res & Limit(&c->echo_model.min_noise_floor_power, 0, 2000000.f); + res = res & Limit(&c->echo_model.stationary_gate_slope, 0, 1000000.f); + res = res & Limit(&c->echo_model.noise_gate_power, 0, 1000000.f); + res = res & Limit(&c->echo_model.noise_gate_slope, 0, 1000000.f); + res = res & Limit(&c->echo_model.render_pre_window_size, 0, 100); + res = res & Limit(&c->echo_model.render_post_window_size, 0, 100); + + res = res & Limit(&c->comfort_noise.noise_floor_dbfs, -200.f, 0.f); + + res = res & Limit(&c->suppressor.nearend_average_blocks, 1, 5000); + + res = res & + Limit(&c->suppressor.normal_tuning.mask_lf.enr_transparent, 0.f, 100.f); + res = res & + Limit(&c->suppressor.normal_tuning.mask_lf.enr_suppress, 0.f, 100.f); + res = res & + Limit(&c->suppressor.normal_tuning.mask_lf.emr_transparent, 0.f, 100.f); + res = res & + Limit(&c->suppressor.normal_tuning.mask_hf.enr_transparent, 0.f, 100.f); + res = res & + Limit(&c->suppressor.normal_tuning.mask_hf.enr_suppress, 0.f, 100.f); + res = res & + Limit(&c->suppressor.normal_tuning.mask_hf.emr_transparent, 0.f, 100.f); + res = res & Limit(&c->suppressor.normal_tuning.max_inc_factor, 0.f, 100.f); + res = res & Limit(&c->suppressor.normal_tuning.max_dec_factor_lf, 0.f, 100.f); + + res = res & Limit(&c->suppressor.nearend_tuning.mask_lf.enr_transparent, 0.f, + 100.f); + res = res & + Limit(&c->suppressor.nearend_tuning.mask_lf.enr_suppress, 0.f, 100.f); + res = res & Limit(&c->suppressor.nearend_tuning.mask_lf.emr_transparent, 0.f, + 100.f); + res = res & Limit(&c->suppressor.nearend_tuning.mask_hf.enr_transparent, 0.f, + 100.f); + res = res & + Limit(&c->suppressor.nearend_tuning.mask_hf.enr_suppress, 0.f, 100.f); + res = res & Limit(&c->suppressor.nearend_tuning.mask_hf.emr_transparent, 0.f, + 100.f); + res = res & Limit(&c->suppressor.nearend_tuning.max_inc_factor, 0.f, 100.f); + res = + res & Limit(&c->suppressor.nearend_tuning.max_dec_factor_lf, 0.f, 100.f); + + res = res & Limit(&c->suppressor.last_permanent_lf_smoothing_band, 0, 64); + res = res & Limit(&c->suppressor.last_lf_smoothing_band, 0, 64); + res = res & Limit(&c->suppressor.last_lf_band, 0, 63); + res = res & + Limit(&c->suppressor.first_hf_band, c->suppressor.last_lf_band + 1, 64); + + res = res & Limit(&c->suppressor.dominant_nearend_detection.enr_threshold, + 0.f, 1000000.f); + res = res & Limit(&c->suppressor.dominant_nearend_detection.snr_threshold, + 0.f, 1000000.f); + res = res & Limit(&c->suppressor.dominant_nearend_detection.hold_duration, 0, + 10000); + res = res & Limit(&c->suppressor.dominant_nearend_detection.trigger_threshold, + 0, 10000); + + res = res & + Limit(&c->suppressor.subband_nearend_detection.nearend_average_blocks, + 1, 1024); + res = + res & Limit(&c->suppressor.subband_nearend_detection.subband1.low, 0, 65); + res = res & Limit(&c->suppressor.subband_nearend_detection.subband1.high, + c->suppressor.subband_nearend_detection.subband1.low, 65); + res = + res & Limit(&c->suppressor.subband_nearend_detection.subband2.low, 0, 65); + res = res & Limit(&c->suppressor.subband_nearend_detection.subband2.high, + c->suppressor.subband_nearend_detection.subband2.low, 65); + res = res & Limit(&c->suppressor.subband_nearend_detection.nearend_threshold, + 0.f, 1.e24f); + res = res & Limit(&c->suppressor.subband_nearend_detection.snr_threshold, 0.f, + 1.e24f); + + res = res & Limit(&c->suppressor.high_bands_suppression.enr_threshold, 0.f, + 1000000.f); + res = res & Limit(&c->suppressor.high_bands_suppression.max_gain_during_echo, + 0.f, 1.f); + res = res & Limit(&c->suppressor.high_bands_suppression + .anti_howling_activation_threshold, + 0.f, 32768.f * 32768.f); + res = res & Limit(&c->suppressor.high_bands_suppression.anti_howling_gain, + 0.f, 1.f); + + res = res & Limit(&c->suppressor.floor_first_increase, 0.f, 1000000.f); + + return res; +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio/echo_canceller3_config.h b/third_party/libwebrtc/api/audio/echo_canceller3_config.h new file mode 100644 index 0000000000..4b1c7fbc47 --- /dev/null +++ b/third_party/libwebrtc/api/audio/echo_canceller3_config.h @@ -0,0 +1,250 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_ECHO_CANCELLER3_CONFIG_H_ +#define API_AUDIO_ECHO_CANCELLER3_CONFIG_H_ + +#include <stddef.h> // size_t + +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Configuration struct for EchoCanceller3 +struct RTC_EXPORT EchoCanceller3Config { + // Checks and updates the config parameters to lie within (mostly) reasonable + // ranges. Returns true if and only of the config did not need to be changed. + static bool Validate(EchoCanceller3Config* config); + + EchoCanceller3Config(); + EchoCanceller3Config(const EchoCanceller3Config& e); + EchoCanceller3Config& operator=(const EchoCanceller3Config& other); + + struct Buffering { + size_t excess_render_detection_interval_blocks = 250; + size_t max_allowed_excess_render_blocks = 8; + } buffering; + + struct Delay { + Delay(); + Delay(const Delay& e); + Delay& operator=(const Delay& e); + size_t default_delay = 5; + size_t down_sampling_factor = 4; + size_t num_filters = 5; + size_t delay_headroom_samples = 32; + size_t hysteresis_limit_blocks = 1; + size_t fixed_capture_delay_samples = 0; + float delay_estimate_smoothing = 0.7f; + float delay_estimate_smoothing_delay_found = 0.7f; + float delay_candidate_detection_threshold = 0.2f; + struct DelaySelectionThresholds { + int initial; + int converged; + } delay_selection_thresholds = {5, 20}; + bool use_external_delay_estimator = false; + bool log_warning_on_delay_changes = false; + struct AlignmentMixing { + bool downmix; + bool adaptive_selection; + float activity_power_threshold; + bool prefer_first_two_channels; + }; + AlignmentMixing render_alignment_mixing = {false, true, 10000.f, true}; + AlignmentMixing capture_alignment_mixing = {false, true, 10000.f, false}; + bool detect_pre_echo = true; + } delay; + + struct Filter { + struct RefinedConfiguration { + size_t length_blocks; + float leakage_converged; + float leakage_diverged; + float error_floor; + float error_ceil; + float noise_gate; + }; + + struct CoarseConfiguration { + size_t length_blocks; + float rate; + float noise_gate; + }; + + RefinedConfiguration refined = {13, 0.00005f, 0.05f, + 0.001f, 2.f, 20075344.f}; + CoarseConfiguration coarse = {13, 0.7f, 20075344.f}; + + RefinedConfiguration refined_initial = {12, 0.005f, 0.5f, + 0.001f, 2.f, 20075344.f}; + CoarseConfiguration coarse_initial = {12, 0.9f, 20075344.f}; + + size_t config_change_duration_blocks = 250; + float initial_state_seconds = 2.5f; + int coarse_reset_hangover_blocks = 25; + bool conservative_initial_phase = false; + bool enable_coarse_filter_output_usage = true; + bool use_linear_filter = true; + bool high_pass_filter_echo_reference = false; + bool export_linear_aec_output = false; + } filter; + + struct Erle { + float min = 1.f; + float max_l = 4.f; + float max_h = 1.5f; + bool onset_detection = true; + size_t num_sections = 1; + bool clamp_quality_estimate_to_zero = true; + bool clamp_quality_estimate_to_one = true; + } erle; + + struct EpStrength { + float default_gain = 1.f; + float default_len = 0.83f; + float nearend_len = 0.83f; + bool echo_can_saturate = true; + bool bounded_erl = false; + bool erle_onset_compensation_in_dominant_nearend = false; + bool use_conservative_tail_frequency_response = true; + } ep_strength; + + struct EchoAudibility { + float low_render_limit = 4 * 64.f; + float normal_render_limit = 64.f; + float floor_power = 2 * 64.f; + float audibility_threshold_lf = 10; + float audibility_threshold_mf = 10; + float audibility_threshold_hf = 10; + bool use_stationarity_properties = false; + bool use_stationarity_properties_at_init = false; + } echo_audibility; + + struct RenderLevels { + float active_render_limit = 100.f; + float poor_excitation_render_limit = 150.f; + float poor_excitation_render_limit_ds8 = 20.f; + float render_power_gain_db = 0.f; + } render_levels; + + struct EchoRemovalControl { + bool has_clock_drift = false; + bool linear_and_stable_echo_path = false; + } echo_removal_control; + + struct EchoModel { + EchoModel(); + EchoModel(const EchoModel& e); + EchoModel& operator=(const EchoModel& e); + size_t noise_floor_hold = 50; + float min_noise_floor_power = 1638400.f; + float stationary_gate_slope = 10.f; + float noise_gate_power = 27509.42f; + float noise_gate_slope = 0.3f; + size_t render_pre_window_size = 1; + size_t render_post_window_size = 1; + bool model_reverb_in_nonlinear_mode = true; + } echo_model; + + struct ComfortNoise { + float noise_floor_dbfs = -96.03406f; + } comfort_noise; + + struct Suppressor { + Suppressor(); + Suppressor(const Suppressor& e); + Suppressor& operator=(const Suppressor& e); + + size_t nearend_average_blocks = 4; + + struct MaskingThresholds { + MaskingThresholds(float enr_transparent, + float enr_suppress, + float emr_transparent); + MaskingThresholds(const MaskingThresholds& e); + MaskingThresholds& operator=(const MaskingThresholds& e); + float enr_transparent; + float enr_suppress; + float emr_transparent; + }; + + struct Tuning { + Tuning(MaskingThresholds mask_lf, + MaskingThresholds mask_hf, + float max_inc_factor, + float max_dec_factor_lf); + Tuning(const Tuning& e); + Tuning& operator=(const Tuning& e); + MaskingThresholds mask_lf; + MaskingThresholds mask_hf; + float max_inc_factor; + float max_dec_factor_lf; + }; + + Tuning normal_tuning = Tuning(MaskingThresholds(.3f, .4f, .3f), + MaskingThresholds(.07f, .1f, .3f), + 2.0f, + 0.25f); + Tuning nearend_tuning = Tuning(MaskingThresholds(1.09f, 1.1f, .3f), + MaskingThresholds(.1f, .3f, .3f), + 2.0f, + 0.25f); + + bool lf_smoothing_during_initial_phase = true; + int last_permanent_lf_smoothing_band = 0; + int last_lf_smoothing_band = 5; + int last_lf_band = 5; + int first_hf_band = 8; + + struct DominantNearendDetection { + float enr_threshold = .25f; + float enr_exit_threshold = 10.f; + float snr_threshold = 30.f; + int hold_duration = 50; + int trigger_threshold = 12; + bool use_during_initial_phase = true; + bool use_unbounded_echo_spectrum = true; + } dominant_nearend_detection; + + struct SubbandNearendDetection { + size_t nearend_average_blocks = 1; + struct SubbandRegion { + size_t low; + size_t high; + }; + SubbandRegion subband1 = {1, 1}; + SubbandRegion subband2 = {1, 1}; + float nearend_threshold = 1.f; + float snr_threshold = 1.f; + } subband_nearend_detection; + + bool use_subband_nearend_detection = false; + + struct HighBandsSuppression { + float enr_threshold = 1.f; + float max_gain_during_echo = 1.f; + float anti_howling_activation_threshold = 400.f; + float anti_howling_gain = 1.f; + } high_bands_suppression; + + float floor_first_increase = 0.00001f; + bool conservative_hf_suppression = false; + } suppressor; + + struct MultiChannel { + bool detect_stereo_content = true; + float stereo_detection_threshold = 0.0f; + int stereo_detection_timeout_threshold_seconds = 300; + float stereo_detection_hysteresis_seconds = 2.0f; + } multi_channel; +}; +} // namespace webrtc + +#endif // API_AUDIO_ECHO_CANCELLER3_CONFIG_H_ diff --git a/third_party/libwebrtc/api/audio/echo_canceller3_config_json.cc b/third_party/libwebrtc/api/audio/echo_canceller3_config_json.cc new file mode 100644 index 0000000000..96e45ffe6d --- /dev/null +++ b/third_party/libwebrtc/api/audio/echo_canceller3_config_json.cc @@ -0,0 +1,772 @@ +/* + * 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 "api/audio/echo_canceller3_config_json.h" + +#include <stddef.h> + +#include <memory> +#include <string> +#include <vector> + +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" +#include "rtc_base/strings/json.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { +namespace { +void ReadParam(const Json::Value& root, std::string param_name, bool* param) { + RTC_DCHECK(param); + bool v; + if (rtc::GetBoolFromJsonObject(root, param_name, &v)) { + *param = v; + } +} + +void ReadParam(const Json::Value& root, std::string param_name, size_t* param) { + RTC_DCHECK(param); + int v; + if (rtc::GetIntFromJsonObject(root, param_name, &v) && v >= 0) { + *param = v; + } +} + +void ReadParam(const Json::Value& root, std::string param_name, int* param) { + RTC_DCHECK(param); + int v; + if (rtc::GetIntFromJsonObject(root, param_name, &v)) { + *param = v; + } +} + +void ReadParam(const Json::Value& root, std::string param_name, float* param) { + RTC_DCHECK(param); + double v; + if (rtc::GetDoubleFromJsonObject(root, param_name, &v)) { + *param = static_cast<float>(v); + } +} + +void ReadParam(const Json::Value& root, + std::string param_name, + EchoCanceller3Config::Filter::RefinedConfiguration* param) { + RTC_DCHECK(param); + Json::Value json_array; + if (rtc::GetValueFromJsonObject(root, param_name, &json_array)) { + std::vector<double> v; + rtc::JsonArrayToDoubleVector(json_array, &v); + if (v.size() != 6) { + RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name; + return; + } + param->length_blocks = static_cast<size_t>(v[0]); + param->leakage_converged = static_cast<float>(v[1]); + param->leakage_diverged = static_cast<float>(v[2]); + param->error_floor = static_cast<float>(v[3]); + param->error_ceil = static_cast<float>(v[4]); + param->noise_gate = static_cast<float>(v[5]); + } +} + +void ReadParam(const Json::Value& root, + std::string param_name, + EchoCanceller3Config::Filter::CoarseConfiguration* param) { + RTC_DCHECK(param); + Json::Value json_array; + if (rtc::GetValueFromJsonObject(root, param_name, &json_array)) { + std::vector<double> v; + rtc::JsonArrayToDoubleVector(json_array, &v); + if (v.size() != 3) { + RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name; + return; + } + param->length_blocks = static_cast<size_t>(v[0]); + param->rate = static_cast<float>(v[1]); + param->noise_gate = static_cast<float>(v[2]); + } +} + +void ReadParam(const Json::Value& root, + std::string param_name, + EchoCanceller3Config::Delay::AlignmentMixing* param) { + RTC_DCHECK(param); + + Json::Value subsection; + if (rtc::GetValueFromJsonObject(root, param_name, &subsection)) { + ReadParam(subsection, "downmix", ¶m->downmix); + ReadParam(subsection, "adaptive_selection", ¶m->adaptive_selection); + ReadParam(subsection, "activity_power_threshold", + ¶m->activity_power_threshold); + ReadParam(subsection, "prefer_first_two_channels", + ¶m->prefer_first_two_channels); + } +} + +void ReadParam( + const Json::Value& root, + std::string param_name, + EchoCanceller3Config::Suppressor::SubbandNearendDetection::SubbandRegion* + param) { + RTC_DCHECK(param); + Json::Value json_array; + if (rtc::GetValueFromJsonObject(root, param_name, &json_array)) { + std::vector<int> v; + rtc::JsonArrayToIntVector(json_array, &v); + if (v.size() != 2) { + RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name; + return; + } + param->low = static_cast<size_t>(v[0]); + param->high = static_cast<size_t>(v[1]); + } +} + +void ReadParam(const Json::Value& root, + std::string param_name, + EchoCanceller3Config::Suppressor::MaskingThresholds* param) { + RTC_DCHECK(param); + Json::Value json_array; + if (rtc::GetValueFromJsonObject(root, param_name, &json_array)) { + std::vector<double> v; + rtc::JsonArrayToDoubleVector(json_array, &v); + if (v.size() != 3) { + RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name; + return; + } + param->enr_transparent = static_cast<float>(v[0]); + param->enr_suppress = static_cast<float>(v[1]); + param->emr_transparent = static_cast<float>(v[2]); + } +} +} // namespace + +void Aec3ConfigFromJsonString(absl::string_view json_string, + EchoCanceller3Config* config, + bool* parsing_successful) { + RTC_DCHECK(config); + RTC_DCHECK(parsing_successful); + EchoCanceller3Config& cfg = *config; + cfg = EchoCanceller3Config(); + *parsing_successful = true; + + Json::Value root; + Json::CharReaderBuilder builder; + std::string error_message; + std::unique_ptr<Json::CharReader> reader(builder.newCharReader()); + bool success = + reader->parse(json_string.data(), json_string.data() + json_string.size(), + &root, &error_message); + if (!success) { + RTC_LOG(LS_ERROR) << "Incorrect JSON format: " << error_message; + *parsing_successful = false; + return; + } + + Json::Value aec3_root; + success = rtc::GetValueFromJsonObject(root, "aec3", &aec3_root); + if (!success) { + RTC_LOG(LS_ERROR) << "Missing AEC3 config field: " << json_string; + *parsing_successful = false; + return; + } + + Json::Value section; + if (rtc::GetValueFromJsonObject(aec3_root, "buffering", §ion)) { + ReadParam(section, "excess_render_detection_interval_blocks", + &cfg.buffering.excess_render_detection_interval_blocks); + ReadParam(section, "max_allowed_excess_render_blocks", + &cfg.buffering.max_allowed_excess_render_blocks); + } + + if (rtc::GetValueFromJsonObject(aec3_root, "delay", §ion)) { + ReadParam(section, "default_delay", &cfg.delay.default_delay); + ReadParam(section, "down_sampling_factor", &cfg.delay.down_sampling_factor); + ReadParam(section, "num_filters", &cfg.delay.num_filters); + ReadParam(section, "delay_headroom_samples", + &cfg.delay.delay_headroom_samples); + ReadParam(section, "hysteresis_limit_blocks", + &cfg.delay.hysteresis_limit_blocks); + ReadParam(section, "fixed_capture_delay_samples", + &cfg.delay.fixed_capture_delay_samples); + ReadParam(section, "delay_estimate_smoothing", + &cfg.delay.delay_estimate_smoothing); + ReadParam(section, "delay_estimate_smoothing_delay_found", + &cfg.delay.delay_estimate_smoothing_delay_found); + ReadParam(section, "delay_candidate_detection_threshold", + &cfg.delay.delay_candidate_detection_threshold); + + Json::Value subsection; + if (rtc::GetValueFromJsonObject(section, "delay_selection_thresholds", + &subsection)) { + ReadParam(subsection, "initial", + &cfg.delay.delay_selection_thresholds.initial); + ReadParam(subsection, "converged", + &cfg.delay.delay_selection_thresholds.converged); + } + + ReadParam(section, "use_external_delay_estimator", + &cfg.delay.use_external_delay_estimator); + ReadParam(section, "log_warning_on_delay_changes", + &cfg.delay.log_warning_on_delay_changes); + + ReadParam(section, "render_alignment_mixing", + &cfg.delay.render_alignment_mixing); + ReadParam(section, "capture_alignment_mixing", + &cfg.delay.capture_alignment_mixing); + ReadParam(section, "detect_pre_echo", &cfg.delay.detect_pre_echo); + } + + if (rtc::GetValueFromJsonObject(aec3_root, "filter", §ion)) { + ReadParam(section, "refined", &cfg.filter.refined); + ReadParam(section, "coarse", &cfg.filter.coarse); + ReadParam(section, "refined_initial", &cfg.filter.refined_initial); + ReadParam(section, "coarse_initial", &cfg.filter.coarse_initial); + ReadParam(section, "config_change_duration_blocks", + &cfg.filter.config_change_duration_blocks); + ReadParam(section, "initial_state_seconds", + &cfg.filter.initial_state_seconds); + ReadParam(section, "coarse_reset_hangover_blocks", + &cfg.filter.coarse_reset_hangover_blocks); + ReadParam(section, "conservative_initial_phase", + &cfg.filter.conservative_initial_phase); + ReadParam(section, "enable_coarse_filter_output_usage", + &cfg.filter.enable_coarse_filter_output_usage); + ReadParam(section, "use_linear_filter", &cfg.filter.use_linear_filter); + ReadParam(section, "high_pass_filter_echo_reference", + &cfg.filter.high_pass_filter_echo_reference); + ReadParam(section, "export_linear_aec_output", + &cfg.filter.export_linear_aec_output); + } + + if (rtc::GetValueFromJsonObject(aec3_root, "erle", §ion)) { + ReadParam(section, "min", &cfg.erle.min); + ReadParam(section, "max_l", &cfg.erle.max_l); + ReadParam(section, "max_h", &cfg.erle.max_h); + ReadParam(section, "onset_detection", &cfg.erle.onset_detection); + ReadParam(section, "num_sections", &cfg.erle.num_sections); + ReadParam(section, "clamp_quality_estimate_to_zero", + &cfg.erle.clamp_quality_estimate_to_zero); + ReadParam(section, "clamp_quality_estimate_to_one", + &cfg.erle.clamp_quality_estimate_to_one); + } + + if (rtc::GetValueFromJsonObject(aec3_root, "ep_strength", §ion)) { + ReadParam(section, "default_gain", &cfg.ep_strength.default_gain); + ReadParam(section, "default_len", &cfg.ep_strength.default_len); + ReadParam(section, "nearend_len", &cfg.ep_strength.nearend_len); + ReadParam(section, "echo_can_saturate", &cfg.ep_strength.echo_can_saturate); + ReadParam(section, "bounded_erl", &cfg.ep_strength.bounded_erl); + ReadParam(section, "erle_onset_compensation_in_dominant_nearend", + &cfg.ep_strength.erle_onset_compensation_in_dominant_nearend); + ReadParam(section, "use_conservative_tail_frequency_response", + &cfg.ep_strength.use_conservative_tail_frequency_response); + } + + if (rtc::GetValueFromJsonObject(aec3_root, "echo_audibility", §ion)) { + ReadParam(section, "low_render_limit", + &cfg.echo_audibility.low_render_limit); + ReadParam(section, "normal_render_limit", + &cfg.echo_audibility.normal_render_limit); + + ReadParam(section, "floor_power", &cfg.echo_audibility.floor_power); + ReadParam(section, "audibility_threshold_lf", + &cfg.echo_audibility.audibility_threshold_lf); + ReadParam(section, "audibility_threshold_mf", + &cfg.echo_audibility.audibility_threshold_mf); + ReadParam(section, "audibility_threshold_hf", + &cfg.echo_audibility.audibility_threshold_hf); + ReadParam(section, "use_stationarity_properties", + &cfg.echo_audibility.use_stationarity_properties); + ReadParam(section, "use_stationarity_properties_at_init", + &cfg.echo_audibility.use_stationarity_properties_at_init); + } + + if (rtc::GetValueFromJsonObject(aec3_root, "render_levels", §ion)) { + ReadParam(section, "active_render_limit", + &cfg.render_levels.active_render_limit); + ReadParam(section, "poor_excitation_render_limit", + &cfg.render_levels.poor_excitation_render_limit); + ReadParam(section, "poor_excitation_render_limit_ds8", + &cfg.render_levels.poor_excitation_render_limit_ds8); + ReadParam(section, "render_power_gain_db", + &cfg.render_levels.render_power_gain_db); + } + + if (rtc::GetValueFromJsonObject(aec3_root, "echo_removal_control", + §ion)) { + ReadParam(section, "has_clock_drift", + &cfg.echo_removal_control.has_clock_drift); + ReadParam(section, "linear_and_stable_echo_path", + &cfg.echo_removal_control.linear_and_stable_echo_path); + } + + if (rtc::GetValueFromJsonObject(aec3_root, "echo_model", §ion)) { + Json::Value subsection; + ReadParam(section, "noise_floor_hold", &cfg.echo_model.noise_floor_hold); + ReadParam(section, "min_noise_floor_power", + &cfg.echo_model.min_noise_floor_power); + ReadParam(section, "stationary_gate_slope", + &cfg.echo_model.stationary_gate_slope); + ReadParam(section, "noise_gate_power", &cfg.echo_model.noise_gate_power); + ReadParam(section, "noise_gate_slope", &cfg.echo_model.noise_gate_slope); + ReadParam(section, "render_pre_window_size", + &cfg.echo_model.render_pre_window_size); + ReadParam(section, "render_post_window_size", + &cfg.echo_model.render_post_window_size); + ReadParam(section, "model_reverb_in_nonlinear_mode", + &cfg.echo_model.model_reverb_in_nonlinear_mode); + } + + if (rtc::GetValueFromJsonObject(aec3_root, "comfort_noise", §ion)) { + ReadParam(section, "noise_floor_dbfs", &cfg.comfort_noise.noise_floor_dbfs); + } + + Json::Value subsection; + if (rtc::GetValueFromJsonObject(aec3_root, "suppressor", §ion)) { + ReadParam(section, "nearend_average_blocks", + &cfg.suppressor.nearend_average_blocks); + + if (rtc::GetValueFromJsonObject(section, "normal_tuning", &subsection)) { + ReadParam(subsection, "mask_lf", &cfg.suppressor.normal_tuning.mask_lf); + ReadParam(subsection, "mask_hf", &cfg.suppressor.normal_tuning.mask_hf); + ReadParam(subsection, "max_inc_factor", + &cfg.suppressor.normal_tuning.max_inc_factor); + ReadParam(subsection, "max_dec_factor_lf", + &cfg.suppressor.normal_tuning.max_dec_factor_lf); + } + + if (rtc::GetValueFromJsonObject(section, "nearend_tuning", &subsection)) { + ReadParam(subsection, "mask_lf", &cfg.suppressor.nearend_tuning.mask_lf); + ReadParam(subsection, "mask_hf", &cfg.suppressor.nearend_tuning.mask_hf); + ReadParam(subsection, "max_inc_factor", + &cfg.suppressor.nearend_tuning.max_inc_factor); + ReadParam(subsection, "max_dec_factor_lf", + &cfg.suppressor.nearend_tuning.max_dec_factor_lf); + } + + ReadParam(section, "lf_smoothing_during_initial_phase", + &cfg.suppressor.lf_smoothing_during_initial_phase); + ReadParam(section, "last_permanent_lf_smoothing_band", + &cfg.suppressor.last_permanent_lf_smoothing_band); + ReadParam(section, "last_lf_smoothing_band", + &cfg.suppressor.last_lf_smoothing_band); + ReadParam(section, "last_lf_band", &cfg.suppressor.last_lf_band); + ReadParam(section, "first_hf_band", &cfg.suppressor.first_hf_band); + + if (rtc::GetValueFromJsonObject(section, "dominant_nearend_detection", + &subsection)) { + ReadParam(subsection, "enr_threshold", + &cfg.suppressor.dominant_nearend_detection.enr_threshold); + ReadParam(subsection, "enr_exit_threshold", + &cfg.suppressor.dominant_nearend_detection.enr_exit_threshold); + ReadParam(subsection, "snr_threshold", + &cfg.suppressor.dominant_nearend_detection.snr_threshold); + ReadParam(subsection, "hold_duration", + &cfg.suppressor.dominant_nearend_detection.hold_duration); + ReadParam(subsection, "trigger_threshold", + &cfg.suppressor.dominant_nearend_detection.trigger_threshold); + ReadParam( + subsection, "use_during_initial_phase", + &cfg.suppressor.dominant_nearend_detection.use_during_initial_phase); + ReadParam(subsection, "use_unbounded_echo_spectrum", + &cfg.suppressor.dominant_nearend_detection + .use_unbounded_echo_spectrum); + } + + if (rtc::GetValueFromJsonObject(section, "subband_nearend_detection", + &subsection)) { + ReadParam( + subsection, "nearend_average_blocks", + &cfg.suppressor.subband_nearend_detection.nearend_average_blocks); + ReadParam(subsection, "subband1", + &cfg.suppressor.subband_nearend_detection.subband1); + ReadParam(subsection, "subband2", + &cfg.suppressor.subband_nearend_detection.subband2); + ReadParam(subsection, "nearend_threshold", + &cfg.suppressor.subband_nearend_detection.nearend_threshold); + ReadParam(subsection, "snr_threshold", + &cfg.suppressor.subband_nearend_detection.snr_threshold); + } + + ReadParam(section, "use_subband_nearend_detection", + &cfg.suppressor.use_subband_nearend_detection); + + if (rtc::GetValueFromJsonObject(section, "high_bands_suppression", + &subsection)) { + ReadParam(subsection, "enr_threshold", + &cfg.suppressor.high_bands_suppression.enr_threshold); + ReadParam(subsection, "max_gain_during_echo", + &cfg.suppressor.high_bands_suppression.max_gain_during_echo); + ReadParam(subsection, "anti_howling_activation_threshold", + &cfg.suppressor.high_bands_suppression + .anti_howling_activation_threshold); + ReadParam(subsection, "anti_howling_gain", + &cfg.suppressor.high_bands_suppression.anti_howling_gain); + } + + ReadParam(section, "floor_first_increase", + &cfg.suppressor.floor_first_increase); + ReadParam(section, "conservative_hf_suppression", + &cfg.suppressor.conservative_hf_suppression); + } + + if (rtc::GetValueFromJsonObject(aec3_root, "multi_channel", §ion)) { + ReadParam(section, "detect_stereo_content", + &cfg.multi_channel.detect_stereo_content); + ReadParam(section, "stereo_detection_threshold", + &cfg.multi_channel.stereo_detection_threshold); + ReadParam(section, "stereo_detection_timeout_threshold_seconds", + &cfg.multi_channel.stereo_detection_timeout_threshold_seconds); + ReadParam(section, "stereo_detection_hysteresis_seconds", + &cfg.multi_channel.stereo_detection_hysteresis_seconds); + } +} + +EchoCanceller3Config Aec3ConfigFromJsonString(absl::string_view json_string) { + EchoCanceller3Config cfg; + bool not_used; + Aec3ConfigFromJsonString(json_string, &cfg, ¬_used); + return cfg; +} + +std::string Aec3ConfigToJsonString(const EchoCanceller3Config& config) { + rtc::StringBuilder ost; + ost << "{"; + ost << "\"aec3\": {"; + ost << "\"buffering\": {"; + ost << "\"excess_render_detection_interval_blocks\": " + << config.buffering.excess_render_detection_interval_blocks << ","; + ost << "\"max_allowed_excess_render_blocks\": " + << config.buffering.max_allowed_excess_render_blocks; + ost << "},"; + + ost << "\"delay\": {"; + ost << "\"default_delay\": " << config.delay.default_delay << ","; + ost << "\"down_sampling_factor\": " << config.delay.down_sampling_factor + << ","; + ost << "\"num_filters\": " << config.delay.num_filters << ","; + ost << "\"delay_headroom_samples\": " << config.delay.delay_headroom_samples + << ","; + ost << "\"hysteresis_limit_blocks\": " << config.delay.hysteresis_limit_blocks + << ","; + ost << "\"fixed_capture_delay_samples\": " + << config.delay.fixed_capture_delay_samples << ","; + ost << "\"delay_estimate_smoothing\": " + << config.delay.delay_estimate_smoothing << ","; + ost << "\"delay_estimate_smoothing_delay_found\": " + << config.delay.delay_estimate_smoothing_delay_found << ","; + ost << "\"delay_candidate_detection_threshold\": " + << config.delay.delay_candidate_detection_threshold << ","; + + ost << "\"delay_selection_thresholds\": {"; + ost << "\"initial\": " << config.delay.delay_selection_thresholds.initial + << ","; + ost << "\"converged\": " << config.delay.delay_selection_thresholds.converged; + ost << "},"; + + ost << "\"use_external_delay_estimator\": " + << (config.delay.use_external_delay_estimator ? "true" : "false") << ","; + ost << "\"log_warning_on_delay_changes\": " + << (config.delay.log_warning_on_delay_changes ? "true" : "false") << ","; + + ost << "\"render_alignment_mixing\": {"; + ost << "\"downmix\": " + << (config.delay.render_alignment_mixing.downmix ? "true" : "false") + << ","; + ost << "\"adaptive_selection\": " + << (config.delay.render_alignment_mixing.adaptive_selection ? "true" + : "false") + << ","; + ost << "\"activity_power_threshold\": " + << config.delay.render_alignment_mixing.activity_power_threshold << ","; + ost << "\"prefer_first_two_channels\": " + << (config.delay.render_alignment_mixing.prefer_first_two_channels + ? "true" + : "false"); + ost << "},"; + + ost << "\"capture_alignment_mixing\": {"; + ost << "\"downmix\": " + << (config.delay.capture_alignment_mixing.downmix ? "true" : "false") + << ","; + ost << "\"adaptive_selection\": " + << (config.delay.capture_alignment_mixing.adaptive_selection ? "true" + : "false") + << ","; + ost << "\"activity_power_threshold\": " + << config.delay.capture_alignment_mixing.activity_power_threshold << ","; + ost << "\"prefer_first_two_channels\": " + << (config.delay.capture_alignment_mixing.prefer_first_two_channels + ? "true" + : "false"); + ost << "},"; + ost << "\"detect_pre_echo\": " + << (config.delay.detect_pre_echo ? "true" : "false"); + ost << "},"; + + ost << "\"filter\": {"; + + ost << "\"refined\": ["; + ost << config.filter.refined.length_blocks << ","; + ost << config.filter.refined.leakage_converged << ","; + ost << config.filter.refined.leakage_diverged << ","; + ost << config.filter.refined.error_floor << ","; + ost << config.filter.refined.error_ceil << ","; + ost << config.filter.refined.noise_gate; + ost << "],"; + + ost << "\"coarse\": ["; + ost << config.filter.coarse.length_blocks << ","; + ost << config.filter.coarse.rate << ","; + ost << config.filter.coarse.noise_gate; + ost << "],"; + + ost << "\"refined_initial\": ["; + ost << config.filter.refined_initial.length_blocks << ","; + ost << config.filter.refined_initial.leakage_converged << ","; + ost << config.filter.refined_initial.leakage_diverged << ","; + ost << config.filter.refined_initial.error_floor << ","; + ost << config.filter.refined_initial.error_ceil << ","; + ost << config.filter.refined_initial.noise_gate; + ost << "],"; + + ost << "\"coarse_initial\": ["; + ost << config.filter.coarse_initial.length_blocks << ","; + ost << config.filter.coarse_initial.rate << ","; + ost << config.filter.coarse_initial.noise_gate; + ost << "],"; + + ost << "\"config_change_duration_blocks\": " + << config.filter.config_change_duration_blocks << ","; + ost << "\"initial_state_seconds\": " << config.filter.initial_state_seconds + << ","; + ost << "\"coarse_reset_hangover_blocks\": " + << config.filter.coarse_reset_hangover_blocks << ","; + ost << "\"conservative_initial_phase\": " + << (config.filter.conservative_initial_phase ? "true" : "false") << ","; + ost << "\"enable_coarse_filter_output_usage\": " + << (config.filter.enable_coarse_filter_output_usage ? "true" : "false") + << ","; + ost << "\"use_linear_filter\": " + << (config.filter.use_linear_filter ? "true" : "false") << ","; + ost << "\"high_pass_filter_echo_reference\": " + << (config.filter.high_pass_filter_echo_reference ? "true" : "false") + << ","; + ost << "\"export_linear_aec_output\": " + << (config.filter.export_linear_aec_output ? "true" : "false"); + + ost << "},"; + + ost << "\"erle\": {"; + ost << "\"min\": " << config.erle.min << ","; + ost << "\"max_l\": " << config.erle.max_l << ","; + ost << "\"max_h\": " << config.erle.max_h << ","; + ost << "\"onset_detection\": " + << (config.erle.onset_detection ? "true" : "false") << ","; + ost << "\"num_sections\": " << config.erle.num_sections << ","; + ost << "\"clamp_quality_estimate_to_zero\": " + << (config.erle.clamp_quality_estimate_to_zero ? "true" : "false") << ","; + ost << "\"clamp_quality_estimate_to_one\": " + << (config.erle.clamp_quality_estimate_to_one ? "true" : "false"); + ost << "},"; + + ost << "\"ep_strength\": {"; + ost << "\"default_gain\": " << config.ep_strength.default_gain << ","; + ost << "\"default_len\": " << config.ep_strength.default_len << ","; + ost << "\"nearend_len\": " << config.ep_strength.nearend_len << ","; + ost << "\"echo_can_saturate\": " + << (config.ep_strength.echo_can_saturate ? "true" : "false") << ","; + ost << "\"bounded_erl\": " + << (config.ep_strength.bounded_erl ? "true" : "false") << ","; + ost << "\"erle_onset_compensation_in_dominant_nearend\": " + << (config.ep_strength.erle_onset_compensation_in_dominant_nearend + ? "true" + : "false") + << ","; + ost << "\"use_conservative_tail_frequency_response\": " + << (config.ep_strength.use_conservative_tail_frequency_response + ? "true" + : "false"); + ost << "},"; + + ost << "\"echo_audibility\": {"; + ost << "\"low_render_limit\": " << config.echo_audibility.low_render_limit + << ","; + ost << "\"normal_render_limit\": " + << config.echo_audibility.normal_render_limit << ","; + ost << "\"floor_power\": " << config.echo_audibility.floor_power << ","; + ost << "\"audibility_threshold_lf\": " + << config.echo_audibility.audibility_threshold_lf << ","; + ost << "\"audibility_threshold_mf\": " + << config.echo_audibility.audibility_threshold_mf << ","; + ost << "\"audibility_threshold_hf\": " + << config.echo_audibility.audibility_threshold_hf << ","; + ost << "\"use_stationarity_properties\": " + << (config.echo_audibility.use_stationarity_properties ? "true" : "false") + << ","; + ost << "\"use_stationarity_properties_at_init\": " + << (config.echo_audibility.use_stationarity_properties_at_init ? "true" + : "false"); + ost << "},"; + + ost << "\"render_levels\": {"; + ost << "\"active_render_limit\": " << config.render_levels.active_render_limit + << ","; + ost << "\"poor_excitation_render_limit\": " + << config.render_levels.poor_excitation_render_limit << ","; + ost << "\"poor_excitation_render_limit_ds8\": " + << config.render_levels.poor_excitation_render_limit_ds8 << ","; + ost << "\"render_power_gain_db\": " + << config.render_levels.render_power_gain_db; + ost << "},"; + + ost << "\"echo_removal_control\": {"; + ost << "\"has_clock_drift\": " + << (config.echo_removal_control.has_clock_drift ? "true" : "false") + << ","; + ost << "\"linear_and_stable_echo_path\": " + << (config.echo_removal_control.linear_and_stable_echo_path ? "true" + : "false"); + + ost << "},"; + + ost << "\"echo_model\": {"; + ost << "\"noise_floor_hold\": " << config.echo_model.noise_floor_hold << ","; + ost << "\"min_noise_floor_power\": " + << config.echo_model.min_noise_floor_power << ","; + ost << "\"stationary_gate_slope\": " + << config.echo_model.stationary_gate_slope << ","; + ost << "\"noise_gate_power\": " << config.echo_model.noise_gate_power << ","; + ost << "\"noise_gate_slope\": " << config.echo_model.noise_gate_slope << ","; + ost << "\"render_pre_window_size\": " + << config.echo_model.render_pre_window_size << ","; + ost << "\"render_post_window_size\": " + << config.echo_model.render_post_window_size << ","; + ost << "\"model_reverb_in_nonlinear_mode\": " + << (config.echo_model.model_reverb_in_nonlinear_mode ? "true" : "false"); + ost << "},"; + + ost << "\"comfort_noise\": {"; + ost << "\"noise_floor_dbfs\": " << config.comfort_noise.noise_floor_dbfs; + ost << "},"; + + ost << "\"suppressor\": {"; + ost << "\"nearend_average_blocks\": " + << config.suppressor.nearend_average_blocks << ","; + ost << "\"normal_tuning\": {"; + ost << "\"mask_lf\": ["; + ost << config.suppressor.normal_tuning.mask_lf.enr_transparent << ","; + ost << config.suppressor.normal_tuning.mask_lf.enr_suppress << ","; + ost << config.suppressor.normal_tuning.mask_lf.emr_transparent; + ost << "],"; + ost << "\"mask_hf\": ["; + ost << config.suppressor.normal_tuning.mask_hf.enr_transparent << ","; + ost << config.suppressor.normal_tuning.mask_hf.enr_suppress << ","; + ost << config.suppressor.normal_tuning.mask_hf.emr_transparent; + ost << "],"; + ost << "\"max_inc_factor\": " + << config.suppressor.normal_tuning.max_inc_factor << ","; + ost << "\"max_dec_factor_lf\": " + << config.suppressor.normal_tuning.max_dec_factor_lf; + ost << "},"; + ost << "\"nearend_tuning\": {"; + ost << "\"mask_lf\": ["; + ost << config.suppressor.nearend_tuning.mask_lf.enr_transparent << ","; + ost << config.suppressor.nearend_tuning.mask_lf.enr_suppress << ","; + ost << config.suppressor.nearend_tuning.mask_lf.emr_transparent; + ost << "],"; + ost << "\"mask_hf\": ["; + ost << config.suppressor.nearend_tuning.mask_hf.enr_transparent << ","; + ost << config.suppressor.nearend_tuning.mask_hf.enr_suppress << ","; + ost << config.suppressor.nearend_tuning.mask_hf.emr_transparent; + ost << "],"; + ost << "\"max_inc_factor\": " + << config.suppressor.nearend_tuning.max_inc_factor << ","; + ost << "\"max_dec_factor_lf\": " + << config.suppressor.nearend_tuning.max_dec_factor_lf; + ost << "},"; + ost << "\"lf_smoothing_during_initial_phase\": " + << (config.suppressor.lf_smoothing_during_initial_phase ? "true" + : "false") + << ","; + ost << "\"last_permanent_lf_smoothing_band\": " + << config.suppressor.last_permanent_lf_smoothing_band << ","; + ost << "\"last_lf_smoothing_band\": " + << config.suppressor.last_lf_smoothing_band << ","; + ost << "\"last_lf_band\": " << config.suppressor.last_lf_band << ","; + ost << "\"first_hf_band\": " << config.suppressor.first_hf_band << ","; + { + const auto& dnd = config.suppressor.dominant_nearend_detection; + ost << "\"dominant_nearend_detection\": {"; + ost << "\"enr_threshold\": " << dnd.enr_threshold << ","; + ost << "\"enr_exit_threshold\": " << dnd.enr_exit_threshold << ","; + ost << "\"snr_threshold\": " << dnd.snr_threshold << ","; + ost << "\"hold_duration\": " << dnd.hold_duration << ","; + ost << "\"trigger_threshold\": " << dnd.trigger_threshold << ","; + ost << "\"use_during_initial_phase\": " << dnd.use_during_initial_phase + << ","; + ost << "\"use_unbounded_echo_spectrum\": " + << dnd.use_unbounded_echo_spectrum; + ost << "},"; + } + ost << "\"subband_nearend_detection\": {"; + ost << "\"nearend_average_blocks\": " + << config.suppressor.subband_nearend_detection.nearend_average_blocks + << ","; + ost << "\"subband1\": ["; + ost << config.suppressor.subband_nearend_detection.subband1.low << ","; + ost << config.suppressor.subband_nearend_detection.subband1.high; + ost << "],"; + ost << "\"subband2\": ["; + ost << config.suppressor.subband_nearend_detection.subband2.low << ","; + ost << config.suppressor.subband_nearend_detection.subband2.high; + ost << "],"; + ost << "\"nearend_threshold\": " + << config.suppressor.subband_nearend_detection.nearend_threshold << ","; + ost << "\"snr_threshold\": " + << config.suppressor.subband_nearend_detection.snr_threshold; + ost << "},"; + ost << "\"use_subband_nearend_detection\": " + << config.suppressor.use_subband_nearend_detection << ","; + ost << "\"high_bands_suppression\": {"; + ost << "\"enr_threshold\": " + << config.suppressor.high_bands_suppression.enr_threshold << ","; + ost << "\"max_gain_during_echo\": " + << config.suppressor.high_bands_suppression.max_gain_during_echo << ","; + ost << "\"anti_howling_activation_threshold\": " + << config.suppressor.high_bands_suppression + .anti_howling_activation_threshold + << ","; + ost << "\"anti_howling_gain\": " + << config.suppressor.high_bands_suppression.anti_howling_gain; + ost << "},"; + ost << "\"floor_first_increase\": " << config.suppressor.floor_first_increase + << ","; + ost << "\"conservative_hf_suppression\": " + << config.suppressor.conservative_hf_suppression; + ost << "},"; + + ost << "\"multi_channel\": {"; + ost << "\"detect_stereo_content\": " + << (config.multi_channel.detect_stereo_content ? "true" : "false") << ","; + ost << "\"stereo_detection_threshold\": " + << config.multi_channel.stereo_detection_threshold << ","; + ost << "\"stereo_detection_timeout_threshold_seconds\": " + << config.multi_channel.stereo_detection_timeout_threshold_seconds << ","; + ost << "\"stereo_detection_hysteresis_seconds\": " + << config.multi_channel.stereo_detection_hysteresis_seconds; + ost << "}"; + + ost << "}"; + ost << "}"; + + return ost.Release(); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio/echo_canceller3_config_json.h b/third_party/libwebrtc/api/audio/echo_canceller3_config_json.h new file mode 100644 index 0000000000..ecee9541c7 --- /dev/null +++ b/third_party/libwebrtc/api/audio/echo_canceller3_config_json.h @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_ECHO_CANCELLER3_CONFIG_JSON_H_ +#define API_AUDIO_ECHO_CANCELLER3_CONFIG_JSON_H_ + +#include <string> + +#include "absl/strings/string_view.h" +#include "api/audio/echo_canceller3_config.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { +// Parses a JSON-encoded string into an Aec3 config. Fields corresponds to +// substruct names, with the addition that there must be a top-level node +// "aec3". Produces default config values for anything that cannot be parsed +// from the string. If any error was found in the parsing, parsing_successful is +// set to false. +RTC_EXPORT void Aec3ConfigFromJsonString(absl::string_view json_string, + EchoCanceller3Config* config, + bool* parsing_successful); + +// To be deprecated. +// Parses a JSON-encoded string into an Aec3 config. Fields corresponds to +// substruct names, with the addition that there must be a top-level node +// "aec3". Returns default config values for anything that cannot be parsed from +// the string. +RTC_EXPORT EchoCanceller3Config +Aec3ConfigFromJsonString(absl::string_view json_string); + +// Encodes an Aec3 config in JSON format. Fields corresponds to substruct names, +// with the addition that the top-level node is named "aec3". +RTC_EXPORT std::string Aec3ConfigToJsonString( + const EchoCanceller3Config& config); + +} // namespace webrtc + +#endif // API_AUDIO_ECHO_CANCELLER3_CONFIG_JSON_H_ diff --git a/third_party/libwebrtc/api/audio/echo_canceller3_factory.cc b/third_party/libwebrtc/api/audio/echo_canceller3_factory.cc new file mode 100644 index 0000000000..284b117bea --- /dev/null +++ b/third_party/libwebrtc/api/audio/echo_canceller3_factory.cc @@ -0,0 +1,32 @@ +/* + * 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 "api/audio/echo_canceller3_factory.h" + +#include <memory> + +#include "modules/audio_processing/aec3/echo_canceller3.h" + +namespace webrtc { + +EchoCanceller3Factory::EchoCanceller3Factory() {} + +EchoCanceller3Factory::EchoCanceller3Factory(const EchoCanceller3Config& config) + : config_(config) {} + +std::unique_ptr<EchoControl> EchoCanceller3Factory::Create( + int sample_rate_hz, + int num_render_channels, + int num_capture_channels) { + return std::make_unique<EchoCanceller3>( + config_, /*multichannel_config=*/absl::nullopt, sample_rate_hz, + num_render_channels, num_capture_channels); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio/echo_canceller3_factory.h b/third_party/libwebrtc/api/audio/echo_canceller3_factory.h new file mode 100644 index 0000000000..8b5380057b --- /dev/null +++ b/third_party/libwebrtc/api/audio/echo_canceller3_factory.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_ECHO_CANCELLER3_FACTORY_H_ +#define API_AUDIO_ECHO_CANCELLER3_FACTORY_H_ + +#include <memory> + +#include "api/audio/echo_canceller3_config.h" +#include "api/audio/echo_control.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +class RTC_EXPORT EchoCanceller3Factory : public EchoControlFactory { + public: + // Factory producing EchoCanceller3 instances with the default configuration. + EchoCanceller3Factory(); + + // Factory producing EchoCanceller3 instances with the specified + // configuration. + explicit EchoCanceller3Factory(const EchoCanceller3Config& config); + + // Creates an EchoCanceller3 with a specified channel count and sampling rate. + std::unique_ptr<EchoControl> Create(int sample_rate_hz, + int num_render_channels, + int num_capture_channels) override; + + private: + const EchoCanceller3Config config_; +}; +} // namespace webrtc + +#endif // API_AUDIO_ECHO_CANCELLER3_FACTORY_H_ diff --git a/third_party/libwebrtc/api/audio/echo_control.h b/third_party/libwebrtc/api/audio/echo_control.h new file mode 100644 index 0000000000..74fbc27b12 --- /dev/null +++ b/third_party/libwebrtc/api/audio/echo_control.h @@ -0,0 +1,75 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_ECHO_CONTROL_H_ +#define API_AUDIO_ECHO_CONTROL_H_ + +#include <memory> + +#include "rtc_base/checks.h" + +namespace webrtc { + +class AudioBuffer; + +// Interface for an acoustic echo cancellation (AEC) submodule. +class EchoControl { + public: + // Analysis (not changing) of the render signal. + virtual void AnalyzeRender(AudioBuffer* render) = 0; + + // Analysis (not changing) of the capture signal. + virtual void AnalyzeCapture(AudioBuffer* capture) = 0; + + // Processes the capture signal in order to remove the echo. + virtual void ProcessCapture(AudioBuffer* capture, bool level_change) = 0; + + // As above, but also returns the linear filter output. + virtual void ProcessCapture(AudioBuffer* capture, + AudioBuffer* linear_output, + bool level_change) = 0; + + struct Metrics { + double echo_return_loss; + double echo_return_loss_enhancement; + int delay_ms; + }; + + // Collect current metrics from the echo controller. + virtual Metrics GetMetrics() const = 0; + + // Provides an optional external estimate of the audio buffer delay. + virtual void SetAudioBufferDelay(int delay_ms) = 0; + + // Specifies whether the capture output will be used. The purpose of this is + // to allow the echo controller to deactivate some of the processing when the + // resulting output is anyway not used, for instance when the endpoint is + // muted. + // TODO(b/177830919): Make pure virtual. + virtual void SetCaptureOutputUsage(bool capture_output_used) {} + + // Returns wheter the signal is altered. + virtual bool ActiveProcessing() const = 0; + + virtual ~EchoControl() {} +}; + +// Interface for a factory that creates EchoControllers. +class EchoControlFactory { + public: + virtual std::unique_ptr<EchoControl> Create(int sample_rate_hz, + int num_render_channels, + int num_capture_channels) = 0; + + virtual ~EchoControlFactory() = default; +}; +} // namespace webrtc + +#endif // API_AUDIO_ECHO_CONTROL_H_ diff --git a/third_party/libwebrtc/api/audio/echo_control_gn/moz.build b/third_party/libwebrtc/api/audio/echo_control_gn/moz.build new file mode 100644 index 0000000000..2e128f8038 --- /dev/null +++ b/third_party/libwebrtc/api/audio/echo_control_gn/moz.build @@ -0,0 +1,205 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("echo_control_gn") diff --git a/third_party/libwebrtc/api/audio/echo_detector_creator.cc b/third_party/libwebrtc/api/audio/echo_detector_creator.cc new file mode 100644 index 0000000000..15b7c51dca --- /dev/null +++ b/third_party/libwebrtc/api/audio/echo_detector_creator.cc @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020 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 "api/audio/echo_detector_creator.h" + +#include "api/make_ref_counted.h" +#include "modules/audio_processing/residual_echo_detector.h" + +namespace webrtc { + +rtc::scoped_refptr<EchoDetector> CreateEchoDetector() { + return rtc::make_ref_counted<ResidualEchoDetector>(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio/echo_detector_creator.h b/third_party/libwebrtc/api/audio/echo_detector_creator.h new file mode 100644 index 0000000000..5ba171de97 --- /dev/null +++ b/third_party/libwebrtc/api/audio/echo_detector_creator.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020 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 API_AUDIO_ECHO_DETECTOR_CREATOR_H_ +#define API_AUDIO_ECHO_DETECTOR_CREATOR_H_ + +#include "api/scoped_refptr.h" +#include "modules/audio_processing/include/audio_processing.h" + +namespace webrtc { + +// Returns an instance of the WebRTC implementation of a residual echo detector. +// It can be provided to the webrtc::AudioProcessingBuilder to obtain the +// usual residual echo metrics. +rtc::scoped_refptr<EchoDetector> CreateEchoDetector(); + +} // namespace webrtc + +#endif // API_AUDIO_ECHO_DETECTOR_CREATOR_H_ diff --git a/third_party/libwebrtc/api/audio/test/BUILD.gn b/third_party/libwebrtc/api/audio/test/BUILD.gn new file mode 100644 index 0000000000..dfe8c32f80 --- /dev/null +++ b/third_party/libwebrtc/api/audio/test/BUILD.gn @@ -0,0 +1,30 @@ +# 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. + +import("../../../webrtc.gni") +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +if (rtc_include_tests) { + rtc_library("audio_api_unittests") { + testonly = true + sources = [ + "audio_frame_unittest.cc", + "echo_canceller3_config_json_unittest.cc", + "echo_canceller3_config_unittest.cc", + ] + deps = [ + "..:aec3_config", + "..:aec3_config_json", + "..:audio_frame_api", + "../../../test:test_support", + ] + } +} diff --git a/third_party/libwebrtc/api/audio/test/audio_frame_unittest.cc b/third_party/libwebrtc/api/audio/test/audio_frame_unittest.cc new file mode 100644 index 0000000000..dbf45ceabc --- /dev/null +++ b/third_party/libwebrtc/api/audio/test/audio_frame_unittest.cc @@ -0,0 +1,136 @@ +/* + * Copyright 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 "api/audio/audio_frame.h" + +#include <stdint.h> +#include <string.h> // memcmp + +#include "test/gtest.h" + +namespace webrtc { + +namespace { + +bool AllSamplesAre(int16_t sample, const AudioFrame& frame) { + const int16_t* frame_data = frame.data(); + for (size_t i = 0; i < frame.max_16bit_samples(); i++) { + if (frame_data[i] != sample) { + return false; + } + } + return true; +} + +constexpr uint32_t kTimestamp = 27; +constexpr int kSampleRateHz = 16000; +constexpr size_t kNumChannelsMono = 1; +constexpr size_t kNumChannelsStereo = 2; +constexpr size_t kNumChannels5_1 = 6; +constexpr size_t kSamplesPerChannel = kSampleRateHz / 100; + +} // namespace + +TEST(AudioFrameTest, FrameStartsMuted) { + AudioFrame frame; + EXPECT_TRUE(frame.muted()); + EXPECT_TRUE(AllSamplesAre(0, frame)); +} + +TEST(AudioFrameTest, UnmutedFrameIsInitiallyZeroed) { + AudioFrame frame; + frame.mutable_data(); + EXPECT_FALSE(frame.muted()); + EXPECT_TRUE(AllSamplesAre(0, frame)); +} + +TEST(AudioFrameTest, MutedFrameBufferIsZeroed) { + AudioFrame frame; + int16_t* frame_data = frame.mutable_data(); + for (size_t i = 0; i < frame.max_16bit_samples(); i++) { + frame_data[i] = 17; + } + ASSERT_TRUE(AllSamplesAre(17, frame)); + frame.Mute(); + EXPECT_TRUE(frame.muted()); + EXPECT_TRUE(AllSamplesAre(0, frame)); +} + +TEST(AudioFrameTest, UpdateFrameMono) { + AudioFrame frame; + int16_t samples[kNumChannelsMono * kSamplesPerChannel] = {17}; + frame.UpdateFrame(kTimestamp, samples, kSamplesPerChannel, kSampleRateHz, + AudioFrame::kPLC, AudioFrame::kVadActive, kNumChannelsMono); + + EXPECT_EQ(kTimestamp, frame.timestamp_); + EXPECT_EQ(kSamplesPerChannel, frame.samples_per_channel()); + EXPECT_EQ(kSampleRateHz, frame.sample_rate_hz()); + EXPECT_EQ(AudioFrame::kPLC, frame.speech_type_); + EXPECT_EQ(AudioFrame::kVadActive, frame.vad_activity_); + EXPECT_EQ(kNumChannelsMono, frame.num_channels()); + EXPECT_EQ(CHANNEL_LAYOUT_MONO, frame.channel_layout()); + + EXPECT_FALSE(frame.muted()); + EXPECT_EQ(0, memcmp(samples, frame.data(), sizeof(samples))); + + frame.UpdateFrame(kTimestamp, nullptr /* data*/, kSamplesPerChannel, + kSampleRateHz, AudioFrame::kPLC, AudioFrame::kVadActive, + kNumChannelsMono); + EXPECT_TRUE(frame.muted()); + EXPECT_TRUE(AllSamplesAre(0, frame)); +} + +TEST(AudioFrameTest, UpdateFrameMultiChannel) { + AudioFrame frame; + frame.UpdateFrame(kTimestamp, nullptr /* data */, kSamplesPerChannel, + kSampleRateHz, AudioFrame::kPLC, AudioFrame::kVadActive, + kNumChannelsStereo); + EXPECT_EQ(kSamplesPerChannel, frame.samples_per_channel()); + EXPECT_EQ(kNumChannelsStereo, frame.num_channels()); + EXPECT_EQ(CHANNEL_LAYOUT_STEREO, frame.channel_layout()); + + frame.UpdateFrame(kTimestamp, nullptr /* data */, kSamplesPerChannel, + kSampleRateHz, AudioFrame::kPLC, AudioFrame::kVadActive, + kNumChannels5_1); + EXPECT_EQ(kSamplesPerChannel, frame.samples_per_channel()); + EXPECT_EQ(kNumChannels5_1, frame.num_channels()); + EXPECT_EQ(CHANNEL_LAYOUT_5_1, frame.channel_layout()); +} + +TEST(AudioFrameTest, CopyFrom) { + AudioFrame frame1; + AudioFrame frame2; + + int16_t samples[kNumChannelsMono * kSamplesPerChannel] = {17}; + frame2.UpdateFrame(kTimestamp, samples, kSamplesPerChannel, kSampleRateHz, + AudioFrame::kPLC, AudioFrame::kVadActive, + kNumChannelsMono); + frame1.CopyFrom(frame2); + + EXPECT_EQ(frame2.timestamp_, frame1.timestamp_); + EXPECT_EQ(frame2.samples_per_channel_, frame1.samples_per_channel_); + EXPECT_EQ(frame2.sample_rate_hz_, frame1.sample_rate_hz_); + EXPECT_EQ(frame2.speech_type_, frame1.speech_type_); + EXPECT_EQ(frame2.vad_activity_, frame1.vad_activity_); + EXPECT_EQ(frame2.num_channels_, frame1.num_channels_); + + EXPECT_EQ(frame2.muted(), frame1.muted()); + EXPECT_EQ(0, memcmp(frame2.data(), frame1.data(), sizeof(samples))); + + frame2.UpdateFrame(kTimestamp, nullptr /* data */, kSamplesPerChannel, + kSampleRateHz, AudioFrame::kPLC, AudioFrame::kVadActive, + kNumChannelsMono); + frame1.CopyFrom(frame2); + + EXPECT_EQ(frame2.muted(), frame1.muted()); + EXPECT_EQ(0, memcmp(frame2.data(), frame1.data(), sizeof(samples))); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio/test/echo_canceller3_config_json_unittest.cc b/third_party/libwebrtc/api/audio/test/echo_canceller3_config_json_unittest.cc new file mode 100644 index 0000000000..4146dda9fe --- /dev/null +++ b/third_party/libwebrtc/api/audio/test/echo_canceller3_config_json_unittest.cc @@ -0,0 +1,93 @@ +/* + * Copyright 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 "api/audio/echo_canceller3_config_json.h" + +#include "api/audio/echo_canceller3_config.h" +#include "test/gtest.h" + +namespace webrtc { + +TEST(EchoCanceller3JsonHelpers, ToStringAndParseJson) { + EchoCanceller3Config cfg; + cfg.delay.down_sampling_factor = 1u; + cfg.delay.log_warning_on_delay_changes = true; + cfg.filter.refined.error_floor = 2.f; + cfg.filter.coarse_initial.length_blocks = 3u; + cfg.filter.high_pass_filter_echo_reference = + !cfg.filter.high_pass_filter_echo_reference; + cfg.comfort_noise.noise_floor_dbfs = 100.f; + cfg.echo_model.model_reverb_in_nonlinear_mode = false; + cfg.suppressor.normal_tuning.mask_hf.enr_suppress = .5f; + cfg.suppressor.subband_nearend_detection.nearend_average_blocks = 3; + cfg.suppressor.subband_nearend_detection.subband1 = {1, 3}; + cfg.suppressor.subband_nearend_detection.subband1 = {4, 5}; + cfg.suppressor.subband_nearend_detection.nearend_threshold = 2.f; + cfg.suppressor.subband_nearend_detection.snr_threshold = 100.f; + cfg.multi_channel.detect_stereo_content = + !cfg.multi_channel.detect_stereo_content; + cfg.multi_channel.stereo_detection_threshold += 1.0f; + cfg.multi_channel.stereo_detection_timeout_threshold_seconds += 1; + cfg.multi_channel.stereo_detection_hysteresis_seconds += 1; + std::string json_string = Aec3ConfigToJsonString(cfg); + EchoCanceller3Config cfg_transformed = Aec3ConfigFromJsonString(json_string); + + // Expect unchanged values to remain default. + EXPECT_EQ(cfg.ep_strength.default_len, + cfg_transformed.ep_strength.default_len); + EXPECT_EQ(cfg.ep_strength.nearend_len, + cfg_transformed.ep_strength.nearend_len); + EXPECT_EQ(cfg.suppressor.normal_tuning.mask_lf.enr_suppress, + cfg_transformed.suppressor.normal_tuning.mask_lf.enr_suppress); + + // Expect changed values to carry through the transformation. + EXPECT_EQ(cfg.delay.down_sampling_factor, + cfg_transformed.delay.down_sampling_factor); + EXPECT_EQ(cfg.delay.log_warning_on_delay_changes, + cfg_transformed.delay.log_warning_on_delay_changes); + EXPECT_EQ(cfg.filter.coarse_initial.length_blocks, + cfg_transformed.filter.coarse_initial.length_blocks); + EXPECT_EQ(cfg.filter.refined.error_floor, + cfg_transformed.filter.refined.error_floor); + EXPECT_EQ(cfg.filter.high_pass_filter_echo_reference, + cfg_transformed.filter.high_pass_filter_echo_reference); + EXPECT_EQ(cfg.comfort_noise.noise_floor_dbfs, + cfg_transformed.comfort_noise.noise_floor_dbfs); + EXPECT_EQ(cfg.echo_model.model_reverb_in_nonlinear_mode, + cfg_transformed.echo_model.model_reverb_in_nonlinear_mode); + EXPECT_EQ(cfg.suppressor.normal_tuning.mask_hf.enr_suppress, + cfg_transformed.suppressor.normal_tuning.mask_hf.enr_suppress); + EXPECT_EQ(cfg.suppressor.subband_nearend_detection.nearend_average_blocks, + cfg_transformed.suppressor.subband_nearend_detection + .nearend_average_blocks); + EXPECT_EQ(cfg.suppressor.subband_nearend_detection.subband1.low, + cfg_transformed.suppressor.subband_nearend_detection.subband1.low); + EXPECT_EQ(cfg.suppressor.subband_nearend_detection.subband1.high, + cfg_transformed.suppressor.subband_nearend_detection.subband1.high); + EXPECT_EQ(cfg.suppressor.subband_nearend_detection.subband2.low, + cfg_transformed.suppressor.subband_nearend_detection.subband2.low); + EXPECT_EQ(cfg.suppressor.subband_nearend_detection.subband2.high, + cfg_transformed.suppressor.subband_nearend_detection.subband2.high); + EXPECT_EQ( + cfg.suppressor.subband_nearend_detection.nearend_threshold, + cfg_transformed.suppressor.subband_nearend_detection.nearend_threshold); + EXPECT_EQ(cfg.suppressor.subband_nearend_detection.snr_threshold, + cfg_transformed.suppressor.subband_nearend_detection.snr_threshold); + EXPECT_EQ(cfg.multi_channel.detect_stereo_content, + cfg_transformed.multi_channel.detect_stereo_content); + EXPECT_EQ(cfg.multi_channel.stereo_detection_threshold, + cfg_transformed.multi_channel.stereo_detection_threshold); + EXPECT_EQ( + cfg.multi_channel.stereo_detection_timeout_threshold_seconds, + cfg_transformed.multi_channel.stereo_detection_timeout_threshold_seconds); + EXPECT_EQ(cfg.multi_channel.stereo_detection_hysteresis_seconds, + cfg_transformed.multi_channel.stereo_detection_hysteresis_seconds); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio/test/echo_canceller3_config_unittest.cc b/third_party/libwebrtc/api/audio/test/echo_canceller3_config_unittest.cc new file mode 100644 index 0000000000..91312a0f40 --- /dev/null +++ b/third_party/libwebrtc/api/audio/test/echo_canceller3_config_unittest.cc @@ -0,0 +1,46 @@ +/* + * Copyright 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 "api/audio/echo_canceller3_config.h" + +#include "api/audio/echo_canceller3_config_json.h" +#include "test/gtest.h" + +namespace webrtc { + +TEST(EchoCanceller3Config, ValidConfigIsNotModified) { + EchoCanceller3Config config; + EXPECT_TRUE(EchoCanceller3Config::Validate(&config)); + EchoCanceller3Config default_config; + EXPECT_EQ(Aec3ConfigToJsonString(config), + Aec3ConfigToJsonString(default_config)); +} + +TEST(EchoCanceller3Config, InvalidConfigIsCorrected) { + // Change a parameter and validate. + EchoCanceller3Config config; + config.echo_model.min_noise_floor_power = -1600000.f; + EXPECT_FALSE(EchoCanceller3Config::Validate(&config)); + EXPECT_GE(config.echo_model.min_noise_floor_power, 0.f); + // Verify remaining parameters are unchanged. + EchoCanceller3Config default_config; + config.echo_model.min_noise_floor_power = + default_config.echo_model.min_noise_floor_power; + EXPECT_EQ(Aec3ConfigToJsonString(config), + Aec3ConfigToJsonString(default_config)); +} + +TEST(EchoCanceller3Config, ValidatedConfigsAreValid) { + EchoCanceller3Config config; + config.delay.down_sampling_factor = 983; + EXPECT_FALSE(EchoCanceller3Config::Validate(&config)); + EXPECT_TRUE(EchoCanceller3Config::Validate(&config)); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/BUILD.gn b/third_party/libwebrtc/api/audio_codecs/BUILD.gn new file mode 100644 index 0000000000..82ed31a5da --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/BUILD.gn @@ -0,0 +1,144 @@ +# 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. + +import("../../webrtc.gni") +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +rtc_library("audio_codecs_api") { + visibility = [ "*" ] + sources = [ + "audio_codec_pair_id.cc", + "audio_codec_pair_id.h", + "audio_decoder.cc", + "audio_decoder.h", + "audio_decoder_factory.h", + "audio_decoder_factory_template.h", + "audio_encoder.cc", + "audio_encoder.h", + "audio_encoder_factory.h", + "audio_encoder_factory_template.h", + "audio_format.cc", + "audio_format.h", + ] + deps = [ + "..:array_view", + "..:bitrate_allocation", + "..:make_ref_counted", + "..:scoped_refptr", + "../../api:field_trials_view", + "../../rtc_base:buffer", + "../../rtc_base:checks", + "../../rtc_base:event_tracer", + "../../rtc_base:refcount", + "../../rtc_base:sanitizer", + "../../rtc_base/system:rtc_export", + "../units:time_delta", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("builtin_audio_decoder_factory") { + visibility = [ "*" ] + allow_poison = [ "audio_codecs" ] + sources = [ + "builtin_audio_decoder_factory.cc", + "builtin_audio_decoder_factory.h", + ] + deps = [ + ":audio_codecs_api", + "..:scoped_refptr", + "L16:audio_decoder_L16", + "g711:audio_decoder_g711", + "g722:audio_decoder_g722", + ] + defines = [] + if (rtc_include_ilbc) { + deps += [ "ilbc:audio_decoder_ilbc" ] + defines += [ "WEBRTC_USE_BUILTIN_ILBC=1" ] + } else { + defines += [ "WEBRTC_USE_BUILTIN_ILBC=0" ] + } + if (rtc_include_opus) { + deps += [ + "opus:audio_decoder_multiopus", + "opus:audio_decoder_opus", + ] + defines += [ "WEBRTC_USE_BUILTIN_OPUS=1" ] + } else { + defines += [ "WEBRTC_USE_BUILTIN_OPUS=0" ] + } +} + +rtc_library("builtin_audio_encoder_factory") { + visibility = [ "*" ] + allow_poison = [ "audio_codecs" ] + sources = [ + "builtin_audio_encoder_factory.cc", + "builtin_audio_encoder_factory.h", + ] + deps = [ + ":audio_codecs_api", + "..:scoped_refptr", + "L16:audio_encoder_L16", + "g711:audio_encoder_g711", + "g722:audio_encoder_g722", + ] + defines = [] + if (rtc_include_ilbc) { + deps += [ "ilbc:audio_encoder_ilbc" ] + defines += [ "WEBRTC_USE_BUILTIN_ILBC=1" ] + } else { + defines += [ "WEBRTC_USE_BUILTIN_ILBC=0" ] + } + if (rtc_include_opus) { + deps += [ + "opus:audio_encoder_multiopus", + "opus:audio_encoder_opus", + ] + defines += [ "WEBRTC_USE_BUILTIN_OPUS=1" ] + } else { + defines += [ "WEBRTC_USE_BUILTIN_OPUS=0" ] + } +} + +rtc_library("opus_audio_decoder_factory") { + visibility = [ "*" ] + allow_poison = [ "audio_codecs" ] + sources = [ + "opus_audio_decoder_factory.cc", + "opus_audio_decoder_factory.h", + ] + deps = [ + ":audio_codecs_api", + "..:scoped_refptr", + "opus:audio_decoder_multiopus", + "opus:audio_decoder_opus", + ] +} + +rtc_library("opus_audio_encoder_factory") { + visibility = [ "*" ] + allow_poison = [ "audio_codecs" ] + sources = [ + "opus_audio_encoder_factory.cc", + "opus_audio_encoder_factory.h", + ] + deps = [ + ":audio_codecs_api", + "..:scoped_refptr", + "opus:audio_encoder_multiopus", + "opus:audio_encoder_opus", + ] +} diff --git a/third_party/libwebrtc/api/audio_codecs/L16/BUILD.gn b/third_party/libwebrtc/api/audio_codecs/L16/BUILD.gn new file mode 100644 index 0000000000..41e9eb42d8 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/L16/BUILD.gn @@ -0,0 +1,55 @@ +# 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. + +import("../../../webrtc.gni") +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +rtc_library("audio_encoder_L16") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + sources = [ + "audio_encoder_L16.cc", + "audio_encoder_L16.h", + ] + deps = [ + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:pcm16b", + "../../../rtc_base:safe_conversions", + "../../../rtc_base:safe_minmax", + "../../../rtc_base:stringutils", + "../../../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("audio_decoder_L16") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + sources = [ + "audio_decoder_L16.cc", + "audio_decoder_L16.h", + ] + deps = [ + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:pcm16b", + "../../../rtc_base:safe_conversions", + "../../../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} diff --git a/third_party/libwebrtc/api/audio_codecs/L16/audio_decoder_L16.cc b/third_party/libwebrtc/api/audio_codecs/L16/audio_decoder_L16.cc new file mode 100644 index 0000000000..a03abe26f7 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/L16/audio_decoder_L16.cc @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#include "api/audio_codecs/L16/audio_decoder_L16.h" + +#include <memory> + +#include "absl/strings/match.h" +#include "modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h" +#include "modules/audio_coding/codecs/pcm16b/pcm16b_common.h" +#include "rtc_base/numerics/safe_conversions.h" + +namespace webrtc { + +absl::optional<AudioDecoderL16::Config> AudioDecoderL16::SdpToConfig( + const SdpAudioFormat& format) { + Config config; + config.sample_rate_hz = format.clockrate_hz; + config.num_channels = rtc::checked_cast<int>(format.num_channels); + if (absl::EqualsIgnoreCase(format.name, "L16") && config.IsOk()) { + return config; + } + return absl::nullopt; +} + +void AudioDecoderL16::AppendSupportedDecoders( + std::vector<AudioCodecSpec>* specs) { + Pcm16BAppendSupportedCodecSpecs(specs); +} + +std::unique_ptr<AudioDecoder> AudioDecoderL16::MakeAudioDecoder( + const Config& config, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + if (!config.IsOk()) { + return nullptr; + } + return std::make_unique<AudioDecoderPcm16B>(config.sample_rate_hz, + config.num_channels); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/L16/audio_decoder_L16.h b/third_party/libwebrtc/api/audio_codecs/L16/audio_decoder_L16.h new file mode 100644 index 0000000000..5a01b7dc01 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/L16/audio_decoder_L16.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_L16_AUDIO_DECODER_L16_H_ +#define API_AUDIO_CODECS_L16_AUDIO_DECODER_L16_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_decoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/field_trials_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// L16 decoder API for use as a template parameter to +// CreateAudioDecoderFactory<...>(). +struct RTC_EXPORT AudioDecoderL16 { + struct Config { + bool IsOk() const { + return (sample_rate_hz == 8000 || sample_rate_hz == 16000 || + sample_rate_hz == 32000 || sample_rate_hz == 48000) && + (num_channels >= 1 && + num_channels <= AudioDecoder::kMaxNumberOfChannels); + } + int sample_rate_hz = 8000; + int num_channels = 1; + }; + static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format); + static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs); + static std::unique_ptr<AudioDecoder> MakeAudioDecoder( + const Config& config, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_L16_AUDIO_DECODER_L16_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/L16/audio_decoder_L16_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/L16/audio_decoder_L16_gn/moz.build new file mode 100644 index 0000000000..87335c298d --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/L16/audio_decoder_L16_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/L16/audio_decoder_L16.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_decoder_L16_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/L16/audio_encoder_L16.cc b/third_party/libwebrtc/api/audio_codecs/L16/audio_encoder_L16.cc new file mode 100644 index 0000000000..20259b9ad8 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/L16/audio_encoder_L16.cc @@ -0,0 +1,76 @@ +/* + * 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. + */ + +#include "api/audio_codecs/L16/audio_encoder_L16.h" + +#include <memory> + +#include "absl/strings/match.h" +#include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h" +#include "modules/audio_coding/codecs/pcm16b/pcm16b_common.h" +#include "rtc_base/numerics/safe_conversions.h" +#include "rtc_base/numerics/safe_minmax.h" +#include "rtc_base/string_to_number.h" + +namespace webrtc { + +absl::optional<AudioEncoderL16::Config> AudioEncoderL16::SdpToConfig( + const SdpAudioFormat& format) { + if (!rtc::IsValueInRangeForNumericType<int>(format.num_channels)) { + RTC_DCHECK_NOTREACHED(); + return absl::nullopt; + } + Config config; + config.sample_rate_hz = format.clockrate_hz; + config.num_channels = rtc::dchecked_cast<int>(format.num_channels); + auto ptime_iter = format.parameters.find("ptime"); + if (ptime_iter != format.parameters.end()) { + const auto ptime = rtc::StringToNumber<int>(ptime_iter->second); + if (ptime && *ptime > 0) { + config.frame_size_ms = rtc::SafeClamp(10 * (*ptime / 10), 10, 60); + } + } + if (absl::EqualsIgnoreCase(format.name, "L16") && config.IsOk()) { + return config; + } + return absl::nullopt; +} + +void AudioEncoderL16::AppendSupportedEncoders( + std::vector<AudioCodecSpec>* specs) { + Pcm16BAppendSupportedCodecSpecs(specs); +} + +AudioCodecInfo AudioEncoderL16::QueryAudioEncoder( + const AudioEncoderL16::Config& config) { + RTC_DCHECK(config.IsOk()); + return {config.sample_rate_hz, + rtc::dchecked_cast<size_t>(config.num_channels), + config.sample_rate_hz * config.num_channels * 16}; +} + +std::unique_ptr<AudioEncoder> AudioEncoderL16::MakeAudioEncoder( + const AudioEncoderL16::Config& config, + int payload_type, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + AudioEncoderPcm16B::Config c; + c.sample_rate_hz = config.sample_rate_hz; + c.num_channels = config.num_channels; + c.frame_size_ms = config.frame_size_ms; + c.payload_type = payload_type; + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return nullptr; + } + return std::make_unique<AudioEncoderPcm16B>(c); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/L16/audio_encoder_L16.h b/third_party/libwebrtc/api/audio_codecs/L16/audio_encoder_L16.h new file mode 100644 index 0000000000..47509849de --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/L16/audio_encoder_L16.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_L16_AUDIO_ENCODER_L16_H_ +#define API_AUDIO_CODECS_L16_AUDIO_ENCODER_L16_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_encoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/field_trials_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// L16 encoder API for use as a template parameter to +// CreateAudioEncoderFactory<...>(). +struct RTC_EXPORT AudioEncoderL16 { + struct Config { + bool IsOk() const { + return (sample_rate_hz == 8000 || sample_rate_hz == 16000 || + sample_rate_hz == 32000 || sample_rate_hz == 48000) && + num_channels >= 1 && + num_channels <= AudioEncoder::kMaxNumberOfChannels && + frame_size_ms > 0 && frame_size_ms <= 120 && + frame_size_ms % 10 == 0; + } + int sample_rate_hz = 8000; + int num_channels = 1; + int frame_size_ms = 10; + }; + static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format); + static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs); + static AudioCodecInfo QueryAudioEncoder(const Config& config); + static std::unique_ptr<AudioEncoder> MakeAudioEncoder( + const Config& config, + int payload_type, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_L16_AUDIO_ENCODER_L16_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/L16/audio_encoder_L16_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/L16/audio_encoder_L16_gn/moz.build new file mode 100644 index 0000000000..49e0d546f1 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/L16/audio_encoder_L16_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/L16/audio_encoder_L16.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_encoder_L16_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/OWNERS b/third_party/libwebrtc/api/audio_codecs/OWNERS new file mode 100644 index 0000000000..77b414abc3 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/OWNERS @@ -0,0 +1,3 @@ +alessiob@webrtc.org +henrik.lundin@webrtc.org +jakobi@webrtc.org diff --git a/third_party/libwebrtc/api/audio_codecs/audio_codec_pair_id.cc b/third_party/libwebrtc/api/audio_codecs/audio_codec_pair_id.cc new file mode 100644 index 0000000000..6cb51ed6b7 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_codec_pair_id.cc @@ -0,0 +1,91 @@ +/* + * 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 "api/audio_codecs/audio_codec_pair_id.h" + +#include <atomic> +#include <cstdint> + +#include "rtc_base/checks.h" + +namespace webrtc { + +namespace { + +// Returns a new value that it has never returned before. You may call it at +// most 2^63 times in the lifetime of the program. Note: The returned values +// may be easily predictable. +uint64_t GetNextId() { + static std::atomic<uint64_t> next_id(0); + + // Atomically increment `next_id`, and return the previous value. Relaxed + // memory order is sufficient, since all we care about is that different + // callers return different values. + const uint64_t new_id = next_id.fetch_add(1, std::memory_order_relaxed); + + // This check isn't atomic with the increment, so if we start 2^63 + 1 + // invocations of GetNextId() in parallel, the last one to do the atomic + // increment could return the ID 0 before any of the others had time to + // trigger this DCHECK. We blithely assume that this won't happen. + RTC_DCHECK_LT(new_id, uint64_t{1} << 63) << "Used up all ID values"; + + return new_id; +} + +// Make an integer ID more unpredictable. This is a 1:1 mapping, so you can +// feed it any value, but the idea is that you can feed it a sequence such as +// 0, 1, 2, ... and get a new sequence that isn't as trivially predictable, so +// that users won't rely on it being consecutive or increasing or anything like +// that. +constexpr uint64_t ObfuscateId(uint64_t id) { + // Any nonzero coefficient that's relatively prime to 2^64 (that is, any odd + // number) and any constant will give a 1:1 mapping. These high-entropy + // values will prevent the sequence from being trivially predictable. + // + // Both the multiplication and the addition going to overflow almost always, + // but that's fine---we *want* arithmetic mod 2^64. + return uint64_t{0x85fdb20e1294309a} + uint64_t{0xc516ef5c37462469} * id; +} + +// The first ten values. Verified against the Python function +// +// def f(n): +// return (0x85fdb20e1294309a + 0xc516ef5c37462469 * n) % 2**64 +// +// Callers should obviously not depend on these exact values... +// +// (On Visual C++, we have to disable warning C4307 (integral constant +// overflow), even though unsigned integers have perfectly well-defined +// overflow behavior.) +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4307) +#endif +static_assert(ObfuscateId(0) == uint64_t{0x85fdb20e1294309a}, ""); +static_assert(ObfuscateId(1) == uint64_t{0x4b14a16a49da5503}, ""); +static_assert(ObfuscateId(2) == uint64_t{0x102b90c68120796c}, ""); +static_assert(ObfuscateId(3) == uint64_t{0xd5428022b8669dd5}, ""); +static_assert(ObfuscateId(4) == uint64_t{0x9a596f7eefacc23e}, ""); +static_assert(ObfuscateId(5) == uint64_t{0x5f705edb26f2e6a7}, ""); +static_assert(ObfuscateId(6) == uint64_t{0x24874e375e390b10}, ""); +static_assert(ObfuscateId(7) == uint64_t{0xe99e3d93957f2f79}, ""); +static_assert(ObfuscateId(8) == uint64_t{0xaeb52cefccc553e2}, ""); +static_assert(ObfuscateId(9) == uint64_t{0x73cc1c4c040b784b}, ""); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +} // namespace + +AudioCodecPairId AudioCodecPairId::Create() { + return AudioCodecPairId(ObfuscateId(GetNextId())); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/audio_codec_pair_id.h b/third_party/libwebrtc/api/audio_codecs/audio_codec_pair_id.h new file mode 100644 index 0000000000..b10f14ea66 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_codec_pair_id.h @@ -0,0 +1,74 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_AUDIO_CODEC_PAIR_ID_H_ +#define API_AUDIO_CODECS_AUDIO_CODEC_PAIR_ID_H_ + +#include <stdint.h> + +#include <utility> + +namespace webrtc { + +class AudioCodecPairId final { + public: + // Copyable, but not default constructible. + AudioCodecPairId() = delete; + AudioCodecPairId(const AudioCodecPairId&) = default; + AudioCodecPairId(AudioCodecPairId&&) = default; + AudioCodecPairId& operator=(const AudioCodecPairId&) = default; + AudioCodecPairId& operator=(AudioCodecPairId&&) = default; + + friend void swap(AudioCodecPairId& a, AudioCodecPairId& b) { + using std::swap; + swap(a.id_, b.id_); + } + + // Creates a new ID, unequal to any previously created ID. + static AudioCodecPairId Create(); + + // IDs can be tested for equality. + friend bool operator==(AudioCodecPairId a, AudioCodecPairId b) { + return a.id_ == b.id_; + } + friend bool operator!=(AudioCodecPairId a, AudioCodecPairId b) { + return a.id_ != b.id_; + } + + // Comparisons. The ordering of ID values is completely arbitrary, but + // stable, so it's useful e.g. if you want to use IDs as keys in an ordered + // map. + friend bool operator<(AudioCodecPairId a, AudioCodecPairId b) { + return a.id_ < b.id_; + } + friend bool operator<=(AudioCodecPairId a, AudioCodecPairId b) { + return a.id_ <= b.id_; + } + friend bool operator>=(AudioCodecPairId a, AudioCodecPairId b) { + return a.id_ >= b.id_; + } + friend bool operator>(AudioCodecPairId a, AudioCodecPairId b) { + return a.id_ > b.id_; + } + + // Returns a numeric representation of the ID. The numeric values are + // completely arbitrary, but stable, collision-free, and reasonably evenly + // distributed, so they are e.g. useful as hash values in unordered maps. + uint64_t NumericRepresentation() const { return id_; } + + private: + explicit AudioCodecPairId(uint64_t id) : id_(id) {} + + uint64_t id_; +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_AUDIO_CODEC_PAIR_ID_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/audio_codecs_api_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/audio_codecs_api_gn/moz.build new file mode 100644 index 0000000000..846946073e --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_codecs_api_gn/moz.build @@ -0,0 +1,228 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/audio_codec_pair_id.cc", + "/third_party/libwebrtc/api/audio_codecs/audio_decoder.cc", + "/third_party/libwebrtc/api/audio_codecs/audio_encoder.cc", + "/third_party/libwebrtc/api/audio_codecs/audio_format.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_codecs_api_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/audio_decoder.cc b/third_party/libwebrtc/api/audio_codecs/audio_decoder.cc new file mode 100644 index 0000000000..28f5b8aae8 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_decoder.cc @@ -0,0 +1,170 @@ +/* + * 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 "api/audio_codecs/audio_decoder.h" + + +#include <memory> +#include <utility> + +#include "api/array_view.h" +#include "rtc_base/checks.h" +#include "rtc_base/sanitizer.h" +#include "rtc_base/trace_event.h" + +namespace webrtc { + +namespace { + +class OldStyleEncodedFrame final : public AudioDecoder::EncodedAudioFrame { + public: + OldStyleEncodedFrame(AudioDecoder* decoder, rtc::Buffer&& payload) + : decoder_(decoder), payload_(std::move(payload)) {} + + size_t Duration() const override { + const int ret = decoder_->PacketDuration(payload_.data(), payload_.size()); + return ret < 0 ? 0 : static_cast<size_t>(ret); + } + + absl::optional<DecodeResult> Decode( + rtc::ArrayView<int16_t> decoded) const override { + auto speech_type = AudioDecoder::kSpeech; + const int ret = decoder_->Decode( + payload_.data(), payload_.size(), decoder_->SampleRateHz(), + decoded.size() * sizeof(int16_t), decoded.data(), &speech_type); + return ret < 0 ? absl::nullopt + : absl::optional<DecodeResult>( + {static_cast<size_t>(ret), speech_type}); + } + + private: + AudioDecoder* const decoder_; + const rtc::Buffer payload_; +}; + +} // namespace + +bool AudioDecoder::EncodedAudioFrame::IsDtxPacket() const { + return false; +} + +AudioDecoder::ParseResult::ParseResult() = default; +AudioDecoder::ParseResult::ParseResult(ParseResult&& b) = default; +AudioDecoder::ParseResult::ParseResult(uint32_t timestamp, + int priority, + std::unique_ptr<EncodedAudioFrame> frame) + : timestamp(timestamp), priority(priority), frame(std::move(frame)) { + RTC_DCHECK_GE(priority, 0); +} + +AudioDecoder::ParseResult::~ParseResult() = default; + +AudioDecoder::ParseResult& AudioDecoder::ParseResult::operator=( + ParseResult&& b) = default; + +std::vector<AudioDecoder::ParseResult> AudioDecoder::ParsePayload( + rtc::Buffer&& payload, + uint32_t timestamp) { + std::vector<ParseResult> results; + std::unique_ptr<EncodedAudioFrame> frame( + new OldStyleEncodedFrame(this, std::move(payload))); + results.emplace_back(timestamp, 0, std::move(frame)); + return results; +} + +int AudioDecoder::Decode(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + size_t max_decoded_bytes, + int16_t* decoded, + SpeechType* speech_type) { + TRACE_EVENT0("webrtc", "AudioDecoder::Decode"); + rtc::MsanCheckInitialized(rtc::MakeArrayView(encoded, encoded_len)); + int duration = PacketDuration(encoded, encoded_len); + if (duration >= 0 && + duration * Channels() * sizeof(int16_t) > max_decoded_bytes) { + return -1; + } + return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded, + speech_type); +} + +int AudioDecoder::DecodeRedundant(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + size_t max_decoded_bytes, + int16_t* decoded, + SpeechType* speech_type) { + TRACE_EVENT0("webrtc", "AudioDecoder::DecodeRedundant"); + rtc::MsanCheckInitialized(rtc::MakeArrayView(encoded, encoded_len)); + int duration = PacketDurationRedundant(encoded, encoded_len); + if (duration >= 0 && + duration * Channels() * sizeof(int16_t) > max_decoded_bytes) { + return -1; + } + return DecodeRedundantInternal(encoded, encoded_len, sample_rate_hz, decoded, + speech_type); +} + +int AudioDecoder::DecodeRedundantInternal(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + int16_t* decoded, + SpeechType* speech_type) { + return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded, + speech_type); +} + +bool AudioDecoder::HasDecodePlc() const { + return false; +} + +size_t AudioDecoder::DecodePlc(size_t num_frames, int16_t* decoded) { + return 0; +} + +// TODO(bugs.webrtc.org/9676): Remove default implementation. +void AudioDecoder::GeneratePlc(size_t /*requested_samples_per_channel*/, + rtc::BufferT<int16_t>* /*concealment_audio*/) {} + +int AudioDecoder::ErrorCode() { + return 0; +} + +int AudioDecoder::PacketDuration(const uint8_t* encoded, + size_t encoded_len) const { + return kNotImplemented; +} + +int AudioDecoder::PacketDurationRedundant(const uint8_t* encoded, + size_t encoded_len) const { + return kNotImplemented; +} + +bool AudioDecoder::PacketHasFec(const uint8_t* encoded, + size_t encoded_len) const { + return false; +} + +AudioDecoder::SpeechType AudioDecoder::ConvertSpeechType(int16_t type) { + switch (type) { + case 0: // TODO(hlundin): Both iSAC and Opus return 0 for speech. + case 1: + return kSpeech; + case 2: + return kComfortNoise; + default: + RTC_DCHECK_NOTREACHED(); + return kSpeech; + } +} + +constexpr int AudioDecoder::kMaxNumberOfChannels; +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/audio_decoder.h b/third_party/libwebrtc/api/audio_codecs/audio_decoder.h new file mode 100644 index 0000000000..41138741bb --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_decoder.h @@ -0,0 +1,195 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_AUDIO_DECODER_H_ +#define API_AUDIO_CODECS_AUDIO_DECODER_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "rtc_base/buffer.h" + +namespace webrtc { + +class AudioDecoder { + public: + enum SpeechType { + kSpeech = 1, + kComfortNoise = 2, + }; + + // Used by PacketDuration below. Save the value -1 for errors. + enum { kNotImplemented = -2 }; + + AudioDecoder() = default; + virtual ~AudioDecoder() = default; + + AudioDecoder(const AudioDecoder&) = delete; + AudioDecoder& operator=(const AudioDecoder&) = delete; + + class EncodedAudioFrame { + public: + struct DecodeResult { + size_t num_decoded_samples; + SpeechType speech_type; + }; + + virtual ~EncodedAudioFrame() = default; + + // Returns the duration in samples-per-channel of this audio frame. + // If no duration can be ascertained, returns zero. + virtual size_t Duration() const = 0; + + // Returns true if this packet contains DTX. + virtual bool IsDtxPacket() const; + + // Decodes this frame of audio and writes the result in `decoded`. + // `decoded` must be large enough to store as many samples as indicated by a + // call to Duration() . On success, returns an absl::optional containing the + // total number of samples across all channels, as well as whether the + // decoder produced comfort noise or speech. On failure, returns an empty + // absl::optional. Decode may be called at most once per frame object. + virtual absl::optional<DecodeResult> Decode( + rtc::ArrayView<int16_t> decoded) const = 0; + }; + + struct ParseResult { + ParseResult(); + ParseResult(uint32_t timestamp, + int priority, + std::unique_ptr<EncodedAudioFrame> frame); + ParseResult(ParseResult&& b); + ~ParseResult(); + + ParseResult& operator=(ParseResult&& b); + + // The timestamp of the frame is in samples per channel. + uint32_t timestamp; + // The relative priority of the frame compared to other frames of the same + // payload and the same timeframe. A higher value means a lower priority. + // The highest priority is zero - negative values are not allowed. + int priority; + std::unique_ptr<EncodedAudioFrame> frame; + }; + + // Let the decoder parse this payload and prepare zero or more decodable + // frames. Each frame must be between 10 ms and 120 ms long. The caller must + // ensure that the AudioDecoder object outlives any frame objects returned by + // this call. The decoder is free to swap or move the data from the `payload` + // buffer. `timestamp` is the input timestamp, in samples, corresponding to + // the start of the payload. + virtual std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload, + uint32_t timestamp); + + // TODO(bugs.webrtc.org/10098): The Decode and DecodeRedundant methods are + // obsolete; callers should call ParsePayload instead. For now, subclasses + // must still implement DecodeInternal. + + // Decodes `encode_len` bytes from `encoded` and writes the result in + // `decoded`. The maximum bytes allowed to be written into `decoded` is + // `max_decoded_bytes`. Returns the total number of samples across all + // channels. If the decoder produced comfort noise, `speech_type` + // is set to kComfortNoise, otherwise it is kSpeech. The desired output + // sample rate is provided in `sample_rate_hz`, which must be valid for the + // codec at hand. + int Decode(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + size_t max_decoded_bytes, + int16_t* decoded, + SpeechType* speech_type); + + // Same as Decode(), but interfaces to the decoders redundant decode function. + // The default implementation simply calls the regular Decode() method. + int DecodeRedundant(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + size_t max_decoded_bytes, + int16_t* decoded, + SpeechType* speech_type); + + // Indicates if the decoder implements the DecodePlc method. + virtual bool HasDecodePlc() const; + + // Calls the packet-loss concealment of the decoder to update the state after + // one or several lost packets. The caller has to make sure that the + // memory allocated in `decoded` should accommodate `num_frames` frames. + virtual size_t DecodePlc(size_t num_frames, int16_t* decoded); + + // Asks the decoder to generate packet-loss concealment and append it to the + // end of `concealment_audio`. The concealment audio should be in + // channel-interleaved format, with as many channels as the last decoded + // packet produced. The implementation must produce at least + // requested_samples_per_channel, or nothing at all. This is a signal to the + // caller to conceal the loss with other means. If the implementation provides + // concealment samples, it is also responsible for "stitching" it together + // with the decoded audio on either side of the concealment. + // Note: The default implementation of GeneratePlc will be deleted soon. All + // implementations must provide their own, which can be a simple as a no-op. + // TODO(bugs.webrtc.org/9676): Remove default implementation. + virtual void GeneratePlc(size_t requested_samples_per_channel, + rtc::BufferT<int16_t>* concealment_audio); + + // Resets the decoder state (empty buffers etc.). + virtual void Reset() = 0; + + // Returns the last error code from the decoder. + virtual int ErrorCode(); + + // Returns the duration in samples-per-channel of the payload in `encoded` + // which is `encoded_len` bytes long. Returns kNotImplemented if no duration + // estimate is available, or -1 in case of an error. + virtual int PacketDuration(const uint8_t* encoded, size_t encoded_len) const; + + // Returns the duration in samples-per-channel of the redandant payload in + // `encoded` which is `encoded_len` bytes long. Returns kNotImplemented if no + // duration estimate is available, or -1 in case of an error. + virtual int PacketDurationRedundant(const uint8_t* encoded, + size_t encoded_len) const; + + // Detects whether a packet has forward error correction. The packet is + // comprised of the samples in `encoded` which is `encoded_len` bytes long. + // Returns true if the packet has FEC and false otherwise. + virtual bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const; + + // Returns the actual sample rate of the decoder's output. This value may not + // change during the lifetime of the decoder. + virtual int SampleRateHz() const = 0; + + // The number of channels in the decoder's output. This value may not change + // during the lifetime of the decoder. + virtual size_t Channels() const = 0; + + // The maximum number of audio channels supported by WebRTC decoders. + static constexpr int kMaxNumberOfChannels = 24; + + protected: + static SpeechType ConvertSpeechType(int16_t type); + + virtual int DecodeInternal(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + int16_t* decoded, + SpeechType* speech_type) = 0; + + virtual int DecodeRedundantInternal(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + int16_t* decoded, + SpeechType* speech_type); +}; + +} // namespace webrtc +#endif // API_AUDIO_CODECS_AUDIO_DECODER_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/audio_decoder_factory.h b/third_party/libwebrtc/api/audio_codecs/audio_decoder_factory.h new file mode 100644 index 0000000000..2811f6704b --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_decoder_factory.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_H_ +#define API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_decoder.h" +#include "api/audio_codecs/audio_format.h" +#include "rtc_base/ref_count.h" + +namespace webrtc { + +// A factory that creates AudioDecoders. +class AudioDecoderFactory : public rtc::RefCountInterface { + public: + virtual std::vector<AudioCodecSpec> GetSupportedDecoders() = 0; + + virtual bool IsSupportedDecoder(const SdpAudioFormat& format) = 0; + + // Create a new decoder instance. The `codec_pair_id` argument is used to link + // encoders and decoders that talk to the same remote entity: if a + // AudioEncoderFactory::MakeAudioEncoder() and a + // AudioDecoderFactory::MakeAudioDecoder() call receive non-null IDs that + // compare equal, the factory implementations may assume that the encoder and + // decoder form a pair. (The intended use case for this is to set up + // communication between the AudioEncoder and AudioDecoder instances, which is + // needed for some codecs with built-in bandwidth adaptation.) + // + // Returns null if the format isn't supported. + // + // Note: Implementations need to be robust against combinations other than + // one encoder, one decoder getting the same ID; such decoders must still + // work. + virtual std::unique_ptr<AudioDecoder> MakeAudioDecoder( + const SdpAudioFormat& format, + absl::optional<AudioCodecPairId> codec_pair_id) = 0; +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/audio_decoder_factory_template.h b/third_party/libwebrtc/api/audio_codecs/audio_decoder_factory_template.h new file mode 100644 index 0000000000..7ea0c91372 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_decoder_factory_template.h @@ -0,0 +1,145 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_TEMPLATE_H_ +#define API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_TEMPLATE_H_ + +#include <memory> +#include <vector> + +#include "api/audio_codecs/audio_decoder_factory.h" +#include "api/field_trials_view.h" +#include "api/make_ref_counted.h" +#include "api/scoped_refptr.h" + +namespace webrtc { + +namespace audio_decoder_factory_template_impl { + +template <typename... Ts> +struct Helper; + +// Base case: 0 template parameters. +template <> +struct Helper<> { + static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) {} + static bool IsSupportedDecoder(const SdpAudioFormat& format) { return false; } + static std::unique_ptr<AudioDecoder> MakeAudioDecoder( + const SdpAudioFormat& format, + absl::optional<AudioCodecPairId> codec_pair_id, + const FieldTrialsView* field_trials) { + return nullptr; + } +}; + +// Inductive case: Called with n + 1 template parameters; calls subroutines +// with n template parameters. +template <typename T, typename... Ts> +struct Helper<T, Ts...> { + static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) { + T::AppendSupportedDecoders(specs); + Helper<Ts...>::AppendSupportedDecoders(specs); + } + static bool IsSupportedDecoder(const SdpAudioFormat& format) { + auto opt_config = T::SdpToConfig(format); + static_assert(std::is_same<decltype(opt_config), + absl::optional<typename T::Config>>::value, + "T::SdpToConfig() must return a value of type " + "absl::optional<T::Config>"); + return opt_config ? true : Helper<Ts...>::IsSupportedDecoder(format); + } + static std::unique_ptr<AudioDecoder> MakeAudioDecoder( + const SdpAudioFormat& format, + absl::optional<AudioCodecPairId> codec_pair_id, + const FieldTrialsView* field_trials) { + auto opt_config = T::SdpToConfig(format); + return opt_config ? T::MakeAudioDecoder(*opt_config, codec_pair_id) + : Helper<Ts...>::MakeAudioDecoder(format, codec_pair_id, + field_trials); + } +}; + +template <typename... Ts> +class AudioDecoderFactoryT : public AudioDecoderFactory { + public: + explicit AudioDecoderFactoryT(const FieldTrialsView* field_trials) { + field_trials_ = field_trials; + } + + std::vector<AudioCodecSpec> GetSupportedDecoders() override { + std::vector<AudioCodecSpec> specs; + Helper<Ts...>::AppendSupportedDecoders(&specs); + return specs; + } + + bool IsSupportedDecoder(const SdpAudioFormat& format) override { + return Helper<Ts...>::IsSupportedDecoder(format); + } + + std::unique_ptr<AudioDecoder> MakeAudioDecoder( + const SdpAudioFormat& format, + absl::optional<AudioCodecPairId> codec_pair_id) override { + return Helper<Ts...>::MakeAudioDecoder(format, codec_pair_id, + field_trials_); + } + + const FieldTrialsView* field_trials_; +}; + +} // namespace audio_decoder_factory_template_impl + +// Make an AudioDecoderFactory that can create instances of the given decoders. +// +// Each decoder type is given as a template argument to the function; it should +// be a struct with the following static member functions: +// +// // Converts `audio_format` to a ConfigType instance. Returns an empty +// // optional if `audio_format` doesn't correctly specify a decoder of our +// // type. +// absl::optional<ConfigType> SdpToConfig(const SdpAudioFormat& audio_format); +// +// // Appends zero or more AudioCodecSpecs to the list that will be returned +// // by AudioDecoderFactory::GetSupportedDecoders(). +// void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs); +// +// // Creates an AudioDecoder for the specified format. Used to implement +// // AudioDecoderFactory::MakeAudioDecoder(). +// std::unique_ptr<AudioDecoder> MakeAudioDecoder( +// const ConfigType& config, +// absl::optional<AudioCodecPairId> codec_pair_id); +// +// ConfigType should be a type that encapsulates all the settings needed to +// create an AudioDecoder. T::Config (where T is the decoder struct) should +// either be the config type, or an alias for it. +// +// Whenever it tries to do something, the new factory will try each of the +// decoder types in the order they were specified in the template argument +// list, stopping at the first one that claims to be able to do the job. +// +// TODO(kwiberg): Point at CreateBuiltinAudioDecoderFactory() for an example of +// how it is used. +template <typename... Ts> +rtc::scoped_refptr<AudioDecoderFactory> CreateAudioDecoderFactory( + const FieldTrialsView* field_trials = nullptr) { + // There's no technical reason we couldn't allow zero template parameters, + // but such a factory couldn't create any decoders, and callers can do this + // by mistake by simply forgetting the <> altogether. So we forbid it in + // order to prevent caller foot-shooting. + static_assert(sizeof...(Ts) >= 1, + "Caller must give at least one template parameter"); + + return rtc::make_ref_counted< + audio_decoder_factory_template_impl::AudioDecoderFactoryT<Ts...>>( + field_trials); +} + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_TEMPLATE_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/audio_encoder.cc b/third_party/libwebrtc/api/audio_codecs/audio_encoder.cc new file mode 100644 index 0000000000..31bb8739f7 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_encoder.cc @@ -0,0 +1,114 @@ +/* + * 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. + */ + +#include "api/audio_codecs/audio_encoder.h" + +#include "rtc_base/checks.h" +#include "rtc_base/trace_event.h" + +namespace webrtc { + +ANAStats::ANAStats() = default; +ANAStats::~ANAStats() = default; +ANAStats::ANAStats(const ANAStats&) = default; + +AudioEncoder::EncodedInfo::EncodedInfo() = default; +AudioEncoder::EncodedInfo::EncodedInfo(const EncodedInfo&) = default; +AudioEncoder::EncodedInfo::EncodedInfo(EncodedInfo&&) = default; +AudioEncoder::EncodedInfo::~EncodedInfo() = default; +AudioEncoder::EncodedInfo& AudioEncoder::EncodedInfo::operator=( + const EncodedInfo&) = default; +AudioEncoder::EncodedInfo& AudioEncoder::EncodedInfo::operator=(EncodedInfo&&) = + default; + +int AudioEncoder::RtpTimestampRateHz() const { + return SampleRateHz(); +} + +AudioEncoder::EncodedInfo AudioEncoder::Encode( + uint32_t rtp_timestamp, + rtc::ArrayView<const int16_t> audio, + rtc::Buffer* encoded) { + TRACE_EVENT0("webrtc", "AudioEncoder::Encode"); + RTC_CHECK_EQ(audio.size(), + static_cast<size_t>(NumChannels() * SampleRateHz() / 100)); + + const size_t old_size = encoded->size(); + EncodedInfo info = EncodeImpl(rtp_timestamp, audio, encoded); + RTC_CHECK_EQ(encoded->size() - old_size, info.encoded_bytes); + return info; +} + +bool AudioEncoder::SetFec(bool enable) { + return !enable; +} + +bool AudioEncoder::SetDtx(bool enable) { + return !enable; +} + +bool AudioEncoder::GetDtx() const { + return false; +} + +bool AudioEncoder::SetApplication(Application application) { + return false; +} + +void AudioEncoder::SetMaxPlaybackRate(int frequency_hz) {} + +void AudioEncoder::SetTargetBitrate(int target_bps) {} + +rtc::ArrayView<std::unique_ptr<AudioEncoder>> +AudioEncoder::ReclaimContainedEncoders() { + return nullptr; +} + +bool AudioEncoder::EnableAudioNetworkAdaptor(const std::string& config_string, + RtcEventLog* event_log) { + return false; +} + +void AudioEncoder::DisableAudioNetworkAdaptor() {} + +void AudioEncoder::OnReceivedUplinkPacketLossFraction( + float uplink_packet_loss_fraction) {} + +void AudioEncoder::OnReceivedUplinkRecoverablePacketLossFraction( + float uplink_recoverable_packet_loss_fraction) { + RTC_DCHECK_NOTREACHED(); +} + +void AudioEncoder::OnReceivedTargetAudioBitrate(int target_audio_bitrate_bps) { + OnReceivedUplinkBandwidth(target_audio_bitrate_bps, absl::nullopt); +} + +void AudioEncoder::OnReceivedUplinkBandwidth( + int target_audio_bitrate_bps, + absl::optional<int64_t> bwe_period_ms) {} + +void AudioEncoder::OnReceivedUplinkAllocation(BitrateAllocationUpdate update) { + OnReceivedUplinkBandwidth(update.target_bitrate.bps(), + update.bwe_period.ms()); +} + +void AudioEncoder::OnReceivedRtt(int rtt_ms) {} + +void AudioEncoder::OnReceivedOverhead(size_t overhead_bytes_per_packet) {} + +void AudioEncoder::SetReceiverFrameLengthRange(int min_frame_length_ms, + int max_frame_length_ms) {} + +ANAStats AudioEncoder::GetANAStats() const { + return ANAStats(); +} + +constexpr int AudioEncoder::kMaxNumberOfChannels; +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/audio_encoder.h b/third_party/libwebrtc/api/audio_codecs/audio_encoder.h new file mode 100644 index 0000000000..7f5a34214f --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_encoder.h @@ -0,0 +1,260 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_AUDIO_ENCODER_H_ +#define API_AUDIO_CODECS_AUDIO_ENCODER_H_ + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "absl/base/attributes.h" +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/call/bitrate_allocation.h" +#include "api/units/time_delta.h" +#include "rtc_base/buffer.h" + +namespace webrtc { + +class RtcEventLog; + +// Statistics related to Audio Network Adaptation. +struct ANAStats { + ANAStats(); + ANAStats(const ANAStats&); + ~ANAStats(); + // Number of actions taken by the ANA bitrate controller since the start of + // the call. If this value is not set, it indicates that the bitrate + // controller is disabled. + absl::optional<uint32_t> bitrate_action_counter; + // Number of actions taken by the ANA channel controller since the start of + // the call. If this value is not set, it indicates that the channel + // controller is disabled. + absl::optional<uint32_t> channel_action_counter; + // Number of actions taken by the ANA DTX controller since the start of the + // call. If this value is not set, it indicates that the DTX controller is + // disabled. + absl::optional<uint32_t> dtx_action_counter; + // Number of actions taken by the ANA FEC controller since the start of the + // call. If this value is not set, it indicates that the FEC controller is + // disabled. + absl::optional<uint32_t> fec_action_counter; + // Number of times the ANA frame length controller decided to increase the + // frame length since the start of the call. If this value is not set, it + // indicates that the frame length controller is disabled. + absl::optional<uint32_t> frame_length_increase_counter; + // Number of times the ANA frame length controller decided to decrease the + // frame length since the start of the call. If this value is not set, it + // indicates that the frame length controller is disabled. + absl::optional<uint32_t> frame_length_decrease_counter; + // The uplink packet loss fractions as set by the ANA FEC controller. If this + // value is not set, it indicates that the ANA FEC controller is not active. + absl::optional<float> uplink_packet_loss_fraction; +}; + +// This is the interface class for encoders in AudioCoding module. Each codec +// type must have an implementation of this class. +class AudioEncoder { + public: + // Used for UMA logging of codec usage. The same codecs, with the + // same values, must be listed in + // src/tools/metrics/histograms/histograms.xml in chromium to log + // correct values. + enum class CodecType { + kOther = 0, // Codec not specified, and/or not listed in this enum + kOpus = 1, + kIsac = 2, + kPcmA = 3, + kPcmU = 4, + kG722 = 5, + kIlbc = 6, + + // Number of histogram bins in the UMA logging of codec types. The + // total number of different codecs that are logged cannot exceed this + // number. + kMaxLoggedAudioCodecTypes + }; + + struct EncodedInfoLeaf { + size_t encoded_bytes = 0; + uint32_t encoded_timestamp = 0; + int payload_type = 0; + bool send_even_if_empty = false; + bool speech = true; + CodecType encoder_type = CodecType::kOther; + }; + + // This is the main struct for auxiliary encoding information. Each encoded + // packet should be accompanied by one EncodedInfo struct, containing the + // total number of `encoded_bytes`, the `encoded_timestamp` and the + // `payload_type`. If the packet contains redundant encodings, the `redundant` + // vector will be populated with EncodedInfoLeaf structs. Each struct in the + // vector represents one encoding; the order of structs in the vector is the + // same as the order in which the actual payloads are written to the byte + // stream. When EncoderInfoLeaf structs are present in the vector, the main + // struct's `encoded_bytes` will be the sum of all the `encoded_bytes` in the + // vector. + struct EncodedInfo : public EncodedInfoLeaf { + EncodedInfo(); + EncodedInfo(const EncodedInfo&); + EncodedInfo(EncodedInfo&&); + ~EncodedInfo(); + EncodedInfo& operator=(const EncodedInfo&); + EncodedInfo& operator=(EncodedInfo&&); + + std::vector<EncodedInfoLeaf> redundant; + }; + + virtual ~AudioEncoder() = default; + + // Returns the input sample rate in Hz and the number of input channels. + // These are constants set at instantiation time. + virtual int SampleRateHz() const = 0; + virtual size_t NumChannels() const = 0; + + // Returns the rate at which the RTP timestamps are updated. The default + // implementation returns SampleRateHz(). + virtual int RtpTimestampRateHz() const; + + // Returns the number of 10 ms frames the encoder will put in the next + // packet. This value may only change when Encode() outputs a packet; i.e., + // the encoder may vary the number of 10 ms frames from packet to packet, but + // it must decide the length of the next packet no later than when outputting + // the preceding packet. + virtual size_t Num10MsFramesInNextPacket() const = 0; + + // Returns the maximum value that can be returned by + // Num10MsFramesInNextPacket(). + virtual size_t Max10MsFramesInAPacket() const = 0; + + // Returns the current target bitrate in bits/s. The value -1 means that the + // codec adapts the target automatically, and a current target cannot be + // provided. + virtual int GetTargetBitrate() const = 0; + + // Accepts one 10 ms block of input audio (i.e., SampleRateHz() / 100 * + // NumChannels() samples). Multi-channel audio must be sample-interleaved. + // The encoder appends zero or more bytes of output to `encoded` and returns + // additional encoding information. Encode() checks some preconditions, calls + // EncodeImpl() which does the actual work, and then checks some + // postconditions. + EncodedInfo Encode(uint32_t rtp_timestamp, + rtc::ArrayView<const int16_t> audio, + rtc::Buffer* encoded); + + // Resets the encoder to its starting state, discarding any input that has + // been fed to the encoder but not yet emitted in a packet. + virtual void Reset() = 0; + + // Enables or disables codec-internal FEC (forward error correction). Returns + // true if the codec was able to comply. The default implementation returns + // true when asked to disable FEC and false when asked to enable it (meaning + // that FEC isn't supported). + virtual bool SetFec(bool enable); + + // Enables or disables codec-internal VAD/DTX. Returns true if the codec was + // able to comply. The default implementation returns true when asked to + // disable DTX and false when asked to enable it (meaning that DTX isn't + // supported). + virtual bool SetDtx(bool enable); + + // Returns the status of codec-internal DTX. The default implementation always + // returns false. + virtual bool GetDtx() const; + + // Sets the application mode. Returns true if the codec was able to comply. + // The default implementation just returns false. + enum class Application { kSpeech, kAudio }; + virtual bool SetApplication(Application application); + + // Tells the encoder about the highest sample rate the decoder is expected to + // use when decoding the bitstream. The encoder would typically use this + // information to adjust the quality of the encoding. The default + // implementation does nothing. + virtual void SetMaxPlaybackRate(int frequency_hz); + + // Tells the encoder what average bitrate we'd like it to produce. The + // encoder is free to adjust or disregard the given bitrate (the default + // implementation does the latter). + ABSL_DEPRECATED("Use OnReceivedTargetAudioBitrate instead") + virtual void SetTargetBitrate(int target_bps); + + // Causes this encoder to let go of any other encoders it contains, and + // returns a pointer to an array where they are stored (which is required to + // live as long as this encoder). Unless the returned array is empty, you may + // not call any methods on this encoder afterwards, except for the + // destructor. The default implementation just returns an empty array. + // NOTE: This method is subject to change. Do not call or override it. + virtual rtc::ArrayView<std::unique_ptr<AudioEncoder>> + ReclaimContainedEncoders(); + + // Enables audio network adaptor. Returns true if successful. + virtual bool EnableAudioNetworkAdaptor(const std::string& config_string, + RtcEventLog* event_log); + + // Disables audio network adaptor. + virtual void DisableAudioNetworkAdaptor(); + + // Provides uplink packet loss fraction to this encoder to allow it to adapt. + // `uplink_packet_loss_fraction` is in the range [0.0, 1.0]. + virtual void OnReceivedUplinkPacketLossFraction( + float uplink_packet_loss_fraction); + + ABSL_DEPRECATED("") + virtual void OnReceivedUplinkRecoverablePacketLossFraction( + float uplink_recoverable_packet_loss_fraction); + + // Provides target audio bitrate to this encoder to allow it to adapt. + virtual void OnReceivedTargetAudioBitrate(int target_bps); + + // Provides target audio bitrate and corresponding probing interval of + // the bandwidth estimator to this encoder to allow it to adapt. + virtual void OnReceivedUplinkBandwidth(int target_audio_bitrate_bps, + absl::optional<int64_t> bwe_period_ms); + + // Provides target audio bitrate and corresponding probing interval of + // the bandwidth estimator to this encoder to allow it to adapt. + virtual void OnReceivedUplinkAllocation(BitrateAllocationUpdate update); + + // Provides RTT to this encoder to allow it to adapt. + virtual void OnReceivedRtt(int rtt_ms); + + // Provides overhead to this encoder to adapt. The overhead is the number of + // bytes that will be added to each packet the encoder generates. + virtual void OnReceivedOverhead(size_t overhead_bytes_per_packet); + + // To allow encoder to adapt its frame length, it must be provided the frame + // length range that receivers can accept. + virtual void SetReceiverFrameLengthRange(int min_frame_length_ms, + int max_frame_length_ms); + + // Get statistics related to audio network adaptation. + virtual ANAStats GetANAStats() const; + + // The range of frame lengths that are supported or nullopt if there's no sch + // information. This is used to calculated the full bitrate range, including + // overhead. + virtual absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange() + const = 0; + + // The maximum number of audio channels supported by WebRTC encoders. + static constexpr int kMaxNumberOfChannels = 24; + + protected: + // Subclasses implement this to perform the actual encoding. Called by + // Encode(). + virtual EncodedInfo EncodeImpl(uint32_t rtp_timestamp, + rtc::ArrayView<const int16_t> audio, + rtc::Buffer* encoded) = 0; +}; +} // namespace webrtc +#endif // API_AUDIO_CODECS_AUDIO_ENCODER_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/audio_encoder_factory.h b/third_party/libwebrtc/api/audio_codecs/audio_encoder_factory.h new file mode 100644 index 0000000000..6128b1b6f3 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_encoder_factory.h @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_H_ +#define API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_encoder.h" +#include "api/audio_codecs/audio_format.h" +#include "rtc_base/ref_count.h" + +namespace webrtc { + +// A factory that creates AudioEncoders. +class AudioEncoderFactory : public rtc::RefCountInterface { + public: + // Returns a prioritized list of audio codecs, to use for signaling etc. + virtual std::vector<AudioCodecSpec> GetSupportedEncoders() = 0; + + // Returns information about how this format would be encoded, provided it's + // supported. More format and format variations may be supported than those + // returned by GetSupportedEncoders(). + virtual absl::optional<AudioCodecInfo> QueryAudioEncoder( + const SdpAudioFormat& format) = 0; + + // Creates an AudioEncoder for the specified format. The encoder will tags its + // payloads with the specified payload type. The `codec_pair_id` argument is + // used to link encoders and decoders that talk to the same remote entity: if + // a AudioEncoderFactory::MakeAudioEncoder() and a + // AudioDecoderFactory::MakeAudioDecoder() call receive non-null IDs that + // compare equal, the factory implementations may assume that the encoder and + // decoder form a pair. (The intended use case for this is to set up + // communication between the AudioEncoder and AudioDecoder instances, which is + // needed for some codecs with built-in bandwidth adaptation.) + // + // Returns null if the format isn't supported. + // + // Note: Implementations need to be robust against combinations other than + // one encoder, one decoder getting the same ID; such encoders must still + // work. + // + // TODO(ossu): Try to avoid audio encoders having to know their payload type. + virtual std::unique_ptr<AudioEncoder> MakeAudioEncoder( + int payload_type, + const SdpAudioFormat& format, + absl::optional<AudioCodecPairId> codec_pair_id) = 0; +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/audio_encoder_factory_template.h b/third_party/libwebrtc/api/audio_codecs/audio_encoder_factory_template.h new file mode 100644 index 0000000000..8a70ba2268 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_encoder_factory_template.h @@ -0,0 +1,163 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_TEMPLATE_H_ +#define API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_TEMPLATE_H_ + +#include <memory> +#include <vector> + +#include "api/audio_codecs/audio_encoder_factory.h" +#include "api/field_trials_view.h" +#include "api/make_ref_counted.h" +#include "api/scoped_refptr.h" + +namespace webrtc { + +namespace audio_encoder_factory_template_impl { + +template <typename... Ts> +struct Helper; + +// Base case: 0 template parameters. +template <> +struct Helper<> { + static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {} + static absl::optional<AudioCodecInfo> QueryAudioEncoder( + const SdpAudioFormat& format) { + return absl::nullopt; + } + static std::unique_ptr<AudioEncoder> MakeAudioEncoder( + int payload_type, + const SdpAudioFormat& format, + absl::optional<AudioCodecPairId> codec_pair_id, + const FieldTrialsView* field_trials) { + return nullptr; + } +}; + +// Inductive case: Called with n + 1 template parameters; calls subroutines +// with n template parameters. +template <typename T, typename... Ts> +struct Helper<T, Ts...> { + static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) { + T::AppendSupportedEncoders(specs); + Helper<Ts...>::AppendSupportedEncoders(specs); + } + static absl::optional<AudioCodecInfo> QueryAudioEncoder( + const SdpAudioFormat& format) { + auto opt_config = T::SdpToConfig(format); + static_assert(std::is_same<decltype(opt_config), + absl::optional<typename T::Config>>::value, + "T::SdpToConfig() must return a value of type " + "absl::optional<T::Config>"); + return opt_config ? absl::optional<AudioCodecInfo>( + T::QueryAudioEncoder(*opt_config)) + : Helper<Ts...>::QueryAudioEncoder(format); + } + static std::unique_ptr<AudioEncoder> MakeAudioEncoder( + int payload_type, + const SdpAudioFormat& format, + absl::optional<AudioCodecPairId> codec_pair_id, + const FieldTrialsView* field_trials) { + auto opt_config = T::SdpToConfig(format); + if (opt_config) { + return T::MakeAudioEncoder(*opt_config, payload_type, codec_pair_id); + } else { + return Helper<Ts...>::MakeAudioEncoder(payload_type, format, + codec_pair_id, field_trials); + } + } +}; + +template <typename... Ts> +class AudioEncoderFactoryT : public AudioEncoderFactory { + public: + explicit AudioEncoderFactoryT(const FieldTrialsView* field_trials) { + field_trials_ = field_trials; + } + + std::vector<AudioCodecSpec> GetSupportedEncoders() override { + std::vector<AudioCodecSpec> specs; + Helper<Ts...>::AppendSupportedEncoders(&specs); + return specs; + } + + absl::optional<AudioCodecInfo> QueryAudioEncoder( + const SdpAudioFormat& format) override { + return Helper<Ts...>::QueryAudioEncoder(format); + } + + std::unique_ptr<AudioEncoder> MakeAudioEncoder( + int payload_type, + const SdpAudioFormat& format, + absl::optional<AudioCodecPairId> codec_pair_id) override { + return Helper<Ts...>::MakeAudioEncoder(payload_type, format, codec_pair_id, + field_trials_); + } + + const FieldTrialsView* field_trials_; +}; + +} // namespace audio_encoder_factory_template_impl + +// Make an AudioEncoderFactory that can create instances of the given encoders. +// +// Each encoder type is given as a template argument to the function; it should +// be a struct with the following static member functions: +// +// // Converts `audio_format` to a ConfigType instance. Returns an empty +// // optional if `audio_format` doesn't correctly specify an encoder of our +// // type. +// absl::optional<ConfigType> SdpToConfig(const SdpAudioFormat& audio_format); +// +// // Appends zero or more AudioCodecSpecs to the list that will be returned +// // by AudioEncoderFactory::GetSupportedEncoders(). +// void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs); +// +// // Returns information about how this format would be encoded. Used to +// // implement AudioEncoderFactory::QueryAudioEncoder(). +// AudioCodecInfo QueryAudioEncoder(const ConfigType& config); +// +// // Creates an AudioEncoder for the specified format. Used to implement +// // AudioEncoderFactory::MakeAudioEncoder(). +// std::unique_ptr<AudioDecoder> MakeAudioEncoder( +// const ConfigType& config, +// int payload_type, +// absl::optional<AudioCodecPairId> codec_pair_id); +// +// ConfigType should be a type that encapsulates all the settings needed to +// create an AudioEncoder. T::Config (where T is the encoder struct) should +// either be the config type, or an alias for it. +// +// Whenever it tries to do something, the new factory will try each of the +// encoders in the order they were specified in the template argument list, +// stopping at the first one that claims to be able to do the job. +// +// TODO(kwiberg): Point at CreateBuiltinAudioEncoderFactory() for an example of +// how it is used. +template <typename... Ts> +rtc::scoped_refptr<AudioEncoderFactory> CreateAudioEncoderFactory( + const FieldTrialsView* field_trials = nullptr) { + // There's no technical reason we couldn't allow zero template parameters, + // but such a factory couldn't create any encoders, and callers can do this + // by mistake by simply forgetting the <> altogether. So we forbid it in + // order to prevent caller foot-shooting. + static_assert(sizeof...(Ts) >= 1, + "Caller must give at least one template parameter"); + + return rtc::make_ref_counted< + audio_encoder_factory_template_impl::AudioEncoderFactoryT<Ts...>>( + field_trials); +} + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_TEMPLATE_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/audio_format.cc b/third_party/libwebrtc/api/audio_codecs/audio_format.cc new file mode 100644 index 0000000000..2a529a49ee --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_format.cc @@ -0,0 +1,86 @@ +/* + * 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. + */ + +#include "api/audio_codecs/audio_format.h" + +#include <utility> + +#include "absl/strings/match.h" + +namespace webrtc { + +SdpAudioFormat::SdpAudioFormat(const SdpAudioFormat&) = default; +SdpAudioFormat::SdpAudioFormat(SdpAudioFormat&&) = default; + +SdpAudioFormat::SdpAudioFormat(absl::string_view name, + int clockrate_hz, + size_t num_channels) + : name(name), clockrate_hz(clockrate_hz), num_channels(num_channels) {} + +SdpAudioFormat::SdpAudioFormat(absl::string_view name, + int clockrate_hz, + size_t num_channels, + const Parameters& param) + : name(name), + clockrate_hz(clockrate_hz), + num_channels(num_channels), + parameters(param) {} + +SdpAudioFormat::SdpAudioFormat(absl::string_view name, + int clockrate_hz, + size_t num_channels, + Parameters&& param) + : name(name), + clockrate_hz(clockrate_hz), + num_channels(num_channels), + parameters(std::move(param)) {} + +bool SdpAudioFormat::Matches(const SdpAudioFormat& o) const { + return absl::EqualsIgnoreCase(name, o.name) && + clockrate_hz == o.clockrate_hz && num_channels == o.num_channels; +} + +SdpAudioFormat::~SdpAudioFormat() = default; +SdpAudioFormat& SdpAudioFormat::operator=(const SdpAudioFormat&) = default; +SdpAudioFormat& SdpAudioFormat::operator=(SdpAudioFormat&&) = default; + +bool operator==(const SdpAudioFormat& a, const SdpAudioFormat& b) { + return absl::EqualsIgnoreCase(a.name, b.name) && + a.clockrate_hz == b.clockrate_hz && a.num_channels == b.num_channels && + a.parameters == b.parameters; +} + +AudioCodecInfo::AudioCodecInfo(int sample_rate_hz, + size_t num_channels, + int bitrate_bps) + : AudioCodecInfo(sample_rate_hz, + num_channels, + bitrate_bps, + bitrate_bps, + bitrate_bps) {} + +AudioCodecInfo::AudioCodecInfo(int sample_rate_hz, + size_t num_channels, + int default_bitrate_bps, + int min_bitrate_bps, + int max_bitrate_bps) + : sample_rate_hz(sample_rate_hz), + num_channels(num_channels), + default_bitrate_bps(default_bitrate_bps), + min_bitrate_bps(min_bitrate_bps), + max_bitrate_bps(max_bitrate_bps) { + RTC_DCHECK_GT(sample_rate_hz, 0); + RTC_DCHECK_GT(num_channels, 0); + RTC_DCHECK_GE(min_bitrate_bps, 0); + RTC_DCHECK_LE(min_bitrate_bps, default_bitrate_bps); + RTC_DCHECK_GE(max_bitrate_bps, default_bitrate_bps); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/audio_format.h b/third_party/libwebrtc/api/audio_codecs/audio_format.h new file mode 100644 index 0000000000..0cf67799b8 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/audio_format.h @@ -0,0 +1,133 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_AUDIO_FORMAT_H_ +#define API_AUDIO_CODECS_AUDIO_FORMAT_H_ + +#include <stddef.h> + +#include <map> +#include <string> + +#include "absl/strings/string_view.h" +#include "rtc_base/checks.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// SDP specification for a single audio codec. +struct RTC_EXPORT SdpAudioFormat { + using Parameters = std::map<std::string, std::string>; + + SdpAudioFormat(const SdpAudioFormat&); + SdpAudioFormat(SdpAudioFormat&&); + SdpAudioFormat(absl::string_view name, int clockrate_hz, size_t num_channels); + SdpAudioFormat(absl::string_view name, + int clockrate_hz, + size_t num_channels, + const Parameters& param); + SdpAudioFormat(absl::string_view name, + int clockrate_hz, + size_t num_channels, + Parameters&& param); + ~SdpAudioFormat(); + + // Returns true if this format is compatible with `o`. In SDP terminology: + // would it represent the same codec between an offer and an answer? As + // opposed to operator==, this method disregards codec parameters. + bool Matches(const SdpAudioFormat& o) const; + + SdpAudioFormat& operator=(const SdpAudioFormat&); + SdpAudioFormat& operator=(SdpAudioFormat&&); + + friend bool operator==(const SdpAudioFormat& a, const SdpAudioFormat& b); + friend bool operator!=(const SdpAudioFormat& a, const SdpAudioFormat& b) { + return !(a == b); + } + + std::string name; + int clockrate_hz; + size_t num_channels; + Parameters parameters; +}; + +// Information about how an audio format is treated by the codec implementation. +// Contains basic information, such as sample rate and number of channels, which +// isn't uniformly presented by SDP. Also contains flags indicating support for +// integrating with other parts of WebRTC, like external VAD and comfort noise +// level calculation. +// +// To avoid API breakage, and make the code clearer, AudioCodecInfo should not +// be directly initializable with any flags indicating optional support. If it +// were, these initializers would break any time a new flag was added. It's also +// more difficult to understand: +// AudioCodecInfo info{16000, 1, 32000, true, false, false, true, true}; +// than +// AudioCodecInfo info(16000, 1, 32000); +// info.allow_comfort_noise = true; +// info.future_flag_b = true; +// info.future_flag_c = true; +struct AudioCodecInfo { + AudioCodecInfo(int sample_rate_hz, size_t num_channels, int bitrate_bps); + AudioCodecInfo(int sample_rate_hz, + size_t num_channels, + int default_bitrate_bps, + int min_bitrate_bps, + int max_bitrate_bps); + AudioCodecInfo(const AudioCodecInfo& b) = default; + ~AudioCodecInfo() = default; + + bool operator==(const AudioCodecInfo& b) const { + return sample_rate_hz == b.sample_rate_hz && + num_channels == b.num_channels && + default_bitrate_bps == b.default_bitrate_bps && + min_bitrate_bps == b.min_bitrate_bps && + max_bitrate_bps == b.max_bitrate_bps && + allow_comfort_noise == b.allow_comfort_noise && + supports_network_adaption == b.supports_network_adaption; + } + + bool operator!=(const AudioCodecInfo& b) const { return !(*this == b); } + + bool HasFixedBitrate() const { + RTC_DCHECK_GE(min_bitrate_bps, 0); + RTC_DCHECK_LE(min_bitrate_bps, default_bitrate_bps); + RTC_DCHECK_GE(max_bitrate_bps, default_bitrate_bps); + return min_bitrate_bps == max_bitrate_bps; + } + + int sample_rate_hz; + size_t num_channels; + int default_bitrate_bps; + int min_bitrate_bps; + int max_bitrate_bps; + + bool allow_comfort_noise = true; // This codec can be used with an external + // comfort noise generator. + bool supports_network_adaption = false; // This codec can adapt to varying + // network conditions. +}; + +// AudioCodecSpec ties an audio format to specific information about the codec +// and its implementation. +struct AudioCodecSpec { + bool operator==(const AudioCodecSpec& b) const { + return format == b.format && info == b.info; + } + + bool operator!=(const AudioCodecSpec& b) const { return !(*this == b); } + + SdpAudioFormat format; + AudioCodecInfo info; +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_AUDIO_FORMAT_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/builtin_audio_decoder_factory.cc b/third_party/libwebrtc/api/audio_codecs/builtin_audio_decoder_factory.cc new file mode 100644 index 0000000000..881113d985 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/builtin_audio_decoder_factory.cc @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#include "api/audio_codecs/builtin_audio_decoder_factory.h" + +#include <memory> +#include <vector> + +#include "api/audio_codecs/L16/audio_decoder_L16.h" +#include "api/audio_codecs/audio_decoder_factory_template.h" +#include "api/audio_codecs/g711/audio_decoder_g711.h" +#include "api/audio_codecs/g722/audio_decoder_g722.h" +#if WEBRTC_USE_BUILTIN_ILBC +#include "api/audio_codecs/ilbc/audio_decoder_ilbc.h" // nogncheck +#endif +#if WEBRTC_USE_BUILTIN_OPUS +#include "api/audio_codecs/opus/audio_decoder_multi_channel_opus.h" +#include "api/audio_codecs/opus/audio_decoder_opus.h" // nogncheck +#endif + +namespace webrtc { + +namespace { + +// Modify an audio decoder to not advertise support for anything. +template <typename T> +struct NotAdvertised { + using Config = typename T::Config; + static absl::optional<Config> SdpToConfig( + const SdpAudioFormat& audio_format) { + return T::SdpToConfig(audio_format); + } + static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) { + // Don't advertise support for anything. + } + static std::unique_ptr<AudioDecoder> MakeAudioDecoder( + const Config& config, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt) { + return T::MakeAudioDecoder(config, codec_pair_id); + } +}; + +} // namespace + +rtc::scoped_refptr<AudioDecoderFactory> CreateBuiltinAudioDecoderFactory() { + return CreateAudioDecoderFactory< + +#if WEBRTC_USE_BUILTIN_OPUS + AudioDecoderOpus, NotAdvertised<AudioDecoderMultiChannelOpus>, +#endif + + AudioDecoderG722, + +#if WEBRTC_USE_BUILTIN_ILBC + AudioDecoderIlbc, +#endif + + AudioDecoderG711, NotAdvertised<AudioDecoderL16>>(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/builtin_audio_decoder_factory.h b/third_party/libwebrtc/api/audio_codecs/builtin_audio_decoder_factory.h new file mode 100644 index 0000000000..72e1e3d96e --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/builtin_audio_decoder_factory.h @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_ +#define API_AUDIO_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_ + +#include "api/audio_codecs/audio_decoder_factory.h" +#include "api/scoped_refptr.h" + +namespace webrtc { + +// Creates a new factory that can create the built-in types of audio decoders. +// Note: This will link with all the code implementing those codecs, so if you +// only need a subset of the codecs, consider using +// CreateAudioDecoderFactory<...codecs listed here...>() or +// CreateOpusAudioDecoderFactory() instead. +rtc::scoped_refptr<AudioDecoderFactory> CreateBuiltinAudioDecoderFactory(); + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/builtin_audio_decoder_factory_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/builtin_audio_decoder_factory_gn/moz.build new file mode 100644 index 0000000000..366307ea13 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/builtin_audio_decoder_factory_gn/moz.build @@ -0,0 +1,234 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" +DEFINES["WEBRTC_USE_BUILTIN_ILBC"] = "1" +DEFINES["WEBRTC_USE_BUILTIN_OPUS"] = "1" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/builtin_audio_decoder_factory.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("builtin_audio_decoder_factory_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/builtin_audio_encoder_factory.cc b/third_party/libwebrtc/api/audio_codecs/builtin_audio_encoder_factory.cc new file mode 100644 index 0000000000..4546a2eaee --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/builtin_audio_encoder_factory.cc @@ -0,0 +1,74 @@ +/* + * 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. + */ + +#include "api/audio_codecs/builtin_audio_encoder_factory.h" + +#include <memory> +#include <vector> + +#include "api/audio_codecs/L16/audio_encoder_L16.h" +#include "api/audio_codecs/audio_encoder_factory_template.h" +#include "api/audio_codecs/g711/audio_encoder_g711.h" +#include "api/audio_codecs/g722/audio_encoder_g722.h" +#if WEBRTC_USE_BUILTIN_ILBC +#include "api/audio_codecs/ilbc/audio_encoder_ilbc.h" // nogncheck +#endif +#if WEBRTC_USE_BUILTIN_OPUS +#include "api/audio_codecs/opus/audio_encoder_multi_channel_opus.h" +#include "api/audio_codecs/opus/audio_encoder_opus.h" // nogncheck +#endif + +namespace webrtc { + +namespace { + +// Modify an audio encoder to not advertise support for anything. +template <typename T> +struct NotAdvertised { + using Config = typename T::Config; + static absl::optional<Config> SdpToConfig( + const SdpAudioFormat& audio_format) { + return T::SdpToConfig(audio_format); + } + static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) { + // Don't advertise support for anything. + } + static AudioCodecInfo QueryAudioEncoder(const Config& config) { + return T::QueryAudioEncoder(config); + } + static std::unique_ptr<AudioEncoder> MakeAudioEncoder( + const Config& config, + int payload_type, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr) { + return T::MakeAudioEncoder(config, payload_type, codec_pair_id, + field_trials); + } +}; + +} // namespace + +rtc::scoped_refptr<AudioEncoderFactory> CreateBuiltinAudioEncoderFactory() { + return CreateAudioEncoderFactory< + +#if WEBRTC_USE_BUILTIN_OPUS + AudioEncoderOpus, NotAdvertised<AudioEncoderMultiChannelOpus>, +#endif + + AudioEncoderG722, + +#if WEBRTC_USE_BUILTIN_ILBC + AudioEncoderIlbc, +#endif + + AudioEncoderG711, NotAdvertised<AudioEncoderL16>>(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/builtin_audio_encoder_factory.h b/third_party/libwebrtc/api/audio_codecs/builtin_audio_encoder_factory.h new file mode 100644 index 0000000000..f833de10f1 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/builtin_audio_encoder_factory.h @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_BUILTIN_AUDIO_ENCODER_FACTORY_H_ +#define API_AUDIO_CODECS_BUILTIN_AUDIO_ENCODER_FACTORY_H_ + +#include "api/audio_codecs/audio_encoder_factory.h" +#include "api/scoped_refptr.h" + +namespace webrtc { + +// Creates a new factory that can create the built-in types of audio encoders. +// Note: This will link with all the code implementing those codecs, so if you +// only need a subset of the codecs, consider using +// CreateAudioEncoderFactory<...codecs listed here...>() or +// CreateOpusAudioEncoderFactory() instead. +rtc::scoped_refptr<AudioEncoderFactory> CreateBuiltinAudioEncoderFactory(); + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_BUILTIN_AUDIO_ENCODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/builtin_audio_encoder_factory_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/builtin_audio_encoder_factory_gn/moz.build new file mode 100644 index 0000000000..db0e3fbe00 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/builtin_audio_encoder_factory_gn/moz.build @@ -0,0 +1,234 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" +DEFINES["WEBRTC_USE_BUILTIN_ILBC"] = "1" +DEFINES["WEBRTC_USE_BUILTIN_OPUS"] = "1" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/builtin_audio_encoder_factory.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("builtin_audio_encoder_factory_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/g711/BUILD.gn b/third_party/libwebrtc/api/audio_codecs/g711/BUILD.gn new file mode 100644 index 0000000000..b2ff324f12 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g711/BUILD.gn @@ -0,0 +1,55 @@ +# 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. + +import("../../../webrtc.gni") +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +rtc_library("audio_encoder_g711") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + sources = [ + "audio_encoder_g711.cc", + "audio_encoder_g711.h", + ] + deps = [ + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:g711", + "../../../rtc_base:safe_conversions", + "../../../rtc_base:safe_minmax", + "../../../rtc_base:stringutils", + "../../../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("audio_decoder_g711") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + sources = [ + "audio_decoder_g711.cc", + "audio_decoder_g711.h", + ] + deps = [ + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:g711", + "../../../rtc_base:safe_conversions", + "../../../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} diff --git a/third_party/libwebrtc/api/audio_codecs/g711/audio_decoder_g711.cc b/third_party/libwebrtc/api/audio_codecs/g711/audio_decoder_g711.cc new file mode 100644 index 0000000000..838f7e9624 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g711/audio_decoder_g711.cc @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#include "api/audio_codecs/g711/audio_decoder_g711.h" + +#include <memory> +#include <vector> + +#include "absl/strings/match.h" +#include "modules/audio_coding/codecs/g711/audio_decoder_pcm.h" +#include "rtc_base/numerics/safe_conversions.h" + +namespace webrtc { + +absl::optional<AudioDecoderG711::Config> AudioDecoderG711::SdpToConfig( + const SdpAudioFormat& format) { + const bool is_pcmu = absl::EqualsIgnoreCase(format.name, "PCMU"); + const bool is_pcma = absl::EqualsIgnoreCase(format.name, "PCMA"); + if (format.clockrate_hz == 8000 && format.num_channels >= 1 && + (is_pcmu || is_pcma)) { + Config config; + config.type = is_pcmu ? Config::Type::kPcmU : Config::Type::kPcmA; + config.num_channels = rtc::dchecked_cast<int>(format.num_channels); + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return absl::nullopt; + } + return config; + } else { + return absl::nullopt; + } +} + +void AudioDecoderG711::AppendSupportedDecoders( + std::vector<AudioCodecSpec>* specs) { + for (const char* type : {"PCMU", "PCMA"}) { + specs->push_back({{type, 8000, 1}, {8000, 1, 64000}}); + } +} + +std::unique_ptr<AudioDecoder> AudioDecoderG711::MakeAudioDecoder( + const Config& config, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return nullptr; + } + switch (config.type) { + case Config::Type::kPcmU: + return std::make_unique<AudioDecoderPcmU>(config.num_channels); + case Config::Type::kPcmA: + return std::make_unique<AudioDecoderPcmA>(config.num_channels); + default: + RTC_DCHECK_NOTREACHED(); + return nullptr; + } +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/g711/audio_decoder_g711.h b/third_party/libwebrtc/api/audio_codecs/g711/audio_decoder_g711.h new file mode 100644 index 0000000000..0f7a98d345 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g711/audio_decoder_g711.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_G711_AUDIO_DECODER_G711_H_ +#define API_AUDIO_CODECS_G711_AUDIO_DECODER_G711_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_decoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/field_trials_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// G711 decoder API for use as a template parameter to +// CreateAudioDecoderFactory<...>(). +struct RTC_EXPORT AudioDecoderG711 { + struct Config { + enum class Type { kPcmU, kPcmA }; + bool IsOk() const { + return (type == Type::kPcmU || type == Type::kPcmA) && + num_channels >= 1 && + num_channels <= AudioDecoder::kMaxNumberOfChannels; + } + Type type; + int num_channels; + }; + static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format); + static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs); + static std::unique_ptr<AudioDecoder> MakeAudioDecoder( + const Config& config, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_G711_AUDIO_DECODER_G711_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/g711/audio_decoder_g711_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/g711/audio_decoder_g711_gn/moz.build new file mode 100644 index 0000000000..4782d01dd1 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g711/audio_decoder_g711_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/g711/audio_decoder_g711.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_decoder_g711_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/g711/audio_encoder_g711.cc b/third_party/libwebrtc/api/audio_codecs/g711/audio_encoder_g711.cc new file mode 100644 index 0000000000..1dca3b80d3 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g711/audio_encoder_g711.cc @@ -0,0 +1,95 @@ +/* + * 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. + */ + +#include "api/audio_codecs/g711/audio_encoder_g711.h" + +#include <memory> +#include <vector> + +#include "absl/strings/match.h" +#include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h" +#include "rtc_base/numerics/safe_conversions.h" +#include "rtc_base/numerics/safe_minmax.h" +#include "rtc_base/string_to_number.h" + +namespace webrtc { + +absl::optional<AudioEncoderG711::Config> AudioEncoderG711::SdpToConfig( + const SdpAudioFormat& format) { + const bool is_pcmu = absl::EqualsIgnoreCase(format.name, "PCMU"); + const bool is_pcma = absl::EqualsIgnoreCase(format.name, "PCMA"); + if (format.clockrate_hz == 8000 && format.num_channels >= 1 && + (is_pcmu || is_pcma)) { + Config config; + config.type = is_pcmu ? Config::Type::kPcmU : Config::Type::kPcmA; + config.num_channels = rtc::dchecked_cast<int>(format.num_channels); + config.frame_size_ms = 20; + auto ptime_iter = format.parameters.find("ptime"); + if (ptime_iter != format.parameters.end()) { + const auto ptime = rtc::StringToNumber<int>(ptime_iter->second); + if (ptime && *ptime > 0) { + config.frame_size_ms = rtc::SafeClamp(10 * (*ptime / 10), 10, 60); + } + } + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return absl::nullopt; + } + return config; + } else { + return absl::nullopt; + } +} + +void AudioEncoderG711::AppendSupportedEncoders( + std::vector<AudioCodecSpec>* specs) { + for (const char* type : {"PCMU", "PCMA"}) { + specs->push_back({{type, 8000, 1}, {8000, 1, 64000}}); + } +} + +AudioCodecInfo AudioEncoderG711::QueryAudioEncoder(const Config& config) { + RTC_DCHECK(config.IsOk()); + return {8000, rtc::dchecked_cast<size_t>(config.num_channels), + 64000 * config.num_channels}; +} + +std::unique_ptr<AudioEncoder> AudioEncoderG711::MakeAudioEncoder( + const Config& config, + int payload_type, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return nullptr; + } + switch (config.type) { + case Config::Type::kPcmU: { + AudioEncoderPcmU::Config impl_config; + impl_config.num_channels = config.num_channels; + impl_config.frame_size_ms = config.frame_size_ms; + impl_config.payload_type = payload_type; + return std::make_unique<AudioEncoderPcmU>(impl_config); + } + case Config::Type::kPcmA: { + AudioEncoderPcmA::Config impl_config; + impl_config.num_channels = config.num_channels; + impl_config.frame_size_ms = config.frame_size_ms; + impl_config.payload_type = payload_type; + return std::make_unique<AudioEncoderPcmA>(impl_config); + } + default: { + RTC_DCHECK_NOTREACHED(); + return nullptr; + } + } +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/g711/audio_encoder_g711.h b/third_party/libwebrtc/api/audio_codecs/g711/audio_encoder_g711.h new file mode 100644 index 0000000000..4b3eb845e0 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g711/audio_encoder_g711.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_G711_AUDIO_ENCODER_G711_H_ +#define API_AUDIO_CODECS_G711_AUDIO_ENCODER_G711_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_encoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/field_trials_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// G711 encoder API for use as a template parameter to +// CreateAudioEncoderFactory<...>(). +struct RTC_EXPORT AudioEncoderG711 { + struct Config { + enum class Type { kPcmU, kPcmA }; + bool IsOk() const { + return (type == Type::kPcmU || type == Type::kPcmA) && + frame_size_ms > 0 && frame_size_ms % 10 == 0 && + num_channels >= 1 && + num_channels <= AudioEncoder::kMaxNumberOfChannels; + } + Type type = Type::kPcmU; + int num_channels = 1; + int frame_size_ms = 20; + }; + static absl::optional<AudioEncoderG711::Config> SdpToConfig( + const SdpAudioFormat& audio_format); + static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs); + static AudioCodecInfo QueryAudioEncoder(const Config& config); + static std::unique_ptr<AudioEncoder> MakeAudioEncoder( + const Config& config, + int payload_type, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_G711_AUDIO_ENCODER_G711_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/g711/audio_encoder_g711_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/g711/audio_encoder_g711_gn/moz.build new file mode 100644 index 0000000000..c972978c13 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g711/audio_encoder_g711_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/g711/audio_encoder_g711.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_encoder_g711_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/g722/BUILD.gn b/third_party/libwebrtc/api/audio_codecs/g722/BUILD.gn new file mode 100644 index 0000000000..af13ac3de3 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g722/BUILD.gn @@ -0,0 +1,62 @@ +# 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. + +import("../../../webrtc.gni") +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +rtc_source_set("audio_encoder_g722_config") { + visibility = [ "*" ] + sources = [ "audio_encoder_g722_config.h" ] + deps = [ "..:audio_codecs_api" ] +} + +rtc_library("audio_encoder_g722") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + sources = [ + "audio_encoder_g722.cc", + "audio_encoder_g722.h", + ] + deps = [ + ":audio_encoder_g722_config", + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:g722", + "../../../rtc_base:safe_conversions", + "../../../rtc_base:safe_minmax", + "../../../rtc_base:stringutils", + "../../../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("audio_decoder_g722") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + sources = [ + "audio_decoder_g722.cc", + "audio_decoder_g722.h", + ] + deps = [ + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:g722", + "../../../rtc_base:safe_conversions", + "../../../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} diff --git a/third_party/libwebrtc/api/audio_codecs/g722/audio_decoder_g722.cc b/third_party/libwebrtc/api/audio_codecs/g722/audio_decoder_g722.cc new file mode 100644 index 0000000000..ed7163471a --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g722/audio_decoder_g722.cc @@ -0,0 +1,56 @@ +/* + * 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. + */ + +#include "api/audio_codecs/g722/audio_decoder_g722.h" + +#include <memory> +#include <vector> + +#include "absl/strings/match.h" +#include "modules/audio_coding/codecs/g722/audio_decoder_g722.h" +#include "rtc_base/numerics/safe_conversions.h" + +namespace webrtc { + +absl::optional<AudioDecoderG722::Config> AudioDecoderG722::SdpToConfig( + const SdpAudioFormat& format) { + if (absl::EqualsIgnoreCase(format.name, "G722") && + format.clockrate_hz == 8000 && + (format.num_channels == 1 || format.num_channels == 2)) { + return Config{rtc::dchecked_cast<int>(format.num_channels)}; + } + return absl::nullopt; +} + +void AudioDecoderG722::AppendSupportedDecoders( + std::vector<AudioCodecSpec>* specs) { + specs->push_back({{"G722", 8000, 1}, {16000, 1, 64000}}); +} + +std::unique_ptr<AudioDecoder> AudioDecoderG722::MakeAudioDecoder( + Config config, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return nullptr; + } + switch (config.num_channels) { + case 1: + return std::make_unique<AudioDecoderG722Impl>(); + case 2: + return std::make_unique<AudioDecoderG722StereoImpl>(); + default: + RTC_DCHECK_NOTREACHED(); + return nullptr; + } +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/g722/audio_decoder_g722.h b/third_party/libwebrtc/api/audio_codecs/g722/audio_decoder_g722.h new file mode 100644 index 0000000000..6f7b253039 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g722/audio_decoder_g722.h @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_G722_AUDIO_DECODER_G722_H_ +#define API_AUDIO_CODECS_G722_AUDIO_DECODER_G722_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_decoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/field_trials_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// G722 decoder API for use as a template parameter to +// CreateAudioDecoderFactory<...>(). +struct RTC_EXPORT AudioDecoderG722 { + struct Config { + bool IsOk() const { return num_channels == 1 || num_channels == 2; } + int num_channels; + }; + static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format); + static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs); + static std::unique_ptr<AudioDecoder> MakeAudioDecoder( + Config config, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_G722_AUDIO_DECODER_G722_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/g722/audio_decoder_g722_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/g722/audio_decoder_g722_gn/moz.build new file mode 100644 index 0000000000..77003c77a9 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g722/audio_decoder_g722_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/g722/audio_decoder_g722.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_decoder_g722_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722.cc b/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722.cc new file mode 100644 index 0000000000..56a6c4da6a --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722.cc @@ -0,0 +1,74 @@ +/* + * 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. + */ + +#include "api/audio_codecs/g722/audio_encoder_g722.h" + +#include <memory> +#include <vector> + +#include "absl/strings/match.h" +#include "modules/audio_coding/codecs/g722/audio_encoder_g722.h" +#include "rtc_base/numerics/safe_conversions.h" +#include "rtc_base/numerics/safe_minmax.h" +#include "rtc_base/string_to_number.h" + +namespace webrtc { + +absl::optional<AudioEncoderG722Config> AudioEncoderG722::SdpToConfig( + const SdpAudioFormat& format) { + if (!absl::EqualsIgnoreCase(format.name, "g722") || + format.clockrate_hz != 8000) { + return absl::nullopt; + } + + AudioEncoderG722Config config; + config.num_channels = rtc::checked_cast<int>(format.num_channels); + auto ptime_iter = format.parameters.find("ptime"); + if (ptime_iter != format.parameters.end()) { + auto ptime = rtc::StringToNumber<int>(ptime_iter->second); + if (ptime && *ptime > 0) { + const int whole_packets = *ptime / 10; + config.frame_size_ms = rtc::SafeClamp<int>(whole_packets * 10, 10, 60); + } + } + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return absl::nullopt; + } + return config; +} + +void AudioEncoderG722::AppendSupportedEncoders( + std::vector<AudioCodecSpec>* specs) { + const SdpAudioFormat fmt = {"G722", 8000, 1}; + const AudioCodecInfo info = QueryAudioEncoder(*SdpToConfig(fmt)); + specs->push_back({fmt, info}); +} + +AudioCodecInfo AudioEncoderG722::QueryAudioEncoder( + const AudioEncoderG722Config& config) { + RTC_DCHECK(config.IsOk()); + return {16000, rtc::dchecked_cast<size_t>(config.num_channels), + 64000 * config.num_channels}; +} + +std::unique_ptr<AudioEncoder> AudioEncoderG722::MakeAudioEncoder( + const AudioEncoderG722Config& config, + int payload_type, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return nullptr; + } + return std::make_unique<AudioEncoderG722Impl>(config, payload_type); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722.h b/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722.h new file mode 100644 index 0000000000..78ceddd1e9 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_H_ +#define API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_encoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/audio_codecs/g722/audio_encoder_g722_config.h" +#include "api/field_trials_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// G722 encoder API for use as a template parameter to +// CreateAudioEncoderFactory<...>(). +struct RTC_EXPORT AudioEncoderG722 { + using Config = AudioEncoderG722Config; + static absl::optional<AudioEncoderG722Config> SdpToConfig( + const SdpAudioFormat& audio_format); + static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs); + static AudioCodecInfo QueryAudioEncoder(const AudioEncoderG722Config& config); + static std::unique_ptr<AudioEncoder> MakeAudioEncoder( + const AudioEncoderG722Config& config, + int payload_type, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722_config.h b/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722_config.h new file mode 100644 index 0000000000..f3f3a9f016 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722_config.h @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_CONFIG_H_ +#define API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_CONFIG_H_ + +#include "api/audio_codecs/audio_encoder.h" + +namespace webrtc { + +struct AudioEncoderG722Config { + bool IsOk() const { + return frame_size_ms > 0 && frame_size_ms % 10 == 0 && num_channels >= 1 && + num_channels <= AudioEncoder::kMaxNumberOfChannels; + } + int frame_size_ms = 20; + int num_channels = 1; +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_CONFIG_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722_config_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722_config_gn/moz.build new file mode 100644 index 0000000000..41e1e248c5 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722_config_gn/moz.build @@ -0,0 +1,209 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_encoder_g722_config_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722_gn/moz.build new file mode 100644 index 0000000000..c3beba6cdb --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/g722/audio_encoder_g722.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_encoder_g722_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/ilbc/BUILD.gn b/third_party/libwebrtc/api/audio_codecs/ilbc/BUILD.gn new file mode 100644 index 0000000000..22cf48220f --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/ilbc/BUILD.gn @@ -0,0 +1,58 @@ +# 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. + +import("../../../webrtc.gni") +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +rtc_source_set("audio_encoder_ilbc_config") { + visibility = [ "*" ] + sources = [ "audio_encoder_ilbc_config.h" ] +} + +rtc_library("audio_encoder_ilbc") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + sources = [ + "audio_encoder_ilbc.cc", + "audio_encoder_ilbc.h", + ] + deps = [ + ":audio_encoder_ilbc_config", + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:ilbc", + "../../../rtc_base:safe_conversions", + "../../../rtc_base:safe_minmax", + "../../../rtc_base:stringutils", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("audio_decoder_ilbc") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + sources = [ + "audio_decoder_ilbc.cc", + "audio_decoder_ilbc.h", + ] + deps = [ + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:ilbc", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} diff --git a/third_party/libwebrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.cc b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.cc new file mode 100644 index 0000000000..c58316903a --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.cc @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#include "api/audio_codecs/ilbc/audio_decoder_ilbc.h" + +#include <memory> +#include <vector> + +#include "absl/strings/match.h" +#include "modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h" + +namespace webrtc { + +absl::optional<AudioDecoderIlbc::Config> AudioDecoderIlbc::SdpToConfig( + const SdpAudioFormat& format) { + if (absl::EqualsIgnoreCase(format.name, "ILBC") && + format.clockrate_hz == 8000 && format.num_channels == 1) { + return Config(); + } + return absl::nullopt; +} + +void AudioDecoderIlbc::AppendSupportedDecoders( + std::vector<AudioCodecSpec>* specs) { + specs->push_back({{"ILBC", 8000, 1}, {8000, 1, 13300}}); +} + +std::unique_ptr<AudioDecoder> AudioDecoderIlbc::MakeAudioDecoder( + Config config, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + return std::make_unique<AudioDecoderIlbcImpl>(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.h b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.h new file mode 100644 index 0000000000..60566c88df --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_ILBC_AUDIO_DECODER_ILBC_H_ +#define API_AUDIO_CODECS_ILBC_AUDIO_DECODER_ILBC_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_decoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/field_trials_view.h" + +namespace webrtc { + +// ILBC decoder API for use as a template parameter to +// CreateAudioDecoderFactory<...>(). +struct AudioDecoderIlbc { + struct Config {}; // Empty---no config values needed! + static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format); + static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs); + static std::unique_ptr<AudioDecoder> MakeAudioDecoder( + Config config, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_ILBC_AUDIO_DECODER_ILBC_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/ilbc/audio_decoder_ilbc_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_decoder_ilbc_gn/moz.build new file mode 100644 index 0000000000..53e9d1a4a7 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_decoder_ilbc_gn/moz.build @@ -0,0 +1,232 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_decoder_ilbc_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc new file mode 100644 index 0000000000..b497948491 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc @@ -0,0 +1,88 @@ +/* + * 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. + */ + +#include "api/audio_codecs/ilbc/audio_encoder_ilbc.h" + +#include <memory> +#include <vector> + +#include "absl/strings/match.h" +#include "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h" +#include "rtc_base/numerics/safe_conversions.h" +#include "rtc_base/numerics/safe_minmax.h" +#include "rtc_base/string_to_number.h" + +namespace webrtc { +namespace { +int GetIlbcBitrate(int ptime) { + switch (ptime) { + case 20: + case 40: + // 38 bytes per frame of 20 ms => 15200 bits/s. + return 15200; + case 30: + case 60: + // 50 bytes per frame of 30 ms => (approx) 13333 bits/s. + return 13333; + default: + RTC_CHECK_NOTREACHED(); + } +} +} // namespace + +absl::optional<AudioEncoderIlbcConfig> AudioEncoderIlbc::SdpToConfig( + const SdpAudioFormat& format) { + if (!absl::EqualsIgnoreCase(format.name.c_str(), "ILBC") || + format.clockrate_hz != 8000 || format.num_channels != 1) { + return absl::nullopt; + } + + AudioEncoderIlbcConfig config; + auto ptime_iter = format.parameters.find("ptime"); + if (ptime_iter != format.parameters.end()) { + auto ptime = rtc::StringToNumber<int>(ptime_iter->second); + if (ptime && *ptime > 0) { + const int whole_packets = *ptime / 10; + config.frame_size_ms = rtc::SafeClamp<int>(whole_packets * 10, 20, 60); + } + } + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return absl::nullopt; + } + return config; +} + +void AudioEncoderIlbc::AppendSupportedEncoders( + std::vector<AudioCodecSpec>* specs) { + const SdpAudioFormat fmt = {"ILBC", 8000, 1}; + const AudioCodecInfo info = QueryAudioEncoder(*SdpToConfig(fmt)); + specs->push_back({fmt, info}); +} + +AudioCodecInfo AudioEncoderIlbc::QueryAudioEncoder( + const AudioEncoderIlbcConfig& config) { + RTC_DCHECK(config.IsOk()); + return {8000, 1, GetIlbcBitrate(config.frame_size_ms)}; +} + +std::unique_ptr<AudioEncoder> AudioEncoderIlbc::MakeAudioEncoder( + const AudioEncoderIlbcConfig& config, + int payload_type, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return nullptr; + } + return std::make_unique<AudioEncoderIlbcImpl>(config, payload_type); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.h b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.h new file mode 100644 index 0000000000..a5306841ce --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.h @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_ +#define API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_encoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/audio_codecs/ilbc/audio_encoder_ilbc_config.h" +#include "api/field_trials_view.h" + +namespace webrtc { + +// ILBC encoder API for use as a template parameter to +// CreateAudioEncoderFactory<...>(). +struct AudioEncoderIlbc { + using Config = AudioEncoderIlbcConfig; + static absl::optional<AudioEncoderIlbcConfig> SdpToConfig( + const SdpAudioFormat& audio_format); + static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs); + static AudioCodecInfo QueryAudioEncoder(const AudioEncoderIlbcConfig& config); + static std::unique_ptr<AudioEncoder> MakeAudioEncoder( + const AudioEncoderIlbcConfig& config, + int payload_type, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_config.h b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_config.h new file mode 100644 index 0000000000..4d82f9901c --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_config.h @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_CONFIG_H_ +#define API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_CONFIG_H_ + +namespace webrtc { + +struct AudioEncoderIlbcConfig { + bool IsOk() const { + return (frame_size_ms == 20 || frame_size_ms == 30 || frame_size_ms == 40 || + frame_size_ms == 60); + } + int frame_size_ms = 30; // Valid values are 20, 30, 40, and 60 ms. + // Note that frame size 40 ms produces encodings with two 20 ms frames in + // them, and frame size 60 ms consists of two 30 ms frames. +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_CONFIG_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_config_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_config_gn/moz.build new file mode 100644 index 0000000000..75737b8f19 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_config_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_encoder_ilbc_config_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_gn/moz.build new file mode 100644 index 0000000000..bddfe42193 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_gn/moz.build @@ -0,0 +1,232 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_encoder_ilbc_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/opus/BUILD.gn b/third_party/libwebrtc/api/audio_codecs/opus/BUILD.gn new file mode 100644 index 0000000000..eb90a0b9ac --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/BUILD.gn @@ -0,0 +1,110 @@ +# 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. + +import("../../../webrtc.gni") +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +rtc_library("audio_encoder_opus_config") { + visibility = [ "*" ] + sources = [ + "audio_encoder_multi_channel_opus_config.cc", + "audio_encoder_multi_channel_opus_config.h", + "audio_encoder_opus_config.cc", + "audio_encoder_opus_config.h", + ] + deps = [ "../../../rtc_base/system:rtc_export" ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + defines = [] + if (rtc_opus_variable_complexity) { + defines += [ "WEBRTC_OPUS_VARIABLE_COMPLEXITY=1" ] + } else { + defines += [ "WEBRTC_OPUS_VARIABLE_COMPLEXITY=0" ] + } +} + +rtc_source_set("audio_decoder_opus_config") { + visibility = [ "*" ] + sources = [ "audio_decoder_multi_channel_opus_config.h" ] + deps = [ "..:audio_codecs_api" ] +} + +rtc_library("audio_encoder_opus") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + public = [ "audio_encoder_opus.h" ] + sources = [ "audio_encoder_opus.cc" ] + deps = [ + ":audio_encoder_opus_config", + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:webrtc_opus", + "../../../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("audio_decoder_opus") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + sources = [ + "audio_decoder_opus.cc", + "audio_decoder_opus.h", + ] + deps = [ + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:webrtc_opus", + "../../../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("audio_encoder_multiopus") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + public = [ "audio_encoder_multi_channel_opus.h" ] + sources = [ "audio_encoder_multi_channel_opus.cc" ] + deps = [ + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:webrtc_multiopus", + "../../../rtc_base/system:rtc_export", + "../opus:audio_encoder_opus_config", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("audio_decoder_multiopus") { + visibility = [ "*" ] + poisonous = [ "audio_codecs" ] + sources = [ + "audio_decoder_multi_channel_opus.cc", + "audio_decoder_multi_channel_opus.h", + ] + deps = [ + ":audio_decoder_opus_config", + "..:audio_codecs_api", + "../../../api:field_trials_view", + "../../../modules/audio_coding:webrtc_multiopus", + "../../../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multi_channel_opus.cc b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multi_channel_opus.cc new file mode 100644 index 0000000000..0fb4e05511 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multi_channel_opus.cc @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 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 "api/audio_codecs/opus/audio_decoder_multi_channel_opus.h" + +#include <memory> +#include <utility> +#include <vector> + +#include "absl/memory/memory.h" +#include "absl/strings/match.h" +#include "modules/audio_coding/codecs/opus/audio_decoder_multi_channel_opus_impl.h" + +namespace webrtc { + +absl::optional<AudioDecoderMultiChannelOpusConfig> +AudioDecoderMultiChannelOpus::SdpToConfig(const SdpAudioFormat& format) { + return AudioDecoderMultiChannelOpusImpl::SdpToConfig(format); +} + +void AudioDecoderMultiChannelOpus::AppendSupportedDecoders( + std::vector<AudioCodecSpec>* specs) { + // To get full utilization of the surround support of the Opus lib, we can + // mark which channel is the low frequency effects (LFE). But that is not done + // ATM. + { + AudioCodecInfo surround_5_1_opus_info{48000, 6, + /* default_bitrate_bps= */ 128000}; + surround_5_1_opus_info.allow_comfort_noise = false; + surround_5_1_opus_info.supports_network_adaption = false; + SdpAudioFormat opus_format({"multiopus", + 48000, + 6, + {{"minptime", "10"}, + {"useinbandfec", "1"}, + {"channel_mapping", "0,4,1,2,3,5"}, + {"num_streams", "4"}, + {"coupled_streams", "2"}}}); + specs->push_back({std::move(opus_format), surround_5_1_opus_info}); + } + { + AudioCodecInfo surround_7_1_opus_info{48000, 8, + /* default_bitrate_bps= */ 200000}; + surround_7_1_opus_info.allow_comfort_noise = false; + surround_7_1_opus_info.supports_network_adaption = false; + SdpAudioFormat opus_format({"multiopus", + 48000, + 8, + {{"minptime", "10"}, + {"useinbandfec", "1"}, + {"channel_mapping", "0,6,1,2,3,4,5,7"}, + {"num_streams", "5"}, + {"coupled_streams", "3"}}}); + specs->push_back({std::move(opus_format), surround_7_1_opus_info}); + } +} + +std::unique_ptr<AudioDecoder> AudioDecoderMultiChannelOpus::MakeAudioDecoder( + AudioDecoderMultiChannelOpusConfig config, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + return AudioDecoderMultiChannelOpusImpl::MakeAudioDecoder(config); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multi_channel_opus.h b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multi_channel_opus.h new file mode 100644 index 0000000000..eafd6c6939 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multi_channel_opus.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 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 API_AUDIO_CODECS_OPUS_AUDIO_DECODER_MULTI_CHANNEL_OPUS_H_ +#define API_AUDIO_CODECS_OPUS_AUDIO_DECODER_MULTI_CHANNEL_OPUS_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_decoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/audio_codecs/opus/audio_decoder_multi_channel_opus_config.h" +#include "api/field_trials_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Opus decoder API for use as a template parameter to +// CreateAudioDecoderFactory<...>(). +struct RTC_EXPORT AudioDecoderMultiChannelOpus { + using Config = AudioDecoderMultiChannelOpusConfig; + static absl::optional<AudioDecoderMultiChannelOpusConfig> SdpToConfig( + const SdpAudioFormat& audio_format); + static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs); + static std::unique_ptr<AudioDecoder> MakeAudioDecoder( + AudioDecoderMultiChannelOpusConfig config, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_OPUS_AUDIO_DECODER_MULTI_CHANNEL_OPUS_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multi_channel_opus_config.h b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multi_channel_opus_config.h new file mode 100644 index 0000000000..f97c5c3193 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multi_channel_opus_config.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019 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 API_AUDIO_CODECS_OPUS_AUDIO_DECODER_MULTI_CHANNEL_OPUS_CONFIG_H_ +#define API_AUDIO_CODECS_OPUS_AUDIO_DECODER_MULTI_CHANNEL_OPUS_CONFIG_H_ + +#include <vector> + +#include "api/audio_codecs/audio_decoder.h" + +namespace webrtc { +struct AudioDecoderMultiChannelOpusConfig { + // The number of channels that the decoder will output. + int num_channels; + + // Number of mono or stereo encoded Opus streams. + int num_streams; + + // Number of channel pairs coupled together, see RFC 7845 section + // 5.1.1. Has to be less than the number of streams. + int coupled_streams; + + // Channel mapping table, defines the mapping from encoded streams to output + // channels. See RFC 7845 section 5.1.1. + std::vector<unsigned char> channel_mapping; + + bool IsOk() const { + if (num_channels < 1 || num_channels > AudioDecoder::kMaxNumberOfChannels || + num_streams < 0 || coupled_streams < 0) { + return false; + } + if (num_streams < coupled_streams) { + return false; + } + if (channel_mapping.size() != static_cast<size_t>(num_channels)) { + return false; + } + + // Every mono stream codes one channel, every coupled stream codes two. This + // is the total coded channel count: + const int max_coded_channel = num_streams + coupled_streams; + for (const auto& x : channel_mapping) { + // Coded channels >= max_coded_channel don't exist. Except for 255, which + // tells Opus to put silence in output channel x. + if (x >= max_coded_channel && x != 255) { + return false; + } + } + + if (num_channels > 255 || max_coded_channel >= 255) { + return false; + } + return true; + } +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_OPUS_AUDIO_DECODER_MULTI_CHANNEL_OPUS_CONFIG_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multiopus_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multiopus_gn/moz.build new file mode 100644 index 0000000000..2b2bc6d9a7 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multiopus_gn/moz.build @@ -0,0 +1,226 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/media/libopus/include/", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_multi_channel_opus.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_decoder_multiopus_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus.cc b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus.cc new file mode 100644 index 0000000000..efc9a73546 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus.cc @@ -0,0 +1,86 @@ +/* + * 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. + */ + +#include "api/audio_codecs/opus/audio_decoder_opus.h" + +#include <memory> +#include <utility> +#include <vector> + +#include "absl/strings/match.h" +#include "modules/audio_coding/codecs/opus/audio_decoder_opus.h" + +namespace webrtc { + +bool AudioDecoderOpus::Config::IsOk() const { + if (sample_rate_hz != 16000 && sample_rate_hz != 48000) { + // Unsupported sample rate. (libopus supports a few other rates as + // well; we can add support for them when needed.) + return false; + } + if (num_channels != 1 && num_channels != 2) { + return false; + } + return true; +} + +absl::optional<AudioDecoderOpus::Config> AudioDecoderOpus::SdpToConfig( + const SdpAudioFormat& format) { + const auto num_channels = [&]() -> absl::optional<int> { + auto stereo = format.parameters.find("stereo"); + if (stereo != format.parameters.end()) { + if (stereo->second == "0") { + return 1; + } else if (stereo->second == "1") { + return 2; + } else { + return absl::nullopt; // Bad stereo parameter. + } + } + return 1; // Default to mono. + }(); + if (absl::EqualsIgnoreCase(format.name, "opus") && + format.clockrate_hz == 48000 && format.num_channels == 2 && + num_channels) { + Config config; + config.num_channels = *num_channels; + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return absl::nullopt; + } + return config; + } else { + return absl::nullopt; + } +} + +void AudioDecoderOpus::AppendSupportedDecoders( + std::vector<AudioCodecSpec>* specs) { + AudioCodecInfo opus_info{48000, 1, 64000, 6000, 510000}; + opus_info.allow_comfort_noise = false; + opus_info.supports_network_adaption = true; + SdpAudioFormat opus_format( + {"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}}); + specs->push_back({std::move(opus_format), opus_info}); +} + +std::unique_ptr<AudioDecoder> AudioDecoderOpus::MakeAudioDecoder( + Config config, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return nullptr; + } + return std::make_unique<AudioDecoderOpusImpl>(config.num_channels, + config.sample_rate_hz); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus.h b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus.h new file mode 100644 index 0000000000..138c0377df --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_OPUS_AUDIO_DECODER_OPUS_H_ +#define API_AUDIO_CODECS_OPUS_AUDIO_DECODER_OPUS_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_decoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/field_trials_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Opus decoder API for use as a template parameter to +// CreateAudioDecoderFactory<...>(). +struct RTC_EXPORT AudioDecoderOpus { + struct Config { + bool IsOk() const; // Checks if the values are currently OK. + int sample_rate_hz = 48000; + int num_channels = 1; + }; + static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format); + static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs); + static std::unique_ptr<AudioDecoder> MakeAudioDecoder( + Config config, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_OPUS_AUDIO_DECODER_OPUS_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus_config_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus_config_gn/moz.build new file mode 100644 index 0000000000..e2c470d5ee --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus_config_gn/moz.build @@ -0,0 +1,209 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_decoder_opus_config_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus_gn/moz.build new file mode 100644 index 0000000000..58e6355a55 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus_gn/moz.build @@ -0,0 +1,233 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/media/libopus/include/", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/opus/audio_decoder_opus.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_decoder_opus_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus.cc b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus.cc new file mode 100644 index 0000000000..14f480b1ec --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus.cc @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019 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 "api/audio_codecs/opus/audio_encoder_multi_channel_opus.h" + +#include <utility> + +#include "modules/audio_coding/codecs/opus/audio_encoder_multi_channel_opus_impl.h" + +namespace webrtc { + +absl::optional<AudioEncoderMultiChannelOpusConfig> +AudioEncoderMultiChannelOpus::SdpToConfig(const SdpAudioFormat& format) { + return AudioEncoderMultiChannelOpusImpl::SdpToConfig(format); +} + +void AudioEncoderMultiChannelOpus::AppendSupportedEncoders( + std::vector<AudioCodecSpec>* specs) { + // To get full utilization of the surround support of the Opus lib, we can + // mark which channel is the low frequency effects (LFE). But that is not done + // ATM. + { + AudioCodecInfo surround_5_1_opus_info{48000, 6, + /* default_bitrate_bps= */ 128000}; + surround_5_1_opus_info.allow_comfort_noise = false; + surround_5_1_opus_info.supports_network_adaption = false; + SdpAudioFormat opus_format({"multiopus", + 48000, + 6, + {{"minptime", "10"}, + {"useinbandfec", "1"}, + {"channel_mapping", "0,4,1,2,3,5"}, + {"num_streams", "4"}, + {"coupled_streams", "2"}}}); + specs->push_back({std::move(opus_format), surround_5_1_opus_info}); + } + { + AudioCodecInfo surround_7_1_opus_info{48000, 8, + /* default_bitrate_bps= */ 200000}; + surround_7_1_opus_info.allow_comfort_noise = false; + surround_7_1_opus_info.supports_network_adaption = false; + SdpAudioFormat opus_format({"multiopus", + 48000, + 8, + {{"minptime", "10"}, + {"useinbandfec", "1"}, + {"channel_mapping", "0,6,1,2,3,4,5,7"}, + {"num_streams", "5"}, + {"coupled_streams", "3"}}}); + specs->push_back({std::move(opus_format), surround_7_1_opus_info}); + } +} + +AudioCodecInfo AudioEncoderMultiChannelOpus::QueryAudioEncoder( + const AudioEncoderMultiChannelOpusConfig& config) { + return AudioEncoderMultiChannelOpusImpl::QueryAudioEncoder(config); +} + +std::unique_ptr<AudioEncoder> AudioEncoderMultiChannelOpus::MakeAudioEncoder( + const AudioEncoderMultiChannelOpusConfig& config, + int payload_type, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + return AudioEncoderMultiChannelOpusImpl::MakeAudioEncoder(config, + payload_type); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus.h b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus.h new file mode 100644 index 0000000000..c1c4db3577 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 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 API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_MULTI_CHANNEL_OPUS_H_ +#define API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_MULTI_CHANNEL_OPUS_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_encoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/audio_codecs/opus/audio_encoder_multi_channel_opus_config.h" +#include "api/field_trials_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Opus encoder API for use as a template parameter to +// CreateAudioEncoderFactory<...>(). +struct RTC_EXPORT AudioEncoderMultiChannelOpus { + using Config = AudioEncoderMultiChannelOpusConfig; + static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format); + static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs); + static AudioCodecInfo QueryAudioEncoder(const Config& config); + static std::unique_ptr<AudioEncoder> MakeAudioEncoder( + const Config& config, + int payload_type, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_MULTI_CHANNEL_OPUS_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus_config.cc b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus_config.cc new file mode 100644 index 0000000000..0052c429b2 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus_config.cc @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2019 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 "api/audio_codecs/opus/audio_encoder_multi_channel_opus_config.h" + +namespace webrtc { + +namespace { +constexpr int kDefaultComplexity = 9; +} // namespace + +AudioEncoderMultiChannelOpusConfig::AudioEncoderMultiChannelOpusConfig() + : frame_size_ms(kDefaultFrameSizeMs), + num_channels(1), + application(ApplicationMode::kVoip), + bitrate_bps(32000), + fec_enabled(false), + cbr_enabled(false), + dtx_enabled(false), + max_playback_rate_hz(48000), + complexity(kDefaultComplexity), + num_streams(-1), + coupled_streams(-1) {} +AudioEncoderMultiChannelOpusConfig::AudioEncoderMultiChannelOpusConfig( + const AudioEncoderMultiChannelOpusConfig&) = default; +AudioEncoderMultiChannelOpusConfig::~AudioEncoderMultiChannelOpusConfig() = + default; +AudioEncoderMultiChannelOpusConfig& AudioEncoderMultiChannelOpusConfig:: +operator=(const AudioEncoderMultiChannelOpusConfig&) = default; + +bool AudioEncoderMultiChannelOpusConfig::IsOk() const { + if (frame_size_ms <= 0 || frame_size_ms % 10 != 0) + return false; + if (num_channels >= 255) { + return false; + } + if (bitrate_bps < kMinBitrateBps || bitrate_bps > kMaxBitrateBps) + return false; + if (complexity < 0 || complexity > 10) + return false; + + // Check the lengths: + if (num_streams < 0 || coupled_streams < 0) { + return false; + } + if (num_streams < coupled_streams) { + return false; + } + if (channel_mapping.size() != static_cast<size_t>(num_channels)) { + return false; + } + + // Every mono stream codes one channel, every coupled stream codes two. This + // is the total coded channel count: + const int max_coded_channel = num_streams + coupled_streams; + for (const auto& x : channel_mapping) { + // Coded channels >= max_coded_channel don't exist. Except for 255, which + // tells Opus to ignore input channel x. + if (x >= max_coded_channel && x != 255) { + return false; + } + } + + // Inverse mapping. + constexpr int kNotSet = -1; + std::vector<int> coded_channels_to_input_channels(max_coded_channel, kNotSet); + for (size_t i = 0; i < num_channels; ++i) { + if (channel_mapping[i] == 255) { + continue; + } + + // If it's not ignored, put it in the inverted mapping. But first check if + // we've told Opus to use another input channel for this coded channel: + const int coded_channel = channel_mapping[i]; + if (coded_channels_to_input_channels[coded_channel] != kNotSet) { + // Coded channel `coded_channel` comes from both input channels + // `coded_channels_to_input_channels[coded_channel]` and `i`. + return false; + } + + coded_channels_to_input_channels[coded_channel] = i; + } + + // Check that we specified what input the encoder should use to produce + // every coded channel. + for (int i = 0; i < max_coded_channel; ++i) { + if (coded_channels_to_input_channels[i] == kNotSet) { + // Coded channel `i` has unspecified input channel. + return false; + } + } + + if (num_channels > 255 || max_coded_channel >= 255) { + return false; + } + return true; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus_config.h b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus_config.h new file mode 100644 index 0000000000..9b51246c15 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus_config.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019 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 API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_MULTI_CHANNEL_OPUS_CONFIG_H_ +#define API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_MULTI_CHANNEL_OPUS_CONFIG_H_ + +#include <stddef.h> + +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/opus/audio_encoder_opus_config.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +struct RTC_EXPORT AudioEncoderMultiChannelOpusConfig { + static constexpr int kDefaultFrameSizeMs = 20; + + // Opus API allows a min bitrate of 500bps, but Opus documentation suggests + // bitrate should be in the range of 6000 to 510000, inclusive. + static constexpr int kMinBitrateBps = 6000; + static constexpr int kMaxBitrateBps = 510000; + + AudioEncoderMultiChannelOpusConfig(); + AudioEncoderMultiChannelOpusConfig(const AudioEncoderMultiChannelOpusConfig&); + ~AudioEncoderMultiChannelOpusConfig(); + AudioEncoderMultiChannelOpusConfig& operator=( + const AudioEncoderMultiChannelOpusConfig&); + + int frame_size_ms; + size_t num_channels; + enum class ApplicationMode { kVoip, kAudio }; + ApplicationMode application; + int bitrate_bps; + bool fec_enabled; + bool cbr_enabled; + bool dtx_enabled; + int max_playback_rate_hz; + std::vector<int> supported_frame_lengths_ms; + + int complexity; + + // Number of mono/stereo Opus streams. + int num_streams; + + // Number of channel pairs coupled together, see RFC 7845 section + // 5.1.1. Has to be less than the number of streams + int coupled_streams; + + // Channel mapping table, defines the mapping from encoded streams to input + // channels. See RFC 7845 section 5.1.1. + std::vector<unsigned char> channel_mapping; + + bool IsOk() const; +}; + +} // namespace webrtc +#endif // API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_MULTI_CHANNEL_OPUS_CONFIG_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multiopus_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multiopus_gn/moz.build new file mode 100644 index 0000000000..91afd0a4e4 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multiopus_gn/moz.build @@ -0,0 +1,226 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/media/libopus/include/", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_encoder_multiopus_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus.cc b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus.cc new file mode 100644 index 0000000000..5b6322da4c --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus.cc @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#include "api/audio_codecs/opus/audio_encoder_opus.h" + +#include "modules/audio_coding/codecs/opus/audio_encoder_opus.h" + +namespace webrtc { + +absl::optional<AudioEncoderOpusConfig> AudioEncoderOpus::SdpToConfig( + const SdpAudioFormat& format) { + return AudioEncoderOpusImpl::SdpToConfig(format); +} + +void AudioEncoderOpus::AppendSupportedEncoders( + std::vector<AudioCodecSpec>* specs) { + AudioEncoderOpusImpl::AppendSupportedEncoders(specs); +} + +AudioCodecInfo AudioEncoderOpus::QueryAudioEncoder( + const AudioEncoderOpusConfig& config) { + return AudioEncoderOpusImpl::QueryAudioEncoder(config); +} + +std::unique_ptr<AudioEncoder> AudioEncoderOpus::MakeAudioEncoder( + const AudioEncoderOpusConfig& config, + int payload_type, + absl::optional<AudioCodecPairId> /*codec_pair_id*/, + const FieldTrialsView* field_trials) { + if (!config.IsOk()) { + RTC_DCHECK_NOTREACHED(); + return nullptr; + } + return AudioEncoderOpusImpl::MakeAudioEncoder(config, payload_type); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus.h b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus.h new file mode 100644 index 0000000000..df93ae5303 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_OPUS_H_ +#define API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_OPUS_H_ + +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_encoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/audio_codecs/opus/audio_encoder_opus_config.h" +#include "api/field_trials_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Opus encoder API for use as a template parameter to +// CreateAudioEncoderFactory<...>(). +struct RTC_EXPORT AudioEncoderOpus { + using Config = AudioEncoderOpusConfig; + static absl::optional<AudioEncoderOpusConfig> SdpToConfig( + const SdpAudioFormat& audio_format); + static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs); + static AudioCodecInfo QueryAudioEncoder(const AudioEncoderOpusConfig& config); + static std::unique_ptr<AudioEncoder> MakeAudioEncoder( + const AudioEncoderOpusConfig& config, + int payload_type, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr); +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_OPUS_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_config.cc b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_config.cc new file mode 100644 index 0000000000..a9ab924b38 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_config.cc @@ -0,0 +1,75 @@ +/* + * 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. + */ + +#include "api/audio_codecs/opus/audio_encoder_opus_config.h" + +namespace webrtc { + +namespace { + +#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) +constexpr int kDefaultComplexity = 5; +#else +constexpr int kDefaultComplexity = 9; +#endif + +constexpr int kDefaultLowRateComplexity = + WEBRTC_OPUS_VARIABLE_COMPLEXITY ? 9 : kDefaultComplexity; + +} // namespace + +constexpr int AudioEncoderOpusConfig::kDefaultFrameSizeMs; +constexpr int AudioEncoderOpusConfig::kMinBitrateBps; +constexpr int AudioEncoderOpusConfig::kMaxBitrateBps; + +AudioEncoderOpusConfig::AudioEncoderOpusConfig() + : frame_size_ms(kDefaultFrameSizeMs), + sample_rate_hz(48000), + num_channels(1), + application(ApplicationMode::kVoip), + bitrate_bps(32000), + fec_enabled(false), + cbr_enabled(false), + max_playback_rate_hz(48000), + complexity(kDefaultComplexity), + low_rate_complexity(kDefaultLowRateComplexity), + complexity_threshold_bps(12500), + complexity_threshold_window_bps(1500), + dtx_enabled(false), + uplink_bandwidth_update_interval_ms(200), + payload_type(-1) {} +AudioEncoderOpusConfig::AudioEncoderOpusConfig(const AudioEncoderOpusConfig&) = + default; +AudioEncoderOpusConfig::~AudioEncoderOpusConfig() = default; +AudioEncoderOpusConfig& AudioEncoderOpusConfig::operator=( + const AudioEncoderOpusConfig&) = default; + +bool AudioEncoderOpusConfig::IsOk() const { + if (frame_size_ms <= 0 || frame_size_ms % 10 != 0) + return false; + if (sample_rate_hz != 16000 && sample_rate_hz != 48000) { + // Unsupported input sample rate. (libopus supports a few other rates as + // well; we can add support for them when needed.) + return false; + } + if (num_channels >= 255) { + return false; + } + if (!bitrate_bps) + return false; + if (*bitrate_bps < kMinBitrateBps || *bitrate_bps > kMaxBitrateBps) + return false; + if (complexity < 0 || complexity > 10) + return false; + if (low_rate_complexity < 0 || low_rate_complexity > 10) + return false; + return true; +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_config.h b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_config.h new file mode 100644 index 0000000000..d5d7256c70 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_config.h @@ -0,0 +1,74 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_OPUS_CONFIG_H_ +#define API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_OPUS_CONFIG_H_ + +#include <stddef.h> + +#include <vector> + +#include "absl/types/optional.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +struct RTC_EXPORT AudioEncoderOpusConfig { + static constexpr int kDefaultFrameSizeMs = 20; + + // Opus API allows a min bitrate of 500bps, but Opus documentation suggests + // bitrate should be in the range of 6000 to 510000, inclusive. + static constexpr int kMinBitrateBps = 6000; + static constexpr int kMaxBitrateBps = 510000; + + AudioEncoderOpusConfig(); + AudioEncoderOpusConfig(const AudioEncoderOpusConfig&); + ~AudioEncoderOpusConfig(); + AudioEncoderOpusConfig& operator=(const AudioEncoderOpusConfig&); + + bool IsOk() const; // Checks if the values are currently OK. + + int frame_size_ms; + int sample_rate_hz; + size_t num_channels; + enum class ApplicationMode { kVoip, kAudio }; + ApplicationMode application; + + // NOTE: This member must always be set. + // TODO(kwiberg): Turn it into just an int. + absl::optional<int> bitrate_bps; + + bool fec_enabled; + bool cbr_enabled; + int max_playback_rate_hz; + + // `complexity` is used when the bitrate goes above + // `complexity_threshold_bps` + `complexity_threshold_window_bps`; + // `low_rate_complexity` is used when the bitrate falls below + // `complexity_threshold_bps` - `complexity_threshold_window_bps`. In the + // interval in the middle, we keep using the most recent of the two + // complexity settings. + int complexity; + int low_rate_complexity; + int complexity_threshold_bps; + int complexity_threshold_window_bps; + + bool dtx_enabled; + std::vector<int> supported_frame_lengths_ms; + int uplink_bandwidth_update_interval_ms; + + // NOTE: This member isn't necessary, and will soon go away. See + // https://bugs.chromium.org/p/webrtc/issues/detail?id=7847 + int payload_type; +}; + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_OPUS_CONFIG_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_config_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_config_gn/moz.build new file mode 100644 index 0000000000..06732b48f4 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_config_gn/moz.build @@ -0,0 +1,222 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_OPUS_VARIABLE_COMPLEXITY"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_config.cc" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus_config.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_encoder_opus_config_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_gn/moz.build b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_gn/moz.build new file mode 100644 index 0000000000..ab84d3f755 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus_gn/moz.build @@ -0,0 +1,233 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/media/libopus/include/", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_codecs/opus/audio_encoder_opus.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_encoder_opus_gn") diff --git a/third_party/libwebrtc/api/audio_codecs/opus_audio_decoder_factory.cc b/third_party/libwebrtc/api/audio_codecs/opus_audio_decoder_factory.cc new file mode 100644 index 0000000000..ed68f2584e --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus_audio_decoder_factory.cc @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019 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 "api/audio_codecs/opus_audio_decoder_factory.h" + +#include <memory> +#include <vector> + +#include "api/audio_codecs/audio_decoder_factory_template.h" +#include "api/audio_codecs/opus/audio_decoder_multi_channel_opus.h" +#include "api/audio_codecs/opus/audio_decoder_opus.h" + +namespace webrtc { + +namespace { + +// Modify an audio decoder to not advertise support for anything. +template <typename T> +struct NotAdvertised { + using Config = typename T::Config; + static absl::optional<Config> SdpToConfig( + const SdpAudioFormat& audio_format) { + return T::SdpToConfig(audio_format); + } + static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) { + // Don't advertise support for anything. + } + static std::unique_ptr<AudioDecoder> MakeAudioDecoder( + const Config& config, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt) { + return T::MakeAudioDecoder(config, codec_pair_id); + } +}; + +} // namespace + +rtc::scoped_refptr<AudioDecoderFactory> CreateOpusAudioDecoderFactory() { + return CreateAudioDecoderFactory< + AudioDecoderOpus, NotAdvertised<AudioDecoderMultiChannelOpus>>(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/opus_audio_decoder_factory.h b/third_party/libwebrtc/api/audio_codecs/opus_audio_decoder_factory.h new file mode 100644 index 0000000000..b4f497f8ff --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus_audio_decoder_factory.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019 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 API_AUDIO_CODECS_OPUS_AUDIO_DECODER_FACTORY_H_ +#define API_AUDIO_CODECS_OPUS_AUDIO_DECODER_FACTORY_H_ + +#include "api/audio_codecs/audio_decoder_factory.h" +#include "api/scoped_refptr.h" + +namespace webrtc { + +// Creates a new factory that can create only Opus audio decoders. Works like +// CreateAudioDecoderFactory<AudioDecoderOpus>(), but is easier to use and is +// not inline because it isn't a template. +rtc::scoped_refptr<AudioDecoderFactory> CreateOpusAudioDecoderFactory(); + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_OPUS_AUDIO_DECODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/opus_audio_encoder_factory.cc b/third_party/libwebrtc/api/audio_codecs/opus_audio_encoder_factory.cc new file mode 100644 index 0000000000..8c286f21e1 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus_audio_encoder_factory.cc @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019 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 "api/audio_codecs/opus_audio_encoder_factory.h" + +#include <memory> +#include <vector> + +#include "api/audio_codecs/audio_encoder_factory_template.h" +#include "api/audio_codecs/opus/audio_encoder_multi_channel_opus.h" +#include "api/audio_codecs/opus/audio_encoder_opus.h" + +namespace webrtc { +namespace { + +// Modify an audio encoder to not advertise support for anything. +template <typename T> +struct NotAdvertised { + using Config = typename T::Config; + static absl::optional<Config> SdpToConfig( + const SdpAudioFormat& audio_format) { + return T::SdpToConfig(audio_format); + } + static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) { + // Don't advertise support for anything. + } + static AudioCodecInfo QueryAudioEncoder(const Config& config) { + return T::QueryAudioEncoder(config); + } + static std::unique_ptr<AudioEncoder> MakeAudioEncoder( + const Config& config, + int payload_type, + absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt, + const FieldTrialsView* field_trials = nullptr) { + return T::MakeAudioEncoder(config, payload_type, codec_pair_id, + field_trials); + } +}; + +} // namespace + +rtc::scoped_refptr<AudioEncoderFactory> CreateOpusAudioEncoderFactory() { + return CreateAudioEncoderFactory< + AudioEncoderOpus, NotAdvertised<AudioEncoderMultiChannelOpus>>(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/opus_audio_encoder_factory.h b/third_party/libwebrtc/api/audio_codecs/opus_audio_encoder_factory.h new file mode 100644 index 0000000000..8c1683b6f5 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/opus_audio_encoder_factory.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019 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 API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_FACTORY_H_ +#define API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_FACTORY_H_ + +#include "api/audio_codecs/audio_encoder_factory.h" +#include "api/scoped_refptr.h" + +namespace webrtc { + +// Creates a new factory that can create only Opus audio encoders. Works like +// CreateAudioEncoderFactory<AudioEncoderOpus>(), but is easier to use and is +// not inline because it isn't a template. +rtc::scoped_refptr<AudioEncoderFactory> CreateOpusAudioEncoderFactory(); + +} // namespace webrtc + +#endif // API_AUDIO_CODECS_OPUS_AUDIO_ENCODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/audio_codecs/test/BUILD.gn b/third_party/libwebrtc/api/audio_codecs/test/BUILD.gn new file mode 100644 index 0000000000..89f5fef1ea --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/test/BUILD.gn @@ -0,0 +1,39 @@ +# 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. + +import("../../../webrtc.gni") +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +if (rtc_include_tests) { + rtc_library("audio_codecs_api_unittests") { + testonly = true + sources = [ + "audio_decoder_factory_template_unittest.cc", + "audio_encoder_factory_template_unittest.cc", + ] + deps = [ + "..:audio_codecs_api", + "../../../test:audio_codec_mocks", + "../../../test:scoped_key_value_config", + "../../../test:test_support", + "../L16:audio_decoder_L16", + "../L16:audio_encoder_L16", + "../g711:audio_decoder_g711", + "../g711:audio_encoder_g711", + "../g722:audio_decoder_g722", + "../g722:audio_encoder_g722", + "../ilbc:audio_decoder_ilbc", + "../ilbc:audio_encoder_ilbc", + "../opus:audio_decoder_opus", + "../opus:audio_encoder_opus", + ] + } +} diff --git a/third_party/libwebrtc/api/audio_codecs/test/audio_decoder_factory_template_unittest.cc b/third_party/libwebrtc/api/audio_codecs/test/audio_decoder_factory_template_unittest.cc new file mode 100644 index 0000000000..0b18cf934a --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/test/audio_decoder_factory_template_unittest.cc @@ -0,0 +1,222 @@ +/* + * 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. + */ + +#include "api/audio_codecs/audio_decoder_factory_template.h" + +#include <memory> + +#include "api/audio_codecs/L16/audio_decoder_L16.h" +#include "api/audio_codecs/g711/audio_decoder_g711.h" +#include "api/audio_codecs/g722/audio_decoder_g722.h" +#include "api/audio_codecs/ilbc/audio_decoder_ilbc.h" +#include "api/audio_codecs/opus/audio_decoder_opus.h" +#include "test/gmock.h" +#include "test/gtest.h" +#include "test/mock_audio_decoder.h" +#include "test/scoped_key_value_config.h" + +namespace webrtc { + +namespace { + +struct BogusParams { + static SdpAudioFormat AudioFormat() { return {"bogus", 8000, 1}; } + static AudioCodecInfo CodecInfo() { return {8000, 1, 12345}; } +}; + +struct ShamParams { + static SdpAudioFormat AudioFormat() { + return {"sham", 16000, 2, {{"param", "value"}}}; + } + static AudioCodecInfo CodecInfo() { return {16000, 2, 23456}; } +}; + +template <typename Params> +struct AudioDecoderFakeApi { + struct Config { + SdpAudioFormat audio_format; + }; + + static absl::optional<Config> SdpToConfig( + const SdpAudioFormat& audio_format) { + if (Params::AudioFormat() == audio_format) { + Config config = {audio_format}; + return config; + } else { + return absl::nullopt; + } + } + + static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) { + specs->push_back({Params::AudioFormat(), Params::CodecInfo()}); + } + + static AudioCodecInfo QueryAudioDecoder(const Config&) { + return Params::CodecInfo(); + } + + static std::unique_ptr<AudioDecoder> MakeAudioDecoder( + const Config&, + absl::optional<AudioCodecPairId> /*codec_pair_id*/ = absl::nullopt) { + auto dec = std::make_unique<testing::StrictMock<MockAudioDecoder>>(); + EXPECT_CALL(*dec, SampleRateHz()) + .WillOnce(::testing::Return(Params::CodecInfo().sample_rate_hz)); + EXPECT_CALL(*dec, Die()); + return std::move(dec); + } +}; + +} // namespace + +TEST(AudioDecoderFactoryTemplateTest, NoDecoderTypes) { + test::ScopedKeyValueConfig field_trials; + rtc::scoped_refptr<AudioDecoderFactory> factory( + rtc::make_ref_counted< + audio_decoder_factory_template_impl::AudioDecoderFactoryT<>>( + &field_trials)); + EXPECT_THAT(factory->GetSupportedDecoders(), ::testing::IsEmpty()); + EXPECT_FALSE(factory->IsSupportedDecoder({"foo", 8000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioDecoder({"bar", 16000, 1}, absl::nullopt)); +} + +TEST(AudioDecoderFactoryTemplateTest, OneDecoderType) { + auto factory = CreateAudioDecoderFactory<AudioDecoderFakeApi<BogusParams>>(); + EXPECT_THAT(factory->GetSupportedDecoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"bogus", 8000, 1}, {8000, 1, 12345}})); + EXPECT_FALSE(factory->IsSupportedDecoder({"foo", 8000, 1})); + EXPECT_TRUE(factory->IsSupportedDecoder({"bogus", 8000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioDecoder({"bar", 16000, 1}, absl::nullopt)); + auto dec = factory->MakeAudioDecoder({"bogus", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, dec); + EXPECT_EQ(8000, dec->SampleRateHz()); +} + +TEST(AudioDecoderFactoryTemplateTest, TwoDecoderTypes) { + auto factory = CreateAudioDecoderFactory<AudioDecoderFakeApi<BogusParams>, + AudioDecoderFakeApi<ShamParams>>(); + EXPECT_THAT(factory->GetSupportedDecoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"bogus", 8000, 1}, {8000, 1, 12345}}, + AudioCodecSpec{{"sham", 16000, 2, {{"param", "value"}}}, + {16000, 2, 23456}})); + EXPECT_FALSE(factory->IsSupportedDecoder({"foo", 8000, 1})); + EXPECT_TRUE(factory->IsSupportedDecoder({"bogus", 8000, 1})); + EXPECT_TRUE( + factory->IsSupportedDecoder({"sham", 16000, 2, {{"param", "value"}}})); + EXPECT_EQ(nullptr, + factory->MakeAudioDecoder({"bar", 16000, 1}, absl::nullopt)); + auto dec1 = factory->MakeAudioDecoder({"bogus", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, dec1); + EXPECT_EQ(8000, dec1->SampleRateHz()); + EXPECT_EQ(nullptr, + factory->MakeAudioDecoder({"sham", 16000, 2}, absl::nullopt)); + auto dec2 = factory->MakeAudioDecoder( + {"sham", 16000, 2, {{"param", "value"}}}, absl::nullopt); + ASSERT_NE(nullptr, dec2); + EXPECT_EQ(16000, dec2->SampleRateHz()); +} + +TEST(AudioDecoderFactoryTemplateTest, G711) { + auto factory = CreateAudioDecoderFactory<AudioDecoderG711>(); + EXPECT_THAT(factory->GetSupportedDecoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"PCMU", 8000, 1}, {8000, 1, 64000}}, + AudioCodecSpec{{"PCMA", 8000, 1}, {8000, 1, 64000}})); + EXPECT_FALSE(factory->IsSupportedDecoder({"G711", 8000, 1})); + EXPECT_TRUE(factory->IsSupportedDecoder({"PCMU", 8000, 1})); + EXPECT_TRUE(factory->IsSupportedDecoder({"pcma", 8000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioDecoder({"pcmu", 16000, 1}, absl::nullopt)); + auto dec1 = factory->MakeAudioDecoder({"pcmu", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, dec1); + EXPECT_EQ(8000, dec1->SampleRateHz()); + auto dec2 = factory->MakeAudioDecoder({"PCMA", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, dec2); + EXPECT_EQ(8000, dec2->SampleRateHz()); +} + +TEST(AudioDecoderFactoryTemplateTest, G722) { + auto factory = CreateAudioDecoderFactory<AudioDecoderG722>(); + EXPECT_THAT(factory->GetSupportedDecoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"G722", 8000, 1}, {16000, 1, 64000}})); + EXPECT_FALSE(factory->IsSupportedDecoder({"foo", 8000, 1})); + EXPECT_TRUE(factory->IsSupportedDecoder({"G722", 8000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioDecoder({"bar", 16000, 1}, absl::nullopt)); + auto dec1 = factory->MakeAudioDecoder({"G722", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, dec1); + EXPECT_EQ(16000, dec1->SampleRateHz()); + EXPECT_EQ(1u, dec1->Channels()); + auto dec2 = factory->MakeAudioDecoder({"G722", 8000, 2}, absl::nullopt); + ASSERT_NE(nullptr, dec2); + EXPECT_EQ(16000, dec2->SampleRateHz()); + EXPECT_EQ(2u, dec2->Channels()); + auto dec3 = factory->MakeAudioDecoder({"G722", 8000, 3}, absl::nullopt); + ASSERT_EQ(nullptr, dec3); +} + +TEST(AudioDecoderFactoryTemplateTest, Ilbc) { + auto factory = CreateAudioDecoderFactory<AudioDecoderIlbc>(); + EXPECT_THAT(factory->GetSupportedDecoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"ILBC", 8000, 1}, {8000, 1, 13300}})); + EXPECT_FALSE(factory->IsSupportedDecoder({"foo", 8000, 1})); + EXPECT_TRUE(factory->IsSupportedDecoder({"ilbc", 8000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioDecoder({"bar", 8000, 1}, absl::nullopt)); + auto dec = factory->MakeAudioDecoder({"ilbc", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, dec); + EXPECT_EQ(8000, dec->SampleRateHz()); +} + +TEST(AudioDecoderFactoryTemplateTest, L16) { + auto factory = CreateAudioDecoderFactory<AudioDecoderL16>(); + EXPECT_THAT( + factory->GetSupportedDecoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"L16", 8000, 1}, {8000, 1, 8000 * 16}}, + AudioCodecSpec{{"L16", 16000, 1}, {16000, 1, 16000 * 16}}, + AudioCodecSpec{{"L16", 32000, 1}, {32000, 1, 32000 * 16}}, + AudioCodecSpec{{"L16", 8000, 2}, {8000, 2, 8000 * 16 * 2}}, + AudioCodecSpec{{"L16", 16000, 2}, {16000, 2, 16000 * 16 * 2}}, + AudioCodecSpec{{"L16", 32000, 2}, {32000, 2, 32000 * 16 * 2}})); + EXPECT_FALSE(factory->IsSupportedDecoder({"foo", 8000, 1})); + EXPECT_TRUE(factory->IsSupportedDecoder({"L16", 48000, 1})); + EXPECT_FALSE(factory->IsSupportedDecoder({"L16", 96000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioDecoder({"L16", 8000, 0}, absl::nullopt)); + auto dec = factory->MakeAudioDecoder({"L16", 48000, 2}, absl::nullopt); + ASSERT_NE(nullptr, dec); + EXPECT_EQ(48000, dec->SampleRateHz()); +} + +TEST(AudioDecoderFactoryTemplateTest, Opus) { + auto factory = CreateAudioDecoderFactory<AudioDecoderOpus>(); + AudioCodecInfo opus_info{48000, 1, 64000, 6000, 510000}; + opus_info.allow_comfort_noise = false; + opus_info.supports_network_adaption = true; + const SdpAudioFormat opus_format( + {"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}}); + EXPECT_THAT(factory->GetSupportedDecoders(), + ::testing::ElementsAre(AudioCodecSpec{opus_format, opus_info})); + EXPECT_FALSE(factory->IsSupportedDecoder({"opus", 48000, 1})); + EXPECT_TRUE(factory->IsSupportedDecoder({"opus", 48000, 2})); + EXPECT_EQ(nullptr, + factory->MakeAudioDecoder({"bar", 16000, 1}, absl::nullopt)); + auto dec = factory->MakeAudioDecoder({"opus", 48000, 2}, absl::nullopt); + ASSERT_NE(nullptr, dec); + EXPECT_EQ(48000, dec->SampleRateHz()); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_codecs/test/audio_encoder_factory_template_unittest.cc b/third_party/libwebrtc/api/audio_codecs/test/audio_encoder_factory_template_unittest.cc new file mode 100644 index 0000000000..dbba387724 --- /dev/null +++ b/third_party/libwebrtc/api/audio_codecs/test/audio_encoder_factory_template_unittest.cc @@ -0,0 +1,224 @@ +/* + * 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. + */ + +#include "api/audio_codecs/audio_encoder_factory_template.h" + +#include <memory> + +#include "api/audio_codecs/L16/audio_encoder_L16.h" +#include "api/audio_codecs/g711/audio_encoder_g711.h" +#include "api/audio_codecs/g722/audio_encoder_g722.h" +#include "api/audio_codecs/ilbc/audio_encoder_ilbc.h" +#include "api/audio_codecs/opus/audio_encoder_opus.h" +#include "test/gmock.h" +#include "test/gtest.h" +#include "test/mock_audio_encoder.h" +#include "test/scoped_key_value_config.h" + +namespace webrtc { + +namespace { + +struct BogusParams { + static SdpAudioFormat AudioFormat() { return {"bogus", 8000, 1}; } + static AudioCodecInfo CodecInfo() { return {8000, 1, 12345}; } +}; + +struct ShamParams { + static SdpAudioFormat AudioFormat() { + return {"sham", 16000, 2, {{"param", "value"}}}; + } + static AudioCodecInfo CodecInfo() { return {16000, 2, 23456}; } +}; + +template <typename Params> +struct AudioEncoderFakeApi { + struct Config { + SdpAudioFormat audio_format; + }; + + static absl::optional<Config> SdpToConfig( + const SdpAudioFormat& audio_format) { + if (Params::AudioFormat() == audio_format) { + Config config = {audio_format}; + return config; + } else { + return absl::nullopt; + } + } + + static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) { + specs->push_back({Params::AudioFormat(), Params::CodecInfo()}); + } + + static AudioCodecInfo QueryAudioEncoder(const Config&) { + return Params::CodecInfo(); + } + + static std::unique_ptr<AudioEncoder> MakeAudioEncoder( + const Config&, + int payload_type, + absl::optional<AudioCodecPairId> /*codec_pair_id*/ = absl::nullopt) { + auto enc = std::make_unique<testing::StrictMock<MockAudioEncoder>>(); + EXPECT_CALL(*enc, SampleRateHz()) + .WillOnce(::testing::Return(Params::CodecInfo().sample_rate_hz)); + return std::move(enc); + } +}; + +} // namespace + +TEST(AudioEncoderFactoryTemplateTest, NoEncoderTypes) { + test::ScopedKeyValueConfig field_trials; + rtc::scoped_refptr<AudioEncoderFactory> factory( + rtc::make_ref_counted< + audio_encoder_factory_template_impl::AudioEncoderFactoryT<>>( + &field_trials)); + EXPECT_THAT(factory->GetSupportedEncoders(), ::testing::IsEmpty()); + EXPECT_EQ(absl::nullopt, factory->QueryAudioEncoder({"foo", 8000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioEncoder(17, {"bar", 16000, 1}, absl::nullopt)); +} + +TEST(AudioEncoderFactoryTemplateTest, OneEncoderType) { + auto factory = CreateAudioEncoderFactory<AudioEncoderFakeApi<BogusParams>>(); + EXPECT_THAT(factory->GetSupportedEncoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"bogus", 8000, 1}, {8000, 1, 12345}})); + EXPECT_EQ(absl::nullopt, factory->QueryAudioEncoder({"foo", 8000, 1})); + EXPECT_EQ(AudioCodecInfo(8000, 1, 12345), + factory->QueryAudioEncoder({"bogus", 8000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioEncoder(17, {"bar", 16000, 1}, absl::nullopt)); + auto enc = factory->MakeAudioEncoder(17, {"bogus", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, enc); + EXPECT_EQ(8000, enc->SampleRateHz()); +} + +TEST(AudioEncoderFactoryTemplateTest, TwoEncoderTypes) { + auto factory = CreateAudioEncoderFactory<AudioEncoderFakeApi<BogusParams>, + AudioEncoderFakeApi<ShamParams>>(); + EXPECT_THAT(factory->GetSupportedEncoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"bogus", 8000, 1}, {8000, 1, 12345}}, + AudioCodecSpec{{"sham", 16000, 2, {{"param", "value"}}}, + {16000, 2, 23456}})); + EXPECT_EQ(absl::nullopt, factory->QueryAudioEncoder({"foo", 8000, 1})); + EXPECT_EQ(AudioCodecInfo(8000, 1, 12345), + factory->QueryAudioEncoder({"bogus", 8000, 1})); + EXPECT_EQ( + AudioCodecInfo(16000, 2, 23456), + factory->QueryAudioEncoder({"sham", 16000, 2, {{"param", "value"}}})); + EXPECT_EQ(nullptr, + factory->MakeAudioEncoder(17, {"bar", 16000, 1}, absl::nullopt)); + auto enc1 = factory->MakeAudioEncoder(17, {"bogus", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, enc1); + EXPECT_EQ(8000, enc1->SampleRateHz()); + EXPECT_EQ(nullptr, + factory->MakeAudioEncoder(17, {"sham", 16000, 2}, absl::nullopt)); + auto enc2 = factory->MakeAudioEncoder( + 17, {"sham", 16000, 2, {{"param", "value"}}}, absl::nullopt); + ASSERT_NE(nullptr, enc2); + EXPECT_EQ(16000, enc2->SampleRateHz()); +} + +TEST(AudioEncoderFactoryTemplateTest, G711) { + auto factory = CreateAudioEncoderFactory<AudioEncoderG711>(); + EXPECT_THAT(factory->GetSupportedEncoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"PCMU", 8000, 1}, {8000, 1, 64000}}, + AudioCodecSpec{{"PCMA", 8000, 1}, {8000, 1, 64000}})); + EXPECT_EQ(absl::nullopt, factory->QueryAudioEncoder({"PCMA", 16000, 1})); + EXPECT_EQ(AudioCodecInfo(8000, 1, 64000), + factory->QueryAudioEncoder({"PCMA", 8000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioEncoder(17, {"PCMU", 16000, 1}, absl::nullopt)); + auto enc1 = factory->MakeAudioEncoder(17, {"PCMU", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, enc1); + EXPECT_EQ(8000, enc1->SampleRateHz()); + auto enc2 = factory->MakeAudioEncoder(17, {"PCMA", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, enc2); + EXPECT_EQ(8000, enc2->SampleRateHz()); +} + +TEST(AudioEncoderFactoryTemplateTest, G722) { + auto factory = CreateAudioEncoderFactory<AudioEncoderG722>(); + EXPECT_THAT(factory->GetSupportedEncoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"G722", 8000, 1}, {16000, 1, 64000}})); + EXPECT_EQ(absl::nullopt, factory->QueryAudioEncoder({"foo", 8000, 1})); + EXPECT_EQ(AudioCodecInfo(16000, 1, 64000), + factory->QueryAudioEncoder({"G722", 8000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioEncoder(17, {"bar", 16000, 1}, absl::nullopt)); + auto enc = factory->MakeAudioEncoder(17, {"G722", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, enc); + EXPECT_EQ(16000, enc->SampleRateHz()); +} + +TEST(AudioEncoderFactoryTemplateTest, Ilbc) { + auto factory = CreateAudioEncoderFactory<AudioEncoderIlbc>(); + EXPECT_THAT(factory->GetSupportedEncoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"ILBC", 8000, 1}, {8000, 1, 13333}})); + EXPECT_EQ(absl::nullopt, factory->QueryAudioEncoder({"foo", 8000, 1})); + EXPECT_EQ(AudioCodecInfo(8000, 1, 13333), + factory->QueryAudioEncoder({"ilbc", 8000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioEncoder(17, {"bar", 8000, 1}, absl::nullopt)); + auto enc = factory->MakeAudioEncoder(17, {"ilbc", 8000, 1}, absl::nullopt); + ASSERT_NE(nullptr, enc); + EXPECT_EQ(8000, enc->SampleRateHz()); +} + +TEST(AudioEncoderFactoryTemplateTest, L16) { + auto factory = CreateAudioEncoderFactory<AudioEncoderL16>(); + EXPECT_THAT( + factory->GetSupportedEncoders(), + ::testing::ElementsAre( + AudioCodecSpec{{"L16", 8000, 1}, {8000, 1, 8000 * 16}}, + AudioCodecSpec{{"L16", 16000, 1}, {16000, 1, 16000 * 16}}, + AudioCodecSpec{{"L16", 32000, 1}, {32000, 1, 32000 * 16}}, + AudioCodecSpec{{"L16", 8000, 2}, {8000, 2, 8000 * 16 * 2}}, + AudioCodecSpec{{"L16", 16000, 2}, {16000, 2, 16000 * 16 * 2}}, + AudioCodecSpec{{"L16", 32000, 2}, {32000, 2, 32000 * 16 * 2}})); + EXPECT_EQ(absl::nullopt, factory->QueryAudioEncoder({"L16", 8000, 0})); + EXPECT_EQ(AudioCodecInfo(48000, 1, 48000 * 16), + factory->QueryAudioEncoder({"L16", 48000, 1})); + EXPECT_EQ(nullptr, + factory->MakeAudioEncoder(17, {"L16", 8000, 0}, absl::nullopt)); + auto enc = factory->MakeAudioEncoder(17, {"L16", 48000, 2}, absl::nullopt); + ASSERT_NE(nullptr, enc); + EXPECT_EQ(48000, enc->SampleRateHz()); +} + +TEST(AudioEncoderFactoryTemplateTest, Opus) { + auto factory = CreateAudioEncoderFactory<AudioEncoderOpus>(); + AudioCodecInfo info = {48000, 1, 32000, 6000, 510000}; + info.allow_comfort_noise = false; + info.supports_network_adaption = true; + EXPECT_THAT( + factory->GetSupportedEncoders(), + ::testing::ElementsAre(AudioCodecSpec{ + {"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}}, + info})); + EXPECT_EQ(absl::nullopt, factory->QueryAudioEncoder({"foo", 8000, 1})); + EXPECT_EQ( + info, + factory->QueryAudioEncoder( + {"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}})); + EXPECT_EQ(nullptr, + factory->MakeAudioEncoder(17, {"bar", 16000, 1}, absl::nullopt)); + auto enc = factory->MakeAudioEncoder(17, {"opus", 48000, 2}, absl::nullopt); + ASSERT_NE(nullptr, enc); + EXPECT_EQ(48000, enc->SampleRateHz()); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/audio_options.cc b/third_party/libwebrtc/api/audio_options.cc new file mode 100644 index 0000000000..658515062c --- /dev/null +++ b/third_party/libwebrtc/api/audio_options.cc @@ -0,0 +1,107 @@ +/* + * 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 "api/audio_options.h" + +#include "api/array_view.h" +#include "rtc_base/strings/string_builder.h" + +namespace cricket { +namespace { + +template <class T> +void ToStringIfSet(rtc::SimpleStringBuilder* result, + const char* key, + const absl::optional<T>& val) { + if (val) { + (*result) << key << ": " << *val << ", "; + } +} + +template <typename T> +void SetFrom(absl::optional<T>* s, const absl::optional<T>& o) { + if (o) { + *s = o; + } +} + +} // namespace + +AudioOptions::AudioOptions() = default; +AudioOptions::~AudioOptions() = default; + +void AudioOptions::SetAll(const AudioOptions& change) { + SetFrom(&echo_cancellation, change.echo_cancellation); +#if defined(WEBRTC_IOS) + SetFrom(&ios_force_software_aec_HACK, change.ios_force_software_aec_HACK); +#endif + SetFrom(&auto_gain_control, change.auto_gain_control); + SetFrom(&noise_suppression, change.noise_suppression); + SetFrom(&highpass_filter, change.highpass_filter); + SetFrom(&stereo_swapping, change.stereo_swapping); + SetFrom(&audio_jitter_buffer_max_packets, + change.audio_jitter_buffer_max_packets); + SetFrom(&audio_jitter_buffer_fast_accelerate, + change.audio_jitter_buffer_fast_accelerate); + SetFrom(&audio_jitter_buffer_min_delay_ms, + change.audio_jitter_buffer_min_delay_ms); + SetFrom(&combined_audio_video_bwe, change.combined_audio_video_bwe); + SetFrom(&audio_network_adaptor, change.audio_network_adaptor); + SetFrom(&audio_network_adaptor_config, change.audio_network_adaptor_config); + SetFrom(&init_recording_on_send, change.init_recording_on_send); +} + +bool AudioOptions::operator==(const AudioOptions& o) const { + return echo_cancellation == o.echo_cancellation && +#if defined(WEBRTC_IOS) + ios_force_software_aec_HACK == o.ios_force_software_aec_HACK && +#endif + auto_gain_control == o.auto_gain_control && + noise_suppression == o.noise_suppression && + highpass_filter == o.highpass_filter && + stereo_swapping == o.stereo_swapping && + audio_jitter_buffer_max_packets == o.audio_jitter_buffer_max_packets && + audio_jitter_buffer_fast_accelerate == + o.audio_jitter_buffer_fast_accelerate && + audio_jitter_buffer_min_delay_ms == + o.audio_jitter_buffer_min_delay_ms && + combined_audio_video_bwe == o.combined_audio_video_bwe && + audio_network_adaptor == o.audio_network_adaptor && + audio_network_adaptor_config == o.audio_network_adaptor_config && + init_recording_on_send == o.init_recording_on_send; +} + +std::string AudioOptions::ToString() const { + char buffer[1024]; + rtc::SimpleStringBuilder result(buffer); + result << "AudioOptions {"; + ToStringIfSet(&result, "aec", echo_cancellation); +#if defined(WEBRTC_IOS) + ToStringIfSet(&result, "ios_force_software_aec_HACK", + ios_force_software_aec_HACK); +#endif + ToStringIfSet(&result, "agc", auto_gain_control); + ToStringIfSet(&result, "ns", noise_suppression); + ToStringIfSet(&result, "hf", highpass_filter); + ToStringIfSet(&result, "swap", stereo_swapping); + ToStringIfSet(&result, "audio_jitter_buffer_max_packets", + audio_jitter_buffer_max_packets); + ToStringIfSet(&result, "audio_jitter_buffer_fast_accelerate", + audio_jitter_buffer_fast_accelerate); + ToStringIfSet(&result, "audio_jitter_buffer_min_delay_ms", + audio_jitter_buffer_min_delay_ms); + ToStringIfSet(&result, "combined_audio_video_bwe", combined_audio_video_bwe); + ToStringIfSet(&result, "audio_network_adaptor", audio_network_adaptor); + ToStringIfSet(&result, "init_recording_on_send", init_recording_on_send); + result << "}"; + return result.str(); +} + +} // namespace cricket diff --git a/third_party/libwebrtc/api/audio_options.h b/third_party/libwebrtc/api/audio_options.h new file mode 100644 index 0000000000..39ba3886ea --- /dev/null +++ b/third_party/libwebrtc/api/audio_options.h @@ -0,0 +1,80 @@ +/* + * 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. + */ + +#ifndef API_AUDIO_OPTIONS_H_ +#define API_AUDIO_OPTIONS_H_ + +#include <stdint.h> + +#include <string> + +#include "absl/types/optional.h" +#include "rtc_base/system/rtc_export.h" + +namespace cricket { + +// Options that can be applied to a VoiceMediaChannel or a VoiceMediaEngine. +// Used to be flags, but that makes it hard to selectively apply options. +// We are moving all of the setting of options to structs like this, +// but some things currently still use flags. +struct RTC_EXPORT AudioOptions { + AudioOptions(); + ~AudioOptions(); + void SetAll(const AudioOptions& change); + + bool operator==(const AudioOptions& o) const; + bool operator!=(const AudioOptions& o) const { return !(*this == o); } + + std::string ToString() const; + + // Audio processing that attempts to filter away the output signal from + // later inbound pickup. + absl::optional<bool> echo_cancellation; +#if defined(WEBRTC_IOS) + // Forces software echo cancellation on iOS. This is a temporary workaround + // (until Apple fixes the bug) for a device with non-functioning AEC. May + // improve performance on that particular device, but will cause unpredictable + // behavior in all other cases. See http://bugs.webrtc.org/8682. + absl::optional<bool> ios_force_software_aec_HACK; +#endif + // Audio processing to adjust the sensitivity of the local mic dynamically. + absl::optional<bool> auto_gain_control; + // Audio processing to filter out background noise. + absl::optional<bool> noise_suppression; + // Audio processing to remove background noise of lower frequencies. + absl::optional<bool> highpass_filter; + // Audio processing to swap the left and right channels. + absl::optional<bool> stereo_swapping; + // Audio receiver jitter buffer (NetEq) max capacity in number of packets. + absl::optional<int> audio_jitter_buffer_max_packets; + // Audio receiver jitter buffer (NetEq) fast accelerate mode. + absl::optional<bool> audio_jitter_buffer_fast_accelerate; + // Audio receiver jitter buffer (NetEq) minimum target delay in milliseconds. + absl::optional<int> audio_jitter_buffer_min_delay_ms; + // Enable combined audio+bandwidth BWE. + // TODO(pthatcher): This flag is set from the + // "googCombinedAudioVideoBwe", but not used anywhere. So delete it, + // and check if any other AudioOptions members are unused. + absl::optional<bool> combined_audio_video_bwe; + // Enable audio network adaptor. + // TODO(webrtc:11717): Remove this API in favor of adaptivePtime in + // RtpEncodingParameters. + absl::optional<bool> audio_network_adaptor; + // Config string for audio network adaptor. + absl::optional<std::string> audio_network_adaptor_config; + // Pre-initialize the ADM for recording when starting to send. Default to + // true. + // TODO(webrtc:13566): Remove this option. See issue for details. + absl::optional<bool> init_recording_on_send; +}; + +} // namespace cricket + +#endif // API_AUDIO_OPTIONS_H_ diff --git a/third_party/libwebrtc/api/audio_options_api_gn/moz.build b/third_party/libwebrtc/api/audio_options_api_gn/moz.build new file mode 100644 index 0000000000..1b19c42e98 --- /dev/null +++ b/third_party/libwebrtc/api/audio_options_api_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/audio_options.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("audio_options_api_gn") diff --git a/third_party/libwebrtc/api/bitrate_allocation_gn/moz.build b/third_party/libwebrtc/api/bitrate_allocation_gn/moz.build new file mode 100644 index 0000000000..a694eff03b --- /dev/null +++ b/third_party/libwebrtc/api/bitrate_allocation_gn/moz.build @@ -0,0 +1,205 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("bitrate_allocation_gn") diff --git a/third_party/libwebrtc/api/call/audio_sink.h b/third_party/libwebrtc/api/call/audio_sink.h new file mode 100644 index 0000000000..fec26593a6 --- /dev/null +++ b/third_party/libwebrtc/api/call/audio_sink.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 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 API_CALL_AUDIO_SINK_H_ +#define API_CALL_AUDIO_SINK_H_ + +#include <stddef.h> +#include <stdint.h> + +namespace webrtc { + +// Represents a simple push audio sink. +class AudioSinkInterface { + public: + virtual ~AudioSinkInterface() {} + + struct Data { + Data(const int16_t* data, + size_t samples_per_channel, + int sample_rate, + size_t channels, + uint32_t timestamp) + : data(data), + samples_per_channel(samples_per_channel), + sample_rate(sample_rate), + channels(channels), + timestamp(timestamp) {} + + const int16_t* data; // The actual 16bit audio data. + size_t samples_per_channel; // Number of frames in the buffer. + int sample_rate; // Sample rate in Hz. + size_t channels; // Number of channels in the audio data. + uint32_t timestamp; // The RTP timestamp of the first sample. + }; + + virtual void OnData(const Data& audio) = 0; +}; + +} // namespace webrtc + +#endif // API_CALL_AUDIO_SINK_H_ diff --git a/third_party/libwebrtc/api/call/bitrate_allocation.h b/third_party/libwebrtc/api/call/bitrate_allocation.h new file mode 100644 index 0000000000..4b4e5e7ae1 --- /dev/null +++ b/third_party/libwebrtc/api/call/bitrate_allocation.h @@ -0,0 +1,45 @@ +/* + * Copyright 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. + */ +#ifndef API_CALL_BITRATE_ALLOCATION_H_ +#define API_CALL_BITRATE_ALLOCATION_H_ + +#include "api/units/data_rate.h" +#include "api/units/time_delta.h" + +namespace webrtc { + +// BitrateAllocationUpdate provides information to allocated streams about their +// bitrate allocation. It originates from the BitrateAllocater class and is +// propagated from there. +struct BitrateAllocationUpdate { + // The allocated target bitrate. Media streams should produce this amount of + // data. (Note that this may include packet overhead depending on + // configuration.) + DataRate target_bitrate = DataRate::Zero(); + // The allocated part of the estimated link capacity. This is more stable than + // the target as it is based on the underlying link capacity estimate. This + // should be used to change encoder configuration when the cost of change is + // high. + DataRate stable_target_bitrate = DataRate::Zero(); + // Predicted packet loss ratio. + double packet_loss_ratio = 0; + // Predicted round trip time. + TimeDelta round_trip_time = TimeDelta::PlusInfinity(); + // `bwe_period` is deprecated, use `stable_target_bitrate` allocation instead. + TimeDelta bwe_period = TimeDelta::PlusInfinity(); + // Congestion window pushback bitrate reduction fraction. Used in + // VideoStreamEncoder to reduce the bitrate by the given fraction + // by dropping frames. + double cwnd_reduce_ratio = 0; +}; + +} // namespace webrtc + +#endif // API_CALL_BITRATE_ALLOCATION_H_ diff --git a/third_party/libwebrtc/api/call/call_factory_interface.h b/third_party/libwebrtc/api/call/call_factory_interface.h new file mode 100644 index 0000000000..6051409cc3 --- /dev/null +++ b/third_party/libwebrtc/api/call/call_factory_interface.h @@ -0,0 +1,38 @@ +/* + * Copyright 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. + */ + +#ifndef API_CALL_CALL_FACTORY_INTERFACE_H_ +#define API_CALL_CALL_FACTORY_INTERFACE_H_ + +#include <memory> + +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// These classes are not part of the API, and are treated as opaque pointers. +class Call; +struct CallConfig; + +// This interface exists to allow webrtc to be optionally built without media +// support (i.e., if only being used for data channels). PeerConnectionFactory +// is constructed with a CallFactoryInterface, which may or may not be null. +class CallFactoryInterface { + public: + virtual ~CallFactoryInterface() {} + + virtual Call* CreateCall(const CallConfig& config) = 0; +}; + +RTC_EXPORT std::unique_ptr<CallFactoryInterface> CreateCallFactory(); + +} // namespace webrtc + +#endif // API_CALL_CALL_FACTORY_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/call/transport.cc b/third_party/libwebrtc/api/call/transport.cc new file mode 100644 index 0000000000..bcadc762de --- /dev/null +++ b/third_party/libwebrtc/api/call/transport.cc @@ -0,0 +1,23 @@ +/* + * 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 "api/call/transport.h" + +#include <cstdint> + +namespace webrtc { + +PacketOptions::PacketOptions() = default; + +PacketOptions::PacketOptions(const PacketOptions&) = default; + +PacketOptions::~PacketOptions() = default; + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/call/transport.h b/third_party/libwebrtc/api/call/transport.h new file mode 100644 index 0000000000..8bff28825d --- /dev/null +++ b/third_party/libwebrtc/api/call/transport.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef API_CALL_TRANSPORT_H_ +#define API_CALL_TRANSPORT_H_ + +#include <stddef.h> +#include <stdint.h> + +#include "api/ref_counted_base.h" +#include "api/scoped_refptr.h" + +namespace webrtc { + +// TODO(holmer): Look into unifying this with the PacketOptions in +// asyncpacketsocket.h. +struct PacketOptions { + PacketOptions(); + PacketOptions(const PacketOptions&); + ~PacketOptions(); + + // A 16 bits positive id. Negative ids are invalid and should be interpreted + // as packet_id not being set. + int packet_id = -1; + // Additional data bound to the RTP packet for use in application code, + // outside of WebRTC. + rtc::scoped_refptr<rtc::RefCountedBase> additional_data; + // Whether this is a retransmission of an earlier packet. + bool is_retransmit = false; + bool included_in_feedback = false; + bool included_in_allocation = false; +}; + +class Transport { + public: + virtual bool SendRtp(const uint8_t* packet, + size_t length, + const PacketOptions& options) = 0; + virtual bool SendRtcp(const uint8_t* packet, size_t length) = 0; + + protected: + virtual ~Transport() {} +}; + +} // namespace webrtc + +#endif // API_CALL_TRANSPORT_H_ diff --git a/third_party/libwebrtc/api/call_api_gn/moz.build b/third_party/libwebrtc/api/call_api_gn/moz.build new file mode 100644 index 0000000000..e446d82280 --- /dev/null +++ b/third_party/libwebrtc/api/call_api_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("call_api_gn") diff --git a/third_party/libwebrtc/api/callfactory_api_gn/moz.build b/third_party/libwebrtc/api/callfactory_api_gn/moz.build new file mode 100644 index 0000000000..b0f2bbbf35 --- /dev/null +++ b/third_party/libwebrtc/api/callfactory_api_gn/moz.build @@ -0,0 +1,216 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("callfactory_api_gn") diff --git a/third_party/libwebrtc/api/candidate.cc b/third_party/libwebrtc/api/candidate.cc new file mode 100644 index 0000000000..a14dda350c --- /dev/null +++ b/third_party/libwebrtc/api/candidate.cc @@ -0,0 +1,167 @@ +/* + * Copyright 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. + */ + +#include "api/candidate.h" + +#include "rtc_base/helpers.h" +#include "rtc_base/ip_address.h" +#include "rtc_base/logging.h" +#include "rtc_base/strings/string_builder.h" + +namespace cricket { + +Candidate::Candidate() + : id_(rtc::CreateRandomString(8)), + component_(0), + priority_(0), + network_type_(rtc::ADAPTER_TYPE_UNKNOWN), + underlying_type_for_vpn_(rtc::ADAPTER_TYPE_UNKNOWN), + generation_(0), + network_id_(0), + network_cost_(0) {} + +Candidate::Candidate(int component, + absl::string_view protocol, + const rtc::SocketAddress& address, + uint32_t priority, + absl::string_view username, + absl::string_view password, + absl::string_view type, + uint32_t generation, + absl::string_view foundation, + uint16_t network_id, + uint16_t network_cost) + : id_(rtc::CreateRandomString(8)), + component_(component), + protocol_(protocol), + address_(address), + priority_(priority), + username_(username), + password_(password), + type_(type), + network_type_(rtc::ADAPTER_TYPE_UNKNOWN), + underlying_type_for_vpn_(rtc::ADAPTER_TYPE_UNKNOWN), + generation_(generation), + foundation_(foundation), + network_id_(network_id), + network_cost_(network_cost) {} + +Candidate::Candidate(const Candidate&) = default; + +Candidate::~Candidate() = default; + +bool Candidate::IsEquivalent(const Candidate& c) const { + // We ignore the network name, since that is just debug information, and + // the priority and the network cost, since they should be the same if the + // rest are. + return (component_ == c.component_) && (protocol_ == c.protocol_) && + (address_ == c.address_) && (username_ == c.username_) && + (password_ == c.password_) && (type_ == c.type_) && + (generation_ == c.generation_) && (foundation_ == c.foundation_) && + (related_address_ == c.related_address_) && + (network_id_ == c.network_id_); +} + +bool Candidate::MatchesForRemoval(const Candidate& c) const { + return component_ == c.component_ && protocol_ == c.protocol_ && + address_ == c.address_; +} + +std::string Candidate::ToStringInternal(bool sensitive) const { + rtc::StringBuilder ost; + std::string address = + sensitive ? address_.ToSensitiveString() : address_.ToString(); + ost << "Cand[" << transport_name_ << ":" << foundation_ << ":" << component_ + << ":" << protocol_ << ":" << priority_ << ":" << address << ":" << type_ + << ":" << related_address_.ToString() << ":" << username_ << ":" + << password_ << ":" << network_id_ << ":" << network_cost_ << ":" + << generation_ << "]"; + return ost.Release(); +} + +uint32_t Candidate::GetPriority(uint32_t type_preference, + int network_adapter_preference, + int relay_preference) const { + // RFC 5245 - 4.1.2.1. + // priority = (2^24)*(type preference) + + // (2^8)*(local preference) + + // (2^0)*(256 - component ID) + + // `local_preference` length is 2 bytes, 0-65535 inclusive. + // In our implemenation we will partion local_preference into + // 0 1 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | NIC Pref | Addr Pref | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // NIC Type - Type of the network adapter e.g. 3G/Wifi/Wired. + // Addr Pref - Address preference value as per RFC 3484. + // local preference = (NIC Type << 8 | Addr_Pref) + relay preference. + // The relay preference is based on the number of TURN servers, the + // first TURN server gets the highest preference. + + int addr_pref = IPAddressPrecedence(address_.ipaddr()); + int local_preference = + ((network_adapter_preference << 8) | addr_pref) + relay_preference; + + return (type_preference << 24) | (local_preference << 8) | (256 - component_); +} + +bool Candidate::operator==(const Candidate& o) const { + return id_ == o.id_ && component_ == o.component_ && + protocol_ == o.protocol_ && relay_protocol_ == o.relay_protocol_ && + address_ == o.address_ && priority_ == o.priority_ && + username_ == o.username_ && password_ == o.password_ && + type_ == o.type_ && network_name_ == o.network_name_ && + network_type_ == o.network_type_ && generation_ == o.generation_ && + foundation_ == o.foundation_ && + related_address_ == o.related_address_ && tcptype_ == o.tcptype_ && + transport_name_ == o.transport_name_ && network_id_ == o.network_id_; +} + +bool Candidate::operator!=(const Candidate& o) const { + return !(*this == o); +} + +Candidate Candidate::ToSanitizedCopy(bool use_hostname_address, + bool filter_related_address) const { + Candidate copy(*this); + if (use_hostname_address) { + rtc::IPAddress ip; + if (address().hostname().empty()) { + // IP needs to be redacted, but no hostname available. + rtc::SocketAddress redacted_addr("redacted-ip.invalid", address().port()); + copy.set_address(redacted_addr); + } else if (IPFromString(address().hostname(), &ip)) { + // The hostname is an IP literal, and needs to be redacted too. + rtc::SocketAddress redacted_addr("redacted-literal.invalid", + address().port()); + copy.set_address(redacted_addr); + } else { + rtc::SocketAddress hostname_only_addr(address().hostname(), + address().port()); + copy.set_address(hostname_only_addr); + } + } + if (filter_related_address) { + copy.set_related_address( + rtc::EmptySocketAddressWithFamily(copy.address().family())); + } + return copy; +} + +void Candidate::Assign(std::string& s, absl::string_view view) { + // Assigning via a temporary object, like s = std::string(view), results in + // binary size bloat. To avoid that, extract pointer and size from the + // string view, and use std::string::assign method. + s.assign(view.data(), view.size()); +} + +} // namespace cricket diff --git a/third_party/libwebrtc/api/candidate.h b/third_party/libwebrtc/api/candidate.h new file mode 100644 index 0000000000..281f2f01a5 --- /dev/null +++ b/third_party/libwebrtc/api/candidate.h @@ -0,0 +1,222 @@ +/* + * Copyright 2004 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 API_CANDIDATE_H_ +#define API_CANDIDATE_H_ + +#include <limits.h> +#include <stdint.h> + +#include <algorithm> +#include <string> + +#include "absl/strings/string_view.h" +#include "rtc_base/checks.h" +#include "rtc_base/network_constants.h" +#include "rtc_base/socket_address.h" +#include "rtc_base/system/rtc_export.h" + +namespace cricket { + +// TURN servers are limited to 32 in accordance with +// https://w3c.github.io/webrtc-pc/#dom-rtcconfiguration-iceservers +static constexpr size_t kMaxTurnServers = 32; + +// Candidate for ICE based connection discovery. +// TODO(phoglund): remove things in here that are not needed in the public API. + +class RTC_EXPORT Candidate { + public: + Candidate(); + // TODO(pthatcher): Match the ordering and param list as per RFC 5245 + // candidate-attribute syntax. http://tools.ietf.org/html/rfc5245#section-15.1 + Candidate(int component, + absl::string_view protocol, + const rtc::SocketAddress& address, + uint32_t priority, + absl::string_view username, + absl::string_view password, + absl::string_view type, + uint32_t generation, + absl::string_view foundation, + uint16_t network_id = 0, + uint16_t network_cost = 0); + Candidate(const Candidate&); + ~Candidate(); + + const std::string& id() const { return id_; } + void set_id(absl::string_view id) { Assign(id_, id); } + + int component() const { return component_; } + void set_component(int component) { component_ = component; } + + const std::string& protocol() const { return protocol_; } + void set_protocol(absl::string_view protocol) { Assign(protocol_, protocol); } + + // The protocol used to talk to relay. + const std::string& relay_protocol() const { return relay_protocol_; } + void set_relay_protocol(absl::string_view protocol) { + Assign(relay_protocol_, protocol); + } + + const rtc::SocketAddress& address() const { return address_; } + void set_address(const rtc::SocketAddress& address) { address_ = address; } + + uint32_t priority() const { return priority_; } + void set_priority(const uint32_t priority) { priority_ = priority; } + + // TODO(pthatcher): Remove once Chromium's jingle/glue/utils.cc + // doesn't use it. + // Maps old preference (which was 0.0-1.0) to match priority (which + // is 0-2^32-1) to to match RFC 5245, section 4.1.2.1. Also see + // https://docs.google.com/a/google.com/document/d/ + // 1iNQDiwDKMh0NQOrCqbj3DKKRT0Dn5_5UJYhmZO-t7Uc/edit + float preference() const { + // The preference value is clamped to two decimal precision. + return static_cast<float>(((priority_ >> 24) * 100 / 127) / 100.0); + } + + // TODO(pthatcher): Remove once Chromium's jingle/glue/utils.cc + // doesn't use it. + void set_preference(float preference) { + // Limiting priority to UINT_MAX when value exceeds uint32_t max. + // This can happen for e.g. when preference = 3. + uint64_t prio_val = static_cast<uint64_t>(preference * 127) << 24; + priority_ = static_cast<uint32_t>( + std::min(prio_val, static_cast<uint64_t>(UINT_MAX))); + } + + // TODO(honghaiz): Change to usernameFragment or ufrag. + const std::string& username() const { return username_; } + void set_username(absl::string_view username) { Assign(username_, username); } + + const std::string& password() const { return password_; } + void set_password(absl::string_view password) { Assign(password_, password); } + + const std::string& type() const { return type_; } + void set_type(absl::string_view type) { Assign(type_, type); } + + const std::string& network_name() const { return network_name_; } + void set_network_name(absl::string_view network_name) { + Assign(network_name_, network_name); + } + + rtc::AdapterType network_type() const { return network_type_; } + void set_network_type(rtc::AdapterType network_type) { + network_type_ = network_type; + } + + rtc::AdapterType underlying_type_for_vpn() const { + return underlying_type_for_vpn_; + } + void set_underlying_type_for_vpn(rtc::AdapterType network_type) { + underlying_type_for_vpn_ = network_type; + } + + // Candidates in a new generation replace those in the old generation. + uint32_t generation() const { return generation_; } + void set_generation(uint32_t generation) { generation_ = generation; } + + // `network_cost` measures the cost/penalty of using this candidate. A network + // cost of 0 indicates this candidate can be used freely. A value of + // rtc::kNetworkCostMax indicates it should be used only as the last resort. + void set_network_cost(uint16_t network_cost) { + RTC_DCHECK_LE(network_cost, rtc::kNetworkCostMax); + network_cost_ = network_cost; + } + uint16_t network_cost() const { return network_cost_; } + + // An ID assigned to the network hosting the candidate. + uint16_t network_id() const { return network_id_; } + void set_network_id(uint16_t network_id) { network_id_ = network_id; } + + const std::string& foundation() const { return foundation_; } + void set_foundation(absl::string_view foundation) { + Assign(foundation_, foundation); + } + + const rtc::SocketAddress& related_address() const { return related_address_; } + void set_related_address(const rtc::SocketAddress& related_address) { + related_address_ = related_address; + } + const std::string& tcptype() const { return tcptype_; } + void set_tcptype(absl::string_view tcptype) { Assign(tcptype_, tcptype); } + + // The name of the transport channel of this candidate. + // TODO(phoglund): remove. + const std::string& transport_name() const { return transport_name_; } + void set_transport_name(absl::string_view transport_name) { + Assign(transport_name_, transport_name); + } + + // The URL of the ICE server which this candidate is gathered from. + const std::string& url() const { return url_; } + void set_url(absl::string_view url) { Assign(url_, url); } + + // Determines whether this candidate is equivalent to the given one. + bool IsEquivalent(const Candidate& c) const; + + // Determines whether this candidate can be considered equivalent to the + // given one when looking for a matching candidate to remove. + bool MatchesForRemoval(const Candidate& c) const; + + std::string ToString() const { return ToStringInternal(false); } + + std::string ToSensitiveString() const { return ToStringInternal(true); } + + uint32_t GetPriority(uint32_t type_preference, + int network_adapter_preference, + int relay_preference) const; + + bool operator==(const Candidate& o) const; + bool operator!=(const Candidate& o) const; + + // Returns a sanitized copy configured by the given booleans. If + // `use_host_address` is true, the returned copy has its IP removed from + // `address()`, which leads `address()` to be a hostname address. If + // `filter_related_address`, the returned copy has its related address reset + // to the wildcard address (i.e. 0.0.0.0 for IPv4 and :: for IPv6). Note that + // setting both booleans to false returns an identical copy to the original + // candidate. + Candidate ToSanitizedCopy(bool use_hostname_address, + bool filter_related_address) const; + + private: + // TODO(bugs.webrtc.org/13220): With C++17, we get a std::string assignment + // operator accepting any object implicitly convertible to std::string_view, + // and then we don't need this workaround. + static void Assign(std::string& s, absl::string_view view); + std::string ToStringInternal(bool sensitive) const; + + std::string id_; + int component_; + std::string protocol_; + std::string relay_protocol_; + rtc::SocketAddress address_; + uint32_t priority_; + std::string username_; + std::string password_; + std::string type_; + std::string network_name_; + rtc::AdapterType network_type_; + rtc::AdapterType underlying_type_for_vpn_; + uint32_t generation_; + std::string foundation_; + rtc::SocketAddress related_address_; + std::string tcptype_; + std::string transport_name_; + uint16_t network_id_; + uint16_t network_cost_; + std::string url_; +}; + +} // namespace cricket + +#endif // API_CANDIDATE_H_ diff --git a/third_party/libwebrtc/api/create_peerconnection_factory.cc b/third_party/libwebrtc/api/create_peerconnection_factory.cc new file mode 100644 index 0000000000..f9cc7ad3e2 --- /dev/null +++ b/third_party/libwebrtc/api/create_peerconnection_factory.cc @@ -0,0 +1,83 @@ +/* + * Copyright 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 "api/create_peerconnection_factory.h" + +#include <memory> +#include <utility> + +#include "api/call/call_factory_interface.h" +#include "api/peer_connection_interface.h" +#include "api/rtc_event_log/rtc_event_log_factory.h" +#include "api/scoped_refptr.h" +#include "api/task_queue/default_task_queue_factory.h" +#include "api/transport/field_trial_based_config.h" +#include "media/base/media_engine.h" +#include "media/engine/webrtc_media_engine.h" +#include "modules/audio_device/include/audio_device.h" +#include "modules/audio_processing/include/audio_processing.h" +#include "rtc_base/thread.h" + +namespace webrtc { + +rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory( + rtc::Thread* network_thread, + rtc::Thread* worker_thread, + rtc::Thread* signaling_thread, + rtc::scoped_refptr<AudioDeviceModule> default_adm, + rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory, + rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory, + std::unique_ptr<VideoEncoderFactory> video_encoder_factory, + std::unique_ptr<VideoDecoderFactory> video_decoder_factory, + rtc::scoped_refptr<AudioMixer> audio_mixer, + rtc::scoped_refptr<AudioProcessing> audio_processing, + AudioFrameProcessor* audio_frame_processor, + std::unique_ptr<FieldTrialsView> field_trials) { + if (!field_trials) { + field_trials = std::make_unique<webrtc::FieldTrialBasedConfig>(); + } + + PeerConnectionFactoryDependencies dependencies; + dependencies.network_thread = network_thread; + dependencies.worker_thread = worker_thread; + dependencies.signaling_thread = signaling_thread; + dependencies.task_queue_factory = + CreateDefaultTaskQueueFactory(field_trials.get()); + dependencies.call_factory = CreateCallFactory(); + dependencies.event_log_factory = std::make_unique<RtcEventLogFactory>( + dependencies.task_queue_factory.get()); + dependencies.trials = std::move(field_trials); + + if (network_thread) { + // TODO(bugs.webrtc.org/13145): Add an rtc::SocketFactory* argument. + dependencies.socket_factory = network_thread->socketserver(); + } + cricket::MediaEngineDependencies media_dependencies; + media_dependencies.task_queue_factory = dependencies.task_queue_factory.get(); + media_dependencies.adm = std::move(default_adm); + media_dependencies.audio_encoder_factory = std::move(audio_encoder_factory); + media_dependencies.audio_decoder_factory = std::move(audio_decoder_factory); + media_dependencies.audio_frame_processor = audio_frame_processor; + if (audio_processing) { + media_dependencies.audio_processing = std::move(audio_processing); + } else { + media_dependencies.audio_processing = AudioProcessingBuilder().Create(); + } + media_dependencies.audio_mixer = std::move(audio_mixer); + media_dependencies.video_encoder_factory = std::move(video_encoder_factory); + media_dependencies.video_decoder_factory = std::move(video_decoder_factory); + media_dependencies.trials = dependencies.trials.get(); + dependencies.media_engine = + cricket::CreateMediaEngine(std::move(media_dependencies)); + + return CreateModularPeerConnectionFactory(std::move(dependencies)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/create_peerconnection_factory.h b/third_party/libwebrtc/api/create_peerconnection_factory.h new file mode 100644 index 0000000000..efebc5f3ea --- /dev/null +++ b/third_party/libwebrtc/api/create_peerconnection_factory.h @@ -0,0 +1,57 @@ +/* + * Copyright 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. + */ + +#ifndef API_CREATE_PEERCONNECTION_FACTORY_H_ +#define API_CREATE_PEERCONNECTION_FACTORY_H_ + +#include <memory> + +#include "api/audio/audio_mixer.h" +#include "api/audio_codecs/audio_decoder_factory.h" +#include "api/audio_codecs/audio_encoder_factory.h" +#include "api/peer_connection_interface.h" +#include "api/scoped_refptr.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder_factory.h" + +namespace rtc { +// TODO(bugs.webrtc.org/9987): Move rtc::Thread to api/ or expose a better +// type. At the moment, rtc::Thread is not part of api/ so it cannot be +// included in order to avoid to leak internal types. +class Thread; +} // namespace rtc + +namespace webrtc { + +class AudioDeviceModule; +class AudioFrameProcessor; +class AudioProcessing; + +// Create a new instance of PeerConnectionFactoryInterface with optional video +// codec factories. These video factories represents all video codecs, i.e. no +// extra internal video codecs will be added. +RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface> +CreatePeerConnectionFactory( + rtc::Thread* network_thread, + rtc::Thread* worker_thread, + rtc::Thread* signaling_thread, + rtc::scoped_refptr<AudioDeviceModule> default_adm, + rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory, + rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory, + std::unique_ptr<VideoEncoderFactory> video_encoder_factory, + std::unique_ptr<VideoDecoderFactory> video_decoder_factory, + rtc::scoped_refptr<AudioMixer> audio_mixer, + rtc::scoped_refptr<AudioProcessing> audio_processing, + AudioFrameProcessor* audio_frame_processor = nullptr, + std::unique_ptr<FieldTrialsView> field_trials = nullptr); + +} // namespace webrtc + +#endif // API_CREATE_PEERCONNECTION_FACTORY_H_ diff --git a/third_party/libwebrtc/api/crypto/BUILD.gn b/third_party/libwebrtc/api/crypto/BUILD.gn new file mode 100644 index 0000000000..8d041ea059 --- /dev/null +++ b/third_party/libwebrtc/api/crypto/BUILD.gn @@ -0,0 +1,49 @@ +# Copyright (c) 2019 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") + +group("crypto") { + deps = [ + ":frame_decryptor_interface", + ":frame_encryptor_interface", + ":options", + ] +} + +rtc_library("options") { + visibility = [ "*" ] + sources = [ + "crypto_options.cc", + "crypto_options.h", + ] + deps = [ + "../../rtc_base:ssl", + "../../rtc_base/system:rtc_export", + ] +} + +rtc_source_set("frame_decryptor_interface") { + visibility = [ "*" ] + sources = [ "frame_decryptor_interface.h" ] + deps = [ + "..:array_view", + "..:rtp_parameters", + "../../rtc_base:refcount", + ] +} + +rtc_source_set("frame_encryptor_interface") { + visibility = [ "*" ] + sources = [ "frame_encryptor_interface.h" ] + deps = [ + "..:array_view", + "..:rtp_parameters", + "../../rtc_base:refcount", + ] +} diff --git a/third_party/libwebrtc/api/crypto/crypto_options.cc b/third_party/libwebrtc/api/crypto/crypto_options.cc new file mode 100644 index 0000000000..22c5dd464b --- /dev/null +++ b/third_party/libwebrtc/api/crypto/crypto_options.cc @@ -0,0 +1,89 @@ +/* + * Copyright 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 "api/crypto/crypto_options.h" + +#include "rtc_base/ssl_stream_adapter.h" + +namespace webrtc { + +CryptoOptions::CryptoOptions() {} + +CryptoOptions::CryptoOptions(const CryptoOptions& other) { + srtp = other.srtp; + sframe = other.sframe; +} + +CryptoOptions::~CryptoOptions() {} + +// static +CryptoOptions CryptoOptions::NoGcm() { + CryptoOptions options; + options.srtp.enable_gcm_crypto_suites = false; + return options; +} + +std::vector<int> CryptoOptions::GetSupportedDtlsSrtpCryptoSuites() const { + std::vector<int> crypto_suites; + // Note: kSrtpAes128CmSha1_80 is what is required to be supported (by + // draft-ietf-rtcweb-security-arch), but kSrtpAes128CmSha1_32 is allowed as + // well, and saves a few bytes per packet if it ends up selected. + // As the cipher suite is potentially insecure, it will only be used if + // enabled by both peers. + if (srtp.enable_aes128_sha1_32_crypto_cipher) { + crypto_suites.push_back(rtc::kSrtpAes128CmSha1_32); + } + if (srtp.enable_aes128_sha1_80_crypto_cipher) { + crypto_suites.push_back(rtc::kSrtpAes128CmSha1_80); + } + + // Note: GCM cipher suites are not the top choice since they increase the + // packet size. In order to negotiate them the other side must not support + // kSrtpAes128CmSha1_80. + if (srtp.enable_gcm_crypto_suites) { + crypto_suites.push_back(rtc::kSrtpAeadAes256Gcm); + crypto_suites.push_back(rtc::kSrtpAeadAes128Gcm); + } + RTC_CHECK(!crypto_suites.empty()); + return crypto_suites; +} + +bool CryptoOptions::operator==(const CryptoOptions& other) const { + struct data_being_tested_for_equality { + struct Srtp { + bool enable_gcm_crypto_suites; + bool enable_aes128_sha1_32_crypto_cipher; + bool enable_aes128_sha1_80_crypto_cipher; + bool enable_encrypted_rtp_header_extensions; + } srtp; + struct SFrame { + bool require_frame_encryption; + } sframe; + }; + static_assert(sizeof(data_being_tested_for_equality) == sizeof(*this), + "Did you add something to CryptoOptions and forget to " + "update operator==?"); + + return srtp.enable_gcm_crypto_suites == other.srtp.enable_gcm_crypto_suites && + srtp.enable_aes128_sha1_32_crypto_cipher == + other.srtp.enable_aes128_sha1_32_crypto_cipher && + srtp.enable_aes128_sha1_80_crypto_cipher == + other.srtp.enable_aes128_sha1_80_crypto_cipher && + srtp.enable_encrypted_rtp_header_extensions == + other.srtp.enable_encrypted_rtp_header_extensions && + sframe.require_frame_encryption == + other.sframe.require_frame_encryption; +} + +bool CryptoOptions::operator!=(const CryptoOptions& other) const { + return !(*this == other); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/crypto/crypto_options.h b/third_party/libwebrtc/api/crypto/crypto_options.h new file mode 100644 index 0000000000..317995134a --- /dev/null +++ b/third_party/libwebrtc/api/crypto/crypto_options.h @@ -0,0 +1,72 @@ +/* + * Copyright 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. + */ + +#ifndef API_CRYPTO_CRYPTO_OPTIONS_H_ +#define API_CRYPTO_CRYPTO_OPTIONS_H_ + +#include <vector> + +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// CryptoOptions defines advanced cryptographic settings for native WebRTC. +// These settings must be passed into PeerConnectionFactoryInterface::Options +// and are only applicable to native use cases of WebRTC. +struct RTC_EXPORT CryptoOptions { + CryptoOptions(); + CryptoOptions(const CryptoOptions& other); + ~CryptoOptions(); + + // Helper method to return an instance of the CryptoOptions with GCM crypto + // suites disabled. This method should be used instead of depending on current + // default values set by the constructor. + static CryptoOptions NoGcm(); + + // Returns a list of the supported DTLS-SRTP Crypto suites based on this set + // of crypto options. + std::vector<int> GetSupportedDtlsSrtpCryptoSuites() const; + + bool operator==(const CryptoOptions& other) const; + bool operator!=(const CryptoOptions& other) const; + + // SRTP Related Peer Connection options. + struct Srtp { + // Enable GCM crypto suites from RFC 7714 for SRTP. GCM will only be used + // if both sides enable it. + bool enable_gcm_crypto_suites = false; + + // If set to true, the (potentially insecure) crypto cipher + // kSrtpAes128CmSha1_32 will be included in the list of supported ciphers + // during negotiation. It will only be used if both peers support it and no + // other ciphers get preferred. + bool enable_aes128_sha1_32_crypto_cipher = false; + + // The most commonly used cipher. Can be disabled, mostly for testing + // purposes. + bool enable_aes128_sha1_80_crypto_cipher = true; + + // If set to true, encrypted RTP header extensions as defined in RFC 6904 + // will be negotiated. They will only be used if both peers support them. + bool enable_encrypted_rtp_header_extensions = false; + } srtp; + + // Options to be used when the FrameEncryptor / FrameDecryptor APIs are used. + struct SFrame { + // If set all RtpSenders must have an FrameEncryptor attached to them before + // they are allowed to send packets. All RtpReceivers must have a + // FrameDecryptor attached to them before they are able to receive packets. + bool require_frame_encryption = false; + } sframe; +}; + +} // namespace webrtc + +#endif // API_CRYPTO_CRYPTO_OPTIONS_H_ diff --git a/third_party/libwebrtc/api/crypto/frame_decryptor_interface.h b/third_party/libwebrtc/api/crypto/frame_decryptor_interface.h new file mode 100644 index 0000000000..2f6bdac4b4 --- /dev/null +++ b/third_party/libwebrtc/api/crypto/frame_decryptor_interface.h @@ -0,0 +1,76 @@ +/* + * Copyright 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. + */ + +#ifndef API_CRYPTO_FRAME_DECRYPTOR_INTERFACE_H_ +#define API_CRYPTO_FRAME_DECRYPTOR_INTERFACE_H_ + +#include <vector> + +#include "api/array_view.h" +#include "api/media_types.h" +#include "rtc_base/ref_count.h" + +namespace webrtc { + +// FrameDecryptorInterface allows users to provide a custom decryption +// implementation for all incoming audio and video frames. The user must also +// provide a FrameEncryptorInterface to be able to encrypt the frames being +// sent out of the device. Note this is an additional layer of encyrption in +// addition to the standard SRTP mechanism and is not intended to be used +// without it. You may assume that this interface will have the same lifetime +// as the RTPReceiver it is attached to. It must only be attached to one +// RTPReceiver. Additional data may be null. +class FrameDecryptorInterface : public rtc::RefCountInterface { + public: + // The Status enum represents all possible states that can be + // returned when attempting to decrypt a frame. kRecoverable indicates that + // there was an error with the given frame and so it should not be passed to + // the decoder, however it hints that the receive stream is still decryptable + // which is important for determining when to send key frame requests + // kUnknown should never be returned by the implementor. + enum class Status { kOk, kRecoverable, kFailedToDecrypt, kUnknown }; + + struct Result { + Result(Status status, size_t bytes_written) + : status(status), bytes_written(bytes_written) {} + + bool IsOk() const { return status == Status::kOk; } + + const Status status; + const size_t bytes_written; + }; + + ~FrameDecryptorInterface() override {} + + // Attempts to decrypt the encrypted frame. You may assume the frame size will + // be allocated to the size returned from GetMaxPlaintextSize. You may assume + // that the frames are in order if SRTP is enabled. The stream is not provided + // here and it is up to the implementor to transport this information to the + // receiver if they care about it. You must set bytes_written to how many + // bytes you wrote to in the frame buffer. kOk must be returned if successful, + // kRecoverable should be returned if the failure was due to something other + // than a decryption failure. kFailedToDecrypt should be returned in all other + // cases. + virtual Result Decrypt(cricket::MediaType media_type, + const std::vector<uint32_t>& csrcs, + rtc::ArrayView<const uint8_t> additional_data, + rtc::ArrayView<const uint8_t> encrypted_frame, + rtc::ArrayView<uint8_t> frame) = 0; + + // Returns the total required length in bytes for the output of the + // decryption. This can be larger than the actual number of bytes you need but + // must never be smaller as it informs the size of the frame buffer. + virtual size_t GetMaxPlaintextByteSize(cricket::MediaType media_type, + size_t encrypted_frame_size) = 0; +}; + +} // namespace webrtc + +#endif // API_CRYPTO_FRAME_DECRYPTOR_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/crypto/frame_decryptor_interface_gn/moz.build b/third_party/libwebrtc/api/crypto/frame_decryptor_interface_gn/moz.build new file mode 100644 index 0000000000..1ce4cdd00a --- /dev/null +++ b/third_party/libwebrtc/api/crypto/frame_decryptor_interface_gn/moz.build @@ -0,0 +1,205 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("frame_decryptor_interface_gn") diff --git a/third_party/libwebrtc/api/crypto/frame_encryptor_interface.h b/third_party/libwebrtc/api/crypto/frame_encryptor_interface.h new file mode 100644 index 0000000000..1452b80189 --- /dev/null +++ b/third_party/libwebrtc/api/crypto/frame_encryptor_interface.h @@ -0,0 +1,54 @@ +/* + * Copyright 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. + */ + +#ifndef API_CRYPTO_FRAME_ENCRYPTOR_INTERFACE_H_ +#define API_CRYPTO_FRAME_ENCRYPTOR_INTERFACE_H_ + +#include "api/array_view.h" +#include "api/media_types.h" +#include "rtc_base/ref_count.h" + +namespace webrtc { + +// FrameEncryptorInterface allows users to provide a custom encryption +// implementation to encrypt all outgoing audio and video frames. The user must +// also provide a FrameDecryptorInterface to be able to decrypt the frames on +// the receiving device. Note this is an additional layer of encryption in +// addition to the standard SRTP mechanism and is not intended to be used +// without it. Implementations of this interface will have the same lifetime as +// the RTPSenders it is attached to. Additional data may be null. +class FrameEncryptorInterface : public rtc::RefCountInterface { + public: + ~FrameEncryptorInterface() override {} + + // Attempts to encrypt the provided frame. You may assume the encrypted_frame + // will match the size returned by GetMaxCiphertextByteSize for a give frame. + // You may assume that the frames will arrive in order if SRTP is enabled. + // The ssrc will simply identify which stream the frame is travelling on. You + // must set bytes_written to the number of bytes you wrote in the + // encrypted_frame. 0 must be returned if successful all other numbers can be + // selected by the implementer to represent error codes. + virtual int Encrypt(cricket::MediaType media_type, + uint32_t ssrc, + rtc::ArrayView<const uint8_t> additional_data, + rtc::ArrayView<const uint8_t> frame, + rtc::ArrayView<uint8_t> encrypted_frame, + size_t* bytes_written) = 0; + + // Returns the total required length in bytes for the output of the + // encryption. This can be larger than the actual number of bytes you need but + // must never be smaller as it informs the size of the encrypted_frame buffer. + virtual size_t GetMaxCiphertextByteSize(cricket::MediaType media_type, + size_t frame_size) = 0; +}; + +} // namespace webrtc + +#endif // API_CRYPTO_FRAME_ENCRYPTOR_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/crypto/frame_encryptor_interface_gn/moz.build b/third_party/libwebrtc/api/crypto/frame_encryptor_interface_gn/moz.build new file mode 100644 index 0000000000..b8385d1daa --- /dev/null +++ b/third_party/libwebrtc/api/crypto/frame_encryptor_interface_gn/moz.build @@ -0,0 +1,205 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("frame_encryptor_interface_gn") diff --git a/third_party/libwebrtc/api/crypto/options_gn/moz.build b/third_party/libwebrtc/api/crypto/options_gn/moz.build new file mode 100644 index 0000000000..aee1983c3e --- /dev/null +++ b/third_party/libwebrtc/api/crypto/options_gn/moz.build @@ -0,0 +1,217 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/crypto/crypto_options.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("options_gn") diff --git a/third_party/libwebrtc/api/crypto_params.h b/third_party/libwebrtc/api/crypto_params.h new file mode 100644 index 0000000000..95bd892f9c --- /dev/null +++ b/third_party/libwebrtc/api/crypto_params.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2004 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 API_CRYPTO_PARAMS_H_ +#define API_CRYPTO_PARAMS_H_ + +#include <string> + +#include "absl/strings/string_view.h" + +namespace cricket { + +// Parameters for SRTP negotiation, as described in RFC 4568. +// TODO(benwright) - Rename to SrtpCryptoParams as these only apply to SRTP and +// not generic crypto parameters for WebRTC. +struct CryptoParams { + CryptoParams() : tag(0) {} + CryptoParams(int t, + absl::string_view cs, + absl::string_view kp, + absl::string_view sp) + : tag(t), cipher_suite(cs), key_params(kp), session_params(sp) {} + + bool Matches(const CryptoParams& params) const { + return (tag == params.tag && cipher_suite == params.cipher_suite); + } + + int tag; + std::string cipher_suite; + std::string key_params; + std::string session_params; +}; + +} // namespace cricket + +#endif // API_CRYPTO_PARAMS_H_ diff --git a/third_party/libwebrtc/api/data_channel_interface.cc b/third_party/libwebrtc/api/data_channel_interface.cc new file mode 100644 index 0000000000..bddb9d1b0a --- /dev/null +++ b/third_party/libwebrtc/api/data_channel_interface.cc @@ -0,0 +1,47 @@ +/* + * Copyright 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 "api/data_channel_interface.h" + +namespace webrtc { + +bool DataChannelInterface::ordered() const { + return false; +} + +uint16_t DataChannelInterface::maxRetransmitTime() const { + return 0; +} + +uint16_t DataChannelInterface::maxRetransmits() const { + return 0; +} + +absl::optional<int> DataChannelInterface::maxRetransmitsOpt() const { + return absl::nullopt; +} + +absl::optional<int> DataChannelInterface::maxPacketLifeTime() const { + return absl::nullopt; +} + +std::string DataChannelInterface::protocol() const { + return std::string(); +} + +bool DataChannelInterface::negotiated() const { + return false; +} + +uint64_t DataChannelInterface::MaxSendQueueSize() { + return 16 * 1024 * 1024; // 16 MiB +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/data_channel_interface.h b/third_party/libwebrtc/api/data_channel_interface.h new file mode 100644 index 0000000000..4f74918ff9 --- /dev/null +++ b/third_party/libwebrtc/api/data_channel_interface.h @@ -0,0 +1,202 @@ +/* + * Copyright 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. + */ + +// This file contains interfaces for DataChannels +// http://dev.w3.org/2011/webrtc/editor/webrtc.html#rtcdatachannel + +#ifndef API_DATA_CHANNEL_INTERFACE_H_ +#define API_DATA_CHANNEL_INTERFACE_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <string> + +#include "absl/types/optional.h" +#include "api/priority.h" +#include "api/rtc_error.h" +#include "rtc_base/checks.h" +#include "rtc_base/copy_on_write_buffer.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// C++ version of: https://www.w3.org/TR/webrtc/#idl-def-rtcdatachannelinit +// TODO(deadbeef): Use absl::optional for the "-1 if unset" things. +struct DataChannelInit { + // Deprecated. Reliability is assumed, and channel will be unreliable if + // maxRetransmitTime or MaxRetransmits is set. + bool reliable = false; + + // True if ordered delivery is required. + bool ordered = true; + + // The max period of time in milliseconds in which retransmissions will be + // sent. After this time, no more retransmissions will be sent. + // + // Cannot be set along with `maxRetransmits`. + // This is called `maxPacketLifeTime` in the WebRTC JS API. + // Negative values are ignored, and positive values are clamped to [0-65535] + absl::optional<int> maxRetransmitTime; + + // The max number of retransmissions. + // + // Cannot be set along with `maxRetransmitTime`. + // Negative values are ignored, and positive values are clamped to [0-65535] + absl::optional<int> maxRetransmits; + + // This is set by the application and opaque to the WebRTC implementation. + std::string protocol; + + // True if the channel has been externally negotiated and we do not send an + // in-band signalling in the form of an "open" message. If this is true, `id` + // below must be set; otherwise it should be unset and will be negotiated + // in-band. + bool negotiated = false; + + // The stream id, or SID, for SCTP data channels. -1 if unset (see above). + int id = -1; + + // https://w3c.github.io/webrtc-priority/#new-rtcdatachannelinit-member + absl::optional<Priority> priority; +}; + +// At the JavaScript level, data can be passed in as a string or a blob, so +// this structure's `binary` flag tells whether the data should be interpreted +// as binary or text. +struct DataBuffer { + DataBuffer(const rtc::CopyOnWriteBuffer& data, bool binary) + : data(data), binary(binary) {} + // For convenience for unit tests. + explicit DataBuffer(const std::string& text) + : data(text.data(), text.length()), binary(false) {} + size_t size() const { return data.size(); } + + rtc::CopyOnWriteBuffer data; + // Indicates if the received data contains UTF-8 or binary data. + // Note that the upper layers are left to verify the UTF-8 encoding. + // TODO(jiayl): prefer to use an enum instead of a bool. + bool binary; +}; + +// Used to implement RTCDataChannel events. +// +// The code responding to these callbacks should unwind the stack before +// using any other webrtc APIs; re-entrancy is not supported. +class DataChannelObserver { + public: + // The data channel state have changed. + virtual void OnStateChange() = 0; + // A data buffer was successfully received. + virtual void OnMessage(const DataBuffer& buffer) = 0; + // The data channel's buffered_amount has changed. + virtual void OnBufferedAmountChange(uint64_t sent_data_size) {} + + protected: + virtual ~DataChannelObserver() = default; +}; + +class RTC_EXPORT DataChannelInterface : public rtc::RefCountInterface { + public: + // C++ version of: https://www.w3.org/TR/webrtc/#idl-def-rtcdatachannelstate + // Unlikely to change, but keep in sync with DataChannel.java:State and + // RTCDataChannel.h:RTCDataChannelState. + enum DataState { + kConnecting, + kOpen, // The DataChannel is ready to send data. + kClosing, + kClosed + }; + + static const char* DataStateString(DataState state) { + switch (state) { + case kConnecting: + return "connecting"; + case kOpen: + return "open"; + case kClosing: + return "closing"; + case kClosed: + return "closed"; + } + RTC_CHECK(false) << "Unknown DataChannel state: " << state; + return ""; + } + + // Used to receive events from the data channel. Only one observer can be + // registered at a time. UnregisterObserver should be called before the + // observer object is destroyed. + virtual void RegisterObserver(DataChannelObserver* observer) = 0; + virtual void UnregisterObserver() = 0; + + // The label attribute represents a label that can be used to distinguish this + // DataChannel object from other DataChannel objects. + virtual std::string label() const = 0; + + // The accessors below simply return the properties from the DataChannelInit + // the data channel was constructed with. + virtual bool reliable() const = 0; + // TODO(deadbeef): Remove these dummy implementations when all classes have + // implemented these APIs. They should all just return the values the + // DataChannel was created with. + virtual bool ordered() const; + // TODO(hta): Deprecate and remove the following two functions. + virtual uint16_t maxRetransmitTime() const; + virtual uint16_t maxRetransmits() const; + virtual absl::optional<int> maxRetransmitsOpt() const; + virtual absl::optional<int> maxPacketLifeTime() const; + virtual std::string protocol() const; + virtual bool negotiated() const; + + // Returns the ID from the DataChannelInit, if it was negotiated out-of-band. + // If negotiated in-band, this ID will be populated once the DTLS role is + // determined, and until then this will return -1. + virtual int id() const = 0; + virtual Priority priority() const { return Priority::kLow; } + virtual DataState state() const = 0; + // When state is kClosed, and the DataChannel was not closed using + // the closing procedure, returns the error information about the closing. + // The default implementation returns "no error". + virtual RTCError error() const { return RTCError(); } + virtual uint32_t messages_sent() const = 0; + virtual uint64_t bytes_sent() const = 0; + virtual uint32_t messages_received() const = 0; + virtual uint64_t bytes_received() const = 0; + + // Returns the number of bytes of application data (UTF-8 text and binary + // data) that have been queued using Send but have not yet been processed at + // the SCTP level. See comment above Send below. + // Values are less or equal to MaxSendQueueSize(). + virtual uint64_t buffered_amount() const = 0; + + // Begins the graceful data channel closing procedure. See: + // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.7 + virtual void Close() = 0; + + // Sends `data` to the remote peer. If the data can't be sent at the SCTP + // level (due to congestion control), it's buffered at the data channel level, + // up to a maximum of MaxSendQueueSize(). + // Returns false if the data channel is not in open state or if the send + // buffer is full. + // TODO(webrtc:13289): Return an RTCError with information about the failure. + virtual bool Send(const DataBuffer& buffer) = 0; + + // Amount of bytes that can be queued for sending on the data channel. + // Those are bytes that have not yet been processed at the SCTP level. + static uint64_t MaxSendQueueSize(); + + protected: + ~DataChannelInterface() override = default; +}; + +} // namespace webrtc + +#endif // API_DATA_CHANNEL_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/dtls_transport_interface.cc b/third_party/libwebrtc/api/dtls_transport_interface.cc new file mode 100644 index 0000000000..faebc0972f --- /dev/null +++ b/third_party/libwebrtc/api/dtls_transport_interface.cc @@ -0,0 +1,73 @@ +/* + * Copyright 2019 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 "api/dtls_transport_interface.h" + +namespace webrtc { + +DtlsTransportInformation::DtlsTransportInformation() + : state_(DtlsTransportState::kNew) {} + +DtlsTransportInformation::DtlsTransportInformation(DtlsTransportState state) + : state_(state) {} + +DtlsTransportInformation::DtlsTransportInformation( + DtlsTransportState state, + absl::optional<DtlsTransportTlsRole> role, + absl::optional<int> tls_version, + absl::optional<int> ssl_cipher_suite, + absl::optional<int> srtp_cipher_suite, + std::unique_ptr<rtc::SSLCertChain> remote_ssl_certificates) + : state_(state), + role_(role), + tls_version_(tls_version), + ssl_cipher_suite_(ssl_cipher_suite), + srtp_cipher_suite_(srtp_cipher_suite), + remote_ssl_certificates_(std::move(remote_ssl_certificates)) {} + +// Deprecated version +DtlsTransportInformation::DtlsTransportInformation( + DtlsTransportState state, + absl::optional<int> tls_version, + absl::optional<int> ssl_cipher_suite, + absl::optional<int> srtp_cipher_suite, + std::unique_ptr<rtc::SSLCertChain> remote_ssl_certificates) + : state_(state), + role_(absl::nullopt), + tls_version_(tls_version), + ssl_cipher_suite_(ssl_cipher_suite), + srtp_cipher_suite_(srtp_cipher_suite), + remote_ssl_certificates_(std::move(remote_ssl_certificates)) {} + +DtlsTransportInformation::DtlsTransportInformation( + const DtlsTransportInformation& c) + : state_(c.state()), + role_(c.role_), + tls_version_(c.tls_version_), + ssl_cipher_suite_(c.ssl_cipher_suite_), + srtp_cipher_suite_(c.srtp_cipher_suite_), + remote_ssl_certificates_(c.remote_ssl_certificates() + ? c.remote_ssl_certificates()->Clone() + : nullptr) {} + +DtlsTransportInformation& DtlsTransportInformation::operator=( + const DtlsTransportInformation& c) { + state_ = c.state(); + role_ = c.role_; + tls_version_ = c.tls_version_; + ssl_cipher_suite_ = c.ssl_cipher_suite_; + srtp_cipher_suite_ = c.srtp_cipher_suite_; + remote_ssl_certificates_ = c.remote_ssl_certificates() + ? c.remote_ssl_certificates()->Clone() + : nullptr; + return *this; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/dtls_transport_interface.h b/third_party/libwebrtc/api/dtls_transport_interface.h new file mode 100644 index 0000000000..7b0151249c --- /dev/null +++ b/third_party/libwebrtc/api/dtls_transport_interface.h @@ -0,0 +1,124 @@ +/* + * Copyright 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. + */ + +#ifndef API_DTLS_TRANSPORT_INTERFACE_H_ +#define API_DTLS_TRANSPORT_INTERFACE_H_ + +#include <memory> +#include <utility> + +#include "absl/types/optional.h" +#include "api/ice_transport_interface.h" +#include "api/rtc_error.h" +#include "api/scoped_refptr.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/ssl_certificate.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// States of a DTLS transport, corresponding to the JS API specification. +// http://w3c.github.io/webrtc-pc/#dom-rtcdtlstransportstate +enum class DtlsTransportState { + kNew, // Has not started negotiating yet. + kConnecting, // In the process of negotiating a secure connection. + kConnected, // Completed negotiation and verified fingerprints. + kClosed, // Intentionally closed. + kFailed, // Failure due to an error or failing to verify a remote + // fingerprint. + kNumValues +}; + +enum class DtlsTransportTlsRole { + kServer, // Other end sends CLIENT_HELLO + kClient // This end sends CLIENT_HELLO +}; + +// This object gives snapshot information about the changeable state of a +// DTLSTransport. +class RTC_EXPORT DtlsTransportInformation { + public: + DtlsTransportInformation(); + explicit DtlsTransportInformation(DtlsTransportState state); + DtlsTransportInformation( + DtlsTransportState state, + absl::optional<DtlsTransportTlsRole> role, + absl::optional<int> tls_version, + absl::optional<int> ssl_cipher_suite, + absl::optional<int> srtp_cipher_suite, + std::unique_ptr<rtc::SSLCertChain> remote_ssl_certificates); + ABSL_DEPRECATED("Use version with role parameter") + DtlsTransportInformation( + DtlsTransportState state, + absl::optional<int> tls_version, + absl::optional<int> ssl_cipher_suite, + absl::optional<int> srtp_cipher_suite, + std::unique_ptr<rtc::SSLCertChain> remote_ssl_certificates); + + // Copy and assign + DtlsTransportInformation(const DtlsTransportInformation& c); + DtlsTransportInformation& operator=(const DtlsTransportInformation& c); + // Move + DtlsTransportInformation(DtlsTransportInformation&& other) = default; + DtlsTransportInformation& operator=(DtlsTransportInformation&& other) = + default; + + DtlsTransportState state() const { return state_; } + absl::optional<DtlsTransportTlsRole> role() const { return role_; } + absl::optional<int> tls_version() const { return tls_version_; } + absl::optional<int> ssl_cipher_suite() const { return ssl_cipher_suite_; } + absl::optional<int> srtp_cipher_suite() const { return srtp_cipher_suite_; } + // The accessor returns a temporary pointer, it does not release ownership. + const rtc::SSLCertChain* remote_ssl_certificates() const { + return remote_ssl_certificates_.get(); + } + + private: + DtlsTransportState state_; + absl::optional<DtlsTransportTlsRole> role_; + absl::optional<int> tls_version_; + absl::optional<int> ssl_cipher_suite_; + absl::optional<int> srtp_cipher_suite_; + std::unique_ptr<rtc::SSLCertChain> remote_ssl_certificates_; +}; + +class DtlsTransportObserverInterface { + public: + // This callback carries information about the state of the transport. + // The argument is a pass-by-value snapshot of the state. + virtual void OnStateChange(DtlsTransportInformation info) = 0; + // This callback is called when an error occurs, causing the transport + // to go to the kFailed state. + virtual void OnError(RTCError error) = 0; + + protected: + virtual ~DtlsTransportObserverInterface() = default; +}; + +// A DTLS transport, as represented to the outside world. +// This object is created on the network thread, and can only be +// accessed on that thread, except for functions explicitly marked otherwise. +// References can be held by other threads, and destruction can therefore +// be initiated by other threads. +class DtlsTransportInterface : public rtc::RefCountInterface { + public: + // Returns a pointer to the ICE transport that is owned by the DTLS transport. + virtual rtc::scoped_refptr<IceTransportInterface> ice_transport() = 0; + // Returns information on the state of the DtlsTransport. + // This function can be called from other threads. + virtual DtlsTransportInformation Information() = 0; + // Observer management. + virtual void RegisterObserver(DtlsTransportObserverInterface* observer) = 0; + virtual void UnregisterObserver() = 0; +}; + +} // namespace webrtc + +#endif // API_DTLS_TRANSPORT_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/dtmf_sender_interface.h b/third_party/libwebrtc/api/dtmf_sender_interface.h new file mode 100644 index 0000000000..d63e66bbf7 --- /dev/null +++ b/third_party/libwebrtc/api/dtmf_sender_interface.h @@ -0,0 +1,125 @@ +/* + * Copyright 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. + */ + +#ifndef API_DTMF_SENDER_INTERFACE_H_ +#define API_DTMF_SENDER_INTERFACE_H_ + +#include <string> + +#include "api/media_stream_interface.h" +#include "rtc_base/ref_count.h" + +namespace webrtc { + +// DtmfSender callback interface, used to implement RTCDtmfSender events. +// Applications should implement this interface to get notifications from the +// DtmfSender. +class DtmfSenderObserverInterface { + public: + // Triggered when DTMF `tone` is sent. + // If `tone` is empty that means the DtmfSender has sent out all the given + // tones. + // The callback includes the state of the tone buffer at the time when + // the tone finished playing. + virtual void OnToneChange(const std::string& tone, + const std::string& tone_buffer) {} + // DEPRECATED: Older API without tone buffer. + // TODO(bugs.webrtc.org/9725): Remove old API and default implementation + // when old callers are gone. + virtual void OnToneChange(const std::string& tone) {} + + protected: + virtual ~DtmfSenderObserverInterface() = default; +}; + +// The interface of native implementation of the RTCDTMFSender defined by the +// WebRTC W3C Editor's Draft. +// See: https://www.w3.org/TR/webrtc/#peer-to-peer-dtmf +class DtmfSenderInterface : public rtc::RefCountInterface { + public: + // Provides the spec compliant default 2 second delay for the ',' character. + static const int kDtmfDefaultCommaDelayMs = 2000; + + // Used to receive events from the DTMF sender. Only one observer can be + // registered at a time. UnregisterObserver should be called before the + // observer object is destroyed. + virtual void RegisterObserver(DtmfSenderObserverInterface* observer) = 0; + virtual void UnregisterObserver() = 0; + + // Returns true if this DtmfSender is capable of sending DTMF. Otherwise + // returns false. To be able to send DTMF, the associated RtpSender must be + // able to send packets, and a "telephone-event" codec must be negotiated. + virtual bool CanInsertDtmf() = 0; + + // Queues a task that sends the DTMF `tones`. The `tones` parameter is treated + // as a series of characters. The characters 0 through 9, A through D, #, and + // * generate the associated DTMF tones. The characters a to d are equivalent + // to A to D. The character ',' indicates a delay of 2 seconds before + // processing the next character in the tones parameter. + // + // Unrecognized characters are ignored. + // + // The `duration` parameter indicates the duration in ms to use for each + // character passed in the `tones` parameter. The duration cannot be more + // than 6000 or less than 70. + // + // The `inter_tone_gap` parameter indicates the gap between tones in ms. The + // `inter_tone_gap` must be at least 50 ms but should be as short as + // possible. + // + // The `comma_delay` parameter indicates the delay after the ',' + // character. InsertDtmf specifies `comma_delay` as an argument + // with a default value of 2 seconds as per the WebRTC spec. This parameter + // allows users to comply with legacy WebRTC clients. The `comma_delay` + // must be at least 50 ms. + // + // If InsertDtmf is called on the same object while an existing task for this + // object to generate DTMF is still running, the previous task is canceled. + // Returns true on success and false on failure. + virtual bool InsertDtmf(const std::string& tones, + int duration, + int inter_tone_gap) { + return InsertDtmf(tones, duration, inter_tone_gap, + kDtmfDefaultCommaDelayMs); + } + virtual bool InsertDtmf(const std::string& tones, + int duration, + int inter_tone_gap, + int comma_delay) { + // TODO(bugs.webrtc.org/165700): Remove once downstream implementations + // override this signature rather than the 3-parameter one. + return InsertDtmf(tones, duration, inter_tone_gap); + } + + // Returns the tones remaining to be played out. + virtual std::string tones() const = 0; + + // Returns the current tone duration value in ms. + // This value will be the value last set via the InsertDtmf() method, or the + // default value of 100 ms if InsertDtmf() was never called. + virtual int duration() const = 0; + + // Returns the current value of the between-tone gap in ms. + // This value will be the value last set via the InsertDtmf() method, or the + // default value of 50 ms if InsertDtmf() was never called. + virtual int inter_tone_gap() const = 0; + + // Returns the current value of the "," character delay in ms. + // This value will be the value last set via the InsertDtmf() method, or the + // default value of 2000 ms if InsertDtmf() was never called. + virtual int comma_delay() const { return kDtmfDefaultCommaDelayMs; } + + protected: + ~DtmfSenderInterface() override = default; +}; + +} // namespace webrtc + +#endif // API_DTMF_SENDER_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/fec_controller.h b/third_party/libwebrtc/api/fec_controller.h new file mode 100644 index 0000000000..f3d7a8aa26 --- /dev/null +++ b/third_party/libwebrtc/api/fec_controller.h @@ -0,0 +1,92 @@ +/* + * 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. + */ + +#ifndef API_FEC_CONTROLLER_H_ +#define API_FEC_CONTROLLER_H_ + +#include <memory> +#include <vector> + +#include "api/video/video_frame_type.h" +#include "modules/include/module_fec_types.h" + +namespace webrtc { +// TODO(yinwa): work in progress. API in class FecController should not be +// used by other users until this comment is removed. + +// Callback class used for telling the user about how to configure the FEC, +// and the rates sent the last second is returned to the VCM. +class VCMProtectionCallback { + public: + virtual int ProtectionRequest(const FecProtectionParams* delta_params, + const FecProtectionParams* key_params, + uint32_t* sent_video_rate_bps, + uint32_t* sent_nack_rate_bps, + uint32_t* sent_fec_rate_bps) = 0; + + protected: + virtual ~VCMProtectionCallback() {} +}; + +// FecController calculates how much of the allocated network +// capacity that can be used by an encoder and how much that +// is needed for redundant packets such as FEC and NACK. It uses an +// implementation of `VCMProtectionCallback` to set new FEC parameters and get +// the bitrate currently used for FEC and NACK. +// Usage: +// Setup by calling SetProtectionMethod and SetEncodingData. +// For each encoded image, call UpdateWithEncodedData. +// Each time the bandwidth estimate change, call UpdateFecRates. UpdateFecRates +// will return the bitrate that can be used by an encoder. +// A lock is used to protect internal states, so methods can be called on an +// arbitrary thread. +class FecController { + public: + virtual ~FecController() {} + + virtual void SetProtectionCallback( + VCMProtectionCallback* protection_callback) = 0; + virtual void SetProtectionMethod(bool enable_fec, bool enable_nack) = 0; + + // Informs loss protectoin logic of initial encoding state. + virtual void SetEncodingData(size_t width, + size_t height, + size_t num_temporal_layers, + size_t max_payload_size) = 0; + + // Returns target rate for the encoder given the channel parameters. + // Inputs: estimated_bitrate_bps - the estimated network bitrate in bits/s. + // actual_framerate - encoder frame rate. + // fraction_lost - packet loss rate in % in the network. + // loss_mask_vector - packet loss mask since last time this method + // was called. round_trip_time_ms - round trip time in milliseconds. + virtual uint32_t UpdateFecRates(uint32_t estimated_bitrate_bps, + int actual_framerate, + uint8_t fraction_lost, + std::vector<bool> loss_mask_vector, + int64_t round_trip_time_ms) = 0; + + // Informs of encoded output. + virtual void UpdateWithEncodedData( + size_t encoded_image_length, + VideoFrameType encoded_image_frametype) = 0; + + // Returns whether this FEC Controller needs Loss Vector Mask as input. + virtual bool UseLossVectorMask() = 0; +}; + +class FecControllerFactoryInterface { + public: + virtual std::unique_ptr<FecController> CreateFecController() = 0; + virtual ~FecControllerFactoryInterface() = default; +}; + +} // namespace webrtc +#endif // API_FEC_CONTROLLER_H_ diff --git a/third_party/libwebrtc/api/fec_controller_api_gn/moz.build b/third_party/libwebrtc/api/fec_controller_api_gn/moz.build new file mode 100644 index 0000000000..014e7fe571 --- /dev/null +++ b/third_party/libwebrtc/api/fec_controller_api_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("fec_controller_api_gn") diff --git a/third_party/libwebrtc/api/fec_controller_override.h b/third_party/libwebrtc/api/fec_controller_override.h new file mode 100644 index 0000000000..233812fb0a --- /dev/null +++ b/third_party/libwebrtc/api/fec_controller_override.h @@ -0,0 +1,28 @@ +/* Copyright 2019 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 is an EXPERIMENTAL interface. + +#ifndef API_FEC_CONTROLLER_OVERRIDE_H_ +#define API_FEC_CONTROLLER_OVERRIDE_H_ + +namespace webrtc { + +// Interface for temporarily overriding FecController's bitrate allocation. +class FecControllerOverride { + public: + virtual void SetFecAllowed(bool fec_allowed) = 0; + + protected: + virtual ~FecControllerOverride() = default; +}; + +} // namespace webrtc + +#endif // API_FEC_CONTROLLER_OVERRIDE_H_ diff --git a/third_party/libwebrtc/api/field_trials.cc b/third_party/libwebrtc/api/field_trials.cc new file mode 100644 index 0000000000..4bd11271dc --- /dev/null +++ b/third_party/libwebrtc/api/field_trials.cc @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2020 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 "api/field_trials.h" + +#include <atomic> + +#include "rtc_base/checks.h" +#include "system_wrappers/include/field_trial.h" + +namespace { + +// This part is copied from system_wrappers/field_trial.cc. +webrtc::flat_map<std::string, std::string> InsertIntoMap(const std::string& s) { + std::string::size_type field_start = 0; + webrtc::flat_map<std::string, std::string> key_value_map; + while (field_start < s.size()) { + std::string::size_type separator_pos = s.find('/', field_start); + RTC_CHECK_NE(separator_pos, std::string::npos) + << "Missing separator '/' after field trial key."; + RTC_CHECK_GT(separator_pos, field_start) + << "Field trial key cannot be empty."; + std::string key = s.substr(field_start, separator_pos - field_start); + field_start = separator_pos + 1; + + RTC_CHECK_LT(field_start, s.size()) + << "Missing value after field trial key. String ended."; + separator_pos = s.find('/', field_start); + RTC_CHECK_NE(separator_pos, std::string::npos) + << "Missing terminating '/' in field trial string."; + RTC_CHECK_GT(separator_pos, field_start) + << "Field trial value cannot be empty."; + std::string value = s.substr(field_start, separator_pos - field_start); + field_start = separator_pos + 1; + + // If a key is specified multiple times, only the value linked to the first + // key is stored. note: This will crash in debug build when calling + // InitFieldTrialsFromString(). + key_value_map.emplace(key, value); + } + // This check is technically redundant due to earlier checks. + // We nevertheless keep the check to make it clear that the entire + // string has been processed, and without indexing past the end. + RTC_CHECK_EQ(field_start, s.size()); + + return key_value_map; +} + +// Makes sure that only one instance is created, since the usage +// of global string makes behaviour unpredicatable otherwise. +// TODO(bugs.webrtc.org/10335): Remove once global string is gone. +std::atomic<bool> instance_created_{false}; + +} // namespace + +namespace webrtc { + +FieldTrials::FieldTrials(const std::string& s) + : uses_global_(true), + field_trial_string_(s), + previous_field_trial_string_(webrtc::field_trial::GetFieldTrialString()), + key_value_map_(InsertIntoMap(s)) { + // TODO(bugs.webrtc.org/10335): Remove the global string! + field_trial::InitFieldTrialsFromString(field_trial_string_.c_str()); + RTC_CHECK(!instance_created_.exchange(true)) + << "Only one instance may be instanciated at any given time!"; +} + +std::unique_ptr<FieldTrials> FieldTrials::CreateNoGlobal(const std::string& s) { + return std::unique_ptr<FieldTrials>(new FieldTrials(s, true)); +} + +FieldTrials::FieldTrials(const std::string& s, bool) + : uses_global_(false), + previous_field_trial_string_(nullptr), + key_value_map_(InsertIntoMap(s)) {} + +FieldTrials::~FieldTrials() { + // TODO(bugs.webrtc.org/10335): Remove the global string! + if (uses_global_) { + field_trial::InitFieldTrialsFromString(previous_field_trial_string_); + RTC_CHECK(instance_created_.exchange(false)); + } +} + +std::string FieldTrials::GetValue(absl::string_view key) const { + auto it = key_value_map_.find(std::string(key)); + if (it != key_value_map_.end()) + return it->second; + + // Check the global string so that programs using + // a mix between FieldTrials and the global string continue to work + // TODO(bugs.webrtc.org/10335): Remove the global string! + if (uses_global_) { + return field_trial::FindFullName(std::string(key)); + } + return ""; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/field_trials.h b/third_party/libwebrtc/api/field_trials.h new file mode 100644 index 0000000000..bf7a7cc625 --- /dev/null +++ b/third_party/libwebrtc/api/field_trials.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 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 API_FIELD_TRIALS_H_ +#define API_FIELD_TRIALS_H_ + +#include <memory> +#include <string> + +#include "absl/strings/string_view.h" +#include "api/field_trials_registry.h" +#include "rtc_base/containers/flat_map.h" + +namespace webrtc { + +// The FieldTrials class is used to inject field trials into webrtc. +// +// Field trials allow webrtc clients (such as Chromium) to turn on feature code +// in binaries out in the field and gather information with that. +// +// They are designed to be easy to use with Chromium field trials and to speed +// up developers by reducing the need to wire up APIs to control whether a +// feature is on/off. +// +// The field trials are injected into objects that use them at creation time. +// +// NOTE: Creating multiple FieldTrials-object is currently prohibited +// until we remove the global string (TODO(bugs.webrtc.org/10335)) +// (unless using CreateNoGlobal): +class FieldTrials : public FieldTrialsRegistry { + public: + explicit FieldTrials(const std::string& s); + ~FieldTrials(); + + // Create a FieldTrials object that is not reading/writing from + // global variable (i.e can not be used for all parts of webrtc). + static std::unique_ptr<FieldTrials> CreateNoGlobal(const std::string& s); + + private: + explicit FieldTrials(const std::string& s, bool); + + std::string GetValue(absl::string_view key) const override; + + const bool uses_global_; + const std::string field_trial_string_; + const char* const previous_field_trial_string_; + const flat_map<std::string, std::string> key_value_map_; +}; + +} // namespace webrtc + +#endif // API_FIELD_TRIALS_H_ diff --git a/third_party/libwebrtc/api/field_trials_registry.cc b/third_party/libwebrtc/api/field_trials_registry.cc new file mode 100644 index 0000000000..f97e8a85a9 --- /dev/null +++ b/third_party/libwebrtc/api/field_trials_registry.cc @@ -0,0 +1,31 @@ +/* + * Copyright 2022 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 "api/field_trials_registry.h" + +#include <string> + +#include "absl/algorithm/container.h" +#include "absl/strings/string_view.h" +#include "experiments/registered_field_trials.h" +#include "rtc_base/checks.h" +#include "rtc_base/containers/flat_set.h" + +namespace webrtc { + +std::string FieldTrialsRegistry::Lookup(absl::string_view key) const { +#if WEBRTC_STRICT_FIELD_TRIALS + RTC_DCHECK(absl::c_linear_search(kRegisteredFieldTrials, key) || + test_keys_.contains(key)) + << key << " is not registered."; +#endif + return GetValue(key); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/field_trials_registry.h b/third_party/libwebrtc/api/field_trials_registry.h new file mode 100644 index 0000000000..dc7e8445b1 --- /dev/null +++ b/third_party/libwebrtc/api/field_trials_registry.h @@ -0,0 +1,54 @@ +/* + * Copyright 2022 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 API_FIELD_TRIALS_REGISTRY_H_ +#define API_FIELD_TRIALS_REGISTRY_H_ + +#include <string> +#include <utility> + +#include "absl/strings/string_view.h" +#include "api/field_trials_view.h" +#include "rtc_base/containers/flat_set.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Abstract base class for a field trial registry that verifies that any looked +// up key has been pre-registered in accordance with `g3doc/field-trials.md`. +class RTC_EXPORT FieldTrialsRegistry : public FieldTrialsView { + public: + FieldTrialsRegistry() = default; + + FieldTrialsRegistry(const FieldTrialsRegistry&) = default; + FieldTrialsRegistry& operator=(const FieldTrialsRegistry&) = default; + + ~FieldTrialsRegistry() override = default; + + // Verifies that `key` is a registered field trial and then returns the + // configured value for `key` or an empty string if the field trial isn't + // configured. + std::string Lookup(absl::string_view key) const override; + + // Register additional `keys` for testing. This should only be used for + // imaginary keys that are never used outside test code. + void RegisterKeysForTesting(flat_set<std::string> keys) { + test_keys_ = std::move(keys); + } + + private: + virtual std::string GetValue(absl::string_view key) const = 0; + + // Imaginary keys only used for testing. + flat_set<std::string> test_keys_; +}; + +} // namespace webrtc + +#endif // API_FIELD_TRIALS_REGISTRY_H_ diff --git a/third_party/libwebrtc/api/field_trials_registry_gn/moz.build b/third_party/libwebrtc/api/field_trials_registry_gn/moz.build new file mode 100644 index 0000000000..4210c8af82 --- /dev/null +++ b/third_party/libwebrtc/api/field_trials_registry_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/field_trials_registry.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("field_trials_registry_gn") diff --git a/third_party/libwebrtc/api/field_trials_unittest.cc b/third_party/libwebrtc/api/field_trials_unittest.cc new file mode 100644 index 0000000000..804b52a818 --- /dev/null +++ b/third_party/libwebrtc/api/field_trials_unittest.cc @@ -0,0 +1,152 @@ +/* + * Copyright 2022 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 "api/field_trials.h" + +#include <memory> +#include <utility> + +#include "absl/strings/string_view.h" +#include "api/transport/field_trial_based_config.h" +#include "rtc_base/containers/flat_set.h" +#include "system_wrappers/include/field_trial.h" +#include "test/field_trial.h" +#include "test/gmock.h" +#include "test/gtest.h" + +#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) +#include "test/testsupport/rtc_expect_death.h" +#endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) + +namespace webrtc { +namespace { + +using ::testing::NotNull; +using ::webrtc::field_trial::FieldTrialsAllowedInScopeForTesting; +using ::webrtc::test::ScopedFieldTrials; + +TEST(FieldTrialsTest, EmptyStringHasNoEffect) { + FieldTrialsAllowedInScopeForTesting k({"MyCoolTrial"}); + FieldTrials f(""); + f.RegisterKeysForTesting({"MyCoolTrial"}); + + EXPECT_FALSE(f.IsEnabled("MyCoolTrial")); + EXPECT_FALSE(f.IsDisabled("MyCoolTrial")); +} + +TEST(FieldTrialsTest, EnabledDisabledMustBeFirstInValue) { + FieldTrials f( + "MyCoolTrial/EnabledFoo/" + "MyUncoolTrial/DisabledBar/" + "AnotherTrial/BazEnabled/"); + f.RegisterKeysForTesting({"MyCoolTrial", "MyUncoolTrial", "AnotherTrial"}); + + EXPECT_TRUE(f.IsEnabled("MyCoolTrial")); + EXPECT_TRUE(f.IsDisabled("MyUncoolTrial")); + EXPECT_FALSE(f.IsEnabled("AnotherTrial")); +} + +TEST(FieldTrialsTest, FieldTrialsDoesNotReadGlobalString) { + FieldTrialsAllowedInScopeForTesting k({"MyCoolTrial", "MyUncoolTrial"}); + ScopedFieldTrials g("MyCoolTrial/Enabled/MyUncoolTrial/Disabled/"); + FieldTrials f(""); + f.RegisterKeysForTesting({"MyCoolTrial", "MyUncoolTrial"}); + + EXPECT_FALSE(f.IsEnabled("MyCoolTrial")); + EXPECT_FALSE(f.IsDisabled("MyUncoolTrial")); +} + +TEST(FieldTrialsTest, FieldTrialsWritesGlobalString) { + FieldTrialsAllowedInScopeForTesting k({"MyCoolTrial", "MyUncoolTrial"}); + FieldTrials f("MyCoolTrial/Enabled/MyUncoolTrial/Disabled/"); + EXPECT_TRUE(webrtc::field_trial::IsEnabled("MyCoolTrial")); + EXPECT_TRUE(webrtc::field_trial::IsDisabled("MyUncoolTrial")); +} + +TEST(FieldTrialsTest, FieldTrialsRestoresGlobalStringAfterDestruction) { + static constexpr char s[] = "SomeString/Enabled/"; + ScopedFieldTrials g(s); + { + FieldTrials f("SomeOtherString/Enabled/"); + EXPECT_STREQ(webrtc::field_trial::GetFieldTrialString(), + "SomeOtherString/Enabled/"); + } + EXPECT_STREQ(webrtc::field_trial::GetFieldTrialString(), s); +} + +#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) +TEST(FieldTrialsTest, FieldTrialsDoesNotSupportSimultaneousInstances) { + FieldTrials f("SomeString/Enabled/"); + RTC_EXPECT_DEATH(FieldTrials("SomeOtherString/Enabled/").Lookup("Whatever"), + "Only one instance"); +} +#endif // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) + +TEST(FieldTrialsTest, FieldTrialsSupportsSeparateInstances) { + { FieldTrials f("SomeString/Enabled/"); } + { FieldTrials f("SomeOtherString/Enabled/"); } +} + +TEST(FieldTrialsTest, NonGlobalFieldTrialsInstanceDoesNotModifyGlobalString) { + FieldTrialsAllowedInScopeForTesting k({"SomeString"}); + std::unique_ptr<FieldTrials> f = + FieldTrials::CreateNoGlobal("SomeString/Enabled/"); + ASSERT_THAT(f, NotNull()); + f->RegisterKeysForTesting({"SomeString"}); + + EXPECT_TRUE(f->IsEnabled("SomeString")); + EXPECT_FALSE(webrtc::field_trial::IsEnabled("SomeString")); +} + +TEST(FieldTrialsTest, NonGlobalFieldTrialsSupportSimultaneousInstances) { + std::unique_ptr<FieldTrials> f1 = + FieldTrials::CreateNoGlobal("SomeString/Enabled/"); + std::unique_ptr<FieldTrials> f2 = + FieldTrials::CreateNoGlobal("SomeOtherString/Enabled/"); + ASSERT_THAT(f1, NotNull()); + ASSERT_THAT(f2, NotNull()); + f1->RegisterKeysForTesting({"SomeString", "SomeOtherString"}); + f2->RegisterKeysForTesting({"SomeString", "SomeOtherString"}); + + EXPECT_TRUE(f1->IsEnabled("SomeString")); + EXPECT_FALSE(f1->IsEnabled("SomeOtherString")); + + EXPECT_FALSE(f2->IsEnabled("SomeString")); + EXPECT_TRUE(f2->IsEnabled("SomeOtherString")); +} + +TEST(FieldTrialsTest, GlobalAndNonGlobalFieldTrialsAreDisjoint) { + FieldTrialsAllowedInScopeForTesting k({"SomeString", "SomeOtherString"}); + FieldTrials f1("SomeString/Enabled/"); + std::unique_ptr<FieldTrials> f2 = + FieldTrials::CreateNoGlobal("SomeOtherString/Enabled/"); + ASSERT_THAT(f2, NotNull()); + f1.RegisterKeysForTesting({"SomeString", "SomeOtherString"}); + f2->RegisterKeysForTesting({"SomeString", "SomeOtherString"}); + + EXPECT_TRUE(f1.IsEnabled("SomeString")); + EXPECT_FALSE(f1.IsEnabled("SomeOtherString")); + + EXPECT_FALSE(f2->IsEnabled("SomeString")); + EXPECT_TRUE(f2->IsEnabled("SomeOtherString")); +} + +TEST(FieldTrialsTest, FieldTrialBasedConfigReadsGlobalString) { + FieldTrialsAllowedInScopeForTesting k({"MyCoolTrial", "MyUncoolTrial"}); + ScopedFieldTrials g("MyCoolTrial/Enabled/MyUncoolTrial/Disabled/"); + FieldTrialBasedConfig f; + f.RegisterKeysForTesting({"MyCoolTrial", "MyUncoolTrial"}); + + EXPECT_TRUE(f.IsEnabled("MyCoolTrial")); + EXPECT_TRUE(f.IsDisabled("MyUncoolTrial")); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/api/field_trials_view.h b/third_party/libwebrtc/api/field_trials_view.h new file mode 100644 index 0000000000..45e6f7899b --- /dev/null +++ b/third_party/libwebrtc/api/field_trials_view.h @@ -0,0 +1,49 @@ +/* + * Copyright 2019 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 API_FIELD_TRIALS_VIEW_H_ +#define API_FIELD_TRIALS_VIEW_H_ + +#include <string> + +#include "absl/strings/string_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// An interface that provides the means to access field trials. +// +// Note that there are no guarantess that the meaning of a particular key-value +// mapping will be preserved over time and no announcements will be made if they +// are changed. It's up to the library user to ensure that the behavior does not +// break. +class RTC_EXPORT FieldTrialsView { + public: + virtual ~FieldTrialsView() = default; + + // Returns the configured value for `key` or an empty string if the field + // trial isn't configured. + virtual std::string Lookup(absl::string_view key) const = 0; + + bool IsEnabled(absl::string_view key) const { + return Lookup(key).find("Enabled") == 0; + } + + bool IsDisabled(absl::string_view key) const { + return Lookup(key).find("Disabled") == 0; + } +}; + +// TODO(bugs.webrtc.org/10335): Remove once all migrated to +// api/field_trials_view.h +typedef FieldTrialsView WebRtcKeyValueConfig; + +} // namespace webrtc + +#endif // API_FIELD_TRIALS_VIEW_H_ diff --git a/third_party/libwebrtc/api/field_trials_view_gn/moz.build b/third_party/libwebrtc/api/field_trials_view_gn/moz.build new file mode 100644 index 0000000000..2c7f147d4a --- /dev/null +++ b/third_party/libwebrtc/api/field_trials_view_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("field_trials_view_gn") diff --git a/third_party/libwebrtc/api/frame_transformer_factory.cc b/third_party/libwebrtc/api/frame_transformer_factory.cc new file mode 100644 index 0000000000..af08372e37 --- /dev/null +++ b/third_party/libwebrtc/api/frame_transformer_factory.cc @@ -0,0 +1,33 @@ +/* + * Copyright 2022 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 "api/frame_transformer_factory.h" + +#include "modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.h" + +namespace webrtc { + +std::unique_ptr<TransformableVideoFrameInterface> CreateVideoSenderFrame() { + RTC_CHECK_NOTREACHED(); + return nullptr; +} + +std::unique_ptr<TransformableVideoFrameInterface> CreateVideoReceiverFrame() { + RTC_CHECK_NOTREACHED(); + return nullptr; +} + +std::unique_ptr<TransformableVideoFrameInterface> CloneVideoFrame( + TransformableVideoFrameInterface* original) { + // At the moment, only making sender frames from receiver frames is supported. + return CloneSenderVideoFrame(original); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/frame_transformer_factory.h b/third_party/libwebrtc/api/frame_transformer_factory.h new file mode 100644 index 0000000000..8ba9c292d5 --- /dev/null +++ b/third_party/libwebrtc/api/frame_transformer_factory.h @@ -0,0 +1,39 @@ +/* + * Copyright 2022 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 API_FRAME_TRANSFORMER_FACTORY_H_ +#define API_FRAME_TRANSFORMER_FACTORY_H_ + +#include <memory> +#include <vector> + +#include "api/frame_transformer_interface.h" +#include "api/scoped_refptr.h" +#include "api/video/encoded_frame.h" +#include "api/video/video_frame_metadata.h" + +// This file contains EXPERIMENTAL functions to create video frames from +// either an old video frame or directly from parameters. +// These functions will be used in Chrome functionality to manipulate +// encoded frames from Javascript. +namespace webrtc { + +// TODO(bugs.webrtc.org/14708): Add the required parameters to these APIs. +std::unique_ptr<TransformableVideoFrameInterface> CreateVideoSenderFrame(); +// TODO(bugs.webrtc.org/14708): Consider whether Receiver frames ever make sense +// to create. +std::unique_ptr<TransformableVideoFrameInterface> CreateVideoReceiverFrame(); +// Creates a new frame with the same metadata as the original. +// The original can be a sender or receiver frame. +RTC_EXPORT std::unique_ptr<TransformableVideoFrameInterface> CloneVideoFrame( + TransformableVideoFrameInterface* original); +} // namespace webrtc + +#endif // API_FRAME_TRANSFORMER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/frame_transformer_interface.h b/third_party/libwebrtc/api/frame_transformer_interface.h new file mode 100644 index 0000000000..fba09d5ff0 --- /dev/null +++ b/third_party/libwebrtc/api/frame_transformer_interface.h @@ -0,0 +1,115 @@ +/* + * Copyright 2020 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 API_FRAME_TRANSFORMER_INTERFACE_H_ +#define API_FRAME_TRANSFORMER_INTERFACE_H_ + +#include <memory> +#include <vector> + +#include "api/scoped_refptr.h" +#include "api/video/encoded_frame.h" +#include "api/video/video_frame_metadata.h" +#include "rtc_base/ref_count.h" + +namespace webrtc { + +// Owns the frame payload data. +class TransformableFrameInterface { + public: + virtual ~TransformableFrameInterface() = default; + + // Returns the frame payload data. The data is valid until the next non-const + // method call. + virtual rtc::ArrayView<const uint8_t> GetData() const = 0; + + // Copies `data` into the owned frame payload data. + virtual void SetData(rtc::ArrayView<const uint8_t> data) = 0; + + virtual uint8_t GetPayloadType() const = 0; + virtual uint32_t GetSsrc() const = 0; + virtual uint32_t GetTimestamp() const = 0; + + enum class Direction { + kUnknown, + kReceiver, + kSender, + }; + // TODO(crbug.com/1250638): Remove this distinction between receiver and + // sender frames to allow received frames to be directly re-transmitted on + // other PeerConnectionss. + virtual Direction GetDirection() const { return Direction::kUnknown; } +}; + +class TransformableVideoFrameInterface : public TransformableFrameInterface { + public: + virtual ~TransformableVideoFrameInterface() = default; + virtual bool IsKeyFrame() const = 0; + + // Returns data needed in the frame transformation logic; for example, + // when the transformation applied to the frame is encryption/decryption, the + // additional data holds the serialized generic frame descriptor extension + // calculated in webrtc::RtpDescriptorAuthentication. + // TODO(bugs.webrtc.org/11380) remove from interface once + // webrtc::RtpDescriptorAuthentication is exposed in api/. + virtual std::vector<uint8_t> GetAdditionalData() const = 0; + + virtual const VideoFrameMetadata& GetMetadata() const = 0; + // TODO(https://crbug.com/webrtc/14709): Make pure virtual when Chromium MOCK + // has implemented this. + virtual void SetMetadata(const VideoFrameMetadata&) {} +}; + +// Extends the TransformableFrameInterface to expose audio-specific information. +class TransformableAudioFrameInterface : public TransformableFrameInterface { + public: + virtual ~TransformableAudioFrameInterface() = default; + + // Exposes the frame header, enabling the interface clients to use the + // information in the header as needed, for example to compile the list of + // csrcs. + virtual const RTPHeader& GetHeader() const = 0; + + virtual rtc::ArrayView<const uint32_t> GetContributingSources() const = 0; +}; + +// Objects implement this interface to be notified with the transformed frame. +class TransformedFrameCallback : public rtc::RefCountInterface { + public: + virtual void OnTransformedFrame( + std::unique_ptr<TransformableFrameInterface> frame) = 0; + + protected: + ~TransformedFrameCallback() override = default; +}; + +// Transforms encoded frames. The transformed frame is sent in a callback using +// the TransformedFrameCallback interface (see above). +class FrameTransformerInterface : public rtc::RefCountInterface { + public: + // Transforms `frame` using the implementing class' processing logic. + virtual void Transform( + std::unique_ptr<TransformableFrameInterface> transformable_frame) = 0; + + virtual void RegisterTransformedFrameCallback( + rtc::scoped_refptr<TransformedFrameCallback>) {} + virtual void RegisterTransformedFrameSinkCallback( + rtc::scoped_refptr<TransformedFrameCallback>, + uint32_t ssrc) {} + virtual void UnregisterTransformedFrameCallback() {} + virtual void UnregisterTransformedFrameSinkCallback(uint32_t ssrc) {} + + protected: + ~FrameTransformerInterface() override = default; +}; + +} // namespace webrtc + +#endif // API_FRAME_TRANSFORMER_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/frame_transformer_interface_gn/moz.build b/third_party/libwebrtc/api/frame_transformer_interface_gn/moz.build new file mode 100644 index 0000000000..885c8437ae --- /dev/null +++ b/third_party/libwebrtc/api/frame_transformer_interface_gn/moz.build @@ -0,0 +1,216 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("frame_transformer_interface_gn") diff --git a/third_party/libwebrtc/api/function_view.h b/third_party/libwebrtc/api/function_view.h new file mode 100644 index 0000000000..5ae1bd6cfe --- /dev/null +++ b/third_party/libwebrtc/api/function_view.h @@ -0,0 +1,130 @@ +/* + * Copyright 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. + */ + +#ifndef API_FUNCTION_VIEW_H_ +#define API_FUNCTION_VIEW_H_ + +#include <type_traits> +#include <utility> + +#include "rtc_base/checks.h" + +// Just like std::function, FunctionView will wrap any callable and hide its +// actual type, exposing only its signature. But unlike std::function, +// FunctionView doesn't own its callable---it just points to it. Thus, it's a +// good choice mainly as a function argument when the callable argument will +// not be called again once the function has returned. +// +// Its constructors are implicit, so that callers won't have to convert lambdas +// and other callables to FunctionView<Blah(Blah, Blah)> explicitly. This is +// safe because FunctionView is only a reference to the real callable. +// +// Example use: +// +// void SomeFunction(rtc::FunctionView<int(int)> index_transform); +// ... +// SomeFunction([](int i) { return 2 * i + 1; }); +// +// Note: FunctionView is tiny (essentially just two pointers) and trivially +// copyable, so it's probably cheaper to pass it by value than by const +// reference. + +namespace rtc { + +template <typename T> +class FunctionView; // Undefined. + +template <typename RetT, typename... ArgT> +class FunctionView<RetT(ArgT...)> final { + public: + // Constructor for lambdas and other callables; it accepts every type of + // argument except those noted in its enable_if call. + template < + typename F, + typename std::enable_if< + // Not for function pointers; we have another constructor for that + // below. + !std::is_function<typename std::remove_pointer< + typename std::remove_reference<F>::type>::type>::value && + + // Not for nullptr; we have another constructor for that below. + !std::is_same<std::nullptr_t, + typename std::remove_cv<F>::type>::value && + + // Not for FunctionView objects; we have another constructor for that + // (the implicitly declared copy constructor). + !std::is_same<FunctionView, + typename std::remove_cv<typename std::remove_reference< + F>::type>::type>::value>::type* = nullptr> + FunctionView(F&& f) + : call_(CallVoidPtr<typename std::remove_reference<F>::type>) { + f_.void_ptr = &f; + } + + // Constructor that accepts function pointers. If the argument is null, the + // result is an empty FunctionView. + template < + typename F, + typename std::enable_if<std::is_function<typename std::remove_pointer< + typename std::remove_reference<F>::type>::type>::value>::type* = + nullptr> + FunctionView(F&& f) + : call_(f ? CallFunPtr<typename std::remove_pointer<F>::type> : nullptr) { + f_.fun_ptr = reinterpret_cast<void (*)()>(f); + } + + // Constructor that accepts nullptr. It creates an empty FunctionView. + template <typename F, + typename std::enable_if<std::is_same< + std::nullptr_t, + typename std::remove_cv<F>::type>::value>::type* = nullptr> + FunctionView(F&& f) : call_(nullptr) {} + + // Default constructor. Creates an empty FunctionView. + FunctionView() : call_(nullptr) {} + + RetT operator()(ArgT... args) const { + RTC_DCHECK(call_); + return call_(f_, std::forward<ArgT>(args)...); + } + + // Returns true if we have a function, false if we don't (i.e., we're null). + explicit operator bool() const { return !!call_; } + + private: + union VoidUnion { + void* void_ptr; + void (*fun_ptr)(); + }; + + template <typename F> + static RetT CallVoidPtr(VoidUnion vu, ArgT... args) { + return (*static_cast<F*>(vu.void_ptr))(std::forward<ArgT>(args)...); + } + template <typename F> + static RetT CallFunPtr(VoidUnion vu, ArgT... args) { + return (reinterpret_cast<typename std::add_pointer<F>::type>(vu.fun_ptr))( + std::forward<ArgT>(args)...); + } + + // A pointer to the callable thing, with type information erased. It's a + // union because we have to use separate types depending on if the callable + // thing is a function pointer or something else. + VoidUnion f_; + + // Pointer to a dispatch function that knows the type of the callable thing + // that's stored in f_, and how to call it. A FunctionView object is empty + // (null) iff call_ is null. + RetT (*call_)(VoidUnion, ArgT...); +}; + +} // namespace rtc + +#endif // API_FUNCTION_VIEW_H_ diff --git a/third_party/libwebrtc/api/function_view_gn/moz.build b/third_party/libwebrtc/api/function_view_gn/moz.build new file mode 100644 index 0000000000..59ebc4ae7a --- /dev/null +++ b/third_party/libwebrtc/api/function_view_gn/moz.build @@ -0,0 +1,205 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("function_view_gn") diff --git a/third_party/libwebrtc/api/function_view_unittest.cc b/third_party/libwebrtc/api/function_view_unittest.cc new file mode 100644 index 0000000000..156ea5c22d --- /dev/null +++ b/third_party/libwebrtc/api/function_view_unittest.cc @@ -0,0 +1,176 @@ +/* + * Copyright 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. + */ + +#include "api/function_view.h" + +#include <memory> +#include <utility> + +#include "test/gtest.h" + +namespace rtc { + +namespace { + +int CallWith33(rtc::FunctionView<int(int)> fv) { + return fv ? fv(33) : -1; +} + +int Add33(int x) { + return x + 33; +} + +} // namespace + +// Test the main use case of FunctionView: implicitly converting a callable +// argument. +TEST(FunctionViewTest, ImplicitConversion) { + EXPECT_EQ(38, CallWith33([](int x) { return x + 5; })); + EXPECT_EQ(66, CallWith33(Add33)); + EXPECT_EQ(-1, CallWith33(nullptr)); +} + +TEST(FunctionViewTest, IntIntLambdaWithoutState) { + auto f = [](int x) { return x + 1; }; + EXPECT_EQ(18, f(17)); + rtc::FunctionView<int(int)> fv(f); + EXPECT_TRUE(fv); + EXPECT_EQ(18, fv(17)); +} + +TEST(FunctionViewTest, IntVoidLambdaWithState) { + int x = 13; + auto f = [x]() mutable { return ++x; }; + rtc::FunctionView<int()> fv(f); + EXPECT_TRUE(fv); + EXPECT_EQ(14, f()); + EXPECT_EQ(15, fv()); + EXPECT_EQ(16, f()); + EXPECT_EQ(17, fv()); +} + +TEST(FunctionViewTest, IntIntFunction) { + rtc::FunctionView<int(int)> fv(Add33); + EXPECT_TRUE(fv); + EXPECT_EQ(50, fv(17)); +} + +TEST(FunctionViewTest, IntIntFunctionPointer) { + rtc::FunctionView<int(int)> fv(&Add33); + EXPECT_TRUE(fv); + EXPECT_EQ(50, fv(17)); +} + +TEST(FunctionViewTest, Null) { + // These two call constructors that statically construct null FunctionViews. + EXPECT_FALSE(rtc::FunctionView<int()>()); + EXPECT_FALSE(rtc::FunctionView<int()>(nullptr)); + + // This calls the constructor for function pointers. + EXPECT_FALSE(rtc::FunctionView<int()>(reinterpret_cast<int (*)()>(0))); +} + +// Ensure that FunctionView handles move-only arguments and return values. +TEST(FunctionViewTest, UniquePtrPassthrough) { + auto f = [](std::unique_ptr<int> x) { return x; }; + rtc::FunctionView<std::unique_ptr<int>(std::unique_ptr<int>)> fv(f); + std::unique_ptr<int> x(new int); + int* x_addr = x.get(); + auto y = fv(std::move(x)); + EXPECT_EQ(x_addr, y.get()); +} + +TEST(FunctionViewTest, CopyConstructor) { + auto f17 = [] { return 17; }; + rtc::FunctionView<int()> fv1(f17); + rtc::FunctionView<int()> fv2(fv1); + EXPECT_EQ(17, fv1()); + EXPECT_EQ(17, fv2()); +} + +TEST(FunctionViewTest, MoveConstructorIsCopy) { + auto f17 = [] { return 17; }; + rtc::FunctionView<int()> fv1(f17); + rtc::FunctionView<int()> fv2(std::move(fv1)); // NOLINT + EXPECT_EQ(17, fv1()); + EXPECT_EQ(17, fv2()); +} + +TEST(FunctionViewTest, CopyAssignment) { + auto f17 = [] { return 17; }; + rtc::FunctionView<int()> fv1(f17); + auto f23 = [] { return 23; }; + rtc::FunctionView<int()> fv2(f23); + EXPECT_EQ(17, fv1()); + EXPECT_EQ(23, fv2()); + fv2 = fv1; + EXPECT_EQ(17, fv1()); + EXPECT_EQ(17, fv2()); +} + +TEST(FunctionViewTest, MoveAssignmentIsCopy) { + auto f17 = [] { return 17; }; + rtc::FunctionView<int()> fv1(f17); + auto f23 = [] { return 23; }; + rtc::FunctionView<int()> fv2(f23); + EXPECT_EQ(17, fv1()); + EXPECT_EQ(23, fv2()); + fv2 = std::move(fv1); // NOLINT + EXPECT_EQ(17, fv1()); + EXPECT_EQ(17, fv2()); +} + +TEST(FunctionViewTest, Swap) { + auto f17 = [] { return 17; }; + rtc::FunctionView<int()> fv1(f17); + auto f23 = [] { return 23; }; + rtc::FunctionView<int()> fv2(f23); + EXPECT_EQ(17, fv1()); + EXPECT_EQ(23, fv2()); + using std::swap; + swap(fv1, fv2); + EXPECT_EQ(23, fv1()); + EXPECT_EQ(17, fv2()); +} + +// Ensure that when you copy-construct a FunctionView, the new object points to +// the same function as the old one (as opposed to the new object pointing to +// the old one). +TEST(FunctionViewTest, CopyConstructorChaining) { + auto f17 = [] { return 17; }; + rtc::FunctionView<int()> fv1(f17); + rtc::FunctionView<int()> fv2(fv1); + EXPECT_EQ(17, fv1()); + EXPECT_EQ(17, fv2()); + auto f23 = [] { return 23; }; + fv1 = f23; + EXPECT_EQ(23, fv1()); + EXPECT_EQ(17, fv2()); +} + +// Ensure that when you assign one FunctionView to another, we actually make a +// copy (as opposed to making the second FunctionView point to the first one). +TEST(FunctionViewTest, CopyAssignmentChaining) { + auto f17 = [] { return 17; }; + rtc::FunctionView<int()> fv1(f17); + rtc::FunctionView<int()> fv2; + EXPECT_TRUE(fv1); + EXPECT_EQ(17, fv1()); + EXPECT_FALSE(fv2); + fv2 = fv1; + EXPECT_EQ(17, fv1()); + EXPECT_EQ(17, fv2()); + auto f23 = [] { return 23; }; + fv1 = f23; + EXPECT_EQ(23, fv1()); + EXPECT_EQ(17, fv2()); +} + +} // namespace rtc diff --git a/third_party/libwebrtc/api/g3doc/index.md b/third_party/libwebrtc/api/g3doc/index.md new file mode 100644 index 0000000000..b576514d5e --- /dev/null +++ b/third_party/libwebrtc/api/g3doc/index.md @@ -0,0 +1,51 @@ +<!-- go/cmark --> +<!--* freshness: {owner: 'hta' reviewed: '2021-04-12'} *--> + +# The WebRTC API + +The public API of the WebRTC library consists of the api/ directory and +its subdirectories. No other files should be depended on by webrtc users. + +Before starting to code against the API, it is important to understand +some basic concepts, such as: + +* Memory management, including webrtc's reference counted objects +* [Thread management](threading_design.md) + +## Using WebRTC through the PeerConnection class + +The +[PeerConnectionInterface](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/peer_connection_interface.h?q=webrtc::PeerConnectionInterface) +class is the recommended way to use the WebRTC library. + +It is closely modeled after the Javascript API documented in the [WebRTC +specification](https://w3c.github.io/webrtc-pc/). + +PeerConnections are created using the [PeerConnectionFactoryInterface](https://source.chromium.org/search?q=webrtc::PeerConnectionFactoryInterface). + +There are two levels of customization available: + +* Pass a PeerConnectionFactoryDependencies object to the function that creates + a PeerConnectionFactory. This object defines factories for a lot of internal + objects inside the PeerConnection, so that users can override them. + All PeerConnections using this interface will have the same options. +* Pass a PeerConnectionInterface::RTCConfiguration object to the + CreatePeerConnectionOrError() function on the + PeerConnectionFactoryInterface. These customizations will apply only to a + single PeerConnection. + +Most functions on the PeerConnection interface are asynchronous, and take a +callback that is executed when the function is finished. The callbacks are +mostly called on the thread that is passed as the "signaling thread" field of +the PeerConnectionFactoryDependencies, or the thread that called +PeerConnectionFactory::CreatePeerConnectionOrError() if no thread is given. + +See each class' module documentation for details. + +## Using WebRTC components without the PeerConnection class + +This needs to be done carefully, and in consultation with the WebRTC team. There +are non-obvious dependencies between many of the components. + + + diff --git a/third_party/libwebrtc/api/g3doc/threading_design.md b/third_party/libwebrtc/api/g3doc/threading_design.md new file mode 100644 index 0000000000..8023b5eda0 --- /dev/null +++ b/third_party/libwebrtc/api/g3doc/threading_design.md @@ -0,0 +1,74 @@ +<!-- go/cmark --> +<!--* freshness: {owner: 'hta' reviewed: '2021-04-12'} *--> + +# API Threading Design considerations + +The header files in this directory form the API to the WebRTC library +that is intended for client applications' use. + +This API is designed to be used on top of a multithreaded runtime. + +The public API functions are designed to be called from a single thread* +(the "client thread"), and can do internal dispatching to the thread +where activity needs to happen. Those threads can be passed in by the +client, typically as arguments to factory constructors, or they can be +created by the library if factory constructors that don't take threads +are used. + +Many of the functions are designed to be used in an asynchronous manner, +where a function is called to initiate an activity, and a callback will +be called when the activity is completed, or a handler function will +be called on an observer object when interesting events happen. + +Note: Often, even functions that look like simple functions (such as +information query functions) will need to jump between threads to perform +their function - which means that things may happen on other threads +between calls; writing "increment(x); increment(x)" is not a safe +way to increment X by exactly two, since the increment function may have +jumped to another thread that already had a queue of things to handle, +causing large amounts of other activity to have intervened between +the two calls. + +(*) The term "thread" is used here to denote any construct that guarantees +sequential execution - other names for such constructs are task runners +and sequenced task queues. + +## Client threads and callbacks + +At the moment, the API does not give any guarantee on which thread* the +callbacks and events are called on. So it's best to write all callback +and event handlers like this (pseudocode): +``` +void ObserverClass::Handler(event) { + if (!called_on_client_thread()) { + dispatch_to_client_thread(bind(handler(event))); + return; + } + // Process event, we're now on the right thread +} +``` +In the future, the implementation may change to always call the callbacks +and event handlers on the client thread. + +## Implementation considerations + +The C++ classes that are part of the public API are also used to derive +classes that form part of the implementation. + +This should not directly concern users of the API, but may matter if one +wants to look at how the WebRTC library is implemented, or for legacy code +that directly accesses internal APIs. + +Many APIs are defined in terms of a "proxy object", which will do a blocking +dispatch of the function to another thread, and an "implementation object" +which will do the actual +work, but can only be created, invoked and destroyed on its "home thread". + +Usually, the classes are named "xxxInterface" (in api/), "xxxProxy" and +"xxx" (not in api/). WebRTC users should only need to depend on the files +in api/. In many cases, the "xxxProxy" and "xxx" classes are subclasses +of "xxxInterface", but this property is an implementation feature only, +and should not be relied upon. + +The threading properties of these internal APIs are NOT documented in +this note, and need to be understood by inspecting those classes. diff --git a/third_party/libwebrtc/api/ice_transport_factory.cc b/third_party/libwebrtc/api/ice_transport_factory.cc new file mode 100644 index 0000000000..e88ac183fa --- /dev/null +++ b/third_party/libwebrtc/api/ice_transport_factory.cc @@ -0,0 +1,67 @@ +/* + * Copyright 2019 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 "api/ice_transport_factory.h" + +#include <memory> +#include <utility> + +#include "api/make_ref_counted.h" +#include "p2p/base/ice_transport_internal.h" +#include "p2p/base/p2p_constants.h" +#include "p2p/base/p2p_transport_channel.h" +#include "p2p/base/port_allocator.h" +#include "rtc_base/thread.h" + +namespace webrtc { + +namespace { + +// This implementation of IceTransportInterface is used in cases where +// the only reference to the P2PTransport will be through this class. +// It must be constructed, accessed and destroyed on the signaling thread. +class IceTransportWithTransportChannel : public IceTransportInterface { + public: + IceTransportWithTransportChannel( + std::unique_ptr<cricket::IceTransportInternal> internal) + : internal_(std::move(internal)) {} + + ~IceTransportWithTransportChannel() override { + RTC_DCHECK_RUN_ON(&thread_checker_); + } + + cricket::IceTransportInternal* internal() override { + RTC_DCHECK_RUN_ON(&thread_checker_); + return internal_.get(); + } + + private: + const SequenceChecker thread_checker_{}; + const std::unique_ptr<cricket::IceTransportInternal> internal_ + RTC_GUARDED_BY(thread_checker_); +}; + +} // namespace + +rtc::scoped_refptr<IceTransportInterface> CreateIceTransport( + cricket::PortAllocator* port_allocator) { + IceTransportInit init; + init.set_port_allocator(port_allocator); + return CreateIceTransport(std::move(init)); +} + +rtc::scoped_refptr<IceTransportInterface> CreateIceTransport( + IceTransportInit init) { + return rtc::make_ref_counted<IceTransportWithTransportChannel>( + cricket::P2PTransportChannel::Create( + "", cricket::ICE_CANDIDATE_COMPONENT_RTP, std::move(init))); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/ice_transport_factory.h b/third_party/libwebrtc/api/ice_transport_factory.h new file mode 100644 index 0000000000..2268ea5e12 --- /dev/null +++ b/third_party/libwebrtc/api/ice_transport_factory.h @@ -0,0 +1,47 @@ +/* + * Copyright 2019 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 API_ICE_TRANSPORT_FACTORY_H_ +#define API_ICE_TRANSPORT_FACTORY_H_ + +#include "api/ice_transport_interface.h" +#include "api/scoped_refptr.h" +#include "rtc_base/system/rtc_export.h" + +namespace cricket { +class PortAllocator; +} // namespace cricket + +namespace webrtc { + +// Static factory for an IceTransport object that can be created +// without using a webrtc::PeerConnection. +// The returned object must be accessed and destroyed on the thread that +// created it. +// The PortAllocator must outlive the created IceTransportInterface object. +// TODO(steveanton): Remove in favor of the overload that takes +// IceTransportInit. +RTC_EXPORT rtc::scoped_refptr<IceTransportInterface> CreateIceTransport( + cricket::PortAllocator* port_allocator); + +// Static factory for an IceTransport object that can be created +// without using a webrtc::PeerConnection. +// The returned object must be accessed and destroyed on the thread that +// created it. +// `init.port_allocator()` is required and must outlive the created +// IceTransportInterface object. +// `init.async_resolver_factory()` and `init.event_log()` are optional, but if +// provided must outlive the created IceTransportInterface object. +RTC_EXPORT rtc::scoped_refptr<IceTransportInterface> CreateIceTransport( + IceTransportInit); + +} // namespace webrtc + +#endif // API_ICE_TRANSPORT_FACTORY_H_ diff --git a/third_party/libwebrtc/api/ice_transport_interface.h b/third_party/libwebrtc/api/ice_transport_interface.h new file mode 100644 index 0000000000..2ec41aaa69 --- /dev/null +++ b/third_party/libwebrtc/api/ice_transport_interface.h @@ -0,0 +1,157 @@ +/* + * Copyright 2019 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 API_ICE_TRANSPORT_INTERFACE_H_ +#define API_ICE_TRANSPORT_INTERFACE_H_ + +#include <string> + +#include "api/async_dns_resolver.h" +#include "api/async_resolver_factory.h" +#include "api/rtc_error.h" +#include "api/rtc_event_log/rtc_event_log.h" +#include "api/scoped_refptr.h" +#include "rtc_base/ref_count.h" + +namespace cricket { +class IceTransportInternal; +class PortAllocator; +class IceControllerFactoryInterface; +class ActiveIceControllerFactoryInterface; +} // namespace cricket + +namespace webrtc { +class FieldTrialsView; + +// An ICE transport, as represented to the outside world. +// This object is refcounted, and is therefore alive until the +// last holder has released it. +class IceTransportInterface : public rtc::RefCountInterface { + public: + // Accessor for the internal representation of an ICE transport. + // The returned object can only be safely used on the signalling thread. + // TODO(crbug.com/907849): Add API calls for the functions that have to + // be exposed to clients, and stop allowing access to the + // cricket::IceTransportInternal API. + virtual cricket::IceTransportInternal* internal() = 0; +}; + +struct IceTransportInit final { + public: + IceTransportInit() = default; + IceTransportInit(const IceTransportInit&) = delete; + IceTransportInit(IceTransportInit&&) = default; + IceTransportInit& operator=(const IceTransportInit&) = delete; + IceTransportInit& operator=(IceTransportInit&&) = default; + + cricket::PortAllocator* port_allocator() { return port_allocator_; } + void set_port_allocator(cricket::PortAllocator* port_allocator) { + port_allocator_ = port_allocator; + } + + AsyncDnsResolverFactoryInterface* async_dns_resolver_factory() { + return async_dns_resolver_factory_; + } + void set_async_dns_resolver_factory( + AsyncDnsResolverFactoryInterface* async_dns_resolver_factory) { + RTC_DCHECK(!async_resolver_factory_); + async_dns_resolver_factory_ = async_dns_resolver_factory; + } + AsyncResolverFactory* async_resolver_factory() { + return async_resolver_factory_; + } + ABSL_DEPRECATED("bugs.webrtc.org/12598") + void set_async_resolver_factory( + AsyncResolverFactory* async_resolver_factory) { + RTC_DCHECK(!async_dns_resolver_factory_); + async_resolver_factory_ = async_resolver_factory; + } + + RtcEventLog* event_log() { return event_log_; } + void set_event_log(RtcEventLog* event_log) { event_log_ = event_log; } + + void set_ice_controller_factory( + cricket::IceControllerFactoryInterface* ice_controller_factory) { + ice_controller_factory_ = ice_controller_factory; + } + cricket::IceControllerFactoryInterface* ice_controller_factory() { + return ice_controller_factory_; + } + + // An active ICE controller actively manages the connection used by an ICE + // transport, in contrast with a legacy ICE controller that only picks the + // best connection to use or ping, and lets the transport decide when and + // whether to switch. + // + // Which ICE controller is used is determined based on the field trial + // "WebRTC-UseActiveIceController" as follows: + // + // 1. If the field trial is not enabled + // a. The legacy ICE controller factory is used if one is supplied. + // b. If not, a default ICE controller (BasicIceController) is + // constructed and used. + // + // 2. If the field trial is enabled + // a. If an active ICE controller factory is supplied, it is used and + // the legacy ICE controller factory is not used. + // b. If not, a default active ICE controller is used, wrapping over the + // supplied or the default legacy ICE controller. + void set_active_ice_controller_factory( + cricket::ActiveIceControllerFactoryInterface* + active_ice_controller_factory) { + active_ice_controller_factory_ = active_ice_controller_factory; + } + cricket::ActiveIceControllerFactoryInterface* + active_ice_controller_factory() { + return active_ice_controller_factory_; + } + + const FieldTrialsView* field_trials() { return field_trials_; } + void set_field_trials(const FieldTrialsView* field_trials) { + field_trials_ = field_trials; + } + + private: + cricket::PortAllocator* port_allocator_ = nullptr; + AsyncDnsResolverFactoryInterface* async_dns_resolver_factory_ = nullptr; + // For backwards compatibility. Only one resolver factory can be set. + AsyncResolverFactory* async_resolver_factory_ = nullptr; + RtcEventLog* event_log_ = nullptr; + cricket::IceControllerFactoryInterface* ice_controller_factory_ = nullptr; + cricket::ActiveIceControllerFactoryInterface* active_ice_controller_factory_ = + nullptr; + const FieldTrialsView* field_trials_ = nullptr; + // TODO(https://crbug.com/webrtc/12657): Redesign to have const members. +}; + +// TODO(qingsi): The factory interface is defined in this file instead of its +// namesake file ice_transport_factory.h to avoid the extra dependency on p2p/ +// introduced there by the p2p/-dependent factory methods. Move the factory +// methods to a different file or rename it. +class IceTransportFactory { + public: + virtual ~IceTransportFactory() = default; + // As a refcounted object, the returned ICE transport may outlive the host + // construct into which its reference is given, e.g. a peer connection. As a + // result, the returned ICE transport should not hold references to any object + // that the transport does not own and that has a lifetime bound to the host + // construct. Also, assumptions on the thread safety of the returned transport + // should be clarified by implementations. For example, a peer connection + // requires the returned transport to be constructed and destroyed on the + // network thread and an ICE transport factory that intends to work with a + // peer connection should offer transports compatible with these assumptions. + virtual rtc::scoped_refptr<IceTransportInterface> CreateIceTransport( + const std::string& transport_name, + int component, + IceTransportInit init) = 0; +}; + +} // namespace webrtc +#endif // API_ICE_TRANSPORT_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/jsep.cc b/third_party/libwebrtc/api/jsep.cc new file mode 100644 index 0000000000..5fdc8905c7 --- /dev/null +++ b/third_party/libwebrtc/api/jsep.cc @@ -0,0 +1,57 @@ +/* + * Copyright 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. + */ + +#include "api/jsep.h" + +namespace webrtc { + +std::string IceCandidateInterface::server_url() const { + return ""; +} + +size_t SessionDescriptionInterface::RemoveCandidates( + const std::vector<cricket::Candidate>& candidates) { + return 0; +} + +const char SessionDescriptionInterface::kOffer[] = "offer"; +const char SessionDescriptionInterface::kPrAnswer[] = "pranswer"; +const char SessionDescriptionInterface::kAnswer[] = "answer"; +const char SessionDescriptionInterface::kRollback[] = "rollback"; + +const char* SdpTypeToString(SdpType type) { + switch (type) { + case SdpType::kOffer: + return SessionDescriptionInterface::kOffer; + case SdpType::kPrAnswer: + return SessionDescriptionInterface::kPrAnswer; + case SdpType::kAnswer: + return SessionDescriptionInterface::kAnswer; + case SdpType::kRollback: + return SessionDescriptionInterface::kRollback; + } + return ""; +} + +absl::optional<SdpType> SdpTypeFromString(const std::string& type_str) { + if (type_str == SessionDescriptionInterface::kOffer) { + return SdpType::kOffer; + } else if (type_str == SessionDescriptionInterface::kPrAnswer) { + return SdpType::kPrAnswer; + } else if (type_str == SessionDescriptionInterface::kAnswer) { + return SdpType::kAnswer; + } else if (type_str == SessionDescriptionInterface::kRollback) { + return SdpType::kRollback; + } else { + return absl::nullopt; + } +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/jsep.h b/third_party/libwebrtc/api/jsep.h new file mode 100644 index 0000000000..d2aa57c784 --- /dev/null +++ b/third_party/libwebrtc/api/jsep.h @@ -0,0 +1,253 @@ +/* + * Copyright 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. + */ + +// This file contains declarations of interfaces that wrap SDP-related +// constructs; session descriptions and ICE candidates. The inner "cricket::" +// objects shouldn't be accessed directly; the intention is that an application +// using the PeerConnection API only creates these objects from strings, and +// them passes them into the PeerConnection. +// +// Though in the future, we're planning to provide an SDP parsing API, with a +// structure more friendly than cricket::SessionDescription. + +#ifndef API_JSEP_H_ +#define API_JSEP_H_ + +#include <stddef.h> + +#include <memory> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/rtc_error.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/system/rtc_export.h" + +namespace cricket { +class Candidate; +class SessionDescription; +} // namespace cricket + +namespace webrtc { + +struct SdpParseError { + public: + // The sdp line that causes the error. + std::string line; + // Explains the error. + std::string description; +}; + +// Class representation of an ICE candidate. +// +// An instance of this interface is supposed to be owned by one class at +// a time and is therefore not expected to be thread safe. +// +// An instance can be created by CreateIceCandidate. +class RTC_EXPORT IceCandidateInterface { + public: + virtual ~IceCandidateInterface() {} + // If present, this is the value of the "a=mid" attribute of the candidate's + // m= section in SDP, which identifies the m= section. + virtual std::string sdp_mid() const = 0; + // This indicates the index (starting at zero) of m= section this candidate + // is associated with. Needed when an endpoint doesn't support MIDs. + virtual int sdp_mline_index() const = 0; + // Only for use internally. + virtual const cricket::Candidate& candidate() const = 0; + // The URL of the ICE server which this candidate was gathered from. + // TODO(zhihuang): Remove the default implementation once the subclasses + // implement this method. + virtual std::string server_url() const; + // Creates a SDP-ized form of this candidate. + virtual bool ToString(std::string* out) const = 0; +}; + +// Creates a IceCandidateInterface based on SDP string. +// Returns null if the sdp string can't be parsed. +// `error` may be null. +RTC_EXPORT IceCandidateInterface* CreateIceCandidate(const std::string& sdp_mid, + int sdp_mline_index, + const std::string& sdp, + SdpParseError* error); + +// Creates an IceCandidateInterface based on a parsed candidate structure. +RTC_EXPORT std::unique_ptr<IceCandidateInterface> CreateIceCandidate( + const std::string& sdp_mid, + int sdp_mline_index, + const cricket::Candidate& candidate); + +// This class represents a collection of candidates for a specific m= section. +// Used in SessionDescriptionInterface. +class IceCandidateCollection { + public: + virtual ~IceCandidateCollection() {} + virtual size_t count() const = 0; + // Returns true if an equivalent `candidate` exist in the collection. + virtual bool HasCandidate(const IceCandidateInterface* candidate) const = 0; + virtual const IceCandidateInterface* at(size_t index) const = 0; +}; + +// Enum that describes the type of the SessionDescriptionInterface. +// Corresponds to RTCSdpType in the WebRTC specification. +// https://w3c.github.io/webrtc-pc/#dom-rtcsdptype +enum class SdpType { + kOffer, // Description must be treated as an SDP offer. + kPrAnswer, // Description must be treated as an SDP answer, but not a final + // answer. + kAnswer, // Description must be treated as an SDP final answer, and the + // offer-answer exchange must be considered complete after + // receiving this. + kRollback // Resets any pending offers and sets signaling state back to + // stable. +}; + +// Returns the string form of the given SDP type. String forms are defined in +// SessionDescriptionInterface. +RTC_EXPORT const char* SdpTypeToString(SdpType type); + +// Returns the SdpType from its string form. The string form can be one of the +// constants defined in SessionDescriptionInterface. Passing in any other string +// results in nullopt. +absl::optional<SdpType> SdpTypeFromString(const std::string& type_str); + +// Class representation of an SDP session description. +// +// An instance of this interface is supposed to be owned by one class at a time +// and is therefore not expected to be thread safe. +// +// An instance can be created by CreateSessionDescription. +class RTC_EXPORT SessionDescriptionInterface { + public: + // String representations of the supported SDP types. + static const char kOffer[]; + static const char kPrAnswer[]; + static const char kAnswer[]; + static const char kRollback[]; + + virtual ~SessionDescriptionInterface() {} + + // Create a new SessionDescriptionInterface object + // with the same values as the old object. + // TODO(bugs.webrtc.org:12215): Remove default implementation + virtual std::unique_ptr<SessionDescriptionInterface> Clone() const { + return nullptr; + } + + // Only for use internally. + virtual cricket::SessionDescription* description() = 0; + virtual const cricket::SessionDescription* description() const = 0; + + // Get the session id and session version, which are defined based on + // RFC 4566 for the SDP o= line. + virtual std::string session_id() const = 0; + virtual std::string session_version() const = 0; + + // Returns the type of this session description as an SdpType. Descriptions of + // the various types are found in the SdpType documentation. + // TODO(steveanton): Remove default implementation once Chromium has been + // updated. + virtual SdpType GetType() const; + + // kOffer/kPrAnswer/kAnswer + // TODO(steveanton): Remove this in favor of `GetType` that returns SdpType. + virtual std::string type() const = 0; + + // Adds the specified candidate to the description. + // + // Ownership is not transferred. + // + // Returns false if the session description does not have a media section + // that corresponds to `candidate.sdp_mid()` or + // `candidate.sdp_mline_index()`. + virtual bool AddCandidate(const IceCandidateInterface* candidate) = 0; + + // Removes the candidates from the description, if found. + // + // Returns the number of candidates removed. + virtual size_t RemoveCandidates( + const std::vector<cricket::Candidate>& candidates); + + // Returns the number of m= sections in the session description. + virtual size_t number_of_mediasections() const = 0; + + // Returns a collection of all candidates that belong to a certain m= + // section. + virtual const IceCandidateCollection* candidates( + size_t mediasection_index) const = 0; + + // Serializes the description to SDP. + virtual bool ToString(std::string* out) const = 0; +}; + +// Creates a SessionDescriptionInterface based on the SDP string and the type. +// Returns null if the sdp string can't be parsed or the type is unsupported. +// `error` may be null. +// TODO(steveanton): This function is deprecated. Please use the functions below +// which take an SdpType enum instead. Remove this once it is no longer used. +RTC_EXPORT SessionDescriptionInterface* CreateSessionDescription( + const std::string& type, + const std::string& sdp, + SdpParseError* error); + +// Creates a SessionDescriptionInterface based on the SDP string and the type. +// Returns null if the SDP string cannot be parsed. +// If using the signature with `error_out`, details of the parsing error may be +// written to `error_out` if it is not null. +RTC_EXPORT std::unique_ptr<SessionDescriptionInterface> +CreateSessionDescription(SdpType type, const std::string& sdp); +RTC_EXPORT std::unique_ptr<SessionDescriptionInterface> +CreateSessionDescription(SdpType type, + const std::string& sdp, + SdpParseError* error_out); + +// Creates a SessionDescriptionInterface based on a parsed SDP structure and the +// given type, ID and version. +std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription( + SdpType type, + const std::string& session_id, + const std::string& session_version, + std::unique_ptr<cricket::SessionDescription> description); + +// CreateOffer and CreateAnswer callback interface. +class RTC_EXPORT CreateSessionDescriptionObserver + : public rtc::RefCountInterface { + public: + // This callback transfers the ownership of the `desc`. + // TODO(deadbeef): Make this take an std::unique_ptr<> to avoid confusion + // around ownership. + virtual void OnSuccess(SessionDescriptionInterface* desc) = 0; + // The OnFailure callback takes an RTCError, which consists of an + // error code and a string. + // RTCError is non-copyable, so it must be passed using std::move. + // Earlier versions of the API used a string argument. This version + // is removed; its functionality was the same as passing + // error.message. + virtual void OnFailure(RTCError error) = 0; + + protected: + ~CreateSessionDescriptionObserver() override = default; +}; + +// SetLocalDescription and SetRemoteDescription callback interface. +class RTC_EXPORT SetSessionDescriptionObserver : public rtc::RefCountInterface { + public: + virtual void OnSuccess() = 0; + // See description in CreateSessionDescriptionObserver for OnFailure. + virtual void OnFailure(RTCError error) = 0; + + protected: + ~SetSessionDescriptionObserver() override = default; +}; + +} // namespace webrtc + +#endif // API_JSEP_H_ diff --git a/third_party/libwebrtc/api/jsep_ice_candidate.cc b/third_party/libwebrtc/api/jsep_ice_candidate.cc new file mode 100644 index 0000000000..e18e6e28af --- /dev/null +++ b/third_party/libwebrtc/api/jsep_ice_candidate.cc @@ -0,0 +1,76 @@ +/* + * Copyright 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 "api/jsep_ice_candidate.h" + +#include <memory> +#include <utility> + +#include "absl/algorithm/container.h" +#include "absl/memory/memory.h" + +namespace webrtc { + +std::string JsepIceCandidate::sdp_mid() const { + return sdp_mid_; +} + +int JsepIceCandidate::sdp_mline_index() const { + return sdp_mline_index_; +} + +const cricket::Candidate& JsepIceCandidate::candidate() const { + return candidate_; +} + +std::string JsepIceCandidate::server_url() const { + return candidate_.url(); +} + +JsepCandidateCollection::JsepCandidateCollection() = default; + +JsepCandidateCollection::JsepCandidateCollection(JsepCandidateCollection&& o) + : candidates_(std::move(o.candidates_)) {} + +size_t JsepCandidateCollection::count() const { + return candidates_.size(); +} + +void JsepCandidateCollection::add(JsepIceCandidate* candidate) { + candidates_.push_back(absl::WrapUnique(candidate)); +} + +const IceCandidateInterface* JsepCandidateCollection::at(size_t index) const { + return candidates_[index].get(); +} + +bool JsepCandidateCollection::HasCandidate( + const IceCandidateInterface* candidate) const { + return absl::c_any_of( + candidates_, [&](const std::unique_ptr<JsepIceCandidate>& entry) { + return entry->sdp_mid() == candidate->sdp_mid() && + entry->sdp_mline_index() == candidate->sdp_mline_index() && + entry->candidate().IsEquivalent(candidate->candidate()); + }); +} + +size_t JsepCandidateCollection::remove(const cricket::Candidate& candidate) { + auto iter = absl::c_find_if( + candidates_, [&](const std::unique_ptr<JsepIceCandidate>& c) { + return candidate.MatchesForRemoval(c->candidate()); + }); + if (iter != candidates_.end()) { + candidates_.erase(iter); + return 1; + } + return 0; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/jsep_ice_candidate.h b/third_party/libwebrtc/api/jsep_ice_candidate.h new file mode 100644 index 0000000000..8f47a102e7 --- /dev/null +++ b/third_party/libwebrtc/api/jsep_ice_candidate.h @@ -0,0 +1,90 @@ +/* + * Copyright 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. + */ + +// TODO(deadbeef): Move this out of api/; it's an implementation detail and +// shouldn't be used externally. + +#ifndef API_JSEP_ICE_CANDIDATE_H_ +#define API_JSEP_ICE_CANDIDATE_H_ + +#include <stddef.h> + +#include <memory> +#include <string> +#include <vector> + +#include "api/candidate.h" +#include "api/jsep.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Implementation of IceCandidateInterface. +class RTC_EXPORT JsepIceCandidate : public IceCandidateInterface { + public: + JsepIceCandidate(const std::string& sdp_mid, int sdp_mline_index); + JsepIceCandidate(const std::string& sdp_mid, + int sdp_mline_index, + const cricket::Candidate& candidate); + JsepIceCandidate(const JsepIceCandidate&) = delete; + JsepIceCandidate& operator=(const JsepIceCandidate&) = delete; + ~JsepIceCandidate() override; + // `err` may be null. + bool Initialize(const std::string& sdp, SdpParseError* err); + void SetCandidate(const cricket::Candidate& candidate) { + candidate_ = candidate; + } + + std::string sdp_mid() const override; + int sdp_mline_index() const override; + const cricket::Candidate& candidate() const override; + + std::string server_url() const override; + + bool ToString(std::string* out) const override; + + private: + std::string sdp_mid_; + int sdp_mline_index_; + cricket::Candidate candidate_; +}; + +// Implementation of IceCandidateCollection which stores JsepIceCandidates. +class JsepCandidateCollection : public IceCandidateCollection { + public: + JsepCandidateCollection(); + // Move constructor is defined so that a vector of JsepCandidateCollections + // can be resized. + JsepCandidateCollection(JsepCandidateCollection&& o); + + JsepCandidateCollection(const JsepCandidateCollection&) = delete; + JsepCandidateCollection& operator=(const JsepCandidateCollection&) = delete; + + // Returns a copy of the candidate collection. + JsepCandidateCollection Clone() const; + size_t count() const override; + bool HasCandidate(const IceCandidateInterface* candidate) const override; + // Adds and takes ownership of the JsepIceCandidate. + // TODO(deadbeef): Make this use an std::unique_ptr<>, so ownership logic is + // more clear. + virtual void add(JsepIceCandidate* candidate); + const IceCandidateInterface* at(size_t index) const override; + // Removes the candidate that has a matching address and protocol. + // + // Returns the number of candidates that were removed. + size_t remove(const cricket::Candidate& candidate); + + private: + std::vector<std::unique_ptr<JsepIceCandidate>> candidates_; +}; + +} // namespace webrtc + +#endif // API_JSEP_ICE_CANDIDATE_H_ diff --git a/third_party/libwebrtc/api/jsep_session_description.h b/third_party/libwebrtc/api/jsep_session_description.h new file mode 100644 index 0000000000..0b65734ea9 --- /dev/null +++ b/third_party/libwebrtc/api/jsep_session_description.h @@ -0,0 +1,91 @@ +/* + * Copyright 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. + */ + +// TODO(deadbeef): Move this out of api/; it's an implementation detail and +// shouldn't be used externally. + +#ifndef API_JSEP_SESSION_DESCRIPTION_H_ +#define API_JSEP_SESSION_DESCRIPTION_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "absl/strings/string_view.h" +#include "api/candidate.h" +#include "api/jsep.h" +#include "api/jsep_ice_candidate.h" + +namespace cricket { +class SessionDescription; +} + +namespace webrtc { + +// Implementation of SessionDescriptionInterface. +class JsepSessionDescription : public SessionDescriptionInterface { + public: + explicit JsepSessionDescription(SdpType type); + // TODO(steveanton): Remove this once callers have switched to SdpType. + explicit JsepSessionDescription(const std::string& type); + JsepSessionDescription( + SdpType type, + std::unique_ptr<cricket::SessionDescription> description, + absl::string_view session_id, + absl::string_view session_version); + virtual ~JsepSessionDescription(); + + JsepSessionDescription(const JsepSessionDescription&) = delete; + JsepSessionDescription& operator=(const JsepSessionDescription&) = delete; + + // Takes ownership of `description`. + bool Initialize(std::unique_ptr<cricket::SessionDescription> description, + const std::string& session_id, + const std::string& session_version); + + virtual std::unique_ptr<SessionDescriptionInterface> Clone() const; + + virtual cricket::SessionDescription* description() { + return description_.get(); + } + virtual const cricket::SessionDescription* description() const { + return description_.get(); + } + virtual std::string session_id() const { return session_id_; } + virtual std::string session_version() const { return session_version_; } + virtual SdpType GetType() const { return type_; } + virtual std::string type() const { return SdpTypeToString(type_); } + // Allows changing the type. Used for testing. + virtual bool AddCandidate(const IceCandidateInterface* candidate); + virtual size_t RemoveCandidates( + const std::vector<cricket::Candidate>& candidates); + virtual size_t number_of_mediasections() const; + virtual const IceCandidateCollection* candidates( + size_t mediasection_index) const; + virtual bool ToString(std::string* out) const; + + static const int kDefaultVideoCodecId; + static const char kDefaultVideoCodecName[]; + + private: + std::unique_ptr<cricket::SessionDescription> description_; + std::string session_id_; + std::string session_version_; + SdpType type_; + std::vector<JsepCandidateCollection> candidate_collection_; + + bool GetMediasectionIndex(const IceCandidateInterface* candidate, + size_t* index); + int GetMediasectionIndex(const cricket::Candidate& candidate); +}; + +} // namespace webrtc + +#endif // API_JSEP_SESSION_DESCRIPTION_H_ diff --git a/third_party/libwebrtc/api/legacy_stats_types.cc b/third_party/libwebrtc/api/legacy_stats_types.cc new file mode 100644 index 0000000000..e3b2144edd --- /dev/null +++ b/third_party/libwebrtc/api/legacy_stats_types.cc @@ -0,0 +1,845 @@ +/* + * Copyright 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. + */ + +#include "api/legacy_stats_types.h" + +#include <string.h> + +#include "absl/algorithm/container.h" +#include "api/make_ref_counted.h" +#include "rtc_base/checks.h" +#include "rtc_base/string_encode.h" + +// TODO(tommi): Could we have a static map of value name -> expected type +// and use this to RTC_DCHECK on correct usage (somewhat strongly typed values)? +// Alternatively, we could define the names+type in a separate document and +// generate strongly typed inline C++ code that forces the correct type to be +// used for a given name at compile time. + +namespace webrtc { +namespace { + +// The id of StatsReport of type kStatsReportTypeBwe. +const char kStatsReportVideoBweId[] = "bweforvideo"; + +// NOTE: These names need to be consistent with an external +// specification (W3C Stats Identifiers). +const char* InternalTypeToString(StatsReport::StatsType type) { + switch (type) { + case StatsReport::kStatsReportTypeSession: + return "googLibjingleSession"; + case StatsReport::kStatsReportTypeBwe: + return "VideoBwe"; + case StatsReport::kStatsReportTypeRemoteSsrc: + return "remoteSsrc"; + case StatsReport::kStatsReportTypeSsrc: + return "ssrc"; + case StatsReport::kStatsReportTypeTrack: + return "googTrack"; + case StatsReport::kStatsReportTypeIceLocalCandidate: + return "localcandidate"; + case StatsReport::kStatsReportTypeIceRemoteCandidate: + return "remotecandidate"; + case StatsReport::kStatsReportTypeTransport: + return "transport"; + case StatsReport::kStatsReportTypeComponent: + return "googComponent"; + case StatsReport::kStatsReportTypeCandidatePair: + return "googCandidatePair"; + case StatsReport::kStatsReportTypeCertificate: + return "googCertificate"; + case StatsReport::kStatsReportTypeDataChannel: + return "datachannel"; + } + RTC_DCHECK_NOTREACHED(); + return nullptr; +} + +class BandwidthEstimationId : public StatsReport::IdBase { + public: + BandwidthEstimationId() + : StatsReport::IdBase(StatsReport::kStatsReportTypeBwe) {} + std::string ToString() const override { return kStatsReportVideoBweId; } +}; + +class TypedId : public StatsReport::IdBase { + public: + TypedId(StatsReport::StatsType type, const std::string& id) + : StatsReport::IdBase(type), id_(id) {} + + bool Equals(const IdBase& other) const override { + return IdBase::Equals(other) && + static_cast<const TypedId&>(other).id_ == id_; + } + + std::string ToString() const override { + return std::string(InternalTypeToString(type_)) + kSeparator + id_; + } + + protected: + const std::string id_; +}; + +class TypedIntId : public StatsReport::IdBase { + public: + TypedIntId(StatsReport::StatsType type, int id) + : StatsReport::IdBase(type), id_(id) {} + + bool Equals(const IdBase& other) const override { + return IdBase::Equals(other) && + static_cast<const TypedIntId&>(other).id_ == id_; + } + + std::string ToString() const override { + return std::string(InternalTypeToString(type_)) + kSeparator + + rtc::ToString(id_); + } + + protected: + const int id_; +}; + +class IdWithDirection : public TypedId { + public: + IdWithDirection(StatsReport::StatsType type, + const std::string& id, + StatsReport::Direction direction) + : TypedId(type, id), direction_(direction) {} + + bool Equals(const IdBase& other) const override { + return TypedId::Equals(other) && + static_cast<const IdWithDirection&>(other).direction_ == direction_; + } + + std::string ToString() const override { + std::string ret(TypedId::ToString()); + ret += kSeparator; + ret += direction_ == StatsReport::kSend ? "send" : "recv"; + return ret; + } + + private: + const StatsReport::Direction direction_; +}; + +class CandidateId : public TypedId { + public: + CandidateId(bool local, const std::string& id) + : TypedId(local ? StatsReport::kStatsReportTypeIceLocalCandidate + : StatsReport::kStatsReportTypeIceRemoteCandidate, + id) {} + + std::string ToString() const override { return "Cand-" + id_; } +}; + +class ComponentId : public StatsReport::IdBase { + public: + ComponentId(const std::string& content_name, int component) + : ComponentId(StatsReport::kStatsReportTypeComponent, + content_name, + component) {} + + bool Equals(const IdBase& other) const override { + return IdBase::Equals(other) && + static_cast<const ComponentId&>(other).component_ == component_ && + static_cast<const ComponentId&>(other).content_name_ == + content_name_; + } + + std::string ToString() const override { return ToString("Channel-"); } + + protected: + ComponentId(StatsReport::StatsType type, + const std::string& content_name, + int component) + : IdBase(type), content_name_(content_name), component_(component) {} + + std::string ToString(const char* prefix) const { + std::string ret(prefix); + ret += content_name_; + ret += '-'; + ret += rtc::ToString(component_); + return ret; + } + + private: + const std::string content_name_; + const int component_; +}; + +class CandidatePairId : public ComponentId { + public: + CandidatePairId(const std::string& content_name, int component, int index) + : ComponentId(StatsReport::kStatsReportTypeCandidatePair, + content_name, + component), + index_(index) {} + + bool Equals(const IdBase& other) const override { + return ComponentId::Equals(other) && + static_cast<const CandidatePairId&>(other).index_ == index_; + } + + std::string ToString() const override { + std::string ret(ComponentId::ToString("Conn-")); + ret += '-'; + ret += rtc::ToString(index_); + return ret; + } + + private: + const int index_; +}; + +} // namespace + +StatsReport::IdBase::IdBase(StatsType type) : type_(type) {} +StatsReport::IdBase::~IdBase() {} + +StatsReport::StatsType StatsReport::IdBase::type() const { + return type_; +} + +bool StatsReport::IdBase::Equals(const IdBase& other) const { + return other.type_ == type_; +} + +StatsReport::Value::Value(StatsValueName name, int64_t value, Type int_type) + : name(name), type_(int_type) { + RTC_DCHECK(type_ == kInt || type_ == kInt64); + type_ == kInt ? value_.int_ = static_cast<int>(value) : value_.int64_ = value; +} + +StatsReport::Value::Value(StatsValueName name, float f) + : name(name), type_(kFloat) { + value_.float_ = f; +} + +StatsReport::Value::Value(StatsValueName name, const std::string& value) + : name(name), type_(kString) { + value_.string_ = new std::string(value); +} + +StatsReport::Value::Value(StatsValueName name, const char* value) + : name(name), type_(kStaticString) { + value_.static_string_ = value; +} + +StatsReport::Value::Value(StatsValueName name, bool b) + : name(name), type_(kBool) { + value_.bool_ = b; +} + +StatsReport::Value::Value(StatsValueName name, const Id& value) + : name(name), type_(kId) { + value_.id_ = new Id(value); +} + +StatsReport::Value::~Value() { + switch (type_) { + case kInt: + case kInt64: + case kFloat: + case kBool: + case kStaticString: + break; + case kString: + delete value_.string_; + break; + case kId: + delete value_.id_; + break; + } +} + +bool StatsReport::Value::Equals(const Value& other) const { + if (name != other.name) + return false; + + // There's a 1:1 relation between a name and a type, so we don't have to + // check that. + RTC_DCHECK_EQ(type_, other.type_); + + switch (type_) { + case kInt: + return value_.int_ == other.value_.int_; + case kInt64: + return value_.int64_ == other.value_.int64_; + case kFloat: + return value_.float_ == other.value_.float_; + case kStaticString: { +#if RTC_DCHECK_IS_ON + if (value_.static_string_ != other.value_.static_string_) { + RTC_DCHECK(strcmp(value_.static_string_, other.value_.static_string_) != + 0) + << "Duplicate global?"; + } +#endif + return value_.static_string_ == other.value_.static_string_; + } + case kString: + return *value_.string_ == *other.value_.string_; + case kBool: + return value_.bool_ == other.value_.bool_; + case kId: + return (*value_.id_)->Equals(*other.value_.id_); + } + RTC_DCHECK_NOTREACHED(); + return false; +} + +bool StatsReport::Value::operator==(const std::string& value) const { + return (type_ == kString && value_.string_->compare(value) == 0) || + (type_ == kStaticString && value.compare(value_.static_string_) == 0); +} + +bool StatsReport::Value::operator==(const char* value) const { + if (type_ == kString) + return value_.string_->compare(value) == 0; + if (type_ != kStaticString) + return false; +#if RTC_DCHECK_IS_ON + if (value_.static_string_ != value) + RTC_DCHECK(strcmp(value_.static_string_, value) != 0) + << "Duplicate global?"; +#endif + return value == value_.static_string_; +} + +bool StatsReport::Value::operator==(int64_t value) const { + return type_ == kInt ? value_.int_ == static_cast<int>(value) + : (type_ == kInt64 ? value_.int64_ == value : false); +} + +bool StatsReport::Value::operator==(bool value) const { + return type_ == kBool && value_.bool_ == value; +} + +bool StatsReport::Value::operator==(float value) const { + return type_ == kFloat && value_.float_ == value; +} + +bool StatsReport::Value::operator==(const Id& value) const { + return type_ == kId && (*value_.id_)->Equals(value); +} + +int StatsReport::Value::int_val() const { + RTC_DCHECK_EQ(type_, kInt); + return value_.int_; +} + +int64_t StatsReport::Value::int64_val() const { + RTC_DCHECK_EQ(type_, kInt64); + return value_.int64_; +} + +float StatsReport::Value::float_val() const { + RTC_DCHECK_EQ(type_, kFloat); + return value_.float_; +} + +const char* StatsReport::Value::static_string_val() const { + RTC_DCHECK_EQ(type_, kStaticString); + return value_.static_string_; +} + +const std::string& StatsReport::Value::string_val() const { + RTC_DCHECK_EQ(type_, kString); + return *value_.string_; +} + +bool StatsReport::Value::bool_val() const { + RTC_DCHECK_EQ(type_, kBool); + return value_.bool_; +} + +const char* StatsReport::Value::display_name() const { + switch (name) { + case kStatsValueNameAecDivergentFilterFraction: + return "aecDivergentFilterFraction"; + case kStatsValueNameAudioOutputLevel: + return "audioOutputLevel"; + case kStatsValueNameAudioInputLevel: + return "audioInputLevel"; + case kStatsValueNameBytesSent: + return "bytesSent"; + case kStatsValueNameConcealedSamples: + return "concealedSamples"; + case kStatsValueNameConcealmentEvents: + return "concealmentEvents"; + case kStatsValueNamePacketsSent: + return "packetsSent"; + case kStatsValueNameBytesReceived: + return "bytesReceived"; + case kStatsValueNameLabel: + return "label"; + case kStatsValueNamePacketsReceived: + return "packetsReceived"; + case kStatsValueNamePacketsLost: + return "packetsLost"; + case kStatsValueNameProtocol: + return "protocol"; + case kStatsValueNameTotalSamplesReceived: + return "totalSamplesReceived"; + case kStatsValueNameTransportId: + return "transportId"; + case kStatsValueNameSelectedCandidatePairId: + return "selectedCandidatePairId"; + case kStatsValueNameSsrc: + return "ssrc"; + case kStatsValueNameState: + return "state"; + case kStatsValueNameDataChannelId: + return "datachannelid"; + case kStatsValueNameFramesDecoded: + return "framesDecoded"; + case kStatsValueNameFramesEncoded: + return "framesEncoded"; + case kStatsValueNameJitterBufferDelay: + return "jitterBufferDelay"; + case kStatsValueNameCodecImplementationName: + return "codecImplementationName"; + case kStatsValueNameMediaType: + return "mediaType"; + case kStatsValueNameQpSum: + return "qpSum"; + // 'goog' prefixed constants. + case kStatsValueNameAccelerateRate: + return "googAccelerateRate"; + case kStatsValueNameActiveConnection: + return "googActiveConnection"; + case kStatsValueNameActualEncBitrate: + return "googActualEncBitrate"; + case kStatsValueNameAvailableReceiveBandwidth: + return "googAvailableReceiveBandwidth"; + case kStatsValueNameAvailableSendBandwidth: + return "googAvailableSendBandwidth"; + case kStatsValueNameAvgEncodeMs: + return "googAvgEncodeMs"; + case kStatsValueNameBucketDelay: + return "googBucketDelay"; + case kStatsValueNameBandwidthLimitedResolution: + return "googBandwidthLimitedResolution"; + // STUN ping related attributes. + // + // TODO(zhihuang) Rename these stats to follow the standards. + // Connectivity checks. + case kStatsValueNameSentPingRequestsTotal: + return "requestsSent"; + case kStatsValueNameSentPingRequestsBeforeFirstResponse: + return "consentRequestsSent"; + case kStatsValueNameSentPingResponses: + return "responsesSent"; + case kStatsValueNameRecvPingRequests: + return "requestsReceived"; + case kStatsValueNameRecvPingResponses: + return "responsesReceived"; + // STUN Keepalive pings. + case kStatsValueNameSentStunKeepaliveRequests: + return "stunKeepaliveRequestsSent"; + case kStatsValueNameRecvStunKeepaliveResponses: + return "stunKeepaliveResponsesReceived"; + case kStatsValueNameStunKeepaliveRttTotal: + return "stunKeepaliveRttTotal"; + case kStatsValueNameStunKeepaliveRttSquaredTotal: + return "stunKeepaliveRttSquaredTotal"; + + // Candidate related attributes. Values are taken from + // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*. + case kStatsValueNameCandidateIPAddress: + return "ipAddress"; + case kStatsValueNameCandidateNetworkType: + return "networkType"; + case kStatsValueNameCandidatePortNumber: + return "portNumber"; + case kStatsValueNameCandidatePriority: + return "priority"; + case kStatsValueNameCandidateTransportType: + return "transport"; + case kStatsValueNameCandidateType: + return "candidateType"; + + case kStatsValueNameChannelId: + return "googChannelId"; + case kStatsValueNameCodecName: + return "googCodecName"; + case kStatsValueNameComponent: + return "googComponent"; + case kStatsValueNameContentName: + return "googContentName"; + case kStatsValueNameContentType: + return "googContentType"; + case kStatsValueNameCpuLimitedResolution: + return "googCpuLimitedResolution"; + case kStatsValueNameDecodingCTSG: + return "googDecodingCTSG"; + case kStatsValueNameDecodingCTN: + return "googDecodingCTN"; + case kStatsValueNameDecodingMutedOutput: + return "googDecodingMuted"; + case kStatsValueNameDecodingNormal: + return "googDecodingNormal"; + case kStatsValueNameDecodingPLC: + return "googDecodingPLC"; + case kStatsValueNameDecodingCodecPLC: + return "googDecodingCodecPLC"; + case kStatsValueNameDecodingCNG: + return "googDecodingCNG"; + case kStatsValueNameDecodingPLCCNG: + return "googDecodingPLCCNG"; + case kStatsValueNameDer: + return "googDerBase64"; + case kStatsValueNameDtlsCipher: + return "dtlsCipher"; + case kStatsValueNameEchoDelayMedian: + return "googEchoCancellationEchoDelayMedian"; + case kStatsValueNameEchoDelayStdDev: + return "googEchoCancellationEchoDelayStdDev"; + case kStatsValueNameEchoReturnLoss: + return "googEchoCancellationReturnLoss"; + case kStatsValueNameEchoReturnLossEnhancement: + return "googEchoCancellationReturnLossEnhancement"; + case kStatsValueNameEncodeUsagePercent: + return "googEncodeUsagePercent"; + case kStatsValueNameExpandRate: + return "googExpandRate"; + case kStatsValueNameFingerprint: + return "googFingerprint"; + case kStatsValueNameFingerprintAlgorithm: + return "googFingerprintAlgorithm"; + case kStatsValueNameFirsReceived: + return "googFirsReceived"; + case kStatsValueNameFirsSent: + return "googFirsSent"; + case kStatsValueNameFirstFrameReceivedToDecodedMs: + return "googFirstFrameReceivedToDecodedMs"; + case kStatsValueNameFrameHeightInput: + return "googFrameHeightInput"; + case kStatsValueNameFrameHeightReceived: + return "googFrameHeightReceived"; + case kStatsValueNameFrameHeightSent: + return "googFrameHeightSent"; + case kStatsValueNameFrameRateReceived: + return "googFrameRateReceived"; + case kStatsValueNameFrameRateDecoded: + return "googFrameRateDecoded"; + case kStatsValueNameFrameRateOutput: + return "googFrameRateOutput"; + case kStatsValueNameDecodeMs: + return "googDecodeMs"; + case kStatsValueNameMaxDecodeMs: + return "googMaxDecodeMs"; + case kStatsValueNameCurrentDelayMs: + return "googCurrentDelayMs"; + case kStatsValueNameTargetDelayMs: + return "googTargetDelayMs"; + case kStatsValueNameJitterBufferMs: + return "googJitterBufferMs"; + case kStatsValueNameMinPlayoutDelayMs: + return "googMinPlayoutDelayMs"; + case kStatsValueNameRenderDelayMs: + return "googRenderDelayMs"; + case kStatsValueNameCaptureStartNtpTimeMs: + return "googCaptureStartNtpTimeMs"; + case kStatsValueNameFrameRateInput: + return "googFrameRateInput"; + case kStatsValueNameFrameRateSent: + return "googFrameRateSent"; + case kStatsValueNameFrameWidthInput: + return "googFrameWidthInput"; + case kStatsValueNameFrameWidthReceived: + return "googFrameWidthReceived"; + case kStatsValueNameFrameWidthSent: + return "googFrameWidthSent"; + case kStatsValueNameHasEnteredLowResolution: + return "googHasEnteredLowResolution"; + case kStatsValueNameHugeFramesSent: + return "hugeFramesSent"; + case kStatsValueNameInitiator: + return "googInitiator"; + case kStatsValueNameInterframeDelayMaxMs: + return "googInterframeDelayMax"; + case kStatsValueNameIssuerId: + return "googIssuerId"; + case kStatsValueNameJitterReceived: + return "googJitterReceived"; + case kStatsValueNameLocalAddress: + return "googLocalAddress"; + case kStatsValueNameLocalCandidateId: + return "localCandidateId"; + case kStatsValueNameLocalCandidateType: + return "googLocalCandidateType"; + case kStatsValueNameLocalCertificateId: + return "localCertificateId"; + case kStatsValueNameAdaptationChanges: + return "googAdaptationChanges"; + case kStatsValueNameNacksReceived: + return "googNacksReceived"; + case kStatsValueNameNacksSent: + return "googNacksSent"; + case kStatsValueNamePreemptiveExpandRate: + return "googPreemptiveExpandRate"; + case kStatsValueNamePlisReceived: + return "googPlisReceived"; + case kStatsValueNamePlisSent: + return "googPlisSent"; + case kStatsValueNamePreferredJitterBufferMs: + return "googPreferredJitterBufferMs"; + case kStatsValueNameReceiving: + return "googReadable"; + case kStatsValueNameRemoteAddress: + return "googRemoteAddress"; + case kStatsValueNameRemoteCandidateId: + return "remoteCandidateId"; + case kStatsValueNameRemoteCandidateType: + return "googRemoteCandidateType"; + case kStatsValueNameRemoteCertificateId: + return "remoteCertificateId"; + case kStatsValueNameResidualEchoLikelihood: + return "googResidualEchoLikelihood"; + case kStatsValueNameResidualEchoLikelihoodRecentMax: + return "googResidualEchoLikelihoodRecentMax"; + case kStatsValueNameAnaBitrateActionCounter: + return "googAnaBitrateActionCounter"; + case kStatsValueNameAnaChannelActionCounter: + return "googAnaChannelActionCounter"; + case kStatsValueNameAnaDtxActionCounter: + return "googAnaDtxActionCounter"; + case kStatsValueNameAnaFecActionCounter: + return "googAnaFecActionCounter"; + case kStatsValueNameAnaFrameLengthIncreaseCounter: + return "googAnaFrameLengthIncreaseCounter"; + case kStatsValueNameAnaFrameLengthDecreaseCounter: + return "googAnaFrameLengthDecreaseCounter"; + case kStatsValueNameAnaUplinkPacketLossFraction: + return "googAnaUplinkPacketLossFraction"; + case kStatsValueNameRetransmitBitrate: + return "googRetransmitBitrate"; + case kStatsValueNameRtt: + return "googRtt"; + case kStatsValueNameSecondaryDecodedRate: + return "googSecondaryDecodedRate"; + case kStatsValueNameSecondaryDiscardedRate: + return "googSecondaryDiscardedRate"; + case kStatsValueNameSendPacketsDiscarded: + return "packetsDiscardedOnSend"; + case kStatsValueNameSpeechExpandRate: + return "googSpeechExpandRate"; + case kStatsValueNameSrtpCipher: + return "srtpCipher"; + case kStatsValueNameTargetEncBitrate: + return "googTargetEncBitrate"; + case kStatsValueNameTotalAudioEnergy: + return "totalAudioEnergy"; + case kStatsValueNameTotalSamplesDuration: + return "totalSamplesDuration"; + case kStatsValueNameTransmitBitrate: + return "googTransmitBitrate"; + case kStatsValueNameTransportType: + return "googTransportType"; + case kStatsValueNameTrackId: + return "googTrackId"; + case kStatsValueNameTimingFrameInfo: + return "googTimingFrameInfo"; + case kStatsValueNameWritable: + return "googWritable"; + case kStatsValueNameAudioDeviceUnderrunCounter: + return "googAudioDeviceUnderrunCounter"; + case kStatsValueNameLocalCandidateRelayProtocol: + return "googLocalCandidateRelayProtocol"; + } + + return nullptr; +} + +std::string StatsReport::Value::ToString() const { + switch (type_) { + case kInt: + return rtc::ToString(value_.int_); + case kInt64: + return rtc::ToString(value_.int64_); + case kFloat: + return rtc::ToString(value_.float_); + case kStaticString: + return std::string(value_.static_string_); + case kString: + return *value_.string_; + case kBool: + return value_.bool_ ? "true" : "false"; + case kId: + return (*value_.id_)->ToString(); + } + RTC_DCHECK_NOTREACHED(); + return std::string(); +} + +StatsReport::StatsReport(const Id& id) : id_(id), timestamp_(0.0) { + RTC_DCHECK(id_.get()); +} + +StatsReport::~StatsReport() = default; + +// static +StatsReport::Id StatsReport::NewBandwidthEstimationId() { + return rtc::make_ref_counted<BandwidthEstimationId>(); +} + +// static +StatsReport::Id StatsReport::NewTypedId(StatsType type, const std::string& id) { + return rtc::make_ref_counted<TypedId>(type, id); +} + +// static +StatsReport::Id StatsReport::NewTypedIntId(StatsType type, int id) { + return rtc::make_ref_counted<TypedIntId>(type, id); +} + +// static +StatsReport::Id StatsReport::NewIdWithDirection( + StatsType type, + const std::string& id, + StatsReport::Direction direction) { + return rtc::make_ref_counted<IdWithDirection>(type, id, direction); +} + +// static +StatsReport::Id StatsReport::NewCandidateId(bool local, const std::string& id) { + return rtc::make_ref_counted<CandidateId>(local, id); +} + +// static +StatsReport::Id StatsReport::NewComponentId(const std::string& content_name, + int component) { + return rtc::make_ref_counted<ComponentId>(content_name, component); +} + +// static +StatsReport::Id StatsReport::NewCandidatePairId(const std::string& content_name, + int component, + int index) { + return rtc::make_ref_counted<CandidatePairId>(content_name, component, index); +} + +const char* StatsReport::TypeToString() const { + return InternalTypeToString(id_->type()); +} + +void StatsReport::AddString(StatsReport::StatsValueName name, + const std::string& value) { + const Value* found = FindValue(name); + if (!found || !(*found == value)) + values_[name] = ValuePtr(new Value(name, value)); +} + +void StatsReport::AddString(StatsReport::StatsValueName name, + const char* value) { + const Value* found = FindValue(name); + if (!found || !(*found == value)) + values_[name] = ValuePtr(new Value(name, value)); +} + +void StatsReport::AddInt64(StatsReport::StatsValueName name, int64_t value) { + const Value* found = FindValue(name); + if (!found || !(*found == value)) + values_[name] = ValuePtr(new Value(name, value, Value::kInt64)); +} + +void StatsReport::AddInt(StatsReport::StatsValueName name, int value) { + const Value* found = FindValue(name); + if (!found || !(*found == static_cast<int64_t>(value))) + values_[name] = ValuePtr(new Value(name, value, Value::kInt)); +} + +void StatsReport::AddFloat(StatsReport::StatsValueName name, float value) { + const Value* found = FindValue(name); + if (!found || !(*found == value)) + values_[name] = ValuePtr(new Value(name, value)); +} + +void StatsReport::AddBoolean(StatsReport::StatsValueName name, bool value) { + const Value* found = FindValue(name); + if (!found || !(*found == value)) + values_[name] = ValuePtr(new Value(name, value)); +} + +void StatsReport::AddId(StatsReport::StatsValueName name, const Id& value) { + const Value* found = FindValue(name); + if (!found || !(*found == value)) + values_[name] = ValuePtr(new Value(name, value)); +} + +const StatsReport::Value* StatsReport::FindValue(StatsValueName name) const { + Values::const_iterator it = values_.find(name); + return it == values_.end() ? nullptr : it->second.get(); +} + +StatsCollection::StatsCollection() {} + +StatsCollection::~StatsCollection() { + RTC_DCHECK(thread_checker_.IsCurrent()); + for (auto* r : list_) + delete r; +} + +StatsCollection::const_iterator StatsCollection::begin() const { + RTC_DCHECK(thread_checker_.IsCurrent()); + return list_.begin(); +} + +StatsCollection::const_iterator StatsCollection::end() const { + RTC_DCHECK(thread_checker_.IsCurrent()); + return list_.end(); +} + +size_t StatsCollection::size() const { + RTC_DCHECK(thread_checker_.IsCurrent()); + return list_.size(); +} + +StatsReport* StatsCollection::InsertNew(const StatsReport::Id& id) { + RTC_DCHECK(thread_checker_.IsCurrent()); + RTC_DCHECK(Find(id) == nullptr); + StatsReport* report = new StatsReport(id); + list_.push_back(report); + return report; +} + +StatsReport* StatsCollection::FindOrAddNew(const StatsReport::Id& id) { + RTC_DCHECK(thread_checker_.IsCurrent()); + StatsReport* ret = Find(id); + return ret ? ret : InsertNew(id); +} + +StatsReport* StatsCollection::ReplaceOrAddNew(const StatsReport::Id& id) { + RTC_DCHECK(thread_checker_.IsCurrent()); + RTC_DCHECK(id.get()); + Container::iterator it = absl::c_find_if( + list_, + [&id](const StatsReport* r) -> bool { return r->id()->Equals(id); }); + if (it != end()) { + StatsReport* report = new StatsReport((*it)->id()); + delete *it; + *it = report; + return report; + } + return InsertNew(id); +} + +// Looks for a report with the given `id`. If one is not found, null +// will be returned. +StatsReport* StatsCollection::Find(const StatsReport::Id& id) { + RTC_DCHECK(thread_checker_.IsCurrent()); + Container::iterator it = absl::c_find_if( + list_, + [&id](const StatsReport* r) -> bool { return r->id()->Equals(id); }); + return it == list_.end() ? nullptr : *it; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/legacy_stats_types.h b/third_party/libwebrtc/api/legacy_stats_types.h new file mode 100644 index 0000000000..a62e014834 --- /dev/null +++ b/third_party/libwebrtc/api/legacy_stats_types.h @@ -0,0 +1,455 @@ +/* + * Copyright 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. + */ + +// This file contains structures used for retrieving statistics from an ongoing +// libjingle session. + +#ifndef API_LEGACY_STATS_TYPES_H_ +#define API_LEGACY_STATS_TYPES_H_ + +#include <algorithm> +#include <list> +#include <map> +#include <string> +#include <vector> + +#include "api/scoped_refptr.h" +#include "api/sequence_checker.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +class RTC_EXPORT StatsReport { + public: + // Indicates whether a track is for sending or receiving. + // Used in reports for audio/video tracks. + enum Direction { + kSend = 0, + kReceive, + }; + + enum StatsType { + // StatsReport types. + // A StatsReport of `type` = "googSession" contains overall information + // about the thing libjingle calls a session (which may contain one + // or more RTP sessions. + kStatsReportTypeSession, + + // A StatsReport of `type` = "googTransport" contains information + // about a libjingle "transport". + kStatsReportTypeTransport, + + // A StatsReport of `type` = "googComponent" contains information + // about a libjingle "channel" (typically, RTP or RTCP for a transport). + // This is intended to be the same thing as an ICE "Component". + kStatsReportTypeComponent, + + // A StatsReport of `type` = "googCandidatePair" contains information + // about a libjingle "connection" - a single source/destination port pair. + // This is intended to be the same thing as an ICE "candidate pair". + kStatsReportTypeCandidatePair, + + // A StatsReport of `type` = "VideoBWE" is statistics for video Bandwidth + // Estimation, which is global per-session. The `id` field is "bweforvideo" + // (will probably change in the future). + kStatsReportTypeBwe, + + // A StatsReport of `type` = "ssrc" is statistics for a specific rtp stream. + // The `id` field is the SSRC in decimal form of the rtp stream. + kStatsReportTypeSsrc, + + // A StatsReport of `type` = "remoteSsrc" is statistics for a specific + // rtp stream, generated by the remote end of the connection. + kStatsReportTypeRemoteSsrc, + + // A StatsReport of `type` = "googTrack" is statistics for a specific media + // track. The `id` field is the track id. + kStatsReportTypeTrack, + + // A StatsReport of `type` = "localcandidate" or "remotecandidate" is + // attributes on a specific ICE Candidate. It links to its connection pair + // by candidate id. The string value is taken from + // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*. + kStatsReportTypeIceLocalCandidate, + kStatsReportTypeIceRemoteCandidate, + + // A StatsReport of `type` = "googCertificate" contains an SSL certificate + // transmitted by one of the endpoints of this connection. The `id` is + // controlled by the fingerprint, and is used to identify the certificate in + // the Channel stats (as "googLocalCertificateId" or + // "googRemoteCertificateId") and in any child certificates (as + // "googIssuerId"). + kStatsReportTypeCertificate, + + // A StatsReport of `type` = "datachannel" with statistics for a + // particular DataChannel. + kStatsReportTypeDataChannel, + }; + + enum StatsValueName { + kStatsValueNameActiveConnection, + kStatsValueNameAecDivergentFilterFraction, + kStatsValueNameAudioInputLevel, + kStatsValueNameAudioOutputLevel, + kStatsValueNameBytesReceived, + kStatsValueNameBytesSent, + kStatsValueNameCodecImplementationName, + kStatsValueNameConcealedSamples, + kStatsValueNameConcealmentEvents, + kStatsValueNameDataChannelId, + kStatsValueNameFramesDecoded, + kStatsValueNameFramesEncoded, + kStatsValueNameJitterBufferDelay, + kStatsValueNameMediaType, + kStatsValueNamePacketsLost, + kStatsValueNamePacketsReceived, + kStatsValueNamePacketsSent, + kStatsValueNameProtocol, + kStatsValueNameQpSum, + kStatsValueNameReceiving, + kStatsValueNameSelectedCandidatePairId, + kStatsValueNameSsrc, + kStatsValueNameState, + kStatsValueNameTotalAudioEnergy, + kStatsValueNameTotalSamplesDuration, + kStatsValueNameTotalSamplesReceived, + kStatsValueNameTransportId, + kStatsValueNameSentPingRequestsTotal, + kStatsValueNameSentPingRequestsBeforeFirstResponse, + kStatsValueNameSentPingResponses, + kStatsValueNameRecvPingRequests, + kStatsValueNameRecvPingResponses, + kStatsValueNameSentStunKeepaliveRequests, + kStatsValueNameRecvStunKeepaliveResponses, + kStatsValueNameStunKeepaliveRttTotal, + kStatsValueNameStunKeepaliveRttSquaredTotal, + + // Internal StatsValue names. + kStatsValueNameAccelerateRate, + kStatsValueNameActualEncBitrate, + kStatsValueNameAdaptationChanges, + kStatsValueNameAvailableReceiveBandwidth, + kStatsValueNameAvailableSendBandwidth, + kStatsValueNameAvgEncodeMs, + kStatsValueNameBandwidthLimitedResolution, + kStatsValueNameBucketDelay, + kStatsValueNameCaptureStartNtpTimeMs, + kStatsValueNameCandidateIPAddress, + kStatsValueNameCandidateNetworkType, + kStatsValueNameCandidatePortNumber, + kStatsValueNameCandidatePriority, + kStatsValueNameCandidateTransportType, + kStatsValueNameCandidateType, + kStatsValueNameChannelId, + kStatsValueNameCodecName, + kStatsValueNameComponent, + kStatsValueNameContentName, + kStatsValueNameContentType, + kStatsValueNameCpuLimitedResolution, + kStatsValueNameCurrentDelayMs, + kStatsValueNameDecodeMs, + kStatsValueNameDecodingCNG, + kStatsValueNameDecodingCTN, + kStatsValueNameDecodingCTSG, + kStatsValueNameDecodingMutedOutput, + kStatsValueNameDecodingNormal, + kStatsValueNameDecodingPLC, + kStatsValueNameDecodingCodecPLC, + kStatsValueNameDecodingPLCCNG, + kStatsValueNameDer, + kStatsValueNameDtlsCipher, + kStatsValueNameEchoDelayMedian, + kStatsValueNameEchoDelayStdDev, + kStatsValueNameEchoReturnLoss, + kStatsValueNameEchoReturnLossEnhancement, + kStatsValueNameEncodeUsagePercent, + kStatsValueNameExpandRate, + kStatsValueNameFingerprint, + kStatsValueNameFingerprintAlgorithm, + kStatsValueNameFirsReceived, + kStatsValueNameFirsSent, + kStatsValueNameFirstFrameReceivedToDecodedMs, + kStatsValueNameFrameHeightInput, + kStatsValueNameFrameHeightReceived, + kStatsValueNameFrameHeightSent, + kStatsValueNameFrameRateDecoded, + kStatsValueNameFrameRateInput, + kStatsValueNameFrameRateOutput, + kStatsValueNameFrameRateReceived, + kStatsValueNameFrameRateSent, + kStatsValueNameFrameWidthInput, + kStatsValueNameFrameWidthReceived, + kStatsValueNameFrameWidthSent, + kStatsValueNameHasEnteredLowResolution, + kStatsValueNameHugeFramesSent, + kStatsValueNameInitiator, + kStatsValueNameInterframeDelayMaxMs, // Max over last 10 seconds. + kStatsValueNameIssuerId, + kStatsValueNameJitterBufferMs, + kStatsValueNameJitterReceived, + kStatsValueNameLabel, + kStatsValueNameLocalAddress, + kStatsValueNameLocalCandidateId, + kStatsValueNameLocalCandidateType, + kStatsValueNameLocalCertificateId, + kStatsValueNameMaxDecodeMs, + kStatsValueNameMinPlayoutDelayMs, + kStatsValueNameNacksReceived, + kStatsValueNameNacksSent, + kStatsValueNamePlisReceived, + kStatsValueNamePlisSent, + kStatsValueNamePreemptiveExpandRate, + kStatsValueNamePreferredJitterBufferMs, + kStatsValueNameRemoteAddress, + kStatsValueNameRemoteCandidateId, + kStatsValueNameRemoteCandidateType, + kStatsValueNameRemoteCertificateId, + kStatsValueNameRenderDelayMs, + kStatsValueNameResidualEchoLikelihood, + kStatsValueNameResidualEchoLikelihoodRecentMax, + kStatsValueNameAnaBitrateActionCounter, + kStatsValueNameAnaChannelActionCounter, + kStatsValueNameAnaDtxActionCounter, + kStatsValueNameAnaFecActionCounter, + kStatsValueNameAnaFrameLengthIncreaseCounter, + kStatsValueNameAnaFrameLengthDecreaseCounter, + kStatsValueNameAnaUplinkPacketLossFraction, + kStatsValueNameRetransmitBitrate, + kStatsValueNameRtt, + kStatsValueNameSecondaryDecodedRate, + kStatsValueNameSecondaryDiscardedRate, + kStatsValueNameSendPacketsDiscarded, + kStatsValueNameSpeechExpandRate, + kStatsValueNameSrtpCipher, + kStatsValueNameTargetDelayMs, + kStatsValueNameTargetEncBitrate, + kStatsValueNameTimingFrameInfo, // Result of `TimingFrameInfo::ToString` + kStatsValueNameTrackId, + kStatsValueNameTransmitBitrate, + kStatsValueNameTransportType, + kStatsValueNameWritable, + kStatsValueNameAudioDeviceUnderrunCounter, + kStatsValueNameLocalCandidateRelayProtocol, + }; + + class RTC_EXPORT IdBase : public rtc::RefCountInterface { + public: + ~IdBase() override; + StatsType type() const; + + // Users of IdBase will be using the Id typedef, which is compatible with + // this Equals() function. It simply calls the protected (and overridden) + // Equals() method. + bool Equals(const rtc::scoped_refptr<IdBase>& other) const { + return Equals(*other.get()); + } + + virtual std::string ToString() const = 0; + + protected: + // Protected since users of the IdBase type will be using the Id typedef. + virtual bool Equals(const IdBase& other) const; + + explicit IdBase(StatsType type); // Only meant for derived classes. + const StatsType type_; + + static const char kSeparator = '_'; + }; + + typedef rtc::scoped_refptr<IdBase> Id; + + struct RTC_EXPORT Value { + enum Type { + kInt, // int. + kInt64, // int64_t. + kFloat, // float. + kString, // std::string + kStaticString, // const char*. + kBool, // bool. + kId, // Id. + }; + + Value(StatsValueName name, int64_t value, Type int_type); + Value(StatsValueName name, float f); + Value(StatsValueName name, const std::string& value); + Value(StatsValueName name, const char* value); + Value(StatsValueName name, bool b); + Value(StatsValueName name, const Id& value); + + ~Value(); + + Value(const Value&) = delete; + Value& operator=(const Value&) = delete; + + // Support ref counting. Note that for performance reasons, we + // don't use thread safe operations. Therefore, all operations + // affecting the ref count (in practice, creation and copying of + // the Values mapping) must occur on webrtc's signalling thread. + int AddRef() const { + RTC_DCHECK_RUN_ON(&thread_checker_); + return ++ref_count_; + } + int Release() const { + RTC_DCHECK_RUN_ON(&thread_checker_); + int count = --ref_count_; + if (!count) + delete this; + return count; + } + + // TODO(tommi): This compares name as well as value... + // I think we should only need to compare the value part and + // move the name part into a hash map. + bool Equals(const Value& other) const; + + // Comparison operators. Return true iff the current instance is of the + // correct type and holds the same value. No conversion is performed so + // a string value of "123" is not equal to an int value of 123 and an int + // value of 123 is not equal to a float value of 123.0f. + // One exception to this is that types kInt and kInt64 can be compared and + // kString and kStaticString too. + bool operator==(const std::string& value) const; + bool operator==(const char* value) const; + bool operator==(int64_t value) const; + bool operator==(bool value) const; + bool operator==(float value) const; + bool operator==(const Id& value) const; + + // Getters that allow getting the native value directly. + // The caller must know the type beforehand or else hit a check. + int int_val() const; + int64_t int64_val() const; + float float_val() const; + const char* static_string_val() const; + const std::string& string_val() const; + bool bool_val() const; + const Id& id_val() const; + + // Returns the string representation of `name`. + const char* display_name() const; + + // Converts the native value to a string representation of the value. + std::string ToString() const; + + Type type() const { return type_; } + + // TODO(tommi): Move `name` and `display_name` out of the Value struct. + const StatsValueName name; + + private: + webrtc::SequenceChecker thread_checker_; + mutable int ref_count_ RTC_GUARDED_BY(thread_checker_) = 0; + + const Type type_; + // TODO(tommi): Use C++ 11 union and make value_ const. + union InternalType { + int int_; + int64_t int64_; + float float_; + bool bool_; + std::string* string_; + const char* static_string_; + Id* id_; + } value_; + }; + + typedef rtc::scoped_refptr<Value> ValuePtr; + typedef std::map<StatsValueName, ValuePtr> Values; + + // Ownership of `id` is passed to `this`. + explicit StatsReport(const Id& id); + ~StatsReport(); + + StatsReport(const StatsReport&) = delete; + StatsReport& operator=(const StatsReport&) = delete; + + // Factory functions for various types of stats IDs. + static Id NewBandwidthEstimationId(); + static Id NewTypedId(StatsType type, const std::string& id); + static Id NewTypedIntId(StatsType type, int id); + static Id NewIdWithDirection(StatsType type, + const std::string& id, + Direction direction); + static Id NewCandidateId(bool local, const std::string& id); + static Id NewComponentId(const std::string& content_name, int component); + static Id NewCandidatePairId(const std::string& content_name, + int component, + int index); + + const Id& id() const { return id_; } + StatsType type() const { return id_->type(); } + double timestamp() const { return timestamp_; } + void set_timestamp(double t) { timestamp_ = t; } + bool empty() const { return values_.empty(); } + const Values& values() const { return values_; } + + const char* TypeToString() const; + + void AddString(StatsValueName name, const std::string& value); + void AddString(StatsValueName name, const char* value); + void AddInt64(StatsValueName name, int64_t value); + void AddInt(StatsValueName name, int value); + void AddFloat(StatsValueName name, float value); + void AddBoolean(StatsValueName name, bool value); + void AddId(StatsValueName name, const Id& value); + + const Value* FindValue(StatsValueName name) const; + + private: + // The unique identifier for this object. + // This is used as a key for this report in ordered containers, + // so it must never be changed. + const Id id_; + double timestamp_; // Time since 1970-01-01T00:00:00Z in milliseconds. + Values values_; +}; + +// Typedef for an array of const StatsReport pointers. +// Ownership of the pointers held by this implementation is assumed to lie +// elsewhere and lifetime guarantees are made by the implementation that uses +// this type. In the StatsCollector, object ownership lies with the +// StatsCollection class. +typedef std::vector<const StatsReport*> StatsReports; + +// A map from the report id to the report. +// This class wraps an STL container and provides a limited set of +// functionality in order to keep things simple. +class StatsCollection { + public: + StatsCollection(); + ~StatsCollection(); + + typedef std::list<StatsReport*> Container; + typedef Container::iterator iterator; + typedef Container::const_iterator const_iterator; + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + + // Creates a new report object with `id` that does not already + // exist in the list of reports. + StatsReport* InsertNew(const StatsReport::Id& id); + StatsReport* FindOrAddNew(const StatsReport::Id& id); + StatsReport* ReplaceOrAddNew(const StatsReport::Id& id); + + // Looks for a report with the given `id`. If one is not found, null + // will be returned. + StatsReport* Find(const StatsReport::Id& id); + + private: + Container list_; + webrtc::SequenceChecker thread_checker_; +}; + +} // namespace webrtc + +#endif // API_LEGACY_STATS_TYPES_H_ diff --git a/third_party/libwebrtc/api/libjingle_logging_api_gn/moz.build b/third_party/libwebrtc/api/libjingle_logging_api_gn/moz.build new file mode 100644 index 0000000000..5e41eca1b7 --- /dev/null +++ b/third_party/libwebrtc/api/libjingle_logging_api_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("jingle_logging_api_gn") diff --git a/third_party/libwebrtc/api/libjingle_peerconnection_api_gn/moz.build b/third_party/libwebrtc/api/libjingle_peerconnection_api_gn/moz.build new file mode 100644 index 0000000000..579b7f164b --- /dev/null +++ b/third_party/libwebrtc/api/libjingle_peerconnection_api_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("jingle_peerconnection_api_gn") diff --git a/third_party/libwebrtc/api/make_ref_counted.h b/third_party/libwebrtc/api/make_ref_counted.h new file mode 100644 index 0000000000..cc8871784a --- /dev/null +++ b/third_party/libwebrtc/api/make_ref_counted.h @@ -0,0 +1,119 @@ +/* + * Copyright 2022 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 API_MAKE_REF_COUNTED_H_ +#define API_MAKE_REF_COUNTED_H_ + +#include <utility> + +#include "rtc_base/ref_counted_object.h" + +namespace rtc { + +namespace webrtc_make_ref_counted_internal { +// Determines if the given class has AddRef and Release methods. +template <typename T> +class HasAddRefAndRelease { + private: + template <typename C, + decltype(std::declval<C>().AddRef())* = nullptr, + decltype(std::declval<C>().Release())* = nullptr> + static int Test(int); + template <typename> + static char Test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(Test<T>(0)), int>; +}; +} // namespace webrtc_make_ref_counted_internal + +// General utilities for constructing a reference counted class and the +// appropriate reference count implementation for that class. +// +// These utilities select either the `RefCountedObject` implementation or +// `FinalRefCountedObject` depending on whether the to-be-shared class is +// derived from the RefCountInterface interface or not (respectively). + +// `make_ref_counted`: +// +// Use this when you want to construct a reference counted object of type T and +// get a `scoped_refptr<>` back. Example: +// +// auto p = make_ref_counted<Foo>("bar", 123); +// +// For a class that inherits from RefCountInterface, this is equivalent to: +// +// auto p = scoped_refptr<Foo>(new RefCountedObject<Foo>("bar", 123)); +// +// If the class does not inherit from RefCountInterface, but does have +// AddRef/Release methods (so a T* is convertible to rtc::scoped_refptr), this +// is equivalent to just +// +// auto p = scoped_refptr<Foo>(new Foo("bar", 123)); +// +// Otherwise, the example is equivalent to: +// +// auto p = scoped_refptr<FinalRefCountedObject<Foo>>( +// new FinalRefCountedObject<Foo>("bar", 123)); +// +// In these cases, `make_ref_counted` reduces the amount of boilerplate code but +// also helps with the most commonly intended usage of RefCountedObject whereby +// methods for reference counting, are virtual and designed to satisfy the need +// of an interface. When such a need does not exist, it is more efficient to use +// the `FinalRefCountedObject` template, which does not add the vtable overhead. +// +// Note that in some cases, using RefCountedObject directly may still be what's +// needed. + +// `make_ref_counted` for abstract classes that are convertible to +// RefCountInterface. The is_abstract requirement rejects classes that inherit +// both RefCountInterface and RefCounted object, which is a a discouraged +// pattern, and would result in double inheritance of RefCountedObject if this +// template was applied. +template < + typename T, + typename... Args, + typename std::enable_if<std::is_convertible_v<T*, RefCountInterface*> && + std::is_abstract_v<T>, + T>::type* = nullptr> +scoped_refptr<T> make_ref_counted(Args&&... args) { + return scoped_refptr<T>(new RefCountedObject<T>(std::forward<Args>(args)...)); +} + +// `make_ref_counted` for complete classes that are not convertible to +// RefCountInterface and already carry a ref count. +template < + typename T, + typename... Args, + typename std::enable_if< + !std::is_convertible_v<T*, RefCountInterface*> && + webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value, + T>::type* = nullptr> +scoped_refptr<T> make_ref_counted(Args&&... args) { + return scoped_refptr<T>(new T(std::forward<Args>(args)...)); +} + +// `make_ref_counted` for complete classes that are not convertible to +// RefCountInterface and have no ref count of their own. +template < + typename T, + typename... Args, + typename std::enable_if< + !std::is_convertible_v<T*, RefCountInterface*> && + !webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value, + + T>::type* = nullptr> +scoped_refptr<FinalRefCountedObject<T>> make_ref_counted(Args&&... args) { + return scoped_refptr<FinalRefCountedObject<T>>( + new FinalRefCountedObject<T>(std::forward<Args>(args)...)); +} + +} // namespace rtc + +#endif // API_MAKE_REF_COUNTED_H_ diff --git a/third_party/libwebrtc/api/make_ref_counted_gn/moz.build b/third_party/libwebrtc/api/make_ref_counted_gn/moz.build new file mode 100644 index 0000000000..8b3a500acb --- /dev/null +++ b/third_party/libwebrtc/api/make_ref_counted_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("make_ref_counted_gn") diff --git a/third_party/libwebrtc/api/media_stream_interface.cc b/third_party/libwebrtc/api/media_stream_interface.cc new file mode 100644 index 0000000000..e07907917b --- /dev/null +++ b/third_party/libwebrtc/api/media_stream_interface.cc @@ -0,0 +1,38 @@ +/* + * Copyright 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. + */ + +#include "api/media_stream_interface.h" +#include "api/media_types.h" + +namespace webrtc { + +const char* const MediaStreamTrackInterface::kVideoKind = + cricket::kMediaTypeVideo; +const char* const MediaStreamTrackInterface::kAudioKind = + cricket::kMediaTypeAudio; + +VideoTrackInterface::ContentHint VideoTrackInterface::content_hint() const { + return ContentHint::kNone; +} + +bool AudioTrackInterface::GetSignalLevel(int* level) { + return false; +} + +rtc::scoped_refptr<AudioProcessorInterface> +AudioTrackInterface::GetAudioProcessor() { + return nullptr; +} + +const cricket::AudioOptions AudioSourceInterface::options() const { + return {}; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/media_stream_interface.h b/third_party/libwebrtc/api/media_stream_interface.h new file mode 100644 index 0000000000..9d336739e4 --- /dev/null +++ b/third_party/libwebrtc/api/media_stream_interface.h @@ -0,0 +1,376 @@ +/* + * Copyright 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. + */ + +// This file contains interfaces for MediaStream, MediaTrack and MediaSource. +// These interfaces are used for implementing MediaStream and MediaTrack as +// defined in http://dev.w3.org/2011/webrtc/editor/webrtc.html#stream-api. These +// interfaces must be used only with PeerConnection. + +#ifndef API_MEDIA_STREAM_INTERFACE_H_ +#define API_MEDIA_STREAM_INTERFACE_H_ + +#include <stddef.h> + +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_options.h" +#include "api/scoped_refptr.h" +#include "api/video/recordable_encoded_frame.h" +#include "api/video/video_frame.h" +#include "api/video/video_sink_interface.h" +#include "api/video/video_source_interface.h" +#include "api/video_track_source_constraints.h" +#include "modules/audio_processing/include/audio_processing_statistics.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Generic observer interface. +class ObserverInterface { + public: + virtual void OnChanged() = 0; + + protected: + virtual ~ObserverInterface() {} +}; + +class NotifierInterface { + public: + virtual void RegisterObserver(ObserverInterface* observer) = 0; + virtual void UnregisterObserver(ObserverInterface* observer) = 0; + + virtual ~NotifierInterface() {} +}; + +// Base class for sources. A MediaStreamTrack has an underlying source that +// provides media. A source can be shared by multiple tracks. +class RTC_EXPORT MediaSourceInterface : public rtc::RefCountInterface, + public NotifierInterface { + public: + enum SourceState { kInitializing, kLive, kEnded, kMuted }; + + virtual SourceState state() const = 0; + + virtual bool remote() const = 0; + + protected: + ~MediaSourceInterface() override = default; +}; + +// C++ version of MediaStreamTrack. +// See: https://www.w3.org/TR/mediacapture-streams/#mediastreamtrack +class RTC_EXPORT MediaStreamTrackInterface : public rtc::RefCountInterface, + public NotifierInterface { + public: + enum TrackState { + kLive, + kEnded, + }; + + static const char* const kAudioKind; + static const char* const kVideoKind; + + // The kind() method must return kAudioKind only if the object is a + // subclass of AudioTrackInterface, and kVideoKind only if the + // object is a subclass of VideoTrackInterface. It is typically used + // to protect a static_cast<> to the corresponding subclass. + virtual std::string kind() const = 0; + + // Track identifier. + virtual std::string id() const = 0; + + // A disabled track will produce silence (if audio) or black frames (if + // video). Can be disabled and re-enabled. + virtual bool enabled() const = 0; + virtual bool set_enabled(bool enable) = 0; + + // Live or ended. A track will never be live again after becoming ended. + virtual TrackState state() const = 0; + + protected: + ~MediaStreamTrackInterface() override = default; +}; + +// VideoTrackSourceInterface is a reference counted source used for +// VideoTracks. The same source can be used by multiple VideoTracks. +// VideoTrackSourceInterface is designed to be invoked on the signaling thread +// except for rtc::VideoSourceInterface<VideoFrame> methods that will be invoked +// on the worker thread via a VideoTrack. A custom implementation of a source +// can inherit AdaptedVideoTrackSource instead of directly implementing this +// interface. +class VideoTrackSourceInterface : public MediaSourceInterface, + public rtc::VideoSourceInterface<VideoFrame> { + public: + struct Stats { + // Original size of captured frame, before video adaptation. + int input_width; + int input_height; + }; + + // Indicates that parameters suitable for screencasts should be automatically + // applied to RtpSenders. + // TODO(perkj): Remove these once all known applications have moved to + // explicitly setting suitable parameters for screencasts and don't need this + // implicit behavior. + virtual bool is_screencast() const = 0; + + // Indicates that the encoder should denoise video before encoding it. + // If it is not set, the default configuration is used which is different + // depending on video codec. + // TODO(perkj): Remove this once denoising is done by the source, and not by + // the encoder. + virtual absl::optional<bool> needs_denoising() const = 0; + + // Returns false if no stats are available, e.g, for a remote source, or a + // source which has not seen its first frame yet. + // + // Implementation should avoid blocking. + virtual bool GetStats(Stats* stats) = 0; + + // Returns true if encoded output can be enabled in the source. + virtual bool SupportsEncodedOutput() const = 0; + + // Reliably cause a key frame to be generated in encoded output. + // TODO(bugs.webrtc.org/11115): find optimal naming. + virtual void GenerateKeyFrame() = 0; + + // Add an encoded video sink to the source and additionally cause + // a key frame to be generated from the source. The sink will be + // invoked from a decoder queue. + virtual void AddEncodedSink( + rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) = 0; + + // Removes an encoded video sink from the source. + virtual void RemoveEncodedSink( + rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) = 0; + + // Notify about constraints set on the source. The information eventually gets + // routed to attached sinks via VideoSinkInterface<>::OnConstraintsChanged. + // The call is expected to happen on the network thread. + // TODO(crbug/1255737): make pure virtual once downstream project adapts. + virtual void ProcessConstraints( + const webrtc::VideoTrackSourceConstraints& constraints) {} + + protected: + ~VideoTrackSourceInterface() override = default; +}; + +// VideoTrackInterface is designed to be invoked on the signaling thread except +// for rtc::VideoSourceInterface<VideoFrame> methods that must be invoked +// on the worker thread. +// PeerConnectionFactory::CreateVideoTrack can be used for creating a VideoTrack +// that ensures thread safety and that all methods are called on the right +// thread. +class RTC_EXPORT VideoTrackInterface + : public MediaStreamTrackInterface, + public rtc::VideoSourceInterface<VideoFrame> { + public: + // Video track content hint, used to override the source is_screencast + // property. + // See https://crbug.com/653531 and https://w3c.github.io/mst-content-hint. + enum class ContentHint { kNone, kFluid, kDetailed, kText }; + + // Register a video sink for this track. Used to connect the track to the + // underlying video engine. + void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink, + const rtc::VideoSinkWants& wants) override {} + void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {} + + virtual VideoTrackSourceInterface* GetSource() const = 0; + + virtual ContentHint content_hint() const; + virtual void set_content_hint(ContentHint hint) {} + + protected: + ~VideoTrackInterface() override = default; +}; + +// Interface for receiving audio data from a AudioTrack. +class AudioTrackSinkInterface { + public: + virtual void OnData(const void* audio_data, + int bits_per_sample, + int sample_rate, + size_t number_of_channels, + size_t number_of_frames) { + RTC_DCHECK_NOTREACHED() << "This method must be overridden, or not used."; + } + + // In this method, `absolute_capture_timestamp_ms`, when available, is + // supposed to deliver the timestamp when this audio frame was originally + // captured. This timestamp MUST be based on the same clock as + // rtc::TimeMillis(). + virtual void OnData(const void* audio_data, + int bits_per_sample, + int sample_rate, + size_t number_of_channels, + size_t number_of_frames, + absl::optional<int64_t> absolute_capture_timestamp_ms) { + // TODO(bugs.webrtc.org/10739): Deprecate the old OnData and make this one + // pure virtual. + return OnData(audio_data, bits_per_sample, sample_rate, number_of_channels, + number_of_frames); + } + + // Returns the number of channels encoded by the sink. This can be less than + // the number_of_channels if down-mixing occur. A value of -1 means an unknown + // number. + virtual int NumPreferredChannels() const { return -1; } + + protected: + virtual ~AudioTrackSinkInterface() {} +}; + +// AudioSourceInterface is a reference counted source used for AudioTracks. +// The same source can be used by multiple AudioTracks. +class RTC_EXPORT AudioSourceInterface : public MediaSourceInterface { + public: + class AudioObserver { + public: + virtual void OnSetVolume(double volume) = 0; + + protected: + virtual ~AudioObserver() {} + }; + + // TODO(deadbeef): Makes all the interfaces pure virtual after they're + // implemented in chromium. + + // Sets the volume of the source. `volume` is in the range of [0, 10]. + // TODO(tommi): This method should be on the track and ideally volume should + // be applied in the track in a way that does not affect clones of the track. + virtual void SetVolume(double volume) {} + + // Registers/unregisters observers to the audio source. + virtual void RegisterAudioObserver(AudioObserver* observer) {} + virtual void UnregisterAudioObserver(AudioObserver* observer) {} + + // TODO(tommi): Make pure virtual. + virtual void AddSink(AudioTrackSinkInterface* sink) {} + virtual void RemoveSink(AudioTrackSinkInterface* sink) {} + + // Returns options for the AudioSource. + // (for some of the settings this approach is broken, e.g. setting + // audio network adaptation on the source is the wrong layer of abstraction). + virtual const cricket::AudioOptions options() const; +}; + +// Interface of the audio processor used by the audio track to collect +// statistics. +class AudioProcessorInterface : public rtc::RefCountInterface { + public: + struct AudioProcessorStatistics { + bool typing_noise_detected = false; + AudioProcessingStats apm_statistics; + }; + + // Get audio processor statistics. The `has_remote_tracks` argument should be + // set if there are active remote tracks (this would usually be true during + // a call). If there are no remote tracks some of the stats will not be set by + // the AudioProcessor, because they only make sense if there is at least one + // remote track. + virtual AudioProcessorStatistics GetStats(bool has_remote_tracks) = 0; + + protected: + ~AudioProcessorInterface() override = default; +}; + +class RTC_EXPORT AudioTrackInterface : public MediaStreamTrackInterface { + public: + // TODO(deadbeef): Figure out if the following interface should be const or + // not. + virtual AudioSourceInterface* GetSource() const = 0; + + // Add/Remove a sink that will receive the audio data from the track. + virtual void AddSink(AudioTrackSinkInterface* sink) = 0; + virtual void RemoveSink(AudioTrackSinkInterface* sink) = 0; + + // Get the signal level from the audio track. + // Return true on success, otherwise false. + // TODO(deadbeef): Change the interface to int GetSignalLevel() and pure + // virtual after it's implemented in chromium. + virtual bool GetSignalLevel(int* level); + + // Get the audio processor used by the audio track. Return null if the track + // does not have any processor. + // TODO(deadbeef): Make the interface pure virtual. + virtual rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor(); + + protected: + ~AudioTrackInterface() override = default; +}; + +typedef std::vector<rtc::scoped_refptr<AudioTrackInterface> > AudioTrackVector; +typedef std::vector<rtc::scoped_refptr<VideoTrackInterface> > VideoTrackVector; + +// C++ version of https://www.w3.org/TR/mediacapture-streams/#mediastream. +// +// A major difference is that remote audio/video tracks (received by a +// PeerConnection/RtpReceiver) are not synchronized simply by adding them to +// the same stream; a session description with the correct "a=msid" attributes +// must be pushed down. +// +// Thus, this interface acts as simply a container for tracks. +class MediaStreamInterface : public rtc::RefCountInterface, + public NotifierInterface { + public: + virtual std::string id() const = 0; + + virtual AudioTrackVector GetAudioTracks() = 0; + virtual VideoTrackVector GetVideoTracks() = 0; + virtual rtc::scoped_refptr<AudioTrackInterface> FindAudioTrack( + const std::string& track_id) = 0; + virtual rtc::scoped_refptr<VideoTrackInterface> FindVideoTrack( + const std::string& track_id) = 0; + + // Takes ownership of added tracks. + // Note: Default implementations are for avoiding link time errors in + // implementations that mock this API. + // TODO(bugs.webrtc.org/13980): Remove default implementations. + virtual bool AddTrack(rtc::scoped_refptr<AudioTrackInterface> track) { + RTC_CHECK_NOTREACHED(); + } + virtual bool AddTrack(rtc::scoped_refptr<VideoTrackInterface> track) { + RTC_CHECK_NOTREACHED(); + } + virtual bool RemoveTrack(rtc::scoped_refptr<AudioTrackInterface> track) { + RTC_CHECK_NOTREACHED(); + } + virtual bool RemoveTrack(rtc::scoped_refptr<VideoTrackInterface> track) { + RTC_CHECK_NOTREACHED(); + } + // Deprecated: Should use scoped_refptr versions rather than pointers. + [[deprecated("Pass a scoped_refptr")]] virtual bool AddTrack( + AudioTrackInterface* track) { + return AddTrack(rtc::scoped_refptr<AudioTrackInterface>(track)); + } + [[deprecated("Pass a scoped_refptr")]] virtual bool AddTrack( + VideoTrackInterface* track) { + return AddTrack(rtc::scoped_refptr<VideoTrackInterface>(track)); + } + [[deprecated("Pass a scoped_refptr")]] virtual bool RemoveTrack( + AudioTrackInterface* track) { + return RemoveTrack(rtc::scoped_refptr<AudioTrackInterface>(track)); + } + [[deprecated("Pass a scoped_refptr")]] virtual bool RemoveTrack( + VideoTrackInterface* track) { + return RemoveTrack(rtc::scoped_refptr<VideoTrackInterface>(track)); + } + + protected: + ~MediaStreamInterface() override = default; +}; + +} // namespace webrtc + +#endif // API_MEDIA_STREAM_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/media_stream_interface_gn/moz.build b/third_party/libwebrtc/api/media_stream_interface_gn/moz.build new file mode 100644 index 0000000000..b80f10168f --- /dev/null +++ b/third_party/libwebrtc/api/media_stream_interface_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/media_stream_interface.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("media_stream_interface_gn") diff --git a/third_party/libwebrtc/api/media_stream_track.h b/third_party/libwebrtc/api/media_stream_track.h new file mode 100644 index 0000000000..316dd788ef --- /dev/null +++ b/third_party/libwebrtc/api/media_stream_track.h @@ -0,0 +1,64 @@ +/* + * Copyright 2011 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 API_MEDIA_STREAM_TRACK_H_ +#define API_MEDIA_STREAM_TRACK_H_ + +#include <string> + +#include "absl/strings/string_view.h" +#include "api/media_stream_interface.h" +#include "api/notifier.h" + +namespace webrtc { + +// MediaTrack implements the interface common to AudioTrackInterface and +// VideoTrackInterface. +template <typename T> +class MediaStreamTrack : public Notifier<T> { + public: + typedef typename T::TrackState TypedTrackState; + + std::string id() const override { return id_; } + MediaStreamTrackInterface::TrackState state() const override { + return state_; + } + bool enabled() const override { return enabled_; } + bool set_enabled(bool enable) override { + bool fire_on_change = (enable != enabled_); + enabled_ = enable; + if (fire_on_change) { + Notifier<T>::FireOnChanged(); + } + return fire_on_change; + } + void set_ended() { set_state(MediaStreamTrackInterface::TrackState::kEnded); } + + protected: + explicit MediaStreamTrack(absl::string_view id) + : enabled_(true), id_(id), state_(MediaStreamTrackInterface::kLive) {} + + bool set_state(MediaStreamTrackInterface::TrackState new_state) { + bool fire_on_change = (state_ != new_state); + state_ = new_state; + if (fire_on_change) + Notifier<T>::FireOnChanged(); + return true; + } + + private: + bool enabled_; + const std::string id_; + MediaStreamTrackInterface::TrackState state_; +}; + +} // namespace webrtc + +#endif // API_MEDIA_STREAM_TRACK_H_ diff --git a/third_party/libwebrtc/api/media_types.cc b/third_party/libwebrtc/api/media_types.cc new file mode 100644 index 0000000000..5c7d55b876 --- /dev/null +++ b/third_party/libwebrtc/api/media_types.cc @@ -0,0 +1,37 @@ +/* + * Copyright 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. + */ + +#include "api/media_types.h" + +#include "rtc_base/checks.h" + +namespace cricket { + +const char kMediaTypeVideo[] = "video"; +const char kMediaTypeAudio[] = "audio"; +const char kMediaTypeData[] = "data"; + +std::string MediaTypeToString(MediaType type) { + switch (type) { + case MEDIA_TYPE_AUDIO: + return kMediaTypeAudio; + case MEDIA_TYPE_VIDEO: + return kMediaTypeVideo; + case MEDIA_TYPE_DATA: + return kMediaTypeData; + case MEDIA_TYPE_UNSUPPORTED: + // Unsupported media stores the m=<mediatype> differently. + RTC_DCHECK_NOTREACHED(); + return ""; + } + RTC_CHECK_NOTREACHED(); +} + +} // namespace cricket diff --git a/third_party/libwebrtc/api/media_types.h b/third_party/libwebrtc/api/media_types.h new file mode 100644 index 0000000000..b2ff08c0c3 --- /dev/null +++ b/third_party/libwebrtc/api/media_types.h @@ -0,0 +1,44 @@ +/* + * Copyright 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. + */ + +#ifndef API_MEDIA_TYPES_H_ +#define API_MEDIA_TYPES_H_ + +#include <string> + +#include "rtc_base/system/rtc_export.h" + +// The cricket and webrtc have separate definitions for what a media type is. +// They're not compatible. Watch out for this. + +namespace cricket { + +enum MediaType { + MEDIA_TYPE_AUDIO, + MEDIA_TYPE_VIDEO, + MEDIA_TYPE_DATA, + MEDIA_TYPE_UNSUPPORTED +}; + +extern const char kMediaTypeAudio[]; +extern const char kMediaTypeVideo[]; +extern const char kMediaTypeData[]; + +RTC_EXPORT std::string MediaTypeToString(MediaType type); + +} // namespace cricket + +namespace webrtc { + +enum class MediaType { ANY, AUDIO, VIDEO, DATA }; + +} // namespace webrtc + +#endif // API_MEDIA_TYPES_H_ diff --git a/third_party/libwebrtc/api/metronome/BUILD.gn b/third_party/libwebrtc/api/metronome/BUILD.gn new file mode 100644 index 0000000000..3d3d876df0 --- /dev/null +++ b/third_party/libwebrtc/api/metronome/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright (c) 2022 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") + +rtc_source_set("metronome") { + visibility = [ "*" ] + sources = [ "metronome.h" ] + deps = [ + "../../rtc_base/system:rtc_export", + "../task_queue", + "../units:time_delta", + ] +} diff --git a/third_party/libwebrtc/api/metronome/metronome.cc b/third_party/libwebrtc/api/metronome/metronome.cc new file mode 100644 index 0000000000..8d74f928a0 --- /dev/null +++ b/third_party/libwebrtc/api/metronome/metronome.cc @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 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 "api/metronome/metronome.h" + +namespace webrtc { + +// TODO(crbug.com/1381982): Remove outdated methods. +void Metronome::AddListener(TickListener* listener) {} +void Metronome::RemoveListener(TickListener* listener) {} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/metronome/metronome.h b/third_party/libwebrtc/api/metronome/metronome.h new file mode 100644 index 0000000000..a312b1c862 --- /dev/null +++ b/third_party/libwebrtc/api/metronome/metronome.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 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 API_METRONOME_METRONOME_H_ +#define API_METRONOME_METRONOME_H_ + +#include "api/task_queue/task_queue_base.h" +#include "api/units/time_delta.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// The Metronome posts OnTick() calls requested with RequestCallOnNextTick. +// The API is designed to be fully used from a single task queue. Scheduled +// callbacks are executed on the same sequence as they were requested on. There +// are no features implemented for cancellation. When that's needed, use e.g. +// ScopedTaskSafety from the client. +// +// The metronome concept is still under experimentation, and may not be availble +// in all platforms or applications. See https://crbug.com/1253787 for more +// details. +// +// Metronome implementations must be thread-compatible. +class RTC_EXPORT Metronome { + public: + virtual ~Metronome() = default; + + // Requests a call to `callback` on the next tick. Scheduled callbacks are + // executed on the same sequence as they were requested on. There are no + // features for cancellation. When that's needed, use e.g. ScopedTaskSafety + // from the client. + virtual void RequestCallOnNextTick(absl::AnyInvocable<void() &&> callback) {} + + // Returns the current tick period of the metronome. + virtual TimeDelta TickPeriod() const = 0; +}; + +} // namespace webrtc + +#endif // API_METRONOME_METRONOME_H_ diff --git a/third_party/libwebrtc/api/metronome/metronome_gn/moz.build b/third_party/libwebrtc/api/metronome/metronome_gn/moz.build new file mode 100644 index 0000000000..dce0ca4319 --- /dev/null +++ b/third_party/libwebrtc/api/metronome/metronome_gn/moz.build @@ -0,0 +1,205 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("metronome_gn") diff --git a/third_party/libwebrtc/api/metronome/test/BUILD.gn b/third_party/libwebrtc/api/metronome/test/BUILD.gn new file mode 100644 index 0000000000..f415d98a0b --- /dev/null +++ b/third_party/libwebrtc/api/metronome/test/BUILD.gn @@ -0,0 +1,30 @@ +# Copyright (c) 2022 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") + +rtc_library("fake_metronome") { + testonly = true + sources = [ + "fake_metronome.cc", + "fake_metronome.h", + ] + deps = [ + "..:metronome", + "../..:priority", + "../..:sequence_checker", + "../../../rtc_base:macromagic", + "../../../rtc_base:rtc_event", + "../../../rtc_base:rtc_task_queue", + "../../../rtc_base/synchronization:mutex", + "../../../rtc_base/task_utils:repeating_task", + "../../../test:test_support", + "../../task_queue", + "../../units:time_delta", + ] +} diff --git a/third_party/libwebrtc/api/metronome/test/fake_metronome.cc b/third_party/libwebrtc/api/metronome/test/fake_metronome.cc new file mode 100644 index 0000000000..025f7ce5a6 --- /dev/null +++ b/third_party/libwebrtc/api/metronome/test/fake_metronome.cc @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022 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 "api/metronome/test/fake_metronome.h" + +#include <utility> +#include <vector> + +#include "api/priority.h" +#include "api/sequence_checker.h" +#include "api/task_queue/task_queue_base.h" +#include "api/task_queue/task_queue_factory.h" +#include "api/units/time_delta.h" +#include "rtc_base/event.h" +#include "rtc_base/task_utils/repeating_task.h" + +namespace webrtc::test { + +ForcedTickMetronome::ForcedTickMetronome(TimeDelta tick_period) + : tick_period_(tick_period) {} + +void ForcedTickMetronome::RequestCallOnNextTick( + absl::AnyInvocable<void() &&> callback) { + callbacks_.push_back(std::move(callback)); +} + +TimeDelta ForcedTickMetronome::TickPeriod() const { + return tick_period_; +} + +size_t ForcedTickMetronome::NumListeners() { + return callbacks_.size(); +} + +void ForcedTickMetronome::Tick() { + std::vector<absl::AnyInvocable<void() &&>> callbacks; + callbacks_.swap(callbacks); + for (auto& callback : callbacks) + std::move(callback)(); +} + +FakeMetronome::FakeMetronome(TimeDelta tick_period) + : tick_period_(tick_period) {} + +void FakeMetronome::RequestCallOnNextTick( + absl::AnyInvocable<void() &&> callback) { + TaskQueueBase* current = TaskQueueBase::Current(); + callbacks_.push_back(std::move(callback)); + if (callbacks_.size() == 1) { + current->PostDelayedTask( + [this] { + std::vector<absl::AnyInvocable<void() &&>> callbacks; + callbacks_.swap(callbacks); + for (auto& callback : callbacks) + std::move(callback)(); + }, + tick_period_); + } +} + +TimeDelta FakeMetronome::TickPeriod() const { + return tick_period_; +} + +} // namespace webrtc::test diff --git a/third_party/libwebrtc/api/metronome/test/fake_metronome.h b/third_party/libwebrtc/api/metronome/test/fake_metronome.h new file mode 100644 index 0000000000..73c938e9cd --- /dev/null +++ b/third_party/libwebrtc/api/metronome/test/fake_metronome.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2022 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 API_METRONOME_TEST_FAKE_METRONOME_H_ +#define API_METRONOME_TEST_FAKE_METRONOME_H_ + +#include <memory> +#include <set> +#include <vector> + +#include "api/metronome/metronome.h" +#include "api/task_queue/task_queue_base.h" +#include "api/task_queue/task_queue_factory.h" +#include "api/units/time_delta.h" +#include "rtc_base/synchronization/mutex.h" +#include "rtc_base/task_queue.h" +#include "rtc_base/task_utils/repeating_task.h" +#include "rtc_base/thread_annotations.h" + +namespace webrtc::test { + +// ForcedTickMetronome is a Metronome that ticks when `Tick()` is invoked. +// The constructor argument `tick_period` returned in `TickPeriod()`. +class ForcedTickMetronome : public Metronome { + public: + explicit ForcedTickMetronome(TimeDelta tick_period); + + // Forces all TickListeners to run `OnTick`. + void Tick(); + size_t NumListeners(); + + // Metronome implementation. + void RequestCallOnNextTick(absl::AnyInvocable<void() &&> callback) override; + TimeDelta TickPeriod() const override; + + private: + const TimeDelta tick_period_; + std::vector<absl::AnyInvocable<void() &&>> callbacks_; +}; + +// FakeMetronome is a metronome that ticks based on a repeating task at the +// `tick_period` provided in the constructor. It is designed for use with +// simulated task queues for unit tests. +// +// `Stop()` must be called before destruction, as it cancels the metronome tick +// on the proper task queue. +class FakeMetronome : public Metronome { + public: + explicit FakeMetronome(TimeDelta tick_period); + + // Metronome implementation. + void RequestCallOnNextTick(absl::AnyInvocable<void() &&> callback) override; + TimeDelta TickPeriod() const override; + + private: + const TimeDelta tick_period_; + std::vector<absl::AnyInvocable<void() &&>> callbacks_; +}; + +} // namespace webrtc::test + +#endif // API_METRONOME_TEST_FAKE_METRONOME_H_ diff --git a/third_party/libwebrtc/api/neteq/BUILD.gn b/third_party/libwebrtc/api/neteq/BUILD.gn new file mode 100644 index 0000000000..504fa059bb --- /dev/null +++ b/third_party/libwebrtc/api/neteq/BUILD.gn @@ -0,0 +1,95 @@ +# Copyright (c) 2019 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") + +rtc_source_set("neteq_api") { + visibility = [ "*" ] + sources = [ + "neteq.cc", + "neteq.h", + "neteq_factory.h", + ] + + deps = [ + "..:rtp_headers", + "..:rtp_packet_info", + "..:scoped_refptr", + "../../rtc_base:stringutils", + "../../system_wrappers:system_wrappers", + "../audio_codecs:audio_codecs_api", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_source_set("custom_neteq_factory") { + visibility = [ "*" ] + sources = [ + "custom_neteq_factory.cc", + "custom_neteq_factory.h", + ] + + deps = [ + ":neteq_api", + ":neteq_controller_api", + "..:scoped_refptr", + "../../modules/audio_coding:neteq", + "../../system_wrappers:system_wrappers", + "../audio_codecs:audio_codecs_api", + ] +} + +rtc_source_set("neteq_controller_api") { + visibility = [ "*" ] + sources = [ + "neteq_controller.h", + "neteq_controller_factory.h", + ] + + deps = [ + ":neteq_api", + ":tick_timer", + "../../system_wrappers:system_wrappers", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_source_set("default_neteq_controller_factory") { + visibility = [ "*" ] + sources = [ + "default_neteq_controller_factory.cc", + "default_neteq_controller_factory.h", + ] + + deps = [ + ":neteq_controller_api", + "../../modules/audio_coding:neteq", + ] +} + +rtc_source_set("tick_timer") { + visibility = [ "*" ] + sources = [ + "tick_timer.cc", + "tick_timer.h", + ] + deps = [ + "../../rtc_base:checks", + ] +} + +rtc_source_set("tick_timer_unittest") { + visibility = [ "*" ] + testonly = true + sources = [ "tick_timer_unittest.cc" ] + deps = [ + ":tick_timer", + "../../test:test_support", + "//testing/gtest", + ] +} diff --git a/third_party/libwebrtc/api/neteq/DEPS b/third_party/libwebrtc/api/neteq/DEPS new file mode 100644 index 0000000000..6c1c602b42 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/DEPS @@ -0,0 +1,14 @@ +specific_include_rules = { + "custom_neteq_factory\.h": [ + "+system_wrappers/include/clock.h", + ], + "default_neteq_factory\.h": [ + "+system_wrappers/include/clock.h", + ], + "neteq_controller\.h": [ + "+system_wrappers/include/clock.h", + ], + "neteq_factory\.h": [ + "+system_wrappers/include/clock.h", + ], +} diff --git a/third_party/libwebrtc/api/neteq/OWNERS b/third_party/libwebrtc/api/neteq/OWNERS new file mode 100644 index 0000000000..11257808f2 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/OWNERS @@ -0,0 +1,3 @@ +ivoc@webrtc.org +henrik.lundin@webrtc.org +jakobi@webrtc.org diff --git a/third_party/libwebrtc/api/neteq/custom_neteq_factory.cc b/third_party/libwebrtc/api/neteq/custom_neteq_factory.cc new file mode 100644 index 0000000000..b2df5df9ff --- /dev/null +++ b/third_party/libwebrtc/api/neteq/custom_neteq_factory.cc @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 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 "api/neteq/custom_neteq_factory.h" + +#include <utility> + +#include "modules/audio_coding/neteq/neteq_impl.h" + +namespace webrtc { + +CustomNetEqFactory::CustomNetEqFactory( + std::unique_ptr<NetEqControllerFactory> controller_factory) + : controller_factory_(std::move(controller_factory)) {} + +CustomNetEqFactory::~CustomNetEqFactory() = default; + +std::unique_ptr<NetEq> CustomNetEqFactory::CreateNetEq( + const NetEq::Config& config, + const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory, + Clock* clock) const { + return std::make_unique<NetEqImpl>( + config, NetEqImpl::Dependencies(config, clock, decoder_factory, + *controller_factory_)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/neteq/custom_neteq_factory.h b/third_party/libwebrtc/api/neteq/custom_neteq_factory.h new file mode 100644 index 0000000000..d080f68e8e --- /dev/null +++ b/third_party/libwebrtc/api/neteq/custom_neteq_factory.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 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 API_NETEQ_CUSTOM_NETEQ_FACTORY_H_ +#define API_NETEQ_CUSTOM_NETEQ_FACTORY_H_ + +#include <memory> + +#include "api/audio_codecs/audio_decoder_factory.h" +#include "api/neteq/neteq_controller_factory.h" +#include "api/neteq/neteq_factory.h" +#include "api/scoped_refptr.h" +#include "system_wrappers/include/clock.h" + +namespace webrtc { + +// This factory can be used to generate NetEq instances that make use of a +// custom NetEqControllerFactory. +class CustomNetEqFactory : public NetEqFactory { + public: + explicit CustomNetEqFactory( + std::unique_ptr<NetEqControllerFactory> controller_factory); + ~CustomNetEqFactory() override; + CustomNetEqFactory(const CustomNetEqFactory&) = delete; + CustomNetEqFactory& operator=(const CustomNetEqFactory&) = delete; + + std::unique_ptr<NetEq> CreateNetEq( + const NetEq::Config& config, + const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory, + Clock* clock) const override; + + private: + std::unique_ptr<NetEqControllerFactory> controller_factory_; +}; + +} // namespace webrtc +#endif // API_NETEQ_CUSTOM_NETEQ_FACTORY_H_ diff --git a/third_party/libwebrtc/api/neteq/default_neteq_controller_factory.cc b/third_party/libwebrtc/api/neteq/default_neteq_controller_factory.cc new file mode 100644 index 0000000000..22274dc7cc --- /dev/null +++ b/third_party/libwebrtc/api/neteq/default_neteq_controller_factory.cc @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019 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 "api/neteq/default_neteq_controller_factory.h" +#include "modules/audio_coding/neteq/decision_logic.h" + +namespace webrtc { + +DefaultNetEqControllerFactory::DefaultNetEqControllerFactory() = default; +DefaultNetEqControllerFactory::~DefaultNetEqControllerFactory() = default; + +std::unique_ptr<NetEqController> +DefaultNetEqControllerFactory::CreateNetEqController( + const NetEqController::Config& config) const { + return std::make_unique<DecisionLogic>(config); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/neteq/default_neteq_controller_factory.h b/third_party/libwebrtc/api/neteq/default_neteq_controller_factory.h new file mode 100644 index 0000000000..611afc2586 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/default_neteq_controller_factory.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 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 API_NETEQ_DEFAULT_NETEQ_CONTROLLER_FACTORY_H_ +#define API_NETEQ_DEFAULT_NETEQ_CONTROLLER_FACTORY_H_ + +#include <memory> + +#include "api/neteq/neteq_controller_factory.h" + +namespace webrtc { + +// This NetEqControllerFactory will use WebRTC's built-in controller logic. +class DefaultNetEqControllerFactory : public NetEqControllerFactory { + public: + DefaultNetEqControllerFactory(); + ~DefaultNetEqControllerFactory() override; + DefaultNetEqControllerFactory(const DefaultNetEqControllerFactory&) = delete; + DefaultNetEqControllerFactory& operator=( + const DefaultNetEqControllerFactory&) = delete; + + std::unique_ptr<NetEqController> CreateNetEqController( + const NetEqController::Config& config) const override; +}; + +} // namespace webrtc +#endif // API_NETEQ_DEFAULT_NETEQ_CONTROLLER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/neteq/default_neteq_controller_factory_gn/moz.build b/third_party/libwebrtc/api/neteq/default_neteq_controller_factory_gn/moz.build new file mode 100644 index 0000000000..273be80f73 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/default_neteq_controller_factory_gn/moz.build @@ -0,0 +1,232 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/neteq/default_neteq_controller_factory.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("default_neteq_controller_factory_gn") diff --git a/third_party/libwebrtc/api/neteq/neteq.cc b/third_party/libwebrtc/api/neteq/neteq.cc new file mode 100644 index 0000000000..155ddf2cf3 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/neteq.cc @@ -0,0 +1,37 @@ +/* + * 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 "api/neteq/neteq.h" + +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +NetEq::Config::Config() = default; +NetEq::Config::Config(const Config&) = default; +NetEq::Config::Config(Config&&) = default; +NetEq::Config::~Config() = default; +NetEq::Config& NetEq::Config::operator=(const Config&) = default; +NetEq::Config& NetEq::Config::operator=(Config&&) = default; + +std::string NetEq::Config::ToString() const { + char buf[1024]; + rtc::SimpleStringBuilder ss(buf); + ss << "sample_rate_hz=" << sample_rate_hz << ", enable_post_decode_vad=" + << (enable_post_decode_vad ? "true" : "false") + << ", max_packets_in_buffer=" << max_packets_in_buffer + << ", min_delay_ms=" << min_delay_ms << ", enable_fast_accelerate=" + << (enable_fast_accelerate ? "true" : "false") + << ", enable_muted_state=" << (enable_muted_state ? "true" : "false") + << ", enable_rtx_handling=" << (enable_rtx_handling ? "true" : "false"); + return ss.str(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/neteq/neteq.h b/third_party/libwebrtc/api/neteq/neteq.h new file mode 100644 index 0000000000..5300c5601e --- /dev/null +++ b/third_party/libwebrtc/api/neteq/neteq.h @@ -0,0 +1,322 @@ +/* + * 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. + */ + +#ifndef API_NETEQ_NETEQ_H_ +#define API_NETEQ_NETEQ_H_ + +#include <stddef.h> // Provide access to size_t. + +#include <map> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/audio_codecs/audio_codec_pair_id.h" +#include "api/audio_codecs/audio_decoder.h" +#include "api/audio_codecs/audio_format.h" +#include "api/rtp_headers.h" +#include "api/scoped_refptr.h" + +namespace webrtc { + +// Forward declarations. +class AudioFrame; +class AudioDecoderFactory; +class Clock; + +struct NetEqNetworkStatistics { + uint16_t current_buffer_size_ms; // Current jitter buffer size in ms. + uint16_t preferred_buffer_size_ms; // Target buffer size in ms. + uint16_t jitter_peaks_found; // 1 if adding extra delay due to peaky + // jitter; 0 otherwise. + uint16_t expand_rate; // Fraction (of original stream) of synthesized + // audio inserted through expansion (in Q14). + uint16_t speech_expand_rate; // Fraction (of original stream) of synthesized + // speech inserted through expansion (in Q14). + uint16_t preemptive_rate; // Fraction of data inserted through pre-emptive + // expansion (in Q14). + uint16_t accelerate_rate; // Fraction of data removed through acceleration + // (in Q14). + uint16_t secondary_decoded_rate; // Fraction of data coming from FEC/RED + // decoding (in Q14). + uint16_t secondary_discarded_rate; // Fraction of discarded FEC/RED data (in + // Q14). + // Statistics for packet waiting times, i.e., the time between a packet + // arrives until it is decoded. + int mean_waiting_time_ms; + int median_waiting_time_ms; + int min_waiting_time_ms; + int max_waiting_time_ms; +}; + +// NetEq statistics that persist over the lifetime of the class. +// These metrics are never reset. +struct NetEqLifetimeStatistics { + // Stats below correspond to similarly-named fields in the WebRTC stats spec. + // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats + uint64_t total_samples_received = 0; + uint64_t concealed_samples = 0; + uint64_t concealment_events = 0; + uint64_t jitter_buffer_delay_ms = 0; + uint64_t jitter_buffer_emitted_count = 0; + uint64_t jitter_buffer_target_delay_ms = 0; + uint64_t jitter_buffer_minimum_delay_ms = 0; + uint64_t inserted_samples_for_deceleration = 0; + uint64_t removed_samples_for_acceleration = 0; + uint64_t silent_concealed_samples = 0; + uint64_t fec_packets_received = 0; + uint64_t fec_packets_discarded = 0; + uint64_t packets_discarded = 0; + // Below stats are not part of the spec. + uint64_t delayed_packet_outage_samples = 0; + // This is sum of relative packet arrival delays of received packets so far. + // Since end-to-end delay of a packet is difficult to measure and is not + // necessarily useful for measuring jitter buffer performance, we report a + // relative packet arrival delay. The relative packet arrival delay of a + // packet is defined as the arrival delay compared to the first packet + // received, given that it had zero delay. To avoid clock drift, the "first" + // packet can be made dynamic. + uint64_t relative_packet_arrival_delay_ms = 0; + uint64_t jitter_buffer_packets_received = 0; + // An interruption is a loss-concealment event lasting at least 150 ms. The + // two stats below count the number os such events and the total duration of + // these events. + int32_t interruption_count = 0; + int32_t total_interruption_duration_ms = 0; + // Total number of comfort noise samples generated during DTX. + uint64_t generated_noise_samples = 0; +}; + +// Metrics that describe the operations performed in NetEq, and the internal +// state. +struct NetEqOperationsAndState { + // These sample counters are cumulative, and don't reset. As a reference, the + // total number of output samples can be found in + // NetEqLifetimeStatistics::total_samples_received. + uint64_t preemptive_samples = 0; + uint64_t accelerate_samples = 0; + // Count of the number of buffer flushes. + uint64_t packet_buffer_flushes = 0; + // The statistics below are not cumulative. + // The waiting time of the last decoded packet. + uint64_t last_waiting_time_ms = 0; + // The sum of the packet and jitter buffer size in ms. + uint64_t current_buffer_size_ms = 0; + // The current frame size in ms. + uint64_t current_frame_size_ms = 0; + // Flag to indicate that the next packet is available. + bool next_packet_available = false; +}; + +// This is the interface class for NetEq. +class NetEq { + public: + struct Config { + Config(); + Config(const Config&); + Config(Config&&); + ~Config(); + Config& operator=(const Config&); + Config& operator=(Config&&); + + std::string ToString() const; + + int sample_rate_hz = 48000; // Initial value. Will change with input data. + bool enable_post_decode_vad = false; + size_t max_packets_in_buffer = 200; + int max_delay_ms = 0; + int min_delay_ms = 0; + bool enable_fast_accelerate = false; + bool enable_muted_state = false; + bool enable_rtx_handling = false; + absl::optional<AudioCodecPairId> codec_pair_id; + bool for_test_no_time_stretching = false; // Use only for testing. + }; + + enum ReturnCodes { kOK = 0, kFail = -1 }; + + enum class Operation { + kNormal, + kMerge, + kExpand, + kAccelerate, + kFastAccelerate, + kPreemptiveExpand, + kRfc3389Cng, + kRfc3389CngNoPacket, + kCodecInternalCng, + kDtmf, + kUndefined, + }; + + enum class Mode { + kNormal, + kExpand, + kMerge, + kAccelerateSuccess, + kAccelerateLowEnergy, + kAccelerateFail, + kPreemptiveExpandSuccess, + kPreemptiveExpandLowEnergy, + kPreemptiveExpandFail, + kRfc3389Cng, + kCodecInternalCng, + kCodecPlc, + kDtmf, + kError, + kUndefined, + }; + + // Return type for GetDecoderFormat. + struct DecoderFormat { + int sample_rate_hz; + int num_channels; + SdpAudioFormat sdp_format; + }; + + virtual ~NetEq() {} + + // Inserts a new packet into NetEq. + // Returns 0 on success, -1 on failure. + virtual int InsertPacket(const RTPHeader& rtp_header, + rtc::ArrayView<const uint8_t> payload) = 0; + + // Lets NetEq know that a packet arrived with an empty payload. This typically + // happens when empty packets are used for probing the network channel, and + // these packets use RTP sequence numbers from the same series as the actual + // audio packets. + virtual void InsertEmptyPacket(const RTPHeader& rtp_header) = 0; + + // Instructs NetEq to deliver 10 ms of audio data. The data is written to + // `audio_frame`. All data in `audio_frame` is wiped; `data_`, `speech_type_`, + // `num_channels_`, `sample_rate_hz_`, `samples_per_channel_`, and + // `vad_activity_` are updated upon success. If an error is returned, some + // fields may not have been updated, or may contain inconsistent values. + // If muted state is enabled (through Config::enable_muted_state), `muted` + // may be set to true after a prolonged expand period. When this happens, the + // `data_` in `audio_frame` is not written, but should be interpreted as being + // all zeros. For testing purposes, an override can be supplied in the + // `action_override` argument, which will cause NetEq to take this action + // next, instead of the action it would normally choose. An optional output + // argument for fetching the current sample rate can be provided, which + // will return the same value as last_output_sample_rate_hz() but will avoid + // additional synchronization. + // Returns kOK on success, or kFail in case of an error. + virtual int GetAudio( + AudioFrame* audio_frame, + bool* muted, + int* current_sample_rate_hz = nullptr, + absl::optional<Operation> action_override = absl::nullopt) = 0; + + // Replaces the current set of decoders with the given one. + virtual void SetCodecs(const std::map<int, SdpAudioFormat>& codecs) = 0; + + // Associates `rtp_payload_type` with the given codec, which NetEq will + // instantiate when it needs it. Returns true iff successful. + virtual bool RegisterPayloadType(int rtp_payload_type, + const SdpAudioFormat& audio_format) = 0; + + // Removes `rtp_payload_type` from the codec database. Returns 0 on success, + // -1 on failure. Removing a payload type that is not registered is ok and + // will not result in an error. + virtual int RemovePayloadType(uint8_t rtp_payload_type) = 0; + + // Removes all payload types from the codec database. + virtual void RemoveAllPayloadTypes() = 0; + + // Sets a minimum delay in millisecond for packet buffer. The minimum is + // maintained unless a higher latency is dictated by channel condition. + // Returns true if the minimum is successfully applied, otherwise false is + // returned. + virtual bool SetMinimumDelay(int delay_ms) = 0; + + // Sets a maximum delay in milliseconds for packet buffer. The latency will + // not exceed the given value, even required delay (given the channel + // conditions) is higher. Calling this method has the same effect as setting + // the `max_delay_ms` value in the NetEq::Config struct. + virtual bool SetMaximumDelay(int delay_ms) = 0; + + // Sets a base minimum delay in milliseconds for packet buffer. The minimum + // delay which is set via `SetMinimumDelay` can't be lower than base minimum + // delay. Calling this method is similar to setting the `min_delay_ms` value + // in the NetEq::Config struct. Returns true if the base minimum is + // successfully applied, otherwise false is returned. + virtual bool SetBaseMinimumDelayMs(int delay_ms) = 0; + + // Returns current value of base minimum delay in milliseconds. + virtual int GetBaseMinimumDelayMs() const = 0; + + // Returns the current target delay in ms. This includes any extra delay + // requested through SetMinimumDelay. + virtual int TargetDelayMs() const = 0; + + // Returns the current total delay (packet buffer and sync buffer) in ms, + // with smoothing applied to even out short-time fluctuations due to jitter. + // The packet buffer part of the delay is not updated during DTX/CNG periods. + virtual int FilteredCurrentDelayMs() const = 0; + + // Writes the current network statistics to `stats`. The statistics are reset + // after the call. + virtual int NetworkStatistics(NetEqNetworkStatistics* stats) = 0; + + // Current values only, not resetting any state. + virtual NetEqNetworkStatistics CurrentNetworkStatistics() const = 0; + + // Returns a copy of this class's lifetime statistics. These statistics are + // never reset. + virtual NetEqLifetimeStatistics GetLifetimeStatistics() const = 0; + + // Returns statistics about the performed operations and internal state. These + // statistics are never reset. + virtual NetEqOperationsAndState GetOperationsAndState() const = 0; + + // Enables post-decode VAD. When enabled, GetAudio() will return + // kOutputVADPassive when the signal contains no speech. + virtual void EnableVad() = 0; + + // Disables post-decode VAD. + virtual void DisableVad() = 0; + + // Returns the RTP timestamp for the last sample delivered by GetAudio(). + // The return value will be empty if no valid timestamp is available. + virtual absl::optional<uint32_t> GetPlayoutTimestamp() const = 0; + + // Returns the sample rate in Hz of the audio produced in the last GetAudio + // call. If GetAudio has not been called yet, the configured sample rate + // (Config::sample_rate_hz) is returned. + virtual int last_output_sample_rate_hz() const = 0; + + // Returns the decoder info for the given payload type. Returns empty if no + // such payload type was registered. + virtual absl::optional<DecoderFormat> GetDecoderFormat( + int payload_type) const = 0; + + // Flushes both the packet buffer and the sync buffer. + virtual void FlushBuffers() = 0; + + // Enables NACK and sets the maximum size of the NACK list, which should be + // positive and no larger than Nack::kNackListSizeLimit. If NACK is already + // enabled then the maximum NACK list size is modified accordingly. + virtual void EnableNack(size_t max_nack_list_size) = 0; + + virtual void DisableNack() = 0; + + // Returns a list of RTP sequence numbers corresponding to packets to be + // retransmitted, given an estimate of the round-trip time in milliseconds. + virtual std::vector<uint16_t> GetNackList( + int64_t round_trip_time_ms) const = 0; + + // Returns the length of the audio yet to play in the sync buffer. + // Mainly intended for testing. + virtual int SyncBufferSizeMs() const = 0; +}; + +} // namespace webrtc +#endif // API_NETEQ_NETEQ_H_ diff --git a/third_party/libwebrtc/api/neteq/neteq_api_gn/moz.build b/third_party/libwebrtc/api/neteq/neteq_api_gn/moz.build new file mode 100644 index 0000000000..f06937f581 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/neteq_api_gn/moz.build @@ -0,0 +1,232 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/neteq/neteq.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("neteq_api_gn") diff --git a/third_party/libwebrtc/api/neteq/neteq_controller.h b/third_party/libwebrtc/api/neteq/neteq_controller.h new file mode 100644 index 0000000000..f0101d3d1a --- /dev/null +++ b/third_party/libwebrtc/api/neteq/neteq_controller.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2019 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 API_NETEQ_NETEQ_CONTROLLER_H_ +#define API_NETEQ_NETEQ_CONTROLLER_H_ + +#include <cstddef> +#include <cstdint> + +#include <functional> +#include <memory> + +#include "absl/types/optional.h" +#include "api/neteq/neteq.h" +#include "api/neteq/tick_timer.h" +#include "system_wrappers/include/clock.h" + +namespace webrtc { + +// Decides the actions that NetEq should take. This affects the behavior of the +// jitter buffer, and how it reacts to network conditions. +// This class will undergo substantial refactoring in the near future, and the +// API is expected to undergo significant changes. A target API is given below: +// +// class NetEqController { +// public: +// // Resets object to a clean state. +// void Reset(); +// // Given NetEq status, make a decision. +// Operation GetDecision(NetEqStatus neteq_status); +// // Register every packet received. +// void RegisterPacket(PacketInfo packet_info); +// // Register empty packet. +// void RegisterEmptyPacket(); +// // Register a codec switching. +// void CodecSwithed(); +// // Sets the sample rate. +// void SetSampleRate(int fs_hz); +// // Sets the packet length in samples. +// void SetPacketLengthSamples(); +// // Sets maximum delay. +// void SetMaximumDelay(int delay_ms); +// // Sets mininum delay. +// void SetMinimumDelay(int delay_ms); +// // Sets base mininum delay. +// void SetBaseMinimumDelay(int delay_ms); +// // Gets target buffer level. +// int GetTargetBufferLevelMs() const; +// // Gets filtered buffer level. +// int GetFilteredBufferLevel() const; +// // Gets base minimum delay. +// int GetBaseMinimumDelay() const; +// } + +class NetEqController { + public: + // This struct is used to create a NetEqController. + struct Config { + bool allow_time_stretching; + bool enable_rtx_handling; + int max_packets_in_buffer; + int base_min_delay_ms; + TickTimer* tick_timer; + webrtc::Clock* clock = nullptr; + }; + + struct PacketInfo { + uint32_t timestamp; + bool is_dtx; + bool is_cng; + }; + + struct PacketBufferInfo { + bool dtx_or_cng; + size_t num_samples; + size_t span_samples; + size_t span_samples_no_dtx; + size_t num_packets; + }; + + struct NetEqStatus { + uint32_t target_timestamp; + int16_t expand_mutefactor; + size_t last_packet_samples; + absl::optional<PacketInfo> next_packet; + NetEq::Mode last_mode; + bool play_dtmf; + size_t generated_noise_samples; + PacketBufferInfo packet_buffer_info; + size_t sync_buffer_samples; + }; + + struct PacketArrivedInfo { + size_t packet_length_samples; + uint32_t main_timestamp; + uint16_t main_sequence_number; + bool is_cng_or_dtmf; + bool is_dtx; + bool buffer_flush; + }; + + virtual ~NetEqController() = default; + + // Resets object to a clean state. + virtual void Reset() = 0; + + // Resets parts of the state. Typically done when switching codecs. + virtual void SoftReset() = 0; + + // Given info about the latest received packet, and current jitter buffer + // status, returns the operation. `target_timestamp` and `expand_mutefactor` + // are provided for reference. `last_packet_samples` is the number of samples + // obtained from the last decoded frame. If there is a packet available, it + // should be supplied in `packet`. The mode resulting from the last call to + // NetEqImpl::GetAudio is supplied in `last_mode`. If there is a DTMF event to + // play, `play_dtmf` should be set to true. The output variable + // `reset_decoder` will be set to true if a reset is required; otherwise it is + // left unchanged (i.e., it can remain true if it was true before the call). + virtual NetEq::Operation GetDecision(const NetEqStatus& status, + bool* reset_decoder) = 0; + + // Inform NetEqController that an empty packet has arrived. + virtual void RegisterEmptyPacket() = 0; + + // Sets the sample rate and the output block size. + virtual void SetSampleRate(int fs_hz, size_t output_size_samples) = 0; + + // Sets a minimum or maximum delay in millisecond. + // Returns true if the delay bound is successfully applied, otherwise false. + virtual bool SetMaximumDelay(int delay_ms) = 0; + virtual bool SetMinimumDelay(int delay_ms) = 0; + + // Sets a base minimum delay in milliseconds for packet buffer. The effective + // minimum delay can't be lower than base minimum delay, even if a lower value + // is set using SetMinimumDelay. + // Returns true if the base minimum is successfully applied, otherwise false. + virtual bool SetBaseMinimumDelay(int delay_ms) = 0; + virtual int GetBaseMinimumDelay() const = 0; + + // These methods test the `cng_state_` for different conditions. + virtual bool CngRfc3389On() const = 0; + virtual bool CngOff() const = 0; + + // Resets the `cng_state_` to kCngOff. + virtual void SetCngOff() = 0; + + // Reports back to DecisionLogic whether the decision to do expand remains or + // not. Note that this is necessary, since an expand decision can be changed + // to kNormal in NetEqImpl::GetDecision if there is still enough data in the + // sync buffer. + virtual void ExpandDecision(NetEq::Operation operation) = 0; + + // Adds `value` to `sample_memory_`. + virtual void AddSampleMemory(int32_t value) = 0; + + // Returns the target buffer level in ms. + virtual int TargetLevelMs() const = 0; + + // Returns the target buffer level in ms as it would be if no minimum or + // maximum delay was set. + // TODO(bugs.webrtc.org/14270): Make pure virtual once all implementations are + // updated. + virtual int UnlimitedTargetLevelMs() const { return 0; } + + // Notify the NetEqController that a packet has arrived. Returns the relative + // arrival delay, if it can be computed. + virtual absl::optional<int> PacketArrived(int fs_hz, + bool should_update_stats, + const PacketArrivedInfo& info) = 0; + + // Notify the NetEqController that we are currently in muted state. + // TODO(bugs.webrtc.org/14270): Make pure virtual when downstream is updated. + virtual void NotifyMutedState() {} + + // Returns true if a peak was found. + virtual bool PeakFound() const = 0; + + // Get the filtered buffer level in samples. + virtual int GetFilteredBufferLevel() const = 0; + + // Accessors and mutators. + virtual void set_sample_memory(int32_t value) = 0; + virtual size_t noise_fast_forward() const = 0; + virtual size_t packet_length_samples() const = 0; + virtual void set_packet_length_samples(size_t value) = 0; + virtual void set_prev_time_scale(bool value) = 0; +}; + +} // namespace webrtc +#endif // API_NETEQ_NETEQ_CONTROLLER_H_ diff --git a/third_party/libwebrtc/api/neteq/neteq_controller_api_gn/moz.build b/third_party/libwebrtc/api/neteq/neteq_controller_api_gn/moz.build new file mode 100644 index 0000000000..d09b5aed53 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/neteq_controller_api_gn/moz.build @@ -0,0 +1,216 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("neteq_controller_api_gn") diff --git a/third_party/libwebrtc/api/neteq/neteq_controller_factory.h b/third_party/libwebrtc/api/neteq/neteq_controller_factory.h new file mode 100644 index 0000000000..9aba8a21a7 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/neteq_controller_factory.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019 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 API_NETEQ_NETEQ_CONTROLLER_FACTORY_H_ +#define API_NETEQ_NETEQ_CONTROLLER_FACTORY_H_ + +#include <memory> + +#include "api/neteq/neteq_controller.h" + +namespace webrtc { + +// Creates NetEqController instances using the settings provided in the config +// struct. +class NetEqControllerFactory { + public: + virtual ~NetEqControllerFactory() = default; + + // Creates a new NetEqController object, with parameters set in `config`. + virtual std::unique_ptr<NetEqController> CreateNetEqController( + const NetEqController::Config& config) const = 0; +}; + +} // namespace webrtc +#endif // API_NETEQ_NETEQ_CONTROLLER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/neteq/neteq_factory.h b/third_party/libwebrtc/api/neteq/neteq_factory.h new file mode 100644 index 0000000000..526a1282f5 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/neteq_factory.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019 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 API_NETEQ_NETEQ_FACTORY_H_ +#define API_NETEQ_NETEQ_FACTORY_H_ + +#include <memory> + +#include "api/audio_codecs/audio_decoder_factory.h" +#include "api/neteq/neteq.h" +#include "system_wrappers/include/clock.h" + +namespace webrtc { + +// Creates NetEq instances using the settings provided in the config struct. +class NetEqFactory { + public: + virtual ~NetEqFactory() = default; + + // Creates a new NetEq object, with parameters set in `config`. The `config` + // object will only have to be valid for the duration of the call to this + // method. + virtual std::unique_ptr<NetEq> CreateNetEq( + const NetEq::Config& config, + const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory, + Clock* clock) const = 0; +}; + +} // namespace webrtc +#endif // API_NETEQ_NETEQ_FACTORY_H_ diff --git a/third_party/libwebrtc/api/neteq/tick_timer.cc b/third_party/libwebrtc/api/neteq/tick_timer.cc new file mode 100644 index 0000000000..8f60bf48bf --- /dev/null +++ b/third_party/libwebrtc/api/neteq/tick_timer.cc @@ -0,0 +1,25 @@ +/* + * 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. + */ + +#include "api/neteq/tick_timer.h" + +namespace webrtc { + +TickTimer::Stopwatch::Stopwatch(const TickTimer& ticktimer) + : ticktimer_(ticktimer), starttick_(ticktimer.ticks()) {} + +TickTimer::Countdown::Countdown(const TickTimer& ticktimer, + uint64_t ticks_to_count) + : stopwatch_(ticktimer.GetNewStopwatch()), + ticks_to_count_(ticks_to_count) {} + +TickTimer::Countdown::~Countdown() = default; + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/neteq/tick_timer.h b/third_party/libwebrtc/api/neteq/tick_timer.h new file mode 100644 index 0000000000..e3f54a4522 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/tick_timer.h @@ -0,0 +1,112 @@ +/* + * 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. + */ + +#ifndef API_NETEQ_TICK_TIMER_H_ +#define API_NETEQ_TICK_TIMER_H_ + +#include <stdint.h> + +#include <memory> + +#include "rtc_base/checks.h" + +namespace webrtc { + +// Implements a time counter. The counter is advanced with the Increment() +// methods, and is queried with the ticks() accessor. It is assumed that one +// "tick" of the counter corresponds to 10 ms. +// A TickTimer object can provide two types of associated time-measuring +// objects: Stopwatch and Countdown. +class TickTimer { + public: + // Stopwatch measures time elapsed since it was started, by querying the + // associated TickTimer for the current time. The intended use is to request a + // new Stopwatch object from a TickTimer object with the GetNewStopwatch() + // method. Note: since the Stopwatch object contains a reference to the + // TickTimer it is associated with, it cannot outlive the TickTimer. + class Stopwatch { + public: + explicit Stopwatch(const TickTimer& ticktimer); + + uint64_t ElapsedTicks() const { return ticktimer_.ticks() - starttick_; } + + uint64_t ElapsedMs() const { + const uint64_t elapsed_ticks = ticktimer_.ticks() - starttick_; + const int ms_per_tick = ticktimer_.ms_per_tick(); + return elapsed_ticks < UINT64_MAX / ms_per_tick + ? elapsed_ticks * ms_per_tick + : UINT64_MAX; + } + + private: + const TickTimer& ticktimer_; + const uint64_t starttick_; + }; + + // Countdown counts down from a given start value with each tick of the + // associated TickTimer, until zero is reached. The Finished() method will + // return true if zero has been reached, false otherwise. The intended use is + // to request a new Countdown object from a TickTimer object with the + // GetNewCountdown() method. Note: since the Countdown object contains a + // reference to the TickTimer it is associated with, it cannot outlive the + // TickTimer. + class Countdown { + public: + Countdown(const TickTimer& ticktimer, uint64_t ticks_to_count); + + ~Countdown(); + + bool Finished() const { + return stopwatch_->ElapsedTicks() >= ticks_to_count_; + } + + private: + const std::unique_ptr<Stopwatch> stopwatch_; + const uint64_t ticks_to_count_; + }; + + TickTimer() : TickTimer(10) {} + explicit TickTimer(int ms_per_tick) : ms_per_tick_(ms_per_tick) { + RTC_DCHECK_GT(ms_per_tick_, 0); + } + + TickTimer(const TickTimer&) = delete; + TickTimer& operator=(const TickTimer&) = delete; + + void Increment() { ++ticks_; } + + // Mainly intended for testing. + void Increment(uint64_t x) { ticks_ += x; } + + uint64_t ticks() const { return ticks_; } + + int ms_per_tick() const { return ms_per_tick_; } + + // Returns a new Stopwatch object, based on the current TickTimer. Note that + // the new Stopwatch object contains a reference to the current TickTimer, + // and must therefore not outlive the TickTimer. + std::unique_ptr<Stopwatch> GetNewStopwatch() const { + return std::unique_ptr<Stopwatch>(new Stopwatch(*this)); + } + + // Returns a new Countdown object, based on the current TickTimer. Note that + // the new Countdown object contains a reference to the current TickTimer, + // and must therefore not outlive the TickTimer. + std::unique_ptr<Countdown> GetNewCountdown(uint64_t ticks_to_count) const { + return std::unique_ptr<Countdown>(new Countdown(*this, ticks_to_count)); + } + + private: + uint64_t ticks_ = 0; + const int ms_per_tick_; +}; + +} // namespace webrtc +#endif // API_NETEQ_TICK_TIMER_H_ diff --git a/third_party/libwebrtc/api/neteq/tick_timer_gn/moz.build b/third_party/libwebrtc/api/neteq/tick_timer_gn/moz.build new file mode 100644 index 0000000000..0125225509 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/tick_timer_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/neteq/tick_timer.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("tick_timer_gn") diff --git a/third_party/libwebrtc/api/neteq/tick_timer_unittest.cc b/third_party/libwebrtc/api/neteq/tick_timer_unittest.cc new file mode 100644 index 0000000000..863c0117f4 --- /dev/null +++ b/third_party/libwebrtc/api/neteq/tick_timer_unittest.cc @@ -0,0 +1,135 @@ +/* + * 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. + */ + +#include "api/neteq/tick_timer.h" + +#include <memory> + +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { + +// Verify that the default value for ms_per_tick is 10. +TEST(TickTimer, DefaultMsPerTick) { + TickTimer tt; + EXPECT_EQ(10, tt.ms_per_tick()); +} + +TEST(TickTimer, CustomMsPerTick) { + TickTimer tt(17); + EXPECT_EQ(17, tt.ms_per_tick()); +} + +TEST(TickTimer, Increment) { + TickTimer tt; + EXPECT_EQ(0u, tt.ticks()); + tt.Increment(); + EXPECT_EQ(1u, tt.ticks()); + + for (int i = 0; i < 17; ++i) { + tt.Increment(); + } + EXPECT_EQ(18u, tt.ticks()); + + tt.Increment(17); + EXPECT_EQ(35u, tt.ticks()); +} + +TEST(TickTimer, WrapAround) { + TickTimer tt; + tt.Increment(UINT64_MAX); + EXPECT_EQ(UINT64_MAX, tt.ticks()); + tt.Increment(); + EXPECT_EQ(0u, tt.ticks()); +} + +TEST(TickTimer, Stopwatch) { + TickTimer tt; + // Increment it a "random" number of steps. + tt.Increment(17); + + std::unique_ptr<TickTimer::Stopwatch> sw = tt.GetNewStopwatch(); + ASSERT_TRUE(sw); + + EXPECT_EQ(0u, sw->ElapsedTicks()); // Starts at zero. + EXPECT_EQ(0u, sw->ElapsedMs()); + tt.Increment(); + EXPECT_EQ(1u, sw->ElapsedTicks()); // Increases with the TickTimer. + EXPECT_EQ(10u, sw->ElapsedMs()); +} + +TEST(TickTimer, StopwatchWrapAround) { + TickTimer tt; + tt.Increment(UINT64_MAX); + + std::unique_ptr<TickTimer::Stopwatch> sw = tt.GetNewStopwatch(); + ASSERT_TRUE(sw); + + tt.Increment(); + EXPECT_EQ(0u, tt.ticks()); + EXPECT_EQ(1u, sw->ElapsedTicks()); + EXPECT_EQ(10u, sw->ElapsedMs()); + + tt.Increment(); + EXPECT_EQ(1u, tt.ticks()); + EXPECT_EQ(2u, sw->ElapsedTicks()); + EXPECT_EQ(20u, sw->ElapsedMs()); +} + +TEST(TickTimer, StopwatchMsOverflow) { + TickTimer tt; + std::unique_ptr<TickTimer::Stopwatch> sw = tt.GetNewStopwatch(); + ASSERT_TRUE(sw); + + tt.Increment(UINT64_MAX / 10); + EXPECT_EQ(UINT64_MAX, sw->ElapsedMs()); + + tt.Increment(); + EXPECT_EQ(UINT64_MAX, sw->ElapsedMs()); + + tt.Increment(UINT64_MAX - tt.ticks()); + EXPECT_EQ(UINT64_MAX, tt.ticks()); + EXPECT_EQ(UINT64_MAX, sw->ElapsedMs()); +} + +TEST(TickTimer, StopwatchWithCustomTicktime) { + const int kMsPerTick = 17; + TickTimer tt(kMsPerTick); + std::unique_ptr<TickTimer::Stopwatch> sw = tt.GetNewStopwatch(); + ASSERT_TRUE(sw); + + EXPECT_EQ(0u, sw->ElapsedMs()); + tt.Increment(); + EXPECT_EQ(static_cast<uint64_t>(kMsPerTick), sw->ElapsedMs()); +} + +TEST(TickTimer, Countdown) { + TickTimer tt; + // Increment it a "random" number of steps. + tt.Increment(4711); + + std::unique_ptr<TickTimer::Countdown> cd = tt.GetNewCountdown(17); + ASSERT_TRUE(cd); + + EXPECT_FALSE(cd->Finished()); + tt.Increment(); + EXPECT_FALSE(cd->Finished()); + + tt.Increment(16); // Total increment is now 17. + EXPECT_TRUE(cd->Finished()); + + // Further increments do not change the state. + tt.Increment(); + EXPECT_TRUE(cd->Finished()); + tt.Increment(1234); + EXPECT_TRUE(cd->Finished()); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/network_state_predictor.h b/third_party/libwebrtc/api/network_state_predictor.h new file mode 100644 index 0000000000..9cf5ab6f02 --- /dev/null +++ b/third_party/libwebrtc/api/network_state_predictor.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019 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 API_NETWORK_STATE_PREDICTOR_H_ +#define API_NETWORK_STATE_PREDICTOR_H_ + +#include <memory> +#include <vector> + +namespace webrtc { + +enum class BandwidthUsage { + kBwNormal = 0, + kBwUnderusing = 1, + kBwOverusing = 2, + kLast +}; + +// TODO(yinwa): work in progress. API in class NetworkStatePredictor should not +// be used by other users until this comment is removed. + +// NetworkStatePredictor predict network state based on current network metrics. +// Usage: +// Setup by calling Initialize. +// For each update, call Update. Update returns network state +// prediction. +class NetworkStatePredictor { + public: + virtual ~NetworkStatePredictor() {} + + // Returns current network state prediction. + // Inputs: send_time_ms - packet send time. + // arrival_time_ms - packet arrival time. + // network_state - computed network state. + virtual BandwidthUsage Update(int64_t send_time_ms, + int64_t arrival_time_ms, + BandwidthUsage network_state) = 0; +}; + +class NetworkStatePredictorFactoryInterface { + public: + virtual std::unique_ptr<NetworkStatePredictor> + CreateNetworkStatePredictor() = 0; + virtual ~NetworkStatePredictorFactoryInterface() = default; +}; + +} // namespace webrtc + +#endif // API_NETWORK_STATE_PREDICTOR_H_ diff --git a/third_party/libwebrtc/api/network_state_predictor_api_gn/moz.build b/third_party/libwebrtc/api/network_state_predictor_api_gn/moz.build new file mode 100644 index 0000000000..2a95233bda --- /dev/null +++ b/third_party/libwebrtc/api/network_state_predictor_api_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("network_state_predictor_api_gn") diff --git a/third_party/libwebrtc/api/notifier.h b/third_party/libwebrtc/api/notifier.h new file mode 100644 index 0000000000..fc2480e00a --- /dev/null +++ b/third_party/libwebrtc/api/notifier.h @@ -0,0 +1,68 @@ +/* + * Copyright 2011 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 API_NOTIFIER_H_ +#define API_NOTIFIER_H_ + +#include <list> + +#include "api/media_stream_interface.h" +#include "api/sequence_checker.h" +#include "rtc_base/checks.h" +#include "rtc_base/system/no_unique_address.h" + +namespace webrtc { + +// Implements a template version of a notifier. +// TODO(deadbeef): This is an implementation detail; move out of api/. +template <class T> +class Notifier : public T { + public: + Notifier() { sequence_checker_.Detach(); } + + virtual void RegisterObserver(ObserverInterface* observer) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + RTC_DCHECK(observer != nullptr); + observers_.push_back(observer); + } + + virtual void UnregisterObserver(ObserverInterface* observer) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + for (std::list<ObserverInterface*>::iterator it = observers_.begin(); + it != observers_.end(); it++) { + if (*it == observer) { + observers_.erase(it); + break; + } + } + } + + void FireOnChanged() { + RTC_DCHECK_RUN_ON(&sequence_checker_); + // Copy the list of observers to avoid a crash if the observer object + // unregisters as a result of the OnChanged() call. If the same list is used + // UnregisterObserver will affect the list make the iterator invalid. + std::list<ObserverInterface*> observers = observers_; + for (std::list<ObserverInterface*>::iterator it = observers.begin(); + it != observers.end(); ++it) { + (*it)->OnChanged(); + } + } + + protected: + std::list<ObserverInterface*> observers_ RTC_GUARDED_BY(sequence_checker_); + + private: + RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_; +}; + +} // namespace webrtc + +#endif // API_NOTIFIER_H_ diff --git a/third_party/libwebrtc/api/numerics/BUILD.gn b/third_party/libwebrtc/api/numerics/BUILD.gn new file mode 100644 index 0000000000..408dc5b9f1 --- /dev/null +++ b/third_party/libwebrtc/api/numerics/BUILD.gn @@ -0,0 +1,41 @@ +# Copyright (c) 2020 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") + +rtc_library("numerics") { + visibility = [ "*" ] + + sources = [ + "samples_stats_counter.cc", + "samples_stats_counter.h", + ] + deps = [ + "..:array_view", + "../../rtc_base:checks", + "../../rtc_base:rtc_numerics", + "../../rtc_base:timeutils", + "../units:timestamp", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container" ] +} + +if (rtc_include_tests) { + rtc_library("numerics_unittests") { + visibility = [ "*" ] + testonly = true + + sources = [ "samples_stats_counter_unittest.cc" ] + + deps = [ + ":numerics", + "../../test:test_support", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container" ] + } +} diff --git a/third_party/libwebrtc/api/numerics/DEPS b/third_party/libwebrtc/api/numerics/DEPS new file mode 100644 index 0000000000..2d89d57557 --- /dev/null +++ b/third_party/libwebrtc/api/numerics/DEPS @@ -0,0 +1,6 @@ +specific_include_rules = { + # Some internal headers are allowed even in API headers: + "samples_stats_counter\.h": [ + "+rtc_base/numerics/running_statistics.h", + ] +} diff --git a/third_party/libwebrtc/api/numerics/samples_stats_counter.cc b/third_party/libwebrtc/api/numerics/samples_stats_counter.cc new file mode 100644 index 0000000000..4eb0cde299 --- /dev/null +++ b/third_party/libwebrtc/api/numerics/samples_stats_counter.cc @@ -0,0 +1,101 @@ +/* + * 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 "api/numerics/samples_stats_counter.h" + +#include <algorithm> +#include <cmath> + +#include "absl/algorithm/container.h" +#include "rtc_base/time_utils.h" + +namespace webrtc { + +SamplesStatsCounter::SamplesStatsCounter() = default; +SamplesStatsCounter::SamplesStatsCounter(size_t expected_samples_count) { + samples_.reserve(expected_samples_count); +} + +SamplesStatsCounter::~SamplesStatsCounter() = default; +SamplesStatsCounter::SamplesStatsCounter(const SamplesStatsCounter&) = default; +SamplesStatsCounter& SamplesStatsCounter::operator=( + const SamplesStatsCounter&) = default; +SamplesStatsCounter::SamplesStatsCounter(SamplesStatsCounter&&) = default; +SamplesStatsCounter& SamplesStatsCounter::operator=(SamplesStatsCounter&&) = + default; + +void SamplesStatsCounter::AddSample(double value) { + AddSample(StatsSample{value, Timestamp::Micros(rtc::TimeMicros())}); +} + +void SamplesStatsCounter::AddSample(StatsSample sample) { + stats_.AddSample(sample.value); + samples_.push_back(sample); + sorted_ = false; +} + +void SamplesStatsCounter::AddSamples(const SamplesStatsCounter& other) { + stats_.MergeStatistics(other.stats_); + samples_.insert(samples_.end(), other.samples_.begin(), other.samples_.end()); + sorted_ = false; +} + +double SamplesStatsCounter::GetPercentile(double percentile) { + RTC_DCHECK(!IsEmpty()); + RTC_CHECK_GE(percentile, 0); + RTC_CHECK_LE(percentile, 1); + if (!sorted_) { + absl::c_sort(samples_, [](const StatsSample& a, const StatsSample& b) { + return a.value < b.value; + }); + sorted_ = true; + } + const double raw_rank = percentile * (samples_.size() - 1); + double int_part; + double fract_part = std::modf(raw_rank, &int_part); + size_t rank = static_cast<size_t>(int_part); + if (fract_part >= 1.0) { + // It can happen due to floating point calculation error. + rank++; + fract_part -= 1.0; + } + + RTC_DCHECK_GE(rank, 0); + RTC_DCHECK_LT(rank, samples_.size()); + RTC_DCHECK_GE(fract_part, 0); + RTC_DCHECK_LT(fract_part, 1); + RTC_DCHECK(rank + fract_part == raw_rank); + + const double low = samples_[rank].value; + const double high = samples_[std::min(rank + 1, samples_.size() - 1)].value; + return low + fract_part * (high - low); +} + +SamplesStatsCounter operator*(const SamplesStatsCounter& counter, + double value) { + SamplesStatsCounter out; + for (const auto& sample : counter.GetTimedSamples()) { + out.AddSample( + SamplesStatsCounter::StatsSample{sample.value * value, sample.time}); + } + return out; +} + +SamplesStatsCounter operator/(const SamplesStatsCounter& counter, + double value) { + SamplesStatsCounter out; + for (const auto& sample : counter.GetTimedSamples()) { + out.AddSample( + SamplesStatsCounter::StatsSample{sample.value / value, sample.time}); + } + return out; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/numerics/samples_stats_counter.h b/third_party/libwebrtc/api/numerics/samples_stats_counter.h new file mode 100644 index 0000000000..9d72296317 --- /dev/null +++ b/third_party/libwebrtc/api/numerics/samples_stats_counter.h @@ -0,0 +1,126 @@ +/* + * 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. + */ + +#ifndef API_NUMERICS_SAMPLES_STATS_COUNTER_H_ +#define API_NUMERICS_SAMPLES_STATS_COUNTER_H_ + +#include <map> +#include <string> +#include <vector> + +#include "api/array_view.h" +#include "api/units/timestamp.h" +#include "rtc_base/checks.h" +#include "rtc_base/numerics/running_statistics.h" + +namespace webrtc { + +// This class extends RunningStatistics by providing GetPercentile() method, +// while slightly adapting the interface. +class SamplesStatsCounter { + public: + struct StatsSample { + double value; + Timestamp time; + // Sample's specific metadata. + std::map<std::string, std::string> metadata; + }; + + SamplesStatsCounter(); + explicit SamplesStatsCounter(size_t expected_samples_count); + ~SamplesStatsCounter(); + SamplesStatsCounter(const SamplesStatsCounter&); + SamplesStatsCounter& operator=(const SamplesStatsCounter&); + SamplesStatsCounter(SamplesStatsCounter&&); + SamplesStatsCounter& operator=(SamplesStatsCounter&&); + + // Adds sample to the stats in amortized O(1) time. + void AddSample(double value); + void AddSample(StatsSample sample); + + // Adds samples from another counter. + void AddSamples(const SamplesStatsCounter& other); + + // Returns if there are any values in O(1) time. + bool IsEmpty() const { return samples_.empty(); } + // Returns the amount of samples added into counter in O(1) time. + int64_t NumSamples() const { return stats_.Size(); } + + // Returns min in O(1) time. This function may not be called if there are no + // samples. + double GetMin() const { + RTC_DCHECK(!IsEmpty()); + return *stats_.GetMin(); + } + // Returns max in O(1) time. This function may not be called if there are no + // samples. + double GetMax() const { + RTC_DCHECK(!IsEmpty()); + return *stats_.GetMax(); + } + // Returns average in O(1) time. This function may not be called if there are + // no samples. + double GetAverage() const { + RTC_DCHECK(!IsEmpty()); + return *stats_.GetMean(); + } + // Returns variance in O(1) time. This function may not be called if there are + // no samples. + double GetVariance() const { + RTC_DCHECK(!IsEmpty()); + return *stats_.GetVariance(); + } + // Returns standard deviation in O(1) time. This function may not be called if + // there are no samples. + double GetStandardDeviation() const { + RTC_DCHECK(!IsEmpty()); + return *stats_.GetStandardDeviation(); + } + // Returns percentile in O(nlogn) on first call and in O(1) after, if no + // additions were done. This function may not be called if there are no + // samples. + // + // `percentile` has to be in [0; 1]. 0 percentile is the min in the array and + // 1 percentile is the max in the array. + double GetPercentile(double percentile); + // Returns array view with all samples added into counter. There are no + // guarantees of order, so samples can be in different order comparing to in + // which they were added into counter. Also return value will be invalidate + // after call to any non const method. + rtc::ArrayView<const StatsSample> GetTimedSamples() const { return samples_; } + std::vector<double> GetSamples() const { + std::vector<double> out; + out.reserve(samples_.size()); + for (const auto& sample : samples_) { + out.push_back(sample.value); + } + return out; + } + + private: + webrtc_impl::RunningStatistics<double> stats_; + std::vector<StatsSample> samples_; + bool sorted_ = false; +}; + +// Multiply all sample values on `value` and return new SamplesStatsCounter +// with resulted samples. Doesn't change origin SamplesStatsCounter. +SamplesStatsCounter operator*(const SamplesStatsCounter& counter, double value); +inline SamplesStatsCounter operator*(double value, + const SamplesStatsCounter& counter) { + return counter * value; +} +// Divide all sample values on `value` and return new SamplesStatsCounter with +// resulted samples. Doesn't change origin SamplesStatsCounter. +SamplesStatsCounter operator/(const SamplesStatsCounter& counter, double value); + +} // namespace webrtc + +#endif // API_NUMERICS_SAMPLES_STATS_COUNTER_H_ diff --git a/third_party/libwebrtc/api/numerics/samples_stats_counter_unittest.cc b/third_party/libwebrtc/api/numerics/samples_stats_counter_unittest.cc new file mode 100644 index 0000000000..1f9cabfb29 --- /dev/null +++ b/third_party/libwebrtc/api/numerics/samples_stats_counter_unittest.cc @@ -0,0 +1,221 @@ +/* + * 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. + */ + +#include "api/numerics/samples_stats_counter.h" + +#include <math.h> + +#include <random> +#include <vector> + +#include "absl/algorithm/container.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +SamplesStatsCounter CreateStatsFilledWithIntsFrom1ToN(int n) { + std::vector<double> data; + for (int i = 1; i <= n; i++) { + data.push_back(i); + } + absl::c_shuffle(data, std::mt19937(std::random_device()())); + + SamplesStatsCounter stats; + for (double v : data) { + stats.AddSample(v); + } + return stats; +} + +// Add n samples drawn from uniform distribution in [a;b]. +SamplesStatsCounter CreateStatsFromUniformDistribution(int n, + double a, + double b) { + std::mt19937 gen{std::random_device()()}; + std::uniform_real_distribution<> dis(a, b); + + SamplesStatsCounter stats; + for (int i = 1; i <= n; i++) { + stats.AddSample(dis(gen)); + } + return stats; +} + +class SamplesStatsCounterTest : public ::testing::TestWithParam<int> {}; + +constexpr int SIZE_FOR_MERGE = 10; + +} // namespace + +TEST(SamplesStatsCounterTest, FullSimpleTest) { + SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(100); + + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 100.0); + EXPECT_NEAR(stats.GetAverage(), 50.5, 1e-6); + for (int i = 1; i <= 100; i++) { + double p = i / 100.0; + EXPECT_GE(stats.GetPercentile(p), i); + EXPECT_LT(stats.GetPercentile(p), i + 1); + } +} + +TEST(SamplesStatsCounterTest, VarianceAndDeviation) { + SamplesStatsCounter stats; + stats.AddSample(2); + stats.AddSample(2); + stats.AddSample(-1); + stats.AddSample(5); + + EXPECT_DOUBLE_EQ(stats.GetAverage(), 2.0); + EXPECT_DOUBLE_EQ(stats.GetVariance(), 4.5); + EXPECT_DOUBLE_EQ(stats.GetStandardDeviation(), sqrt(4.5)); +} + +TEST(SamplesStatsCounterTest, FractionPercentile) { + SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(5); + + EXPECT_DOUBLE_EQ(stats.GetPercentile(0.5), 3); +} + +TEST(SamplesStatsCounterTest, TestBorderValues) { + SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(5); + + EXPECT_GE(stats.GetPercentile(0.01), 1); + EXPECT_LT(stats.GetPercentile(0.01), 2); + EXPECT_DOUBLE_EQ(stats.GetPercentile(1.0), 5); +} + +TEST(SamplesStatsCounterTest, VarianceFromUniformDistribution) { + // Check variance converge to 1/12 for [0;1) uniform distribution. + // Acts as a sanity check for NumericStabilityForVariance test. + SamplesStatsCounter stats = CreateStatsFromUniformDistribution(1e6, 0, 1); + + EXPECT_NEAR(stats.GetVariance(), 1. / 12, 1e-3); +} + +TEST(SamplesStatsCounterTest, NumericStabilityForVariance) { + // Same test as VarianceFromUniformDistribution, + // except the range is shifted to [1e9;1e9+1). + // Variance should also converge to 1/12. + // NB: Although we lose precision for the samples themselves, the fractional + // part still enjoys 22 bits of mantissa and errors should even out, + // so that couldn't explain a mismatch. + SamplesStatsCounter stats = + CreateStatsFromUniformDistribution(1e6, 1e9, 1e9 + 1); + + EXPECT_NEAR(stats.GetVariance(), 1. / 12, 1e-3); +} + +TEST_P(SamplesStatsCounterTest, AddSamples) { + int data[SIZE_FOR_MERGE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + // Split the data in different partitions. + // We have 11 distinct tests: + // * Empty merged with full sequence. + // * 1 sample merged with 9 last. + // * 2 samples merged with 8 last. + // [...] + // * Full merged with empty sequence. + // All must lead to the same result. + SamplesStatsCounter stats0, stats1; + for (int i = 0; i < GetParam(); ++i) { + stats0.AddSample(data[i]); + } + for (int i = GetParam(); i < SIZE_FOR_MERGE; ++i) { + stats1.AddSample(data[i]); + } + stats0.AddSamples(stats1); + + EXPECT_EQ(stats0.GetMin(), 0); + EXPECT_EQ(stats0.GetMax(), 9); + EXPECT_DOUBLE_EQ(stats0.GetAverage(), 4.5); + EXPECT_DOUBLE_EQ(stats0.GetVariance(), 8.25); + EXPECT_DOUBLE_EQ(stats0.GetStandardDeviation(), sqrt(8.25)); + EXPECT_DOUBLE_EQ(stats0.GetPercentile(0.1), 0.9); + EXPECT_DOUBLE_EQ(stats0.GetPercentile(0.5), 4.5); + EXPECT_DOUBLE_EQ(stats0.GetPercentile(0.9), 8.1); +} + +TEST(SamplesStatsCounterTest, MultiplyRight) { + SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(10); + + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5); + + SamplesStatsCounter multiplied_stats = stats * 10; + EXPECT_TRUE(!multiplied_stats.IsEmpty()); + EXPECT_DOUBLE_EQ(multiplied_stats.GetMin(), 10.0); + EXPECT_DOUBLE_EQ(multiplied_stats.GetMax(), 100.0); + EXPECT_DOUBLE_EQ(multiplied_stats.GetAverage(), 55.0); + EXPECT_EQ(multiplied_stats.GetSamples().size(), stats.GetSamples().size()); + + // Check that origin stats were not modified. + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5); +} + +TEST(SamplesStatsCounterTest, MultiplyLeft) { + SamplesStatsCounter stats = CreateStatsFilledWithIntsFrom1ToN(10); + + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5); + + SamplesStatsCounter multiplied_stats = 10 * stats; + EXPECT_TRUE(!multiplied_stats.IsEmpty()); + EXPECT_DOUBLE_EQ(multiplied_stats.GetMin(), 10.0); + EXPECT_DOUBLE_EQ(multiplied_stats.GetMax(), 100.0); + EXPECT_DOUBLE_EQ(multiplied_stats.GetAverage(), 55.0); + EXPECT_EQ(multiplied_stats.GetSamples().size(), stats.GetSamples().size()); + + // Check that origin stats were not modified. + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 1.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 5.5); +} + +TEST(SamplesStatsCounterTest, Divide) { + SamplesStatsCounter stats; + for (int i = 1; i <= 10; i++) { + stats.AddSample(i * 10); + } + + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 100.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 55.0); + + SamplesStatsCounter divided_stats = stats / 10; + EXPECT_TRUE(!divided_stats.IsEmpty()); + EXPECT_DOUBLE_EQ(divided_stats.GetMin(), 1.0); + EXPECT_DOUBLE_EQ(divided_stats.GetMax(), 10.0); + EXPECT_DOUBLE_EQ(divided_stats.GetAverage(), 5.5); + EXPECT_EQ(divided_stats.GetSamples().size(), stats.GetSamples().size()); + + // Check that origin stats were not modified. + EXPECT_TRUE(!stats.IsEmpty()); + EXPECT_DOUBLE_EQ(stats.GetMin(), 10.0); + EXPECT_DOUBLE_EQ(stats.GetMax(), 100.0); + EXPECT_DOUBLE_EQ(stats.GetAverage(), 55.0); +} + +INSTANTIATE_TEST_SUITE_P(SamplesStatsCounterTests, + SamplesStatsCounterTest, + ::testing::Range(0, SIZE_FOR_MERGE + 1)); + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/packet_socket_factory.h b/third_party/libwebrtc/api/packet_socket_factory.h new file mode 100644 index 0000000000..29d2606b9b --- /dev/null +++ b/third_party/libwebrtc/api/packet_socket_factory.h @@ -0,0 +1,100 @@ +/* + * Copyright 2019 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 API_PACKET_SOCKET_FACTORY_H_ +#define API_PACKET_SOCKET_FACTORY_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "api/async_dns_resolver.h" +#include "api/wrapping_async_dns_resolver.h" +#include "rtc_base/async_packet_socket.h" +#include "rtc_base/proxy_info.h" +#include "rtc_base/system/rtc_export.h" + +namespace rtc { + +class SSLCertificateVerifier; +class AsyncResolverInterface; + +struct PacketSocketTcpOptions { + PacketSocketTcpOptions() = default; + ~PacketSocketTcpOptions() = default; + + int opts = 0; + std::vector<std::string> tls_alpn_protocols; + std::vector<std::string> tls_elliptic_curves; + // An optional custom SSL certificate verifier that an API user can provide to + // inject their own certificate verification logic (not available to users + // outside of the WebRTC repo). + SSLCertificateVerifier* tls_cert_verifier = nullptr; +}; + +class RTC_EXPORT PacketSocketFactory { + public: + enum Options { + OPT_STUN = 0x04, + + // The TLS options below are mutually exclusive. + OPT_TLS = 0x02, // Real and secure TLS. + OPT_TLS_FAKE = 0x01, // Fake TLS with a dummy SSL handshake. + OPT_TLS_INSECURE = 0x08, // Insecure TLS without certificate validation. + + // Deprecated, use OPT_TLS_FAKE. + OPT_SSLTCP = OPT_TLS_FAKE, + }; + + PacketSocketFactory() = default; + virtual ~PacketSocketFactory() = default; + + virtual AsyncPacketSocket* CreateUdpSocket(const SocketAddress& address, + uint16_t min_port, + uint16_t max_port) = 0; + virtual AsyncListenSocket* CreateServerTcpSocket( + const SocketAddress& local_address, + uint16_t min_port, + uint16_t max_port, + int opts) = 0; + + virtual AsyncPacketSocket* CreateClientTcpSocket( + const SocketAddress& local_address, + const SocketAddress& remote_address, + const ProxyInfo& proxy_info, + const std::string& user_agent, + const PacketSocketTcpOptions& tcp_options) = 0; + + // The AsyncResolverInterface is deprecated; users are encouraged + // to switch to the AsyncDnsResolverInterface. + // TODO(bugs.webrtc.org/12598): Remove once all downstream users + // are converted. + virtual AsyncResolverInterface* CreateAsyncResolver() { + // Default implementation, so that downstream users can remove this + // immediately after changing to CreateAsyncDnsResolver + RTC_DCHECK_NOTREACHED(); + return nullptr; + } + + virtual std::unique_ptr<webrtc::AsyncDnsResolverInterface> + CreateAsyncDnsResolver() { + // Default implementation, to aid in transition to AsyncDnsResolverInterface + return std::make_unique<webrtc::WrappingAsyncDnsResolver>( + CreateAsyncResolver()); + } + + private: + PacketSocketFactory(const PacketSocketFactory&) = delete; + PacketSocketFactory& operator=(const PacketSocketFactory&) = delete; +}; + +} // namespace rtc + +#endif // API_PACKET_SOCKET_FACTORY_H_ diff --git a/third_party/libwebrtc/api/peer_connection_interface.cc b/third_party/libwebrtc/api/peer_connection_interface.cc new file mode 100644 index 0000000000..d01d58d32b --- /dev/null +++ b/third_party/libwebrtc/api/peer_connection_interface.cc @@ -0,0 +1,108 @@ +/* + * Copyright 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 "api/peer_connection_interface.h" + +#include <utility> + +namespace webrtc { + +PeerConnectionInterface::IceServer::IceServer() = default; +PeerConnectionInterface::IceServer::IceServer(const IceServer& rhs) = default; +PeerConnectionInterface::IceServer::~IceServer() = default; + +PeerConnectionInterface::RTCConfiguration::RTCConfiguration() = default; + +PeerConnectionInterface::RTCConfiguration::RTCConfiguration( + const RTCConfiguration& rhs) = default; + +PeerConnectionInterface::RTCConfiguration::RTCConfiguration( + RTCConfigurationType type) { + if (type == RTCConfigurationType::kAggressive) { + // These parameters are also defined in Java and IOS configurations, + // so their values may be overwritten by the Java or IOS configuration. + bundle_policy = kBundlePolicyMaxBundle; + rtcp_mux_policy = kRtcpMuxPolicyRequire; + ice_connection_receiving_timeout = kAggressiveIceConnectionReceivingTimeout; + + // These parameters are not defined in Java or IOS configuration, + // so their values will not be overwritten. + enable_ice_renomination = true; + redetermine_role_on_ice_restart = false; + } +} + +PeerConnectionInterface::RTCConfiguration::~RTCConfiguration() = default; + +PeerConnectionDependencies::PeerConnectionDependencies( + PeerConnectionObserver* observer_in) + : observer(observer_in) {} + +PeerConnectionDependencies::PeerConnectionDependencies( + PeerConnectionDependencies&&) = default; + +PeerConnectionDependencies::~PeerConnectionDependencies() = default; + +PeerConnectionFactoryDependencies::PeerConnectionFactoryDependencies() = + default; + +PeerConnectionFactoryDependencies::PeerConnectionFactoryDependencies( + PeerConnectionFactoryDependencies&&) = default; + +PeerConnectionFactoryDependencies::~PeerConnectionFactoryDependencies() = + default; + +rtc::scoped_refptr<PeerConnectionInterface> +PeerConnectionFactoryInterface::CreatePeerConnection( + const PeerConnectionInterface::RTCConfiguration& configuration, + std::unique_ptr<cricket::PortAllocator> allocator, + std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator, + PeerConnectionObserver* observer) { + PeerConnectionDependencies dependencies(observer); + dependencies.allocator = std::move(allocator); + dependencies.cert_generator = std::move(cert_generator); + auto result = + CreatePeerConnectionOrError(configuration, std::move(dependencies)); + if (!result.ok()) { + return nullptr; + } + return result.MoveValue(); +} + +rtc::scoped_refptr<PeerConnectionInterface> +PeerConnectionFactoryInterface::CreatePeerConnection( + const PeerConnectionInterface::RTCConfiguration& configuration, + PeerConnectionDependencies dependencies) { + auto result = + CreatePeerConnectionOrError(configuration, std::move(dependencies)); + if (!result.ok()) { + return nullptr; + } + return result.MoveValue(); +} + +RTCErrorOr<rtc::scoped_refptr<PeerConnectionInterface>> +PeerConnectionFactoryInterface::CreatePeerConnectionOrError( + const PeerConnectionInterface::RTCConfiguration& configuration, + PeerConnectionDependencies dependencies) { + return RTCError(RTCErrorType::INTERNAL_ERROR); +} + +RtpCapabilities PeerConnectionFactoryInterface::GetRtpSenderCapabilities( + cricket::MediaType kind) const { + return {}; +} + +RtpCapabilities PeerConnectionFactoryInterface::GetRtpReceiverCapabilities( + cricket::MediaType kind) const { + return {}; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/peer_connection_interface.h b/third_party/libwebrtc/api/peer_connection_interface.h new file mode 100644 index 0000000000..1097a1639c --- /dev/null +++ b/third_party/libwebrtc/api/peer_connection_interface.h @@ -0,0 +1,1696 @@ +/* + * Copyright 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. + */ + +// This file contains the PeerConnection interface as defined in +// https://w3c.github.io/webrtc-pc/#peer-to-peer-connections +// +// The PeerConnectionFactory class provides factory methods to create +// PeerConnection, MediaStream and MediaStreamTrack objects. +// +// The following steps are needed to setup a typical call using WebRTC: +// +// 1. Create a PeerConnectionFactoryInterface. Check constructors for more +// information about input parameters. +// +// 2. Create a PeerConnection object. Provide a configuration struct which +// points to STUN and/or TURN servers used to generate ICE candidates, and +// provide an object that implements the PeerConnectionObserver interface, +// which is used to receive callbacks from the PeerConnection. +// +// 3. Create local MediaStreamTracks using the PeerConnectionFactory and add +// them to PeerConnection by calling AddTrack (or legacy method, AddStream). +// +// 4. Create an offer, call SetLocalDescription with it, serialize it, and send +// it to the remote peer +// +// 5. Once an ICE candidate has been gathered, the PeerConnection will call the +// observer function OnIceCandidate. The candidates must also be serialized and +// sent to the remote peer. +// +// 6. Once an answer is received from the remote peer, call +// SetRemoteDescription with the remote answer. +// +// 7. Once a remote candidate is received from the remote peer, provide it to +// the PeerConnection by calling AddIceCandidate. +// +// The receiver of a call (assuming the application is "call"-based) can decide +// to accept or reject the call; this decision will be taken by the application, +// not the PeerConnection. +// +// If the application decides to accept the call, it should: +// +// 1. Create PeerConnectionFactoryInterface if it doesn't exist. +// +// 2. Create a new PeerConnection. +// +// 3. Provide the remote offer to the new PeerConnection object by calling +// SetRemoteDescription. +// +// 4. Generate an answer to the remote offer by calling CreateAnswer and send it +// back to the remote peer. +// +// 5. Provide the local answer to the new PeerConnection by calling +// SetLocalDescription with the answer. +// +// 6. Provide the remote ICE candidates by calling AddIceCandidate. +// +// 7. Once a candidate has been gathered, the PeerConnection will call the +// observer function OnIceCandidate. Send these candidates to the remote peer. + +#ifndef API_PEER_CONNECTION_INTERFACE_H_ +#define API_PEER_CONNECTION_INTERFACE_H_ + +#include <stdint.h> +#include <stdio.h> + +#include <functional> +#include <memory> +#include <string> +#include <vector> + +#include "absl/base/attributes.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/adaptation/resource.h" +#include "api/async_dns_resolver.h" +#include "api/async_resolver_factory.h" +#include "api/audio/audio_mixer.h" +#include "api/audio_codecs/audio_decoder_factory.h" +#include "api/audio_codecs/audio_encoder_factory.h" +#include "api/audio_options.h" +#include "api/call/call_factory_interface.h" +#include "api/candidate.h" +#include "api/crypto/crypto_options.h" +#include "api/data_channel_interface.h" +#include "api/dtls_transport_interface.h" +#include "api/fec_controller.h" +#include "api/field_trials_view.h" +#include "api/ice_transport_interface.h" +#include "api/jsep.h" +#include "api/legacy_stats_types.h" +#include "api/media_stream_interface.h" +#include "api/media_types.h" +#include "api/metronome/metronome.h" +#include "api/neteq/neteq_factory.h" +#include "api/network_state_predictor.h" +#include "api/packet_socket_factory.h" +#include "api/rtc_error.h" +#include "api/rtc_event_log/rtc_event_log_factory_interface.h" +#include "api/rtc_event_log_output.h" +#include "api/rtp_parameters.h" +#include "api/rtp_receiver_interface.h" +#include "api/rtp_sender_interface.h" +#include "api/rtp_transceiver_interface.h" +#include "api/scoped_refptr.h" +#include "api/sctp_transport_interface.h" +#include "api/set_local_description_observer_interface.h" +#include "api/set_remote_description_observer_interface.h" +#include "api/stats/rtc_stats_collector_callback.h" +#include "api/task_queue/task_queue_factory.h" +#include "api/transport/bitrate_settings.h" +#include "api/transport/enums.h" +#include "api/transport/network_control.h" +#include "api/transport/sctp_transport_factory_interface.h" +#include "api/turn_customizer.h" +#include "api/video/video_bitrate_allocator_factory.h" +#include "call/rtp_transport_controller_send_factory_interface.h" +#include "media/base/media_config.h" +#include "media/base/media_engine.h" +// TODO(bugs.webrtc.org/7447): We plan to provide a way to let applications +// inject a PacketSocketFactory and/or NetworkManager, and not expose +// PortAllocator in the PeerConnection api. +#include "p2p/base/port_allocator.h" +#include "rtc_base/network.h" +#include "rtc_base/network_constants.h" +#include "rtc_base/network_monitor_factory.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/rtc_certificate.h" +#include "rtc_base/rtc_certificate_generator.h" +#include "rtc_base/socket_address.h" +#include "rtc_base/ssl_certificate.h" +#include "rtc_base/ssl_stream_adapter.h" +#include "rtc_base/system/rtc_export.h" +#include "rtc_base/thread.h" + +namespace rtc { +class Thread; +} // namespace rtc + +namespace webrtc { + +// MediaStream container interface. +class StreamCollectionInterface : public rtc::RefCountInterface { + public: + // TODO(ronghuawu): Update the function names to c++ style, e.g. find -> Find. + virtual size_t count() = 0; + virtual MediaStreamInterface* at(size_t index) = 0; + virtual MediaStreamInterface* find(const std::string& label) = 0; + virtual MediaStreamTrackInterface* FindAudioTrack(const std::string& id) = 0; + virtual MediaStreamTrackInterface* FindVideoTrack(const std::string& id) = 0; + + protected: + // Dtor protected as objects shouldn't be deleted via this interface. + ~StreamCollectionInterface() override = default; +}; + +class StatsObserver : public rtc::RefCountInterface { + public: + virtual void OnComplete(const StatsReports& reports) = 0; + + protected: + ~StatsObserver() override = default; +}; + +enum class SdpSemantics { + // TODO(https://crbug.com/webrtc/13528): Remove support for kPlanB. + kPlanB_DEPRECATED, + kPlanB [[deprecated]] = kPlanB_DEPRECATED, + kUnifiedPlan, +}; + +class RTC_EXPORT PeerConnectionInterface : public rtc::RefCountInterface { + public: + // See https://w3c.github.io/webrtc-pc/#dom-rtcsignalingstate + enum SignalingState { + kStable, + kHaveLocalOffer, + kHaveLocalPrAnswer, + kHaveRemoteOffer, + kHaveRemotePrAnswer, + kClosed, + }; + static constexpr absl::string_view AsString(SignalingState); + + // See https://w3c.github.io/webrtc-pc/#dom-rtcicegatheringstate + enum IceGatheringState { + kIceGatheringNew, + kIceGatheringGathering, + kIceGatheringComplete + }; + static constexpr absl::string_view AsString(IceGatheringState state); + + // See https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnectionstate + enum class PeerConnectionState { + kNew, + kConnecting, + kConnected, + kDisconnected, + kFailed, + kClosed, + }; + static constexpr absl::string_view AsString(PeerConnectionState state); + + // See https://w3c.github.io/webrtc-pc/#dom-rtciceconnectionstate + enum IceConnectionState { + kIceConnectionNew, + kIceConnectionChecking, + kIceConnectionConnected, + kIceConnectionCompleted, + kIceConnectionFailed, + kIceConnectionDisconnected, + kIceConnectionClosed, + kIceConnectionMax, + }; + static constexpr absl::string_view AsString(IceConnectionState state); + + // TLS certificate policy. + enum TlsCertPolicy { + // For TLS based protocols, ensure the connection is secure by not + // circumventing certificate validation. + kTlsCertPolicySecure, + // For TLS based protocols, disregard security completely by skipping + // certificate validation. This is insecure and should never be used unless + // security is irrelevant in that particular context. + kTlsCertPolicyInsecureNoCheck, + }; + + struct RTC_EXPORT IceServer { + IceServer(); + IceServer(const IceServer&); + ~IceServer(); + + // TODO(jbauch): Remove uri when all code using it has switched to urls. + // List of URIs associated with this server. Valid formats are described + // in RFC7064 and RFC7065, and more may be added in the future. The "host" + // part of the URI may contain either an IP address or a hostname. + std::string uri; + std::vector<std::string> urls; + std::string username; + std::string password; + TlsCertPolicy tls_cert_policy = kTlsCertPolicySecure; + // If the URIs in `urls` only contain IP addresses, this field can be used + // to indicate the hostname, which may be necessary for TLS (using the SNI + // extension). If `urls` itself contains the hostname, this isn't + // necessary. + std::string hostname; + // List of protocols to be used in the TLS ALPN extension. + std::vector<std::string> tls_alpn_protocols; + // List of elliptic curves to be used in the TLS elliptic curves extension. + std::vector<std::string> tls_elliptic_curves; + + bool operator==(const IceServer& o) const { + return uri == o.uri && urls == o.urls && username == o.username && + password == o.password && tls_cert_policy == o.tls_cert_policy && + hostname == o.hostname && + tls_alpn_protocols == o.tls_alpn_protocols && + tls_elliptic_curves == o.tls_elliptic_curves; + } + bool operator!=(const IceServer& o) const { return !(*this == o); } + }; + typedef std::vector<IceServer> IceServers; + + enum IceTransportsType { + // TODO(pthatcher): Rename these kTransporTypeXXX, but update + // Chromium at the same time. + kNone, + kRelay, + kNoHost, + kAll + }; + + // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24#section-4.1.1 + enum BundlePolicy { + kBundlePolicyBalanced, + kBundlePolicyMaxBundle, + kBundlePolicyMaxCompat + }; + + // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24#section-4.1.1 + enum RtcpMuxPolicy { + kRtcpMuxPolicyNegotiate, + kRtcpMuxPolicyRequire, + }; + + enum TcpCandidatePolicy { + kTcpCandidatePolicyEnabled, + kTcpCandidatePolicyDisabled + }; + + enum CandidateNetworkPolicy { + kCandidateNetworkPolicyAll, + kCandidateNetworkPolicyLowCost + }; + + enum ContinualGatheringPolicy { GATHER_ONCE, GATHER_CONTINUALLY }; + + struct PortAllocatorConfig { + // For min_port and max_port, 0 means not specified. + int min_port = 0; + int max_port = 0; + uint32_t flags = 0; // Same as kDefaultPortAllocatorFlags. + }; + + enum class RTCConfigurationType { + // A configuration that is safer to use, despite not having the best + // performance. Currently this is the default configuration. + kSafe, + // An aggressive configuration that has better performance, although it + // may be riskier and may need extra support in the application. + kAggressive + }; + + // TODO(hbos): Change into class with private data and public getters. + // TODO(nisse): In particular, accessing fields directly from an + // application is brittle, since the organization mirrors the + // organization of the implementation, which isn't stable. So we + // need getters and setters at least for fields which applications + // are interested in. + struct RTC_EXPORT RTCConfiguration { + // This struct is subject to reorganization, both for naming + // consistency, and to group settings to match where they are used + // in the implementation. To do that, we need getter and setter + // methods for all settings which are of interest to applications, + // Chrome in particular. + + RTCConfiguration(); + RTCConfiguration(const RTCConfiguration&); + explicit RTCConfiguration(RTCConfigurationType type); + ~RTCConfiguration(); + + bool operator==(const RTCConfiguration& o) const; + bool operator!=(const RTCConfiguration& o) const; + + bool dscp() const { return media_config.enable_dscp; } + void set_dscp(bool enable) { media_config.enable_dscp = enable; } + + bool cpu_adaptation() const { + return media_config.video.enable_cpu_adaptation; + } + void set_cpu_adaptation(bool enable) { + media_config.video.enable_cpu_adaptation = enable; + } + + bool suspend_below_min_bitrate() const { + return media_config.video.suspend_below_min_bitrate; + } + void set_suspend_below_min_bitrate(bool enable) { + media_config.video.suspend_below_min_bitrate = enable; + } + + bool prerenderer_smoothing() const { + return media_config.video.enable_prerenderer_smoothing; + } + void set_prerenderer_smoothing(bool enable) { + media_config.video.enable_prerenderer_smoothing = enable; + } + + bool experiment_cpu_load_estimator() const { + return media_config.video.experiment_cpu_load_estimator; + } + void set_experiment_cpu_load_estimator(bool enable) { + media_config.video.experiment_cpu_load_estimator = enable; + } + + int audio_rtcp_report_interval_ms() const { + return media_config.audio.rtcp_report_interval_ms; + } + void set_audio_rtcp_report_interval_ms(int audio_rtcp_report_interval_ms) { + media_config.audio.rtcp_report_interval_ms = + audio_rtcp_report_interval_ms; + } + + int video_rtcp_report_interval_ms() const { + return media_config.video.rtcp_report_interval_ms; + } + void set_video_rtcp_report_interval_ms(int video_rtcp_report_interval_ms) { + media_config.video.rtcp_report_interval_ms = + video_rtcp_report_interval_ms; + } + + // Settings for the port allcoator. Applied only if the port allocator is + // created by PeerConnectionFactory, not if it is injected with + // PeerConnectionDependencies + int min_port() const { return port_allocator_config.min_port; } + void set_min_port(int port) { port_allocator_config.min_port = port; } + int max_port() const { return port_allocator_config.max_port; } + void set_max_port(int port) { port_allocator_config.max_port = port; } + uint32_t port_allocator_flags() { return port_allocator_config.flags; } + void set_port_allocator_flags(uint32_t flags) { + port_allocator_config.flags = flags; + } + + static const int kUndefined = -1; + // Default maximum number of packets in the audio jitter buffer. + static const int kAudioJitterBufferMaxPackets = 200; + // ICE connection receiving timeout for aggressive configuration. + static const int kAggressiveIceConnectionReceivingTimeout = 1000; + + //////////////////////////////////////////////////////////////////////// + // The below few fields mirror the standard RTCConfiguration dictionary: + // https://w3c.github.io/webrtc-pc/#rtcconfiguration-dictionary + //////////////////////////////////////////////////////////////////////// + + // TODO(pthatcher): Rename this ice_servers, but update Chromium + // at the same time. + IceServers servers; + // TODO(pthatcher): Rename this ice_transport_type, but update + // Chromium at the same time. + IceTransportsType type = kAll; + BundlePolicy bundle_policy = kBundlePolicyBalanced; + RtcpMuxPolicy rtcp_mux_policy = kRtcpMuxPolicyRequire; + std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates; + int ice_candidate_pool_size = 0; + + ////////////////////////////////////////////////////////////////////////// + // The below fields correspond to constraints from the deprecated + // constraints interface for constructing a PeerConnection. + // + // absl::optional fields can be "missing", in which case the implementation + // default will be used. + ////////////////////////////////////////////////////////////////////////// + + // If set to true, don't gather IPv6 ICE candidates on Wi-Fi. + // Only intended to be used on specific devices. Certain phones disable IPv6 + // when the screen is turned off and it would be better to just disable the + // IPv6 ICE candidates on Wi-Fi in those cases. + bool disable_ipv6_on_wifi = false; + + // By default, the PeerConnection will use a limited number of IPv6 network + // interfaces, in order to avoid too many ICE candidate pairs being created + // and delaying ICE completion. + // + // Can be set to INT_MAX to effectively disable the limit. + int max_ipv6_networks = cricket::kDefaultMaxIPv6Networks; + + // Exclude link-local network interfaces + // from consideration for gathering ICE candidates. + bool disable_link_local_networks = false; + + // Minimum bitrate at which screencast video tracks will be encoded at. + // This means adding padding bits up to this bitrate, which can help + // when switching from a static scene to one with motion. + absl::optional<int> screencast_min_bitrate; + + // Use new combined audio/video bandwidth estimation? + absl::optional<bool> combined_audio_video_bwe; + +#if defined(WEBRTC_FUCHSIA) + // TODO(bugs.webrtc.org/11066): Remove entirely once Fuchsia does not use. + // TODO(bugs.webrtc.org/9891) - Move to crypto_options + // Can be used to disable DTLS-SRTP. This should never be done, but can be + // useful for testing purposes, for example in setting up a loopback call + // with a single PeerConnection. + absl::optional<bool> enable_dtls_srtp; +#endif + + ///////////////////////////////////////////////// + // The below fields are not part of the standard. + ///////////////////////////////////////////////// + + // Can be used to disable TCP candidate generation. + TcpCandidatePolicy tcp_candidate_policy = kTcpCandidatePolicyEnabled; + + // Can be used to avoid gathering candidates for a "higher cost" network, + // if a lower cost one exists. For example, if both Wi-Fi and cellular + // interfaces are available, this could be used to avoid using the cellular + // interface. + CandidateNetworkPolicy candidate_network_policy = + kCandidateNetworkPolicyAll; + + // The maximum number of packets that can be stored in the NetEq audio + // jitter buffer. Can be reduced to lower tolerated audio latency. + int audio_jitter_buffer_max_packets = kAudioJitterBufferMaxPackets; + + // Whether to use the NetEq "fast mode" which will accelerate audio quicker + // if it falls behind. + bool audio_jitter_buffer_fast_accelerate = false; + + // The minimum delay in milliseconds for the audio jitter buffer. + int audio_jitter_buffer_min_delay_ms = 0; + + // Timeout in milliseconds before an ICE candidate pair is considered to be + // "not receiving", after which a lower priority candidate pair may be + // selected. + int ice_connection_receiving_timeout = kUndefined; + + // Interval in milliseconds at which an ICE "backup" candidate pair will be + // pinged. This is a candidate pair which is not actively in use, but may + // be switched to if the active candidate pair becomes unusable. + // + // This is relevant mainly to Wi-Fi/cell handoff; the application may not + // want this backup cellular candidate pair pinged frequently, since it + // consumes data/battery. + int ice_backup_candidate_pair_ping_interval = kUndefined; + + // Can be used to enable continual gathering, which means new candidates + // will be gathered as network interfaces change. Note that if continual + // gathering is used, the candidate removal API should also be used, to + // avoid an ever-growing list of candidates. + ContinualGatheringPolicy continual_gathering_policy = GATHER_ONCE; + + // If set to true, candidate pairs will be pinged in order of most likely + // to work (which means using a TURN server, generally), rather than in + // standard priority order. + bool prioritize_most_likely_ice_candidate_pairs = false; + + // Implementation defined settings. A public member only for the benefit of + // the implementation. Applications must not access it directly, and should + // instead use provided accessor methods, e.g., set_cpu_adaptation. + struct cricket::MediaConfig media_config; + + // If set to true, only one preferred TURN allocation will be used per + // network interface. UDP is preferred over TCP and IPv6 over IPv4. This + // can be used to cut down on the number of candidate pairings. + // Deprecated. TODO(webrtc:11026) Remove this flag once the downstream + // dependency is removed. + bool prune_turn_ports = false; + + // The policy used to prune turn port. + PortPrunePolicy turn_port_prune_policy = NO_PRUNE; + + PortPrunePolicy GetTurnPortPrunePolicy() const { + return prune_turn_ports ? PRUNE_BASED_ON_PRIORITY + : turn_port_prune_policy; + } + + // If set to true, this means the ICE transport should presume TURN-to-TURN + // candidate pairs will succeed, even before a binding response is received. + // This can be used to optimize the initial connection time, since the DTLS + // handshake can begin immediately. + bool presume_writable_when_fully_relayed = false; + + // If true, "renomination" will be added to the ice options in the transport + // description. + // See: https://tools.ietf.org/html/draft-thatcher-ice-renomination-00 + bool enable_ice_renomination = false; + + // If true, the ICE role is re-determined when the PeerConnection sets a + // local transport description that indicates an ICE restart. + // + // This is standard RFC5245 ICE behavior, but causes unnecessary role + // thrashing, so an application may wish to avoid it. This role + // re-determining was removed in ICEbis (ICE v2). + bool redetermine_role_on_ice_restart = true; + + // This flag is only effective when `continual_gathering_policy` is + // GATHER_CONTINUALLY. + // + // If true, after the ICE transport type is changed such that new types of + // ICE candidates are allowed by the new transport type, e.g. from + // IceTransportsType::kRelay to IceTransportsType::kAll, candidates that + // have been gathered by the ICE transport but not matching the previous + // transport type and as a result not observed by PeerConnectionObserver, + // will be surfaced to the observer. + bool surface_ice_candidates_on_ice_transport_type_changed = false; + + // The following fields define intervals in milliseconds at which ICE + // connectivity checks are sent. + // + // We consider ICE is "strongly connected" for an agent when there is at + // least one candidate pair that currently succeeds in connectivity check + // from its direction i.e. sending a STUN ping and receives a STUN ping + // response, AND all candidate pairs have sent a minimum number of pings for + // connectivity (this number is implementation-specific). Otherwise, ICE is + // considered in "weak connectivity". + // + // Note that the above notion of strong and weak connectivity is not defined + // in RFC 5245, and they apply to our current ICE implementation only. + // + // 1) ice_check_interval_strong_connectivity defines the interval applied to + // ALL candidate pairs when ICE is strongly connected, and it overrides the + // default value of this interval in the ICE implementation; + // 2) ice_check_interval_weak_connectivity defines the counterpart for ALL + // pairs when ICE is weakly connected, and it overrides the default value of + // this interval in the ICE implementation; + // 3) ice_check_min_interval defines the minimal interval (equivalently the + // maximum rate) that overrides the above two intervals when either of them + // is less. + absl::optional<int> ice_check_interval_strong_connectivity; + absl::optional<int> ice_check_interval_weak_connectivity; + absl::optional<int> ice_check_min_interval; + + // The min time period for which a candidate pair must wait for response to + // connectivity checks before it becomes unwritable. This parameter + // overrides the default value in the ICE implementation if set. + absl::optional<int> ice_unwritable_timeout; + + // The min number of connectivity checks that a candidate pair must sent + // without receiving response before it becomes unwritable. This parameter + // overrides the default value in the ICE implementation if set. + absl::optional<int> ice_unwritable_min_checks; + + // The min time period for which a candidate pair must wait for response to + // connectivity checks it becomes inactive. This parameter overrides the + // default value in the ICE implementation if set. + absl::optional<int> ice_inactive_timeout; + + // The interval in milliseconds at which STUN candidates will resend STUN + // binding requests to keep NAT bindings open. + absl::optional<int> stun_candidate_keepalive_interval; + + // Optional TurnCustomizer. + // With this class one can modify outgoing TURN messages. + // The object passed in must remain valid until PeerConnection::Close() is + // called. + webrtc::TurnCustomizer* turn_customizer = nullptr; + + // Preferred network interface. + // A candidate pair on a preferred network has a higher precedence in ICE + // than one on an un-preferred network, regardless of priority or network + // cost. + absl::optional<rtc::AdapterType> network_preference; + + // Configure the SDP semantics used by this PeerConnection. By default, this + // is Unified Plan which is compliant to the WebRTC 1.0 specification. It is + // possible to overrwite this to the deprecated Plan B SDP format, but note + // that kPlanB will be deleted at some future date, see + // https://crbug.com/webrtc/13528. + // + // kUnifiedPlan will cause the PeerConnection to create offers and answers + // with multiple m= sections where each m= section maps to one RtpSender and + // one RtpReceiver (an RtpTransceiver), either both audio or both video. + // This will also cause the PeerConnection to ignore all but the first + // a=ssrc lines that form a Plan B streams (if the PeerConnection is given + // Plan B SDP to process). + // + // kPlanB will cause the PeerConnection to create offers and answers with at + // most one audio and one video m= section with multiple RtpSenders and + // RtpReceivers specified as multiple a=ssrc lines within the section. This + // will also cause PeerConnection to ignore all but the first m= section of + // the same media type (if the PeerConnection is given Unified Plan SDP to + // process). + SdpSemantics sdp_semantics = SdpSemantics::kUnifiedPlan; + + // TODO(bugs.webrtc.org/9891) - Move to crypto_options or remove. + // Actively reset the SRTP parameters whenever the DTLS transports + // underneath are reset for every offer/answer negotiation. + // This is only intended to be a workaround for crbug.com/835958 + // WARNING: This would cause RTP/RTCP packets decryption failure if not used + // correctly. This flag will be deprecated soon. Do not rely on it. + bool active_reset_srtp_params = false; + + // Defines advanced optional cryptographic settings related to SRTP and + // frame encryption for native WebRTC. Setting this will overwrite any + // settings set in PeerConnectionFactory (which is deprecated). + absl::optional<CryptoOptions> crypto_options; + + // Configure if we should include the SDP attribute extmap-allow-mixed in + // our offer on session level. + bool offer_extmap_allow_mixed = true; + + // TURN logging identifier. + // This identifier is added to a TURN allocation + // and it intended to be used to be able to match client side + // logs with TURN server logs. It will not be added if it's an empty string. + std::string turn_logging_id; + + // Added to be able to control rollout of this feature. + bool enable_implicit_rollback = false; + + // Whether network condition based codec switching is allowed. + absl::optional<bool> allow_codec_switching; + + // The delay before doing a usage histogram report for long-lived + // PeerConnections. Used for testing only. + absl::optional<int> report_usage_pattern_delay_ms; + + // The ping interval (ms) when the connection is stable and writable. This + // parameter overrides the default value in the ICE implementation if set. + absl::optional<int> stable_writable_connection_ping_interval_ms; + + // Whether this PeerConnection will avoid VPNs (kAvoidVpn), prefer VPNs + // (kPreferVpn), only work over VPN (kOnlyUseVpn) or only work over non-VPN + // (kNeverUseVpn) interfaces. This controls which local interfaces the + // PeerConnection will prefer to connect over. Since VPN detection is not + // perfect, adherence to this preference cannot be guaranteed. + VpnPreference vpn_preference = VpnPreference::kDefault; + + // List of address/length subnets that should be treated like + // VPN (in case webrtc fails to auto detect them). + std::vector<rtc::NetworkMask> vpn_list; + + PortAllocatorConfig port_allocator_config; + + // The burst interval of the pacer, see TaskQueuePacedSender constructor. + absl::optional<TimeDelta> pacer_burst_interval; + + // + // Don't forget to update operator== if adding something. + // + }; + + // See: https://www.w3.org/TR/webrtc/#idl-def-rtcofferansweroptions + struct RTCOfferAnswerOptions { + static const int kUndefined = -1; + static const int kMaxOfferToReceiveMedia = 1; + + // The default value for constraint offerToReceiveX:true. + static const int kOfferToReceiveMediaTrue = 1; + + // These options are left as backwards compatibility for clients who need + // "Plan B" semantics. Clients who have switched to "Unified Plan" semantics + // should use the RtpTransceiver API (AddTransceiver) instead. + // + // offer_to_receive_X set to 1 will cause a media description to be + // generated in the offer, even if no tracks of that type have been added. + // Values greater than 1 are treated the same. + // + // If set to 0, the generated directional attribute will not include the + // "recv" direction (meaning it will be "sendonly" or "inactive". + int offer_to_receive_video = kUndefined; + int offer_to_receive_audio = kUndefined; + + bool voice_activity_detection = true; + bool ice_restart = false; + + // If true, will offer to BUNDLE audio/video/data together. Not to be + // confused with RTCP mux (multiplexing RTP and RTCP together). + bool use_rtp_mux = true; + + // If true, "a=packetization:<payload_type> raw" attribute will be offered + // in the SDP for all video payload and accepted in the answer if offered. + bool raw_packetization_for_video = false; + + // This will apply to all video tracks with a Plan B SDP offer/answer. + int num_simulcast_layers = 1; + + // If true: Use SDP format from draft-ietf-mmusic-scdp-sdp-03 + // If false: Use SDP format from draft-ietf-mmusic-sdp-sdp-26 or later + bool use_obsolete_sctp_sdp = false; + + RTCOfferAnswerOptions() = default; + + RTCOfferAnswerOptions(int offer_to_receive_video, + int offer_to_receive_audio, + bool voice_activity_detection, + bool ice_restart, + bool use_rtp_mux) + : offer_to_receive_video(offer_to_receive_video), + offer_to_receive_audio(offer_to_receive_audio), + voice_activity_detection(voice_activity_detection), + ice_restart(ice_restart), + use_rtp_mux(use_rtp_mux) {} + }; + + // Used by GetStats to decide which stats to include in the stats reports. + // `kStatsOutputLevelStandard` includes the standard stats for Javascript API; + // `kStatsOutputLevelDebug` includes both the standard stats and additional + // stats for debugging purposes. + enum StatsOutputLevel { + kStatsOutputLevelStandard, + kStatsOutputLevelDebug, + }; + + // Accessor methods to active local streams. + // This method is not supported with kUnifiedPlan semantics. Please use + // GetSenders() instead. + virtual rtc::scoped_refptr<StreamCollectionInterface> local_streams() = 0; + + // Accessor methods to remote streams. + // This method is not supported with kUnifiedPlan semantics. Please use + // GetReceivers() instead. + virtual rtc::scoped_refptr<StreamCollectionInterface> remote_streams() = 0; + + // Add a new MediaStream to be sent on this PeerConnection. + // Note that a SessionDescription negotiation is needed before the + // remote peer can receive the stream. + // + // This has been removed from the standard in favor of a track-based API. So, + // this is equivalent to simply calling AddTrack for each track within the + // stream, with the one difference that if "stream->AddTrack(...)" is called + // later, the PeerConnection will automatically pick up the new track. Though + // this functionality will be deprecated in the future. + // + // This method is not supported with kUnifiedPlan semantics. Please use + // AddTrack instead. + virtual bool AddStream(MediaStreamInterface* stream) = 0; + + // Remove a MediaStream from this PeerConnection. + // Note that a SessionDescription negotiation is needed before the + // remote peer is notified. + // + // This method is not supported with kUnifiedPlan semantics. Please use + // RemoveTrack instead. + virtual void RemoveStream(MediaStreamInterface* stream) = 0; + + // Add a new MediaStreamTrack to be sent on this PeerConnection, and return + // the newly created RtpSender. The RtpSender will be associated with the + // streams specified in the `stream_ids` list. + // + // Errors: + // - INVALID_PARAMETER: `track` is null, has a kind other than audio or video, + // or a sender already exists for the track. + // - INVALID_STATE: The PeerConnection is closed. + virtual RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrack( + rtc::scoped_refptr<MediaStreamTrackInterface> track, + const std::vector<std::string>& stream_ids) = 0; + + // Add a new MediaStreamTrack as above, but with an additional parameter, + // `init_send_encodings` : initial RtpEncodingParameters for RtpSender, + // similar to init_send_encodings in RtpTransceiverInit. + // Note that a new transceiver will always be created. + // + virtual RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrack( + rtc::scoped_refptr<MediaStreamTrackInterface> track, + const std::vector<std::string>& stream_ids, + const std::vector<RtpEncodingParameters>& init_send_encodings) = 0; + + // Removes the connection between a MediaStreamTrack and the PeerConnection. + // Stops sending on the RtpSender and marks the + // corresponding RtpTransceiver direction as no longer sending. + // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-removetrack + // + // Errors: + // - INVALID_PARAMETER: `sender` is null or (Plan B only) the sender is not + // associated with this PeerConnection. + // - INVALID_STATE: PeerConnection is closed. + // + // Plan B semantics: Removes the RtpSender from this PeerConnection. + // + // TODO(bugs.webrtc.org/9534): Rename to RemoveTrack once the other signature + // is removed; remove default implementation once upstream is updated. + virtual RTCError RemoveTrackOrError( + rtc::scoped_refptr<RtpSenderInterface> sender) { + RTC_CHECK_NOTREACHED(); + return RTCError(); + } + + // AddTransceiver creates a new RtpTransceiver and adds it to the set of + // transceivers. Adding a transceiver will cause future calls to CreateOffer + // to add a media description for the corresponding transceiver. + // + // The initial value of `mid` in the returned transceiver is null. Setting a + // new session description may change it to a non-null value. + // + // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addtransceiver + // + // Optionally, an RtpTransceiverInit structure can be specified to configure + // the transceiver from construction. If not specified, the transceiver will + // default to having a direction of kSendRecv and not be part of any streams. + // + // These methods are only available when Unified Plan is enabled (see + // RTCConfiguration). + // + // Common errors: + // - INTERNAL_ERROR: The configuration does not have Unified Plan enabled. + + // Adds a transceiver with a sender set to transmit the given track. The kind + // of the transceiver (and sender/receiver) will be derived from the kind of + // the track. + // Errors: + // - INVALID_PARAMETER: `track` is null. + virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> + AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track) = 0; + virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> + AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track, + const RtpTransceiverInit& init) = 0; + + // Adds a transceiver with the given kind. Can either be MEDIA_TYPE_AUDIO or + // MEDIA_TYPE_VIDEO. + // Errors: + // - INVALID_PARAMETER: `media_type` is not MEDIA_TYPE_AUDIO or + // MEDIA_TYPE_VIDEO. + virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> + AddTransceiver(cricket::MediaType media_type) = 0; + virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> + AddTransceiver(cricket::MediaType media_type, + const RtpTransceiverInit& init) = 0; + + // Creates a sender without a track. Can be used for "early media"/"warmup" + // use cases, where the application may want to negotiate video attributes + // before a track is available to send. + // + // The standard way to do this would be through "addTransceiver", but we + // don't support that API yet. + // + // `kind` must be "audio" or "video". + // + // `stream_id` is used to populate the msid attribute; if empty, one will + // be generated automatically. + // + // This method is not supported with kUnifiedPlan semantics. Please use + // AddTransceiver instead. + virtual rtc::scoped_refptr<RtpSenderInterface> CreateSender( + const std::string& kind, + const std::string& stream_id) = 0; + + // If Plan B semantics are specified, gets all RtpSenders, created either + // through AddStream, AddTrack, or CreateSender. All senders of a specific + // media type share the same media description. + // + // If Unified Plan semantics are specified, gets the RtpSender for each + // RtpTransceiver. + virtual std::vector<rtc::scoped_refptr<RtpSenderInterface>> GetSenders() + const = 0; + + // If Plan B semantics are specified, gets all RtpReceivers created when a + // remote description is applied. All receivers of a specific media type share + // the same media description. It is also possible to have a media description + // with no associated RtpReceivers, if the directional attribute does not + // indicate that the remote peer is sending any media. + // + // If Unified Plan semantics are specified, gets the RtpReceiver for each + // RtpTransceiver. + virtual std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetReceivers() + const = 0; + + // Get all RtpTransceivers, created either through AddTransceiver, AddTrack or + // by a remote description applied with SetRemoteDescription. + // + // Note: This method is only available when Unified Plan is enabled (see + // RTCConfiguration). + virtual std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> + GetTransceivers() const = 0; + + // The legacy non-compliant GetStats() API. This correspond to the + // callback-based version of getStats() in JavaScript. The returned metrics + // are UNDOCUMENTED and many of them rely on implementation-specific details. + // The goal is to DELETE THIS VERSION but we can't today because it is heavily + // relied upon by third parties. See https://crbug.com/822696. + // + // This version is wired up into Chrome. Any stats implemented are + // automatically exposed to the Web Platform. This has BYPASSED the Chrome + // release processes for years and lead to cross-browser incompatibility + // issues and web application reliance on Chrome-only behavior. + // + // This API is in "maintenance mode", serious regressions should be fixed but + // adding new stats is highly discouraged. + // + // TODO(hbos): Deprecate and remove this when third parties have migrated to + // the spec-compliant GetStats() API. https://crbug.com/822696 + virtual bool GetStats(StatsObserver* observer, + MediaStreamTrackInterface* track, // Optional + StatsOutputLevel level) = 0; + // The spec-compliant GetStats() API. This correspond to the promise-based + // version of getStats() in JavaScript. Implementation status is described in + // api/stats/rtcstats_objects.h. For more details on stats, see spec: + // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-getstats + // TODO(hbos): Takes shared ownership, use rtc::scoped_refptr<> instead. This + // requires stop overriding the current version in third party or making third + // party calls explicit to avoid ambiguity during switch. Make the future + // version abstract as soon as third party projects implement it. + virtual void GetStats(RTCStatsCollectorCallback* callback) = 0; + // Spec-compliant getStats() performing the stats selection algorithm with the + // sender. https://w3c.github.io/webrtc-pc/#dom-rtcrtpsender-getstats + virtual void GetStats( + rtc::scoped_refptr<RtpSenderInterface> selector, + rtc::scoped_refptr<RTCStatsCollectorCallback> callback) = 0; + // Spec-compliant getStats() performing the stats selection algorithm with the + // receiver. https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-getstats + virtual void GetStats( + rtc::scoped_refptr<RtpReceiverInterface> selector, + rtc::scoped_refptr<RTCStatsCollectorCallback> callback) = 0; + // Clear cached stats in the RTCStatsCollector. + virtual void ClearStatsCache() {} + + // Create a data channel with the provided config, or default config if none + // is provided. Note that an offer/answer negotiation is still necessary + // before the data channel can be used. + // + // Also, calling CreateDataChannel is the only way to get a data "m=" section + // in SDP, so it should be done before CreateOffer is called, if the + // application plans to use data channels. + virtual RTCErrorOr<rtc::scoped_refptr<DataChannelInterface>> + CreateDataChannelOrError(const std::string& label, + const DataChannelInit* config) { + return RTCError(RTCErrorType::INTERNAL_ERROR, "dummy function called"); + } + // TODO(crbug.com/788659): Remove "virtual" below and default implementation + // above once mock in Chrome is fixed. + ABSL_DEPRECATED("Use CreateDataChannelOrError") + virtual rtc::scoped_refptr<DataChannelInterface> CreateDataChannel( + const std::string& label, + const DataChannelInit* config) { + auto result = CreateDataChannelOrError(label, config); + if (!result.ok()) { + return nullptr; + } else { + return result.MoveValue(); + } + } + + // NOTE: For the following 6 methods, it's only safe to dereference the + // SessionDescriptionInterface on signaling_thread() (for example, calling + // ToString). + + // Returns the more recently applied description; "pending" if it exists, and + // otherwise "current". See below. + virtual const SessionDescriptionInterface* local_description() const = 0; + virtual const SessionDescriptionInterface* remote_description() const = 0; + + // A "current" description the one currently negotiated from a complete + // offer/answer exchange. + virtual const SessionDescriptionInterface* current_local_description() + const = 0; + virtual const SessionDescriptionInterface* current_remote_description() + const = 0; + + // A "pending" description is one that's part of an incomplete offer/answer + // exchange (thus, either an offer or a pranswer). Once the offer/answer + // exchange is finished, the "pending" description will become "current". + virtual const SessionDescriptionInterface* pending_local_description() + const = 0; + virtual const SessionDescriptionInterface* pending_remote_description() + const = 0; + + // Tells the PeerConnection that ICE should be restarted. This triggers a need + // for negotiation and subsequent CreateOffer() calls will act as if + // RTCOfferAnswerOptions::ice_restart is true. + // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-restartice + // TODO(hbos): Remove default implementation when downstream projects + // implement this. + virtual void RestartIce() = 0; + + // Create a new offer. + // The CreateSessionDescriptionObserver callback will be called when done. + virtual void CreateOffer(CreateSessionDescriptionObserver* observer, + const RTCOfferAnswerOptions& options) = 0; + + // Create an answer to an offer. + // The CreateSessionDescriptionObserver callback will be called when done. + virtual void CreateAnswer(CreateSessionDescriptionObserver* observer, + const RTCOfferAnswerOptions& options) = 0; + + // Sets the local session description. + // + // According to spec, the local session description MUST be the same as was + // returned by CreateOffer() or CreateAnswer() or else the operation should + // fail. Our implementation however allows some amount of "SDP munging", but + // please note that this is HIGHLY DISCOURAGED. If you do not intent to munge + // SDP, the method below that doesn't take `desc` as an argument will create + // the offer or answer for you. + // + // The observer is invoked as soon as the operation completes, which could be + // before or after the SetLocalDescription() method has exited. + virtual void SetLocalDescription( + std::unique_ptr<SessionDescriptionInterface> desc, + rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer) {} + // Creates an offer or answer (depending on current signaling state) and sets + // it as the local session description. + // + // The observer is invoked as soon as the operation completes, which could be + // before or after the SetLocalDescription() method has exited. + virtual void SetLocalDescription( + rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer) {} + // Like SetLocalDescription() above, but the observer is invoked with a delay + // after the operation completes. This helps avoid recursive calls by the + // observer but also makes it possible for states to change in-between the + // operation completing and the observer getting called. This makes them racy + // for synchronizing peer connection states to the application. + // TODO(https://crbug.com/webrtc/11798): Delete these methods in favor of the + // ones taking SetLocalDescriptionObserverInterface as argument. + virtual void SetLocalDescription(SetSessionDescriptionObserver* observer, + SessionDescriptionInterface* desc) = 0; + virtual void SetLocalDescription(SetSessionDescriptionObserver* observer) {} + + // Sets the remote session description. + // + // (Unlike "SDP munging" before SetLocalDescription(), modifying a remote + // offer or answer is allowed by the spec.) + // + // The observer is invoked as soon as the operation completes, which could be + // before or after the SetRemoteDescription() method has exited. + virtual void SetRemoteDescription( + std::unique_ptr<SessionDescriptionInterface> desc, + rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer) = 0; + // Like SetRemoteDescription() above, but the observer is invoked with a delay + // after the operation completes. This helps avoid recursive calls by the + // observer but also makes it possible for states to change in-between the + // operation completing and the observer getting called. This makes them racy + // for synchronizing peer connection states to the application. + // TODO(https://crbug.com/webrtc/11798): Delete this method in favor of the + // ones taking SetRemoteDescriptionObserverInterface as argument. + virtual void SetRemoteDescription(SetSessionDescriptionObserver* observer, + SessionDescriptionInterface* desc) {} + + // According to spec, we must only fire "negotiationneeded" if the Operations + // Chain is empty. This method takes care of validating an event previously + // generated with PeerConnectionObserver::OnNegotiationNeededEvent() to make + // sure that even if there was a delay (e.g. due to a PostTask) between the + // event being generated and the time of firing, the Operations Chain is empty + // and the event is still valid to be fired. + virtual bool ShouldFireNegotiationNeededEvent(uint32_t event_id) { + return true; + } + + virtual PeerConnectionInterface::RTCConfiguration GetConfiguration() = 0; + + // Sets the PeerConnection's global configuration to `config`. + // + // The members of `config` that may be changed are `type`, `servers`, + // `ice_candidate_pool_size` and `prune_turn_ports` (though the candidate + // pool size can't be changed after the first call to SetLocalDescription). + // Note that this means the BUNDLE and RTCP-multiplexing policies cannot be + // changed with this method. + // + // Any changes to STUN/TURN servers or ICE candidate policy will affect the + // next gathering phase, and cause the next call to createOffer to generate + // new ICE credentials, as described in JSEP. This also occurs when + // `prune_turn_ports` changes, for the same reasoning. + // + // If an error occurs, returns false and populates `error` if non-null: + // - INVALID_MODIFICATION if `config` contains a modified parameter other + // than one of the parameters listed above. + // - INVALID_RANGE if `ice_candidate_pool_size` is out of range. + // - SYNTAX_ERROR if parsing an ICE server URL failed. + // - INVALID_PARAMETER if a TURN server is missing `username` or `password`. + // - INTERNAL_ERROR if an unexpected error occurred. + virtual RTCError SetConfiguration( + const PeerConnectionInterface::RTCConfiguration& config) = 0; + + // Provides a remote candidate to the ICE Agent. + // A copy of the `candidate` will be created and added to the remote + // description. So the caller of this method still has the ownership of the + // `candidate`. + // TODO(hbos): The spec mandates chaining this operation onto the operations + // chain; deprecate and remove this version in favor of the callback-based + // signature. + virtual bool AddIceCandidate(const IceCandidateInterface* candidate) = 0; + // TODO(hbos): Remove default implementation once implemented by downstream + // projects. + virtual void AddIceCandidate(std::unique_ptr<IceCandidateInterface> candidate, + std::function<void(RTCError)> callback) {} + + // Removes a group of remote candidates from the ICE agent. Needed mainly for + // continual gathering, to avoid an ever-growing list of candidates as + // networks come and go. Note that the candidates' transport_name must be set + // to the MID of the m= section that generated the candidate. + // TODO(bugs.webrtc.org/8395): Use IceCandidateInterface instead of + // cricket::Candidate, which would avoid the transport_name oddity. + virtual bool RemoveIceCandidates( + const std::vector<cricket::Candidate>& candidates) = 0; + + // SetBitrate limits the bandwidth allocated for all RTP streams sent by + // this PeerConnection. Other limitations might affect these limits and + // are respected (for example "b=AS" in SDP). + // + // Setting `current_bitrate_bps` will reset the current bitrate estimate + // to the provided value. + virtual RTCError SetBitrate(const BitrateSettings& bitrate) = 0; + + // Enable/disable playout of received audio streams. Enabled by default. Note + // that even if playout is enabled, streams will only be played out if the + // appropriate SDP is also applied. Setting `playout` to false will stop + // playout of the underlying audio device but starts a task which will poll + // for audio data every 10ms to ensure that audio processing happens and the + // audio statistics are updated. + virtual void SetAudioPlayout(bool playout) {} + + // Enable/disable recording of transmitted audio streams. Enabled by default. + // Note that even if recording is enabled, streams will only be recorded if + // the appropriate SDP is also applied. + virtual void SetAudioRecording(bool recording) {} + + // Looks up the DtlsTransport associated with a MID value. + // In the Javascript API, DtlsTransport is a property of a sender, but + // because the PeerConnection owns the DtlsTransport in this implementation, + // it is better to look them up on the PeerConnection. + virtual rtc::scoped_refptr<DtlsTransportInterface> LookupDtlsTransportByMid( + const std::string& mid) = 0; + + // Returns the SCTP transport, if any. + virtual rtc::scoped_refptr<SctpTransportInterface> GetSctpTransport() + const = 0; + + // Returns the current SignalingState. + virtual SignalingState signaling_state() = 0; + + // Returns an aggregate state of all ICE *and* DTLS transports. + // This is left in place to avoid breaking native clients who expect our old, + // nonstandard behavior. + // TODO(jonasolsson): deprecate and remove this. + virtual IceConnectionState ice_connection_state() = 0; + + // Returns an aggregated state of all ICE transports. + virtual IceConnectionState standardized_ice_connection_state() = 0; + + // Returns an aggregated state of all ICE and DTLS transports. + virtual PeerConnectionState peer_connection_state() = 0; + + virtual IceGatheringState ice_gathering_state() = 0; + + // Returns the current state of canTrickleIceCandidates per + // https://w3c.github.io/webrtc-pc/#attributes-1 + virtual absl::optional<bool> can_trickle_ice_candidates() { + // TODO(crbug.com/708484): Remove default implementation. + return absl::nullopt; + } + + // When a resource is overused, the PeerConnection will try to reduce the load + // on the sysem, for example by reducing the resolution or frame rate of + // encoded streams. The Resource API allows injecting platform-specific usage + // measurements. The conditions to trigger kOveruse or kUnderuse are up to the + // implementation. + // TODO(hbos): Make pure virtual when implemented by downstream projects. + virtual void AddAdaptationResource(rtc::scoped_refptr<Resource> resource) {} + + // Start RtcEventLog using an existing output-sink. Takes ownership of + // `output` and passes it on to Call, which will take the ownership. If the + // operation fails the output will be closed and deallocated. The event log + // will send serialized events to the output object every `output_period_ms`. + // Applications using the event log should generally make their own trade-off + // regarding the output period. A long period is generally more efficient, + // with potential drawbacks being more bursty thread usage, and more events + // lost in case the application crashes. If the `output_period_ms` argument is + // omitted, webrtc selects a default deemed to be workable in most cases. + virtual bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output, + int64_t output_period_ms) = 0; + virtual bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output) = 0; + + // Stops logging the RtcEventLog. + virtual void StopRtcEventLog() = 0; + + // Terminates all media, closes the transports, and in general releases any + // resources used by the PeerConnection. This is an irreversible operation. + // + // Note that after this method completes, the PeerConnection will no longer + // use the PeerConnectionObserver interface passed in on construction, and + // thus the observer object can be safely destroyed. + virtual void Close() = 0; + + // The thread on which all PeerConnectionObserver callbacks will be invoked, + // as well as callbacks for other classes such as DataChannelObserver. + // + // Also the only thread on which it's safe to use SessionDescriptionInterface + // pointers. + // TODO(deadbeef): Make pure virtual when all subclasses implement it. + virtual rtc::Thread* signaling_thread() const { return nullptr; } + + protected: + // Dtor protected as objects shouldn't be deleted via this interface. + ~PeerConnectionInterface() override = default; +}; + +// PeerConnection callback interface, used for RTCPeerConnection events. +// Application should implement these methods. +class PeerConnectionObserver { + public: + virtual ~PeerConnectionObserver() = default; + + // Triggered when the SignalingState changed. + virtual void OnSignalingChange( + PeerConnectionInterface::SignalingState new_state) = 0; + + // Triggered when media is received on a new stream from remote peer. + virtual void OnAddStream(rtc::scoped_refptr<MediaStreamInterface> stream) {} + + // Triggered when a remote peer closes a stream. + virtual void OnRemoveStream(rtc::scoped_refptr<MediaStreamInterface> stream) { + } + + // Triggered when a remote peer opens a data channel. + virtual void OnDataChannel( + rtc::scoped_refptr<DataChannelInterface> data_channel) = 0; + + // Triggered when renegotiation is needed. For example, an ICE restart + // has begun. + // TODO(hbos): Delete in favor of OnNegotiationNeededEvent() when downstream + // projects have migrated. + virtual void OnRenegotiationNeeded() {} + // Used to fire spec-compliant onnegotiationneeded events, which should only + // fire when the Operations Chain is empty. The observer is responsible for + // queuing a task (e.g. Chromium: jump to main thread) to maybe fire the + // event. The event identified using `event_id` must only fire if + // PeerConnection::ShouldFireNegotiationNeededEvent() returns true since it is + // possible for the event to become invalidated by operations subsequently + // chained. + virtual void OnNegotiationNeededEvent(uint32_t event_id) {} + + // Called any time the legacy IceConnectionState changes. + // + // Note that our ICE states lag behind the standard slightly. The most + // notable differences include the fact that "failed" occurs after 15 + // seconds, not 30, and this actually represents a combination ICE + DTLS + // state, so it may be "failed" if DTLS fails while ICE succeeds. + // + // TODO(jonasolsson): deprecate and remove this. + virtual void OnIceConnectionChange( + PeerConnectionInterface::IceConnectionState new_state) {} + + // Called any time the standards-compliant IceConnectionState changes. + virtual void OnStandardizedIceConnectionChange( + PeerConnectionInterface::IceConnectionState new_state) {} + + // Called any time the PeerConnectionState changes. + virtual void OnConnectionChange( + PeerConnectionInterface::PeerConnectionState new_state) {} + + // Called any time the IceGatheringState changes. + virtual void OnIceGatheringChange( + PeerConnectionInterface::IceGatheringState new_state) = 0; + + // A new ICE candidate has been gathered. + virtual void OnIceCandidate(const IceCandidateInterface* candidate) = 0; + + // Gathering of an ICE candidate failed. + // See https://w3c.github.io/webrtc-pc/#event-icecandidateerror + virtual void OnIceCandidateError(const std::string& address, + int port, + const std::string& url, + int error_code, + const std::string& error_text) {} + + // Ice candidates have been removed. + // TODO(honghaiz): Make this a pure virtual method when all its subclasses + // implement it. + virtual void OnIceCandidatesRemoved( + const std::vector<cricket::Candidate>& candidates) {} + + // Called when the ICE connection receiving status changes. + virtual void OnIceConnectionReceivingChange(bool receiving) {} + + // Called when the selected candidate pair for the ICE connection changes. + virtual void OnIceSelectedCandidatePairChanged( + const cricket::CandidatePairChangeEvent& event) {} + + // This is called when a receiver and its track are created. + // TODO(zhihuang): Make this pure virtual when all subclasses implement it. + // Note: This is called with both Plan B and Unified Plan semantics. Unified + // Plan users should prefer OnTrack, OnAddTrack is only called as backwards + // compatibility (and is called in the exact same situations as OnTrack). + virtual void OnAddTrack( + rtc::scoped_refptr<RtpReceiverInterface> receiver, + const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {} + + // This is called when signaling indicates a transceiver will be receiving + // media from the remote endpoint. This is fired during a call to + // SetRemoteDescription. The receiving track can be accessed by: + // `transceiver->receiver()->track()` and its associated streams by + // `transceiver->receiver()->streams()`. + // Note: This will only be called if Unified Plan semantics are specified. + // This behavior is specified in section 2.2.8.2.5 of the "Set the + // RTCSessionDescription" algorithm: + // https://w3c.github.io/webrtc-pc/#set-description + virtual void OnTrack( + rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {} + + // Called when signaling indicates that media will no longer be received on a + // track. + // With Plan B semantics, the given receiver will have been removed from the + // PeerConnection and the track muted. + // With Unified Plan semantics, the receiver will remain but the transceiver + // will have changed direction to either sendonly or inactive. + // https://w3c.github.io/webrtc-pc/#process-remote-track-removal + // TODO(hbos,deadbeef): Make pure virtual when all subclasses implement it. + virtual void OnRemoveTrack( + rtc::scoped_refptr<RtpReceiverInterface> receiver) {} + + // Called when an interesting usage is detected by WebRTC. + // An appropriate action is to add information about the context of the + // PeerConnection and write the event to some kind of "interesting events" + // log function. + // The heuristics for defining what constitutes "interesting" are + // implementation-defined. + virtual void OnInterestingUsage(int usage_pattern) {} +}; + +// PeerConnectionDependencies holds all of PeerConnections dependencies. +// A dependency is distinct from a configuration as it defines significant +// executable code that can be provided by a user of the API. +// +// All new dependencies should be added as a unique_ptr to allow the +// PeerConnection object to be the definitive owner of the dependencies +// lifetime making injection safer. +struct RTC_EXPORT PeerConnectionDependencies final { + explicit PeerConnectionDependencies(PeerConnectionObserver* observer_in); + // This object is not copyable or assignable. + PeerConnectionDependencies(const PeerConnectionDependencies&) = delete; + PeerConnectionDependencies& operator=(const PeerConnectionDependencies&) = + delete; + // This object is only moveable. + PeerConnectionDependencies(PeerConnectionDependencies&&); + PeerConnectionDependencies& operator=(PeerConnectionDependencies&&) = default; + ~PeerConnectionDependencies(); + // Mandatory dependencies + PeerConnectionObserver* observer = nullptr; + // Optional dependencies + // TODO(bugs.webrtc.org/7447): remove port allocator once downstream is + // updated. The recommended way to inject networking components is to pass a + // PacketSocketFactory when creating the PeerConnectionFactory. + std::unique_ptr<cricket::PortAllocator> allocator; + // Factory for creating resolvers that look up hostnames in DNS + std::unique_ptr<webrtc::AsyncDnsResolverFactoryInterface> + async_dns_resolver_factory; + // Deprecated - use async_dns_resolver_factory + std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory; + std::unique_ptr<webrtc::IceTransportFactory> ice_transport_factory; + std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator; + std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier; + std::unique_ptr<webrtc::VideoBitrateAllocatorFactory> + video_bitrate_allocator_factory; + // Optional field trials to use. + // Overrides those from PeerConnectionFactoryDependencies. + std::unique_ptr<FieldTrialsView> trials; +}; + +// PeerConnectionFactoryDependencies holds all of the PeerConnectionFactory +// dependencies. All new dependencies should be added here instead of +// overloading the function. This simplifies dependency injection and makes it +// clear which are mandatory and optional. If possible please allow the peer +// connection factory to take ownership of the dependency by adding a unique_ptr +// to this structure. +struct RTC_EXPORT PeerConnectionFactoryDependencies final { + PeerConnectionFactoryDependencies(); + // This object is not copyable or assignable. + PeerConnectionFactoryDependencies(const PeerConnectionFactoryDependencies&) = + delete; + PeerConnectionFactoryDependencies& operator=( + const PeerConnectionFactoryDependencies&) = delete; + // This object is only moveable. + PeerConnectionFactoryDependencies(PeerConnectionFactoryDependencies&&); + PeerConnectionFactoryDependencies& operator=( + PeerConnectionFactoryDependencies&&) = default; + ~PeerConnectionFactoryDependencies(); + + // Optional dependencies + rtc::Thread* network_thread = nullptr; + rtc::Thread* worker_thread = nullptr; + rtc::Thread* signaling_thread = nullptr; + rtc::SocketFactory* socket_factory = nullptr; + // The `packet_socket_factory` will only be used if CreatePeerConnection is + // called without a `port_allocator`. + std::unique_ptr<rtc::PacketSocketFactory> packet_socket_factory; + std::unique_ptr<TaskQueueFactory> task_queue_factory; + std::unique_ptr<cricket::MediaEngineInterface> media_engine; + std::unique_ptr<CallFactoryInterface> call_factory; + std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory; + std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory; + std::unique_ptr<NetworkStatePredictorFactoryInterface> + network_state_predictor_factory; + std::unique_ptr<NetworkControllerFactoryInterface> network_controller_factory; + // The `network_manager` will only be used if CreatePeerConnection is called + // without a `port_allocator`, causing the default allocator and network + // manager to be used. + std::unique_ptr<rtc::NetworkManager> network_manager; + // The `network_monitor_factory` will only be used if CreatePeerConnection is + // called without a `port_allocator`, and the above `network_manager' is null. + std::unique_ptr<rtc::NetworkMonitorFactory> network_monitor_factory; + std::unique_ptr<NetEqFactory> neteq_factory; + std::unique_ptr<SctpTransportFactoryInterface> sctp_factory; + std::unique_ptr<FieldTrialsView> trials; + std::unique_ptr<RtpTransportControllerSendFactoryInterface> + transport_controller_send_factory; + std::unique_ptr<Metronome> metronome; +}; + +// PeerConnectionFactoryInterface is the factory interface used for creating +// PeerConnection, MediaStream and MediaStreamTrack objects. +// +// The simplest method for obtaiing one, CreatePeerConnectionFactory will +// create the required libjingle threads, socket and network manager factory +// classes for networking if none are provided, though it requires that the +// application runs a message loop on the thread that called the method (see +// explanation below) +// +// If an application decides to provide its own threads and/or implementation +// of networking classes, it should use the alternate +// CreatePeerConnectionFactory method which accepts threads as input, and use +// the CreatePeerConnection version that takes a PortAllocator as an argument. +class RTC_EXPORT PeerConnectionFactoryInterface + : public rtc::RefCountInterface { + public: + class Options { + public: + Options() {} + + // If set to true, created PeerConnections won't enforce any SRTP + // requirement, allowing unsecured media. Should only be used for + // testing/debugging. + bool disable_encryption = false; + + // If set to true, any platform-supported network monitoring capability + // won't be used, and instead networks will only be updated via polling. + // + // This only has an effect if a PeerConnection is created with the default + // PortAllocator implementation. + bool disable_network_monitor = false; + + // Sets the network types to ignore. For instance, calling this with + // ADAPTER_TYPE_ETHERNET | ADAPTER_TYPE_LOOPBACK will ignore Ethernet and + // loopback interfaces. + int network_ignore_mask = rtc::kDefaultNetworkIgnoreMask; + + // Sets the maximum supported protocol version. The highest version + // supported by both ends will be used for the connection, i.e. if one + // party supports DTLS 1.0 and the other DTLS 1.2, DTLS 1.0 will be used. + rtc::SSLProtocolVersion ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12; + + // Sets crypto related options, e.g. enabled cipher suites. + CryptoOptions crypto_options = CryptoOptions::NoGcm(); + }; + + // Set the options to be used for subsequently created PeerConnections. + virtual void SetOptions(const Options& options) = 0; + + // The preferred way to create a new peer connection. Simply provide the + // configuration and a PeerConnectionDependencies structure. + // TODO(benwright): Make pure virtual once downstream mock PC factory classes + // are updated. + virtual RTCErrorOr<rtc::scoped_refptr<PeerConnectionInterface>> + CreatePeerConnectionOrError( + const PeerConnectionInterface::RTCConfiguration& configuration, + PeerConnectionDependencies dependencies); + // Deprecated creator - does not return an error code on error. + // TODO(bugs.webrtc.org:12238): Deprecate and remove. + ABSL_DEPRECATED("Use CreatePeerConnectionOrError") + virtual rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection( + const PeerConnectionInterface::RTCConfiguration& configuration, + PeerConnectionDependencies dependencies); + + // Deprecated; `allocator` and `cert_generator` may be null, in which case + // default implementations will be used. + // + // `observer` must not be null. + // + // Note that this method does not take ownership of `observer`; it's the + // responsibility of the caller to delete it. It can be safely deleted after + // Close has been called on the returned PeerConnection, which ensures no + // more observer callbacks will be invoked. + ABSL_DEPRECATED("Use CreatePeerConnectionOrError") + virtual rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection( + const PeerConnectionInterface::RTCConfiguration& configuration, + std::unique_ptr<cricket::PortAllocator> allocator, + std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator, + PeerConnectionObserver* observer); + + // Returns the capabilities of an RTP sender of type `kind`. + // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure. + // TODO(orphis): Make pure virtual when all subclasses implement it. + virtual RtpCapabilities GetRtpSenderCapabilities( + cricket::MediaType kind) const; + + // Returns the capabilities of an RTP receiver of type `kind`. + // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure. + // TODO(orphis): Make pure virtual when all subclasses implement it. + virtual RtpCapabilities GetRtpReceiverCapabilities( + cricket::MediaType kind) const; + + virtual rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream( + const std::string& stream_id) = 0; + + // Creates an AudioSourceInterface. + // `options` decides audio processing settings. + virtual rtc::scoped_refptr<AudioSourceInterface> CreateAudioSource( + const cricket::AudioOptions& options) = 0; + + // Creates a new local VideoTrack. The same `source` can be used in several + // tracks. + virtual rtc::scoped_refptr<VideoTrackInterface> CreateVideoTrack( + const std::string& label, + VideoTrackSourceInterface* source) = 0; + + // Creates an new AudioTrack. At the moment `source` can be null. + virtual rtc::scoped_refptr<AudioTrackInterface> CreateAudioTrack( + const std::string& label, + AudioSourceInterface* source) = 0; + + // Starts AEC dump using existing file. Takes ownership of `file` and passes + // it on to VoiceEngine (via other objects) immediately, which will take + // the ownerhip. If the operation fails, the file will be closed. + // A maximum file size in bytes can be specified. When the file size limit is + // reached, logging is stopped automatically. If max_size_bytes is set to a + // value <= 0, no limit will be used, and logging will continue until the + // StopAecDump function is called. + // TODO(webrtc:6463): Delete default implementation when downstream mocks + // classes are updated. + virtual bool StartAecDump(FILE* file, int64_t max_size_bytes) { + return false; + } + + // Stops logging the AEC dump. + virtual void StopAecDump() = 0; + + protected: + // Dtor and ctor protected as objects shouldn't be created or deleted via + // this interface. + PeerConnectionFactoryInterface() {} + ~PeerConnectionFactoryInterface() override = default; +}; + +// CreateModularPeerConnectionFactory is implemented in the "peerconnection" +// build target, which doesn't pull in the implementations of every module +// webrtc may use. +// +// If an application knows it will only require certain modules, it can reduce +// webrtc's impact on its binary size by depending only on the "peerconnection" +// target and the modules the application requires, using +// CreateModularPeerConnectionFactory. For example, if an application +// only uses WebRTC for audio, it can pass in null pointers for the +// video-specific interfaces, and omit the corresponding modules from its +// build. +// +// If `network_thread` or `worker_thread` are null, the PeerConnectionFactory +// will create the necessary thread internally. If `signaling_thread` is null, +// the PeerConnectionFactory will use the thread on which this method is called +// as the signaling thread, wrapping it in an rtc::Thread object if needed. +RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface> +CreateModularPeerConnectionFactory( + PeerConnectionFactoryDependencies dependencies); + +// https://w3c.github.io/webrtc-pc/#dom-rtcsignalingstate +inline constexpr absl::string_view PeerConnectionInterface::AsString( + SignalingState state) { + switch (state) { + case SignalingState::kStable: + return "stable"; + case SignalingState::kHaveLocalOffer: + return "have-local-offer"; + case SignalingState::kHaveLocalPrAnswer: + return "have-local-pranswer"; + case SignalingState::kHaveRemoteOffer: + return "have-remote-offer"; + case SignalingState::kHaveRemotePrAnswer: + return "have-remote-pranswer"; + case SignalingState::kClosed: + return "closed"; + } + // This cannot happen. + // Not using "RTC_CHECK_NOTREACHED()" because AsString() is constexpr. + return ""; +} + +// https://w3c.github.io/webrtc-pc/#dom-rtcicegatheringstate +inline constexpr absl::string_view PeerConnectionInterface::AsString( + IceGatheringState state) { + switch (state) { + case IceGatheringState::kIceGatheringNew: + return "new"; + case IceGatheringState::kIceGatheringGathering: + return "gathering"; + case IceGatheringState::kIceGatheringComplete: + return "complete"; + } + // This cannot happen. + // Not using "RTC_CHECK_NOTREACHED()" because AsString() is constexpr. + return ""; +} + +// https://w3c.github.io/webrtc-pc/#dom-rtciceconnectionstate +inline constexpr absl::string_view PeerConnectionInterface::AsString( + PeerConnectionState state) { + switch (state) { + case PeerConnectionState::kNew: + return "new"; + case PeerConnectionState::kConnecting: + return "connecting"; + case PeerConnectionState::kConnected: + return "connected"; + case PeerConnectionState::kDisconnected: + return "disconnected"; + case PeerConnectionState::kFailed: + return "failed"; + case PeerConnectionState::kClosed: + return "closed"; + } + // This cannot happen. + // Not using "RTC_CHECK_NOTREACHED()" because AsString() is constexpr. + return ""; +} + +inline constexpr absl::string_view PeerConnectionInterface::AsString( + IceConnectionState state) { + switch (state) { + case kIceConnectionNew: + return "new"; + case kIceConnectionChecking: + return "checking"; + case kIceConnectionConnected: + return "connected"; + case kIceConnectionCompleted: + return "completed"; + case kIceConnectionFailed: + return "failed"; + case kIceConnectionDisconnected: + return "disconnected"; + case kIceConnectionClosed: + return "closed"; + case kIceConnectionMax: + // This cannot happen. + // Not using "RTC_CHECK_NOTREACHED()" because AsString() is constexpr. + return ""; + } + // This cannot happen. + // Not using "RTC_CHECK_NOTREACHED()" because AsString() is constexpr. + return ""; +} + +} // namespace webrtc + +#endif // API_PEER_CONNECTION_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/priority.h b/third_party/libwebrtc/api/priority.h new file mode 100644 index 0000000000..4953e453a3 --- /dev/null +++ b/third_party/libwebrtc/api/priority.h @@ -0,0 +1,26 @@ +/* + * Copyright 2020 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 API_PRIORITY_H_ +#define API_PRIORITY_H_ + +namespace webrtc { + +// GENERATED_JAVA_ENUM_PACKAGE: org.webrtc +enum class Priority { + kVeryLow, + kLow, + kMedium, + kHigh, +}; + +} // namespace webrtc + +#endif // API_PRIORITY_H_ diff --git a/third_party/libwebrtc/api/priority_gn/moz.build b/third_party/libwebrtc/api/priority_gn/moz.build new file mode 100644 index 0000000000..08cb5bf2d5 --- /dev/null +++ b/third_party/libwebrtc/api/priority_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("priority_gn") diff --git a/third_party/libwebrtc/api/ref_counted_base.h b/third_party/libwebrtc/api/ref_counted_base.h new file mode 100644 index 0000000000..f20228b740 --- /dev/null +++ b/third_party/libwebrtc/api/ref_counted_base.h @@ -0,0 +1,98 @@ +/* + * Copyright 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. + */ +#ifndef API_REF_COUNTED_BASE_H_ +#define API_REF_COUNTED_BASE_H_ + +#include <type_traits> + +#include "rtc_base/ref_counter.h" + +namespace rtc { + +class RefCountedBase { + public: + RefCountedBase() = default; + + RefCountedBase(const RefCountedBase&) = delete; + RefCountedBase& operator=(const RefCountedBase&) = delete; + + void AddRef() const { ref_count_.IncRef(); } + RefCountReleaseStatus Release() const { + const auto status = ref_count_.DecRef(); + if (status == RefCountReleaseStatus::kDroppedLastRef) { + delete this; + } + return status; + } + + protected: + // Provided for internal webrtc subclasses for corner cases where it's + // necessary to know whether or not a reference is exclusively held. + bool HasOneRef() const { return ref_count_.HasOneRef(); } + + virtual ~RefCountedBase() = default; + + private: + mutable webrtc::webrtc_impl::RefCounter ref_count_{0}; +}; + +// Template based version of `RefCountedBase` for simple implementations that do +// not need (or want) destruction via virtual destructor or the overhead of a +// vtable. +// +// To use: +// struct MyInt : public rtc::RefCountedNonVirtual<MyInt> { +// int foo_ = 0; +// }; +// +// rtc::scoped_refptr<MyInt> my_int(new MyInt()); +// +// sizeof(MyInt) on a 32 bit system would then be 8, int + refcount and no +// vtable generated. +template <typename T> +class RefCountedNonVirtual { + public: + RefCountedNonVirtual() = default; + + RefCountedNonVirtual(const RefCountedNonVirtual&) = delete; + RefCountedNonVirtual& operator=(const RefCountedNonVirtual&) = delete; + + void AddRef() const { ref_count_.IncRef(); } + RefCountReleaseStatus Release() const { + // If you run into this assert, T has virtual methods. There are two + // options: + // 1) The class doesn't actually need virtual methods, the type is complete + // so the virtual attribute(s) can be removed. + // 2) The virtual methods are a part of the design of the class. In this + // case you can consider using `RefCountedBase` instead or alternatively + // use `rtc::RefCountedObject`. + static_assert(!std::is_polymorphic<T>::value, + "T has virtual methods. RefCountedBase is a better fit."); + const auto status = ref_count_.DecRef(); + if (status == RefCountReleaseStatus::kDroppedLastRef) { + delete static_cast<const T*>(this); + } + return status; + } + + protected: + // Provided for internal webrtc subclasses for corner cases where it's + // necessary to know whether or not a reference is exclusively held. + bool HasOneRef() const { return ref_count_.HasOneRef(); } + + ~RefCountedNonVirtual() = default; + + private: + mutable webrtc::webrtc_impl::RefCounter ref_count_{0}; +}; + +} // namespace rtc + +#endif // API_REF_COUNTED_BASE_H_ diff --git a/third_party/libwebrtc/api/refcountedbase_gn/moz.build b/third_party/libwebrtc/api/refcountedbase_gn/moz.build new file mode 100644 index 0000000000..f2a22be846 --- /dev/null +++ b/third_party/libwebrtc/api/refcountedbase_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("refcountedbase_gn") diff --git a/third_party/libwebrtc/api/rtc_error.cc b/third_party/libwebrtc/api/rtc_error.cc new file mode 100644 index 0000000000..4d3033baf5 --- /dev/null +++ b/third_party/libwebrtc/api/rtc_error.cc @@ -0,0 +1,80 @@ +/* + * Copyright 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. + */ + +#include "api/rtc_error.h" + +#include "rtc_base/arraysize.h" + +namespace { + +const char* kRTCErrorTypeNames[] = { + "NONE", + "UNSUPPORTED_OPERATION", + "UNSUPPORTED_PARAMETER", + "INVALID_PARAMETER", + "INVALID_RANGE", + "SYNTAX_ERROR", + "INVALID_STATE", + "INVALID_MODIFICATION", + "NETWORK_ERROR", + "RESOURCE_EXHAUSTED", + "INTERNAL_ERROR", + "OPERATION_ERROR_WITH_DATA", +}; +static_assert( + static_cast<int>(webrtc::RTCErrorType::OPERATION_ERROR_WITH_DATA) == + (arraysize(kRTCErrorTypeNames) - 1), + "kRTCErrorTypeNames must have as many strings as RTCErrorType " + "has values."); + +const char* kRTCErrorDetailTypeNames[] = { + "NONE", + "DATA_CHANNEL_FAILURE", + "DTLS_FAILURE", + "FINGERPRINT_FAILURE", + "SCTP_FAILURE", + "SDP_SYNTAX_ERROR", + "HARDWARE_ENCODER_NOT_AVAILABLE", + "HARDWARE_ENCODER_ERROR", +}; +static_assert( + static_cast<int>(webrtc::RTCErrorDetailType::HARDWARE_ENCODER_ERROR) == + (arraysize(kRTCErrorDetailTypeNames) - 1), + "kRTCErrorDetailTypeNames must have as many strings as " + "RTCErrorDetailType has values."); + +} // namespace + +namespace webrtc { + +// static +RTCError RTCError::OK() { + return RTCError(); +} + +const char* RTCError::message() const { + return message_.c_str(); +} + +void RTCError::set_message(std::string message) { + message_ = std::move(message); +} + +const char* ToString(RTCErrorType error) { + int index = static_cast<int>(error); + return kRTCErrorTypeNames[index]; +} + +const char* ToString(RTCErrorDetailType error) { + int index = static_cast<int>(error); + return kRTCErrorDetailTypeNames[index]; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtc_error.h b/third_party/libwebrtc/api/rtc_error.h new file mode 100644 index 0000000000..42ceed18d9 --- /dev/null +++ b/third_party/libwebrtc/api/rtc_error.h @@ -0,0 +1,331 @@ +/* + * Copyright 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. + */ + +#ifndef API_RTC_ERROR_H_ +#define API_RTC_ERROR_H_ + +#ifdef WEBRTC_UNIT_TEST +#include <ostream> +#endif // WEBRTC_UNIT_TEST +#include <string> +#include <utility> // For std::move. + +#include "absl/types/optional.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Enumeration to represent distinct classes of errors that an application +// may wish to act upon differently. These roughly map to DOMExceptions or +// RTCError "errorDetailEnum" values in the web API, as described in the +// comments below. +enum class RTCErrorType { + // No error. + NONE, + + // An operation is valid, but currently unsupported. + // Maps to OperationError DOMException. + UNSUPPORTED_OPERATION, + + // A supplied parameter is valid, but currently unsupported. + // Maps to OperationError DOMException. + UNSUPPORTED_PARAMETER, + + // General error indicating that a supplied parameter is invalid. + // Maps to InvalidAccessError or TypeError DOMException depending on context. + INVALID_PARAMETER, + + // Slightly more specific than INVALID_PARAMETER; a parameter's value was + // outside the allowed range. + // Maps to RangeError DOMException. + INVALID_RANGE, + + // Slightly more specific than INVALID_PARAMETER; an error occurred while + // parsing string input. + // Maps to SyntaxError DOMException. + SYNTAX_ERROR, + + // The object does not support this operation in its current state. + // Maps to InvalidStateError DOMException. + INVALID_STATE, + + // An attempt was made to modify the object in an invalid way. + // Maps to InvalidModificationError DOMException. + INVALID_MODIFICATION, + + // An error occurred within an underlying network protocol. + // Maps to NetworkError DOMException. + NETWORK_ERROR, + + // Some resource has been exhausted; file handles, hardware resources, ports, + // etc. + // Maps to OperationError DOMException. + RESOURCE_EXHAUSTED, + + // The operation failed due to an internal error. + // Maps to OperationError DOMException. + INTERNAL_ERROR, + + // An error occured that has additional data. + // The additional data is specified in + // https://w3c.github.io/webrtc-pc/#rtcerror-interface + // Maps to RTCError DOMException. + OPERATION_ERROR_WITH_DATA, +}; + +// Detail information, showing what further information should be present. +// https://w3c.github.io/webrtc-pc/#rtcerrordetailtype-enum +enum class RTCErrorDetailType { + NONE, + DATA_CHANNEL_FAILURE, + DTLS_FAILURE, + FINGERPRINT_FAILURE, + SCTP_FAILURE, + SDP_SYNTAX_ERROR, + HARDWARE_ENCODER_NOT_AVAILABLE, + HARDWARE_ENCODER_ERROR, +}; + +// Roughly corresponds to RTCError in the web api. Holds an error type, a +// message, and possibly additional information specific to that error. +// +// Doesn't contain anything beyond a type and message now, but will in the +// future as more errors are implemented. +class RTC_EXPORT RTCError { + public: + // Constructors. + + // Creates a "no error" error. + RTCError() {} + explicit RTCError(RTCErrorType type) : type_(type) {} + + RTCError(RTCErrorType type, std::string message) + : type_(type), message_(std::move(message)) {} + + // In many use cases, it is better to use move than copy, + // but copy and assignment are provided for those cases that need it. + // Note that this has extra overhead because it copies strings. + RTCError(const RTCError& other) = default; + RTCError(RTCError&&) = default; + RTCError& operator=(const RTCError& other) = default; + RTCError& operator=(RTCError&&) = default; + + // Identical to default constructed error. + // + // Preferred over the default constructor for code readability. + static RTCError OK(); + + // Error type. + RTCErrorType type() const { return type_; } + void set_type(RTCErrorType type) { type_ = type; } + + // Human-readable message describing the error. Shouldn't be used for + // anything but logging/diagnostics, since messages are not guaranteed to be + // stable. + const char* message() const; + + void set_message(std::string message); + + RTCErrorDetailType error_detail() const { return error_detail_; } + void set_error_detail(RTCErrorDetailType detail) { error_detail_ = detail; } + absl::optional<uint16_t> sctp_cause_code() const { return sctp_cause_code_; } + void set_sctp_cause_code(uint16_t cause_code) { + sctp_cause_code_ = cause_code; + } + + // Convenience method for situations where you only care whether or not an + // error occurred. + bool ok() const { return type_ == RTCErrorType::NONE; } + + private: + RTCErrorType type_ = RTCErrorType::NONE; + std::string message_; + RTCErrorDetailType error_detail_ = RTCErrorDetailType::NONE; + absl::optional<uint16_t> sctp_cause_code_; +}; + +// Outputs the error as a friendly string. Update this method when adding a new +// error type. +// +// Only intended to be used for logging/diagnostics. The returned char* points +// to literal string that lives for the whole duration of the program. +RTC_EXPORT const char* ToString(RTCErrorType error); +RTC_EXPORT const char* ToString(RTCErrorDetailType error); + +#ifdef WEBRTC_UNIT_TEST +inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) + std::ostream& stream, // no-presubmit-check TODO(webrtc:8982) + RTCErrorType error) { + return stream << ToString(error); +} + +inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) + std::ostream& stream, // no-presubmit-check TODO(webrtc:8982) + RTCErrorDetailType error) { + return stream << ToString(error); +} +#endif // WEBRTC_UNIT_TEST + +// Helper macro that can be used by implementations to create an error with a +// message and log it. `message` should be a string literal or movable +// std::string. +#define LOG_AND_RETURN_ERROR_EX(type, message, severity) \ + { \ + RTC_DCHECK(type != RTCErrorType::NONE); \ + RTC_LOG(severity) << message << " (" << ::webrtc::ToString(type) << ")"; \ + return ::webrtc::RTCError(type, message); \ + } + +#define LOG_AND_RETURN_ERROR(type, message) \ + LOG_AND_RETURN_ERROR_EX(type, message, LS_ERROR) + +// RTCErrorOr<T> is the union of an RTCError object and a T object. RTCErrorOr +// models the concept of an object that is either a usable value, or an error +// Status explaining why such a value is not present. To this end RTCErrorOr<T> +// does not allow its RTCErrorType value to be RTCErrorType::NONE. This is +// enforced by a debug check in most cases. +// +// The primary use-case for RTCErrorOr<T> is as the return value of a function +// which may fail. For example, CreateRtpSender will fail if the parameters +// could not be successfully applied at the media engine level, but if +// successful will return a unique_ptr to an RtpSender. +// +// Example client usage for a RTCErrorOr<std::unique_ptr<T>>: +// +// RTCErrorOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg); +// if (result.ok()) { +// std::unique_ptr<Foo> foo = result.ConsumeValue(); +// foo->DoSomethingCool(); +// } else { +// RTC_LOG(LS_ERROR) << result.error(); +// } +// +// Example factory implementation returning RTCErrorOr<std::unique_ptr<T>>: +// +// RTCErrorOr<std::unique_ptr<Foo>> FooFactory::MakeNewFoo(int arg) { +// if (arg <= 0) { +// return RTCError(RTCErrorType::INVALID_RANGE, "Arg must be positive"); +// } else { +// return std::unique_ptr<Foo>(new Foo(arg)); +// } +// } +// +template <typename T> +class RTCErrorOr { + // Used to convert between RTCErrorOr<Foo>/RtcErrorOr<Bar>, when an implicit + // conversion from Foo to Bar exists. + template <typename U> + friend class RTCErrorOr; + + public: + typedef T element_type; + + // Constructs a new RTCErrorOr with RTCErrorType::INTERNAL_ERROR error. This + // is marked 'explicit' to try to catch cases like 'return {};', where people + // think RTCErrorOr<std::vector<int>> will be initialized with an empty + // vector, instead of a RTCErrorType::INTERNAL_ERROR error. + RTCErrorOr() : error_(RTCErrorType::INTERNAL_ERROR) {} + + // Constructs a new RTCErrorOr with the given non-ok error. After calling + // this constructor, calls to value() will DCHECK-fail. + // + // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return + // value, so it is convenient and sensible to be able to do 'return + // RTCError(...)' when the return type is RTCErrorOr<T>. + // + // REQUIRES: !error.ok(). This requirement is DCHECKed. + RTCErrorOr(RTCError&& error) : error_(std::move(error)) { // NOLINT + RTC_DCHECK(!error_.ok()); + } + + // Constructs a new RTCErrorOr with the given value. After calling this + // constructor, calls to value() will succeed, and calls to error() will + // return a default-constructed RTCError. + // + // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return type + // so it is convenient and sensible to be able to do 'return T()' + // when the return type is RTCErrorOr<T>. + RTCErrorOr(const T& value) : value_(value) {} // NOLINT + RTCErrorOr(T&& value) : value_(std::move(value)) {} // NOLINT + + // Delete the copy constructor and assignment operator; there aren't any use + // cases where you should need to copy an RTCErrorOr, as opposed to moving + // it. Can revisit this decision if use cases arise in the future. + RTCErrorOr(const RTCErrorOr& other) = delete; + RTCErrorOr& operator=(const RTCErrorOr& other) = delete; + + // Move constructor and move-assignment operator. + // + // Visual Studio doesn't support "= default" with move constructors or + // assignment operators (even though they compile, they segfault), so define + // them explicitly. + RTCErrorOr(RTCErrorOr&& other) + : error_(std::move(other.error_)), value_(std::move(other.value_)) {} + RTCErrorOr& operator=(RTCErrorOr&& other) { + error_ = std::move(other.error_); + value_ = std::move(other.value_); + return *this; + } + + // Conversion constructor and assignment operator; T must be copy or move + // constructible from U. + template <typename U> + RTCErrorOr(RTCErrorOr<U> other) // NOLINT + : error_(std::move(other.error_)), value_(std::move(other.value_)) {} + template <typename U> + RTCErrorOr& operator=(RTCErrorOr<U> other) { + error_ = std::move(other.error_); + value_ = std::move(other.value_); + return *this; + } + + // Returns a reference to our error. If this contains a T, then returns + // default-constructed RTCError. + const RTCError& error() const { return error_; } + + // Moves the error. Can be useful if, say "CreateFoo" returns an + // RTCErrorOr<Foo>, and internally calls "CreateBar" which returns an + // RTCErrorOr<Bar>, and wants to forward the error up the stack. + RTCError MoveError() { return std::move(error_); } + + // Returns this->error().ok() + bool ok() const { return error_.ok(); } + + // Returns a reference to our current value, or DCHECK-fails if !this->ok(). + // + // Can be convenient for the implementation; for example, a method may want + // to access the value in some way before returning it to the next method on + // the stack. + const T& value() const { + RTC_DCHECK(ok()); + return value_; + } + T& value() { + RTC_DCHECK(ok()); + return value_; + } + + // Moves our current value out of this object and returns it, or DCHECK-fails + // if !this->ok(). + T MoveValue() { + RTC_DCHECK(ok()); + return std::move(value_); + } + + private: + RTCError error_; + T value_; +}; + +} // namespace webrtc + +#endif // API_RTC_ERROR_H_ diff --git a/third_party/libwebrtc/api/rtc_error_gn/moz.build b/third_party/libwebrtc/api/rtc_error_gn/moz.build new file mode 100644 index 0000000000..07efa1cf55 --- /dev/null +++ b/third_party/libwebrtc/api/rtc_error_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/rtc_error.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rtc_error_gn") diff --git a/third_party/libwebrtc/api/rtc_error_unittest.cc b/third_party/libwebrtc/api/rtc_error_unittest.cc new file mode 100644 index 0000000000..ba307d8f71 --- /dev/null +++ b/third_party/libwebrtc/api/rtc_error_unittest.cc @@ -0,0 +1,242 @@ +/* + * Copyright 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. + */ + +#include "api/rtc_error.h" + +#include <utility> + +#include "test/gtest.h" + +namespace { + +const int kDefaultMoveOnlyIntValue = 0xbadf00d; + +// Class that has no copy constructor, ensuring that RTCErrorOr can +struct MoveOnlyInt { + MoveOnlyInt() {} + explicit MoveOnlyInt(int value) : value(value) {} + MoveOnlyInt(const MoveOnlyInt& other) = delete; + MoveOnlyInt& operator=(const MoveOnlyInt& other) = delete; + MoveOnlyInt(MoveOnlyInt&& other) : value(other.value) {} + MoveOnlyInt& operator=(MoveOnlyInt&& other) { + value = other.value; + return *this; + } + + int value = kDefaultMoveOnlyIntValue; +}; + +// Same as above. Used to test conversion from RTCErrorOr<A> to RTCErrorOr<B> +// when A can be converted to B. +struct MoveOnlyInt2 { + MoveOnlyInt2() {} + explicit MoveOnlyInt2(int value) : value(value) {} + MoveOnlyInt2(const MoveOnlyInt2& other) = delete; + MoveOnlyInt2& operator=(const MoveOnlyInt2& other) = delete; + MoveOnlyInt2(MoveOnlyInt2&& other) : value(other.value) {} + MoveOnlyInt2& operator=(MoveOnlyInt2&& other) { + value = other.value; + return *this; + } + + explicit MoveOnlyInt2(MoveOnlyInt&& other) : value(other.value) {} + MoveOnlyInt2& operator=(MoveOnlyInt&& other) { + value = other.value; + return *this; + } + + int value = kDefaultMoveOnlyIntValue; +}; + +} // namespace + +namespace webrtc { + +// Test that the default constructor creates a "no error" error. +TEST(RTCErrorTest, DefaultConstructor) { + RTCError e; + EXPECT_EQ(RTCErrorType::NONE, e.type()); + EXPECT_EQ(std::string(), e.message()); + EXPECT_TRUE(e.ok()); +} + +TEST(RTCErrorTest, NormalConstructors) { + RTCError a(RTCErrorType::INVALID_PARAMETER); + EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, a.type()); + EXPECT_EQ(std::string(), a.message()); + + // Constructor that takes const char* message. + RTCError b(RTCErrorType::UNSUPPORTED_PARAMETER, "foobar"); + EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, b.type()); + EXPECT_EQ(std::string("foobar"), b.message()); + + // Constructor that takes std::string message. + RTCError c(RTCErrorType::INVALID_RANGE, std::string("new")); + EXPECT_EQ(RTCErrorType::INVALID_RANGE, c.type()); + EXPECT_EQ(std::string("new"), c.message()); +} + +TEST(RTCErrorTest, MoveConstructor) { + // Static string. + RTCError a(RTCErrorType::INVALID_PARAMETER, "foo"); + RTCError b(std::move(a)); + EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, b.type()); + EXPECT_EQ(std::string("foo"), b.message()); + + // Non-static string. + RTCError c(RTCErrorType::UNSUPPORTED_PARAMETER, std::string("bar")); + RTCError d(std::move(c)); + EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, d.type()); + EXPECT_EQ(std::string("bar"), d.message()); +} + +TEST(RTCErrorTest, MoveAssignment) { + // Try all combinations of "is static string"/"is non-static string" moves. + RTCError e(RTCErrorType::INVALID_PARAMETER, "foo"); + + e = RTCError(RTCErrorType::UNSUPPORTED_PARAMETER, "bar"); + EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, e.type()); + EXPECT_EQ(std::string("bar"), e.message()); + + e = RTCError(RTCErrorType::SYNTAX_ERROR, std::string("baz")); + EXPECT_EQ(std::string("baz"), e.message()); + + e = RTCError(RTCErrorType::SYNTAX_ERROR, std::string("another")); + EXPECT_EQ(std::string("another"), e.message()); + + e = RTCError(RTCErrorType::SYNTAX_ERROR, "last"); + EXPECT_EQ(std::string("last"), e.message()); +} + +// Test that the error returned by RTCError::OK() is a "no error" error. +TEST(RTCErrorTest, OKConstant) { + RTCError ok = RTCError::OK(); + EXPECT_EQ(RTCErrorType::NONE, ok.type()); + EXPECT_EQ(std::string(), ok.message()); + EXPECT_TRUE(ok.ok()); +} + +// Test that "error.ok()" behaves as expected. +TEST(RTCErrorTest, OkMethod) { + RTCError success; + RTCError failure(RTCErrorType::INTERNAL_ERROR); + EXPECT_TRUE(success.ok()); + EXPECT_FALSE(failure.ok()); +} + +// Test that a message can be set using either static const strings or +// std::strings. +TEST(RTCErrorTest, SetMessage) { + RTCError e; + // Try all combinations of "is static string"/"is non-static string" calls. + e.set_message("foo"); + EXPECT_EQ(std::string("foo"), e.message()); + + e.set_message("bar"); + EXPECT_EQ(std::string("bar"), e.message()); + + e.set_message(std::string("string")); + EXPECT_EQ(std::string("string"), e.message()); + + e.set_message(std::string("more")); + EXPECT_EQ(std::string("more"), e.message()); + + e.set_message("love to test"); + EXPECT_EQ(std::string("love to test"), e.message()); +} + +// Test that the default constructor creates an "INTERNAL_ERROR". +TEST(RTCErrorOrTest, DefaultConstructor) { + RTCErrorOr<MoveOnlyInt> e; + EXPECT_EQ(RTCErrorType::INTERNAL_ERROR, e.error().type()); +} + +// Test that an RTCErrorOr can be implicitly constructed from a value. +TEST(RTCErrorOrTest, ImplicitValueConstructor) { + RTCErrorOr<MoveOnlyInt> e = [] { return MoveOnlyInt(100); }(); + EXPECT_EQ(100, e.value().value); +} + +// Test that an RTCErrorOr can be implicitly constructed from an RTCError. +TEST(RTCErrorOrTest, ImplicitErrorConstructor) { + RTCErrorOr<MoveOnlyInt> e = [] { + return RTCError(RTCErrorType::SYNTAX_ERROR); + }(); + EXPECT_EQ(RTCErrorType::SYNTAX_ERROR, e.error().type()); +} + +TEST(RTCErrorOrTest, MoveConstructor) { + RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5)); + RTCErrorOr<MoveOnlyInt> b(std::move(a)); + EXPECT_EQ(5, b.value().value); +} + +TEST(RTCErrorOrTest, MoveAssignment) { + RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5)); + RTCErrorOr<MoveOnlyInt> b(MoveOnlyInt(10)); + a = std::move(b); + EXPECT_EQ(10, a.value().value); +} + +TEST(RTCErrorOrTest, ConversionConstructor) { + RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(1)); + RTCErrorOr<MoveOnlyInt2> b(std::move(a)); +} + +TEST(RTCErrorOrTest, ConversionAssignment) { + RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5)); + RTCErrorOr<MoveOnlyInt2> b(MoveOnlyInt2(10)); + b = std::move(a); + EXPECT_EQ(5, b.value().value); +} + +TEST(RTCErrorOrTest, OkMethod) { + RTCErrorOr<int> success(1337); + RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR); + EXPECT_TRUE(success.ok()); + EXPECT_FALSE(error.ok()); +} + +TEST(RTCErrorOrTest, MoveError) { + RTCErrorOr<int> e({RTCErrorType::SYNTAX_ERROR, "message"}); + RTCError err = e.MoveError(); + EXPECT_EQ(RTCErrorType::SYNTAX_ERROR, err.type()); + EXPECT_EQ(std::string("message"), err.message()); +} + +TEST(RTCErrorOrTest, MoveValue) { + RTCErrorOr<MoveOnlyInt> e(MoveOnlyInt(88)); + MoveOnlyInt value = e.MoveValue(); + EXPECT_EQ(88, value.value); +} + +// Death tests. +// Disabled on Android because death tests misbehave on Android, see +// base/test/gtest_util.h. +#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) + +TEST(RTCErrorOrDeathTest, ConstructWithOkError) { + RTCErrorOr<int> err; + EXPECT_DEATH(err = RTCError::OK(), ""); +} + +TEST(RTCErrorOrDeathTest, DereferenceErrorValue) { + RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR); + EXPECT_DEATH(error.value(), ""); +} + +TEST(RTCErrorOrDeathTest, MoveErrorValue) { + RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR); + EXPECT_DEATH(error.MoveValue(), ""); +} + +#endif // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtc_event_log/BUILD.gn b/third_party/libwebrtc/api/rtc_event_log/BUILD.gn new file mode 100644 index 0000000000..158dc06a7b --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log/BUILD.gn @@ -0,0 +1,48 @@ +# Copyright (c) 2019 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") + +rtc_library("rtc_event_log") { + visibility = [ "*" ] + sources = [ + "rtc_event.cc", + "rtc_event.h", + "rtc_event_log.cc", + "rtc_event_log.h", + "rtc_event_log_factory_interface.h", + ] + + deps = [ + "..:libjingle_logging_api", + "../../rtc_base:checks", + "../../rtc_base:timeutils", + "../task_queue", + ] +} + +rtc_library("rtc_event_log_factory") { + visibility = [ "*" ] + sources = [ + "rtc_event_log_factory.cc", + "rtc_event_log_factory.h", + ] + + deps = [ + ":rtc_event_log", + "../../rtc_base:checks", + "../../rtc_base/system:rtc_export", + "../../system_wrappers:field_trial", + "../task_queue", + ] + + if (rtc_enable_protobuf) { + defines = [ "WEBRTC_ENABLE_RTC_EVENT_LOG" ] + deps += [ "../../logging:rtc_event_log_impl" ] + } +} diff --git a/third_party/libwebrtc/api/rtc_event_log/rtc_event.cc b/third_party/libwebrtc/api/rtc_event_log/rtc_event.cc new file mode 100644 index 0000000000..631188b915 --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log/rtc_event.cc @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019 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 "api/rtc_event_log/rtc_event.h" + +#include "rtc_base/time_utils.h" + +namespace webrtc { + +RtcEvent::RtcEvent() : timestamp_us_(rtc::TimeMillis() * 1000) {} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtc_event_log/rtc_event.h b/third_party/libwebrtc/api/rtc_event_log/rtc_event.h new file mode 100644 index 0000000000..aa74944fe5 --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log/rtc_event.h @@ -0,0 +1,88 @@ +/* + * 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. + */ + +#ifndef API_RTC_EVENT_LOG_RTC_EVENT_H_ +#define API_RTC_EVENT_LOG_RTC_EVENT_H_ + +#include <cstdint> + +namespace webrtc { + +// This class allows us to store unencoded RTC events. Subclasses of this class +// store the actual information. This allows us to keep all unencoded events, +// even when their type and associated information differ, in the same buffer. +// Additionally, it prevents dependency leaking - a module that only logs +// events of type RtcEvent_A doesn't need to know about anything associated +// with events of type RtcEvent_B. +class RtcEvent { + public: + // Subclasses of this class have to associate themselves with a unique value + // of Type. This leaks the information of existing subclasses into the + // superclass, but the *actual* information - rtclog::StreamConfig, etc. - + // is kept separate. + enum class Type : uint32_t { + AlrStateEvent, + RouteChangeEvent, + RemoteEstimateEvent, + AudioNetworkAdaptation, + AudioPlayout, + AudioReceiveStreamConfig, + AudioSendStreamConfig, + BweUpdateDelayBased, + BweUpdateLossBased, + DtlsTransportState, + DtlsWritableState, + IceCandidatePairConfig, + IceCandidatePairEvent, + ProbeClusterCreated, + ProbeResultFailure, + ProbeResultSuccess, + RtcpPacketIncoming, + RtcpPacketOutgoing, + RtpPacketIncoming, + RtpPacketOutgoing, + VideoReceiveStreamConfig, + VideoSendStreamConfig, + GenericPacketSent, + GenericPacketReceived, + GenericAckReceived, + FrameDecoded, + NetEqSetMinimumDelay, + BeginV3Log = 0x2501580, + EndV3Log = 0x2501581, + FakeEvent, // For unit testing. + }; + + RtcEvent(); + virtual ~RtcEvent() = default; + + virtual Type GetType() const = 0; + + virtual bool IsConfigEvent() const = 0; + + // Events are grouped by Type before being encoded. + // Optionally, `GetGroupKey` can be overloaded to group the + // events by a secondary key (in addition to the event type.) + // This can, in some cases, improve compression efficiency + // e.g. by grouping events by SSRC. + virtual uint32_t GetGroupKey() const { return 0; } + + int64_t timestamp_ms() const { return timestamp_us_ / 1000; } + int64_t timestamp_us() const { return timestamp_us_; } + + protected: + explicit RtcEvent(int64_t timestamp_us) : timestamp_us_(timestamp_us) {} + + const int64_t timestamp_us_; +}; + +} // namespace webrtc + +#endif // API_RTC_EVENT_LOG_RTC_EVENT_H_ diff --git a/third_party/libwebrtc/api/rtc_event_log/rtc_event_log.cc b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log.cc new file mode 100644 index 0000000000..56189c0ff7 --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log.cc @@ -0,0 +1,21 @@ +/* + * 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 "api/rtc_event_log/rtc_event_log.h" + +namespace webrtc { + +bool RtcEventLogNull::StartLogging( + std::unique_ptr<RtcEventLogOutput> /*output*/, + int64_t /*output_period_ms*/) { + return false; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtc_event_log/rtc_event_log.h b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log.h new file mode 100644 index 0000000000..7b42cdc028 --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015 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 API_RTC_EVENT_LOG_RTC_EVENT_LOG_H_ +#define API_RTC_EVENT_LOG_RTC_EVENT_LOG_H_ + +#include <cstddef> +#include <cstdint> +#include <functional> +#include <memory> + +#include "api/rtc_event_log/rtc_event.h" +#include "api/rtc_event_log_output.h" +#include "api/task_queue/task_queue_factory.h" + +namespace webrtc { + +class RtcEventLog { + public: + enum : size_t { kUnlimitedOutput = 0 }; + enum : int64_t { kImmediateOutput = 0 }; + + // TODO(eladalon): Get rid of the legacy encoding and this enum once all + // clients have migrated to the new format. + enum class EncodingType { Legacy, NewFormat, ProtoFree }; + + virtual ~RtcEventLog() = default; + + // Starts logging to a given output. The output might be limited in size, + // and may close itself once it has reached the maximum size. + virtual bool StartLogging(std::unique_ptr<RtcEventLogOutput> output, + int64_t output_period_ms) = 0; + + // Stops logging to file and waits until the file has been closed, after + // which it would be permissible to read and/or modify it. + virtual void StopLogging() = 0; + + // Stops logging to file and calls `callback` when the file has been closed. + // Note that it is not safe to call any other members, including the + // destructor, until the callback has been called. + // TODO(srte): Remove default implementation when it's safe to do so. + virtual void StopLogging(std::function<void()> callback) { + StopLogging(); + callback(); + } + + // Log an RTC event (the type of event is determined by the subclass). + virtual void Log(std::unique_ptr<RtcEvent> event) = 0; +}; + +// No-op implementation is used if flag is not set, or in tests. +class RtcEventLogNull final : public RtcEventLog { + public: + bool StartLogging(std::unique_ptr<RtcEventLogOutput> output, + int64_t output_period_ms) override; + void StopLogging() override {} + void Log(std::unique_ptr<RtcEvent> event) override {} +}; + +} // namespace webrtc + +#endif // API_RTC_EVENT_LOG_RTC_EVENT_LOG_H_ diff --git a/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_factory.cc b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_factory.cc new file mode 100644 index 0000000000..a3cb68cf54 --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_factory.cc @@ -0,0 +1,48 @@ +/* + * Copyright 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. + */ + +#include "api/rtc_event_log/rtc_event_log_factory.h" + +#include <memory> +#include <utility> + +#include "rtc_base/checks.h" +#include "system_wrappers/include/field_trial.h" + +#ifdef WEBRTC_ENABLE_RTC_EVENT_LOG +#include "logging/rtc_event_log/rtc_event_log_impl.h" +#endif + +namespace webrtc { + +RtcEventLogFactory::RtcEventLogFactory(TaskQueueFactory* task_queue_factory) + : task_queue_factory_(task_queue_factory) { + RTC_DCHECK(task_queue_factory_); +} + +std::unique_ptr<RtcEventLog> RtcEventLogFactory::Create( + RtcEventLog::EncodingType encoding_type) const { +#ifdef WEBRTC_ENABLE_RTC_EVENT_LOG + if (field_trial::IsEnabled("WebRTC-RtcEventLogKillSwitch")) { + return std::make_unique<RtcEventLogNull>(); + } + return std::make_unique<RtcEventLogImpl>( + RtcEventLogImpl::CreateEncoder(encoding_type), task_queue_factory_); +#else + return std::make_unique<RtcEventLogNull>(); +#endif +} + +std::unique_ptr<RtcEventLog> RtcEventLogFactory::CreateRtcEventLog( + RtcEventLog::EncodingType encoding_type) { + return Create(encoding_type); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_factory.h b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_factory.h new file mode 100644 index 0000000000..fd1db3c728 --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_factory.h @@ -0,0 +1,39 @@ +/* + * Copyright 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. + */ + +#ifndef API_RTC_EVENT_LOG_RTC_EVENT_LOG_FACTORY_H_ +#define API_RTC_EVENT_LOG_RTC_EVENT_LOG_FACTORY_H_ + +#include <memory> + +#include "api/rtc_event_log/rtc_event_log.h" +#include "api/rtc_event_log/rtc_event_log_factory_interface.h" +#include "api/task_queue/task_queue_factory.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +class RTC_EXPORT RtcEventLogFactory : public RtcEventLogFactoryInterface { + public: + explicit RtcEventLogFactory(TaskQueueFactory* task_queue_factory); + ~RtcEventLogFactory() override {} + + std::unique_ptr<RtcEventLog> Create( + RtcEventLog::EncodingType encoding_type) const override; + std::unique_ptr<RtcEventLog> CreateRtcEventLog( + RtcEventLog::EncodingType encoding_type) override; + + private: + TaskQueueFactory* const task_queue_factory_; +}; + +} // namespace webrtc + +#endif // API_RTC_EVENT_LOG_RTC_EVENT_LOG_FACTORY_H_ diff --git a/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_factory_interface.h b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_factory_interface.h new file mode 100644 index 0000000000..a6f4dee92f --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_factory_interface.h @@ -0,0 +1,35 @@ +/* + * Copyright 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. + */ + +#ifndef API_RTC_EVENT_LOG_RTC_EVENT_LOG_FACTORY_INTERFACE_H_ +#define API_RTC_EVENT_LOG_RTC_EVENT_LOG_FACTORY_INTERFACE_H_ + +#include <memory> + +#include "api/rtc_event_log/rtc_event_log.h" + +namespace webrtc { + +// This interface exists to allow webrtc to be optionally built without +// RtcEventLog support. A PeerConnectionFactory is constructed with an +// RtcEventLogFactoryInterface, which may or may not be null. +class RtcEventLogFactoryInterface { + public: + virtual ~RtcEventLogFactoryInterface() = default; + + virtual std::unique_ptr<RtcEventLog> Create( + RtcEventLog::EncodingType encoding_type) const = 0; + [[deprecated]] virtual std::unique_ptr<RtcEventLog> CreateRtcEventLog( + RtcEventLog::EncodingType encoding_type) = 0; +}; + +} // namespace webrtc + +#endif // API_RTC_EVENT_LOG_RTC_EVENT_LOG_FACTORY_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_gn/moz.build b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_gn/moz.build new file mode 100644 index 0000000000..a96be6791f --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log/rtc_event_log_gn/moz.build @@ -0,0 +1,226 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/rtc_event_log/rtc_event.cc", + "/third_party/libwebrtc/api/rtc_event_log/rtc_event_log.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rtc_event_log_gn") diff --git a/third_party/libwebrtc/api/rtc_event_log_output.h b/third_party/libwebrtc/api/rtc_event_log_output.h new file mode 100644 index 0000000000..f1f84a5f3a --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log_output.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef API_RTC_EVENT_LOG_OUTPUT_H_ +#define API_RTC_EVENT_LOG_OUTPUT_H_ + +#include <string> + +#include "absl/strings/string_view.h" + +namespace webrtc { + +// NOTE: This class is still under development and may change without notice. +class RtcEventLogOutput { + public: + virtual ~RtcEventLogOutput() = default; + + // An output normally starts out active, though that might not always be + // the case (e.g. failed to open a file for writing). + // Once an output has become inactive (e.g. maximum file size reached), it can + // never become active again. + virtual bool IsActive() const = 0; + + // Write encoded events to an output. Returns true if the output was + // successfully written in its entirety. Otherwise, no guarantee is given + // about how much data was written, if any. The output sink becomes inactive + // after the first time `false` is returned. Write() may not be called on + // an inactive output sink. + virtual bool Write(absl::string_view output) = 0; + + // Indicates that buffers should be written to disk if applicable. + virtual void Flush() {} +}; + +} // namespace webrtc + +#endif // API_RTC_EVENT_LOG_OUTPUT_H_ diff --git a/third_party/libwebrtc/api/rtc_event_log_output_file.cc b/third_party/libwebrtc/api/rtc_event_log_output_file.cc new file mode 100644 index 0000000000..e1d4c7c711 --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log_output_file.cc @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#include "api/rtc_event_log_output_file.h" + +#include <limits> +#include <utility> + +#include "api/rtc_event_log/rtc_event_log.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" + +namespace webrtc { + +// Together with the assumption of no single Write() would ever be called on +// an input with length greater-than-or-equal-to (max(size_t) / 2), this +// guarantees no overflow of the check for remaining file capacity in Write(). +// This does *not* apply to files with unlimited size. +const size_t RtcEventLogOutputFile::kMaxReasonableFileSize = + std::numeric_limits<size_t>::max() / 2; + +RtcEventLogOutputFile::RtcEventLogOutputFile(const std::string& file_name) + : RtcEventLogOutputFile(FileWrapper::OpenWriteOnly(file_name), + RtcEventLog::kUnlimitedOutput) {} + +RtcEventLogOutputFile::RtcEventLogOutputFile(const std::string& file_name, + size_t max_size_bytes) + + // Unlike plain fopen, FileWrapper takes care of filename utf8 -> + // wchar conversion on Windows. + : RtcEventLogOutputFile(FileWrapper::OpenWriteOnly(file_name), + max_size_bytes) {} + +RtcEventLogOutputFile::RtcEventLogOutputFile(FILE* file, size_t max_size_bytes) + : RtcEventLogOutputFile(FileWrapper(file), max_size_bytes) {} + +RtcEventLogOutputFile::RtcEventLogOutputFile(FileWrapper file, + size_t max_size_bytes) + : max_size_bytes_(max_size_bytes), file_(std::move(file)) { + RTC_CHECK_LE(max_size_bytes_, kMaxReasonableFileSize); + if (!file_.is_open()) { + RTC_LOG(LS_ERROR) << "Invalid file. WebRTC event log not started."; + } +} + +bool RtcEventLogOutputFile::IsActive() const { + return IsActiveInternal(); +} + +bool RtcEventLogOutputFile::Write(absl::string_view output) { + RTC_DCHECK(IsActiveInternal()); + // No single write may be so big, that it would risk overflowing the + // calculation of (written_bytes_ + output.length()). + RTC_DCHECK_LT(output.size(), kMaxReasonableFileSize); + + if (max_size_bytes_ == RtcEventLog::kUnlimitedOutput || + written_bytes_ + output.size() <= max_size_bytes_) { + if (file_.Write(output.data(), output.size())) { + written_bytes_ += output.size(); + return true; + } else { + RTC_LOG(LS_ERROR) << "Write to WebRtcEventLog file failed."; + } + } else { + RTC_LOG(LS_VERBOSE) << "Max file size reached."; + } + + // Failed, for one of above reasons. Close output file. + file_.Close(); + return false; +} + +// Internal non-virtual method. +bool RtcEventLogOutputFile::IsActiveInternal() const { + return file_.is_open(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtc_event_log_output_file.h b/third_party/libwebrtc/api/rtc_event_log_output_file.h new file mode 100644 index 0000000000..c9ae0a8ede --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log_output_file.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#ifndef API_RTC_EVENT_LOG_OUTPUT_FILE_H_ +#define API_RTC_EVENT_LOG_OUTPUT_FILE_H_ + +#include <stddef.h> +#include <stdio.h> + +#include <string> + +#include "api/rtc_event_log_output.h" +#include "rtc_base/system/file_wrapper.h" + +namespace webrtc { + +class RtcEventLogOutputFile final : public RtcEventLogOutput { + public: + static const size_t kMaxReasonableFileSize; // Explanation at declaration. + + // Unlimited/limited-size output file (by filename). + explicit RtcEventLogOutputFile(const std::string& file_name); + RtcEventLogOutputFile(const std::string& file_name, size_t max_size_bytes); + + // Limited-size output file (by FILE*). This class takes ownership + // of the FILE*, and closes it on destruction. + RtcEventLogOutputFile(FILE* file, size_t max_size_bytes); + + ~RtcEventLogOutputFile() override = default; + + bool IsActive() const override; + + bool Write(absl::string_view output) override; + + private: + RtcEventLogOutputFile(FileWrapper file, size_t max_size_bytes); + + // IsActive() can be called either from outside or from inside, but we don't + // want to incur the overhead of a virtual function call if called from inside + // some other function of this class. + inline bool IsActiveInternal() const; + + // Maximum size, or zero for no limit. + const size_t max_size_bytes_; + size_t written_bytes_{0}; + FileWrapper file_; +}; + +} // namespace webrtc + +#endif // API_RTC_EVENT_LOG_OUTPUT_FILE_H_ diff --git a/third_party/libwebrtc/api/rtc_event_log_output_file_unittest.cc b/third_party/libwebrtc/api/rtc_event_log_output_file_unittest.cc new file mode 100644 index 0000000000..0aff57fbbc --- /dev/null +++ b/third_party/libwebrtc/api/rtc_event_log_output_file_unittest.cc @@ -0,0 +1,167 @@ +/* + * 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. + */ + +#include "api/rtc_event_log_output_file.h" + +#include <fstream> +#include <iterator> +#include <memory> +#include <string> + +#include "rtc_base/checks.h" +#include "test/gtest.h" +#include "test/testsupport/file_utils.h" + +namespace webrtc { + +class RtcEventLogOutputFileTest : public ::testing::Test { + public: + RtcEventLogOutputFileTest() : output_file_name_(GetOutputFilePath()) { + // Ensure no leftovers from previous runs, which might not have terminated + // in an orderly fashion. + remove(output_file_name_.c_str()); + } + + ~RtcEventLogOutputFileTest() override { remove(output_file_name_.c_str()); } + + protected: + std::string GetOutputFilePath() const { + auto test_info = ::testing::UnitTest::GetInstance()->current_test_info(); + return test::OutputPath() + test_info->test_case_name() + test_info->name(); + } + + std::string GetOutputFileContents() const { + std::ifstream file(output_file_name_, + std::ios_base::in | std::ios_base::binary); + RTC_CHECK(file.is_open()); + RTC_CHECK(file.good()); + std::string file_str((std::istreambuf_iterator<char>(file)), + std::istreambuf_iterator<char>()); + return file_str; + } + + const std::string output_file_name_; +}; + +TEST_F(RtcEventLogOutputFileTest, NonDefectiveOutputsStartOutActive) { + auto output_file = std::make_unique<RtcEventLogOutputFile>(output_file_name_); + EXPECT_TRUE(output_file->IsActive()); +} + +TEST_F(RtcEventLogOutputFileTest, DefectiveOutputsStartOutInactive) { + const std::string illegal_filename = "/////////"; + auto output_file = std::make_unique<RtcEventLogOutputFile>(illegal_filename); + EXPECT_FALSE(output_file->IsActive()); +} + +// Sanity over opening a file (by filename) with an unlimited size. +TEST_F(RtcEventLogOutputFileTest, UnlimitedOutputFile) { + const std::string output_str = "one two three"; + + auto output_file = std::make_unique<RtcEventLogOutputFile>(output_file_name_); + output_file->Write(output_str); + output_file.reset(); // Closing the file flushes the buffer to disk. + + EXPECT_EQ(GetOutputFileContents(), output_str); +} + +// Do not allow writing more bytes to the file than max file size. +TEST_F(RtcEventLogOutputFileTest, LimitedOutputFileCappedToCapacity) { + // Fit two bytes, then the third should be rejected. + auto output_file = + std::make_unique<RtcEventLogOutputFile>(output_file_name_, 2); + + output_file->Write("1"); + output_file->Write("2"); + output_file->Write("3"); + // Unsuccessful writes close the file; no need to delete the output to flush. + + EXPECT_EQ(GetOutputFileContents(), "12"); +} + +// Make sure that calls to Write() either write everything to the file, or +// nothing (short of underlying issues in the module that handles the file, +// which would be beyond our control). +TEST_F(RtcEventLogOutputFileTest, DoNotWritePartialLines) { + const std::string output_str_1 = "0123456789"; + const std::string output_str_2 = "abcdefghij"; + + // Set a file size limit just shy of fitting the entire second line. + const size_t size_limit = output_str_1.length() + output_str_2.length() - 1; + auto output_file = + std::make_unique<RtcEventLogOutputFile>(output_file_name_, size_limit); + + output_file->Write(output_str_1); + output_file->Write(output_str_2); + // Unsuccessful writes close the file; no need to delete the output to flush. + + EXPECT_EQ(GetOutputFileContents(), output_str_1); +} + +TEST_F(RtcEventLogOutputFileTest, UnsuccessfulWriteReturnsFalse) { + auto output_file = + std::make_unique<RtcEventLogOutputFile>(output_file_name_, 2); + EXPECT_FALSE(output_file->Write("abc")); +} + +TEST_F(RtcEventLogOutputFileTest, SuccessfulWriteReturnsTrue) { + auto output_file = + std::make_unique<RtcEventLogOutputFile>(output_file_name_, 3); + EXPECT_TRUE(output_file->Write("abc")); +} + +// Even if capacity is reached, a successful write leaves the output active. +TEST_F(RtcEventLogOutputFileTest, FileStillActiveAfterSuccessfulWrite) { + auto output_file = + std::make_unique<RtcEventLogOutputFile>(output_file_name_, 3); + ASSERT_TRUE(output_file->Write("abc")); + EXPECT_TRUE(output_file->IsActive()); +} + +// Unsuccessful writes switch the output to inactive, even if capacity has +// not yet been reached. +TEST_F(RtcEventLogOutputFileTest, FileInactiveAfterUnsuccessfulWrite) { + auto output_file = + std::make_unique<RtcEventLogOutputFile>(output_file_name_, 2); + ASSERT_FALSE(output_file->Write("abc")); + EXPECT_FALSE(output_file->IsActive()); +} + +TEST_F(RtcEventLogOutputFileTest, AllowReasonableFileSizeLimits) { + auto output_file = std::make_unique<RtcEventLogOutputFile>( + output_file_name_, RtcEventLogOutputFile::kMaxReasonableFileSize); + EXPECT_TRUE(output_file->IsActive()); +} + +#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) +class RtcEventLogOutputFileDeathTest : public RtcEventLogOutputFileTest {}; + +TEST_F(RtcEventLogOutputFileDeathTest, WritingToInactiveFileForbidden) { + RtcEventLogOutputFile output_file(output_file_name_, 2); + ASSERT_FALSE(output_file.Write("abc")); + ASSERT_FALSE(output_file.IsActive()); + EXPECT_DEATH(output_file.Write("abc"), ""); +} + +TEST_F(RtcEventLogOutputFileDeathTest, DisallowUnreasonableFileSizeLimits) { + // Keeping in a temporary unique_ptr to make it clearer that the death is + // triggered by construction, not destruction. + std::unique_ptr<RtcEventLogOutputFile> output_file; + auto create_output_file = [&] { + const size_t unreasonable_size = + RtcEventLogOutputFile::kMaxReasonableFileSize + 1; + output_file = std::make_unique<RtcEventLogOutputFile>(output_file_name_, + unreasonable_size); + }; + EXPECT_DEATH(create_output_file(), ""); +} +#endif + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtp_headers.cc b/third_party/libwebrtc/api/rtp_headers.cc new file mode 100644 index 0000000000..8e1efc7262 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_headers.cc @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#include "api/rtp_headers.h" + +namespace webrtc { + +RTPHeaderExtension::RTPHeaderExtension() + : hasTransmissionTimeOffset(false), + transmissionTimeOffset(0), + hasAbsoluteSendTime(false), + absoluteSendTime(0), + hasTransportSequenceNumber(false), + transportSequenceNumber(0), + hasAudioLevel(false), + voiceActivity(false), + audioLevel(0), + hasVideoRotation(false), + videoRotation(kVideoRotation_0), + hasVideoContentType(false), + videoContentType(VideoContentType::UNSPECIFIED), + has_video_timing(false), + csrcAudioLevels() {} + +RTPHeaderExtension::RTPHeaderExtension(const RTPHeaderExtension& other) = + default; + +RTPHeaderExtension& RTPHeaderExtension::operator=( + const RTPHeaderExtension& other) = default; + +RTPHeader::RTPHeader() + : markerBit(false), + payloadType(0), + sequenceNumber(0), + timestamp(0), + ssrc(0), + numCSRCs(0), + arrOfCSRCs(), + paddingLength(0), + headerLength(0), + payload_type_frequency(0), + extension() {} + +RTPHeader::RTPHeader(const RTPHeader& other) = default; + +RTPHeader& RTPHeader::operator=(const RTPHeader& other) = default; + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtp_headers.h b/third_party/libwebrtc/api/rtp_headers.h new file mode 100644 index 0000000000..261c984d05 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_headers.h @@ -0,0 +1,193 @@ +/* + * 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. + */ + +#ifndef API_RTP_HEADERS_H_ +#define API_RTP_HEADERS_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <string> + +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/units/timestamp.h" +#include "api/video/color_space.h" +#include "api/video/video_content_type.h" +#include "api/video/video_rotation.h" +#include "api/video/video_timing.h" + +namespace webrtc { + +struct FeedbackRequest { + // Determines whether the recv delta as specified in + // https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01 + // should be included. + bool include_timestamps; + // Include feedback of received packets in the range [sequence_number - + // sequence_count + 1, sequence_number]. That is, no feedback will be sent if + // sequence_count is zero. + int sequence_count; +}; + +// The Absolute Capture Time extension is used to stamp RTP packets with a NTP +// timestamp showing when the first audio or video frame in a packet was +// originally captured. The intent of this extension is to provide a way to +// accomplish audio-to-video synchronization when RTCP-terminating intermediate +// systems (e.g. mixers) are involved. See: +// http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time +struct AbsoluteCaptureTime { + // Absolute capture timestamp is the NTP timestamp of when the first frame in + // a packet was originally captured. This timestamp MUST be based on the same + // clock as the clock used to generate NTP timestamps for RTCP sender reports + // on the capture system. + // + // It’s not always possible to do an NTP clock readout at the exact moment of + // when a media frame is captured. A capture system MAY postpone the readout + // until a more convenient time. A capture system SHOULD have known delays + // (e.g. from hardware buffers) subtracted from the readout to make the final + // timestamp as close to the actual capture time as possible. + // + // This field is encoded as a 64-bit unsigned fixed-point number with the high + // 32 bits for the timestamp in seconds and low 32 bits for the fractional + // part. This is also known as the UQ32.32 format and is what the RTP + // specification defines as the canonical format to represent NTP timestamps. + uint64_t absolute_capture_timestamp; + + // Estimated capture clock offset is the sender’s estimate of the offset + // between its own NTP clock and the capture system’s NTP clock. The sender is + // here defined as the system that owns the NTP clock used to generate the NTP + // timestamps for the RTCP sender reports on this stream. The sender system is + // typically either the capture system or a mixer. + // + // This field is encoded as a 64-bit two’s complement signed fixed-point + // number with the high 32 bits for the seconds and low 32 bits for the + // fractional part. It’s intended to make it easy for a receiver, that knows + // how to estimate the sender system’s NTP clock, to also estimate the capture + // system’s NTP clock: + // + // Capture NTP Clock = Sender NTP Clock + Capture Clock Offset + absl::optional<int64_t> estimated_capture_clock_offset; +}; + +inline bool operator==(const AbsoluteCaptureTime& lhs, + const AbsoluteCaptureTime& rhs) { + return (lhs.absolute_capture_timestamp == rhs.absolute_capture_timestamp) && + (lhs.estimated_capture_clock_offset == + rhs.estimated_capture_clock_offset); +} + +inline bool operator!=(const AbsoluteCaptureTime& lhs, + const AbsoluteCaptureTime& rhs) { + return !(lhs == rhs); +} + +enum { kRtpCsrcSize = 15 }; // RFC 3550 page 13 + +// Audio level of CSRCs See: +// https://tools.ietf.org/html/rfc6465 +struct CsrcAudioLevelList { + CsrcAudioLevelList() : numAudioLevels(0) { } + CsrcAudioLevelList(const CsrcAudioLevelList&) = default; + CsrcAudioLevelList& operator=(const CsrcAudioLevelList&) = default; + uint8_t numAudioLevels; + // arrOfAudioLevels has the same ordering as RTPHeader.arrOfCSRCs + uint8_t arrOfAudioLevels[kRtpCsrcSize]; +}; + +struct RTPHeaderExtension { + RTPHeaderExtension(); + RTPHeaderExtension(const RTPHeaderExtension& other); + RTPHeaderExtension& operator=(const RTPHeaderExtension& other); + + static constexpr int kAbsSendTimeFraction = 18; + + Timestamp GetAbsoluteSendTimestamp() const { + RTC_DCHECK(hasAbsoluteSendTime); + RTC_DCHECK(absoluteSendTime < (1ul << 24)); + return Timestamp::Micros((absoluteSendTime * 1000000ll) / + (1 << kAbsSendTimeFraction)); + } + + bool hasTransmissionTimeOffset; + int32_t transmissionTimeOffset; + bool hasAbsoluteSendTime; + uint32_t absoluteSendTime; + absl::optional<AbsoluteCaptureTime> absolute_capture_time; + bool hasTransportSequenceNumber; + uint16_t transportSequenceNumber; + absl::optional<FeedbackRequest> feedback_request; + + // Audio Level includes both level in dBov and voiced/unvoiced bit. See: + // https://tools.ietf.org/html/rfc6464#section-3 + bool hasAudioLevel; + bool voiceActivity; + uint8_t audioLevel; + + // For Coordination of Video Orientation. See + // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ + // ts_126114v120700p.pdf + bool hasVideoRotation; + VideoRotation videoRotation; + + // TODO(ilnik): Refactor this and one above to be absl::optional() and remove + // a corresponding bool flag. + bool hasVideoContentType; + VideoContentType videoContentType; + + bool has_video_timing; + VideoSendTiming video_timing; + + VideoPlayoutDelay playout_delay; + + // For identification of a stream when ssrc is not signaled. See + // https://tools.ietf.org/html/rfc8852 + std::string stream_id; + std::string repaired_stream_id; + + // For identifying the media section used to interpret this RTP packet. See + // https://tools.ietf.org/html/rfc8843 + std::string mid; + + absl::optional<ColorSpace> color_space; + + CsrcAudioLevelList csrcAudioLevels; +}; + +struct RTC_EXPORT RTPHeader { + RTPHeader(); + RTPHeader(const RTPHeader& other); + RTPHeader& operator=(const RTPHeader& other); + + bool markerBit; + uint8_t payloadType; + uint16_t sequenceNumber; + uint32_t timestamp; + uint32_t ssrc; + uint8_t numCSRCs; + uint32_t arrOfCSRCs[kRtpCsrcSize]; + size_t paddingLength; + size_t headerLength; + int payload_type_frequency; + RTPHeaderExtension extension; +}; + +// RTCP mode to use. Compound mode is described by RFC 4585 and reduced-size +// RTCP mode is described by RFC 5506. +enum class RtcpMode { kOff, kCompound, kReducedSize }; + +enum NetworkState { + kNetworkUp, + kNetworkDown, +}; + +} // namespace webrtc + +#endif // API_RTP_HEADERS_H_ diff --git a/third_party/libwebrtc/api/rtp_headers_gn/moz.build b/third_party/libwebrtc/api/rtp_headers_gn/moz.build new file mode 100644 index 0000000000..d26fa6a026 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_headers_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/rtp_headers.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rtp_headers_gn") diff --git a/third_party/libwebrtc/api/rtp_packet_info.cc b/third_party/libwebrtc/api/rtp_packet_info.cc new file mode 100644 index 0000000000..cba274ec38 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_packet_info.cc @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019 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 "api/rtp_packet_info.h" + +#include <algorithm> +#include <utility> + +namespace webrtc { + +RtpPacketInfo::RtpPacketInfo() + : ssrc_(0), rtp_timestamp_(0), receive_time_(Timestamp::MinusInfinity()) {} + +RtpPacketInfo::RtpPacketInfo(uint32_t ssrc, + std::vector<uint32_t> csrcs, + uint32_t rtp_timestamp, + Timestamp receive_time) + : ssrc_(ssrc), + csrcs_(std::move(csrcs)), + rtp_timestamp_(rtp_timestamp), + receive_time_(receive_time) {} + +RtpPacketInfo::RtpPacketInfo(const RTPHeader& rtp_header, + Timestamp receive_time) + : ssrc_(rtp_header.ssrc), + rtp_timestamp_(rtp_header.timestamp), + receive_time_(receive_time) { + const auto& extension = rtp_header.extension; + const auto csrcs_count = std::min<size_t>(rtp_header.numCSRCs, kRtpCsrcSize); + + csrcs_.assign(&rtp_header.arrOfCSRCs[0], &rtp_header.arrOfCSRCs[csrcs_count]); + + if (extension.hasAudioLevel) { + audio_level_ = extension.audioLevel; + } + + absolute_capture_time_ = extension.absolute_capture_time; +} + +bool operator==(const RtpPacketInfo& lhs, const RtpPacketInfo& rhs) { + return (lhs.ssrc() == rhs.ssrc()) && (lhs.csrcs() == rhs.csrcs()) && + (lhs.rtp_timestamp() == rhs.rtp_timestamp()) && + (lhs.receive_time() == rhs.receive_time()) && + (lhs.audio_level() == rhs.audio_level()) && + (lhs.absolute_capture_time() == rhs.absolute_capture_time()) && + (lhs.local_capture_clock_offset() == rhs.local_capture_clock_offset()); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtp_packet_info.h b/third_party/libwebrtc/api/rtp_packet_info.h new file mode 100644 index 0000000000..8df12a36cf --- /dev/null +++ b/third_party/libwebrtc/api/rtp_packet_info.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2019 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 API_RTP_PACKET_INFO_H_ +#define API_RTP_PACKET_INFO_H_ + +#include <cstdint> +#include <utility> +#include <vector> + +#include "absl/types/optional.h" +#include "api/rtp_headers.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// +// Structure to hold information about a received `RtpPacket`. It is primarily +// used to carry per-packet information from when a packet is received until +// the information is passed to `SourceTracker`. +// +class RTC_EXPORT RtpPacketInfo { + public: + RtpPacketInfo(); + + RtpPacketInfo(uint32_t ssrc, + std::vector<uint32_t> csrcs, + uint32_t rtp_timestamp, + Timestamp receive_time); + + RtpPacketInfo(const RTPHeader& rtp_header, Timestamp receive_time); + + RtpPacketInfo(const RtpPacketInfo& other) = default; + RtpPacketInfo(RtpPacketInfo&& other) = default; + RtpPacketInfo& operator=(const RtpPacketInfo& other) = default; + RtpPacketInfo& operator=(RtpPacketInfo&& other) = default; + + uint32_t ssrc() const { return ssrc_; } + void set_ssrc(uint32_t value) { ssrc_ = value; } + + const std::vector<uint32_t>& csrcs() const { return csrcs_; } + void set_csrcs(std::vector<uint32_t> value) { csrcs_ = std::move(value); } + + uint32_t rtp_timestamp() const { return rtp_timestamp_; } + void set_rtp_timestamp(uint32_t value) { rtp_timestamp_ = value; } + + Timestamp receive_time() const { return receive_time_; } + void set_receive_time(Timestamp value) { receive_time_ = value; } + + absl::optional<uint8_t> audio_level() const { return audio_level_; } + RtpPacketInfo& set_audio_level(absl::optional<uint8_t> value) { + audio_level_ = value; + return *this; + } + + const absl::optional<AbsoluteCaptureTime>& absolute_capture_time() const { + return absolute_capture_time_; + } + RtpPacketInfo& set_absolute_capture_time( + const absl::optional<AbsoluteCaptureTime>& value) { + absolute_capture_time_ = value; + return *this; + } + + const absl::optional<TimeDelta>& local_capture_clock_offset() const { + return local_capture_clock_offset_; + } + RtpPacketInfo& set_local_capture_clock_offset( + absl::optional<TimeDelta> value) { + local_capture_clock_offset_ = value; + return *this; + } + + private: + // Fields from the RTP header: + // https://tools.ietf.org/html/rfc3550#section-5.1 + uint32_t ssrc_; + std::vector<uint32_t> csrcs_; + uint32_t rtp_timestamp_; + + // Local `webrtc::Clock`-based timestamp of when the packet was received. + Timestamp receive_time_; + + // Fields from the Audio Level header extension: + // https://tools.ietf.org/html/rfc6464#section-3 + absl::optional<uint8_t> audio_level_; + + // Fields from the Absolute Capture Time header extension: + // http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time + absl::optional<AbsoluteCaptureTime> absolute_capture_time_; + + // Clock offset between the local clock and the capturer's clock. + // Do not confuse with `AbsoluteCaptureTime::estimated_capture_clock_offset` + // which instead represents the clock offset between a remote sender and the + // capturer. The following holds: + // Capture's NTP Clock = Local NTP Clock + Local-Capture Clock Offset + absl::optional<TimeDelta> local_capture_clock_offset_; +}; + +bool operator==(const RtpPacketInfo& lhs, const RtpPacketInfo& rhs); + +inline bool operator!=(const RtpPacketInfo& lhs, const RtpPacketInfo& rhs) { + return !(lhs == rhs); +} + +} // namespace webrtc + +#endif // API_RTP_PACKET_INFO_H_ diff --git a/third_party/libwebrtc/api/rtp_packet_info_gn/moz.build b/third_party/libwebrtc/api/rtp_packet_info_gn/moz.build new file mode 100644 index 0000000000..99c25cbbae --- /dev/null +++ b/third_party/libwebrtc/api/rtp_packet_info_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/rtp_packet_info.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rtp_packet_info_gn") diff --git a/third_party/libwebrtc/api/rtp_packet_info_unittest.cc b/third_party/libwebrtc/api/rtp_packet_info_unittest.cc new file mode 100644 index 0000000000..d35edf75db --- /dev/null +++ b/third_party/libwebrtc/api/rtp_packet_info_unittest.cc @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2019 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 "api/rtp_packet_infos.h" +#include "api/units/time_delta.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { + +TEST(RtpPacketInfoTest, Ssrc) { + constexpr uint32_t kValue = 4038189233; + + RtpPacketInfo lhs; + RtpPacketInfo rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs.set_ssrc(kValue); + EXPECT_EQ(rhs.ssrc(), kValue); + + EXPECT_FALSE(lhs == rhs); + EXPECT_TRUE(lhs != rhs); + + lhs = rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs = RtpPacketInfo(); + EXPECT_NE(rhs.ssrc(), kValue); + + rhs = RtpPacketInfo(/*ssrc=*/kValue, /*csrcs=*/{}, /*rtp_timestamp=*/{}, + /*receive_time=*/Timestamp::Zero()); + EXPECT_EQ(rhs.ssrc(), kValue); +} + +TEST(RtpPacketInfoTest, Csrcs) { + const std::vector<uint32_t> value = {4038189233, 3016333617, 1207992985}; + + RtpPacketInfo lhs; + RtpPacketInfo rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs.set_csrcs(value); + EXPECT_EQ(rhs.csrcs(), value); + + EXPECT_FALSE(lhs == rhs); + EXPECT_TRUE(lhs != rhs); + + lhs = rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs = RtpPacketInfo(); + EXPECT_NE(rhs.csrcs(), value); + + rhs = RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/value, /*rtp_timestamp=*/{}, + /*receive_time=*/Timestamp::Zero()); + EXPECT_EQ(rhs.csrcs(), value); +} + +TEST(RtpPacketInfoTest, RtpTimestamp) { + constexpr uint32_t kValue = 4038189233; + + RtpPacketInfo lhs; + RtpPacketInfo rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs.set_rtp_timestamp(kValue); + EXPECT_EQ(rhs.rtp_timestamp(), kValue); + + EXPECT_FALSE(lhs == rhs); + EXPECT_TRUE(lhs != rhs); + + lhs = rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs = RtpPacketInfo(); + EXPECT_NE(rhs.rtp_timestamp(), kValue); + + rhs = RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/kValue, + /*receive_time=*/Timestamp::Zero()); + EXPECT_EQ(rhs.rtp_timestamp(), kValue); +} + +TEST(RtpPacketInfoTest, ReceiveTimeMs) { + constexpr Timestamp kValue = Timestamp::Micros(8868963877546349045LL); + + RtpPacketInfo lhs; + RtpPacketInfo rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs.set_receive_time(kValue); + EXPECT_EQ(rhs.receive_time(), kValue); + + EXPECT_FALSE(lhs == rhs); + EXPECT_TRUE(lhs != rhs); + + lhs = rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs = RtpPacketInfo(); + EXPECT_NE(rhs.receive_time(), kValue); + + rhs = RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{}, + /*receive_time=*/kValue); + EXPECT_EQ(rhs.receive_time(), kValue); +} + +TEST(RtpPacketInfoTest, AudioLevel) { + constexpr absl::optional<uint8_t> kValue = 31; + + RtpPacketInfo lhs; + RtpPacketInfo rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs.set_audio_level(kValue); + EXPECT_EQ(rhs.audio_level(), kValue); + + EXPECT_FALSE(lhs == rhs); + EXPECT_TRUE(lhs != rhs); + + lhs = rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs = RtpPacketInfo(); + EXPECT_NE(rhs.audio_level(), kValue); + + rhs = RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{}, + /*receive_time=*/Timestamp::Zero()); + rhs.set_audio_level(kValue); + EXPECT_EQ(rhs.audio_level(), kValue); +} + +TEST(RtpPacketInfoTest, AbsoluteCaptureTime) { + constexpr absl::optional<AbsoluteCaptureTime> kValue = AbsoluteCaptureTime{ + .absolute_capture_timestamp = 12, .estimated_capture_clock_offset = 34}; + + RtpPacketInfo lhs; + RtpPacketInfo rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs.set_absolute_capture_time(kValue); + EXPECT_EQ(rhs.absolute_capture_time(), kValue); + + EXPECT_FALSE(lhs == rhs); + EXPECT_TRUE(lhs != rhs); + + lhs = rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs = RtpPacketInfo(); + EXPECT_NE(rhs.absolute_capture_time(), kValue); + + rhs = RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{}, + /*receive_time=*/Timestamp::Zero()); + rhs.set_absolute_capture_time(kValue); + EXPECT_EQ(rhs.absolute_capture_time(), kValue); +} + +TEST(RtpPacketInfoTest, LocalCaptureClockOffset) { + constexpr TimeDelta kValue = TimeDelta::Micros(8868963877546349045LL); + + RtpPacketInfo lhs; + RtpPacketInfo rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs.set_local_capture_clock_offset(kValue); + EXPECT_EQ(rhs.local_capture_clock_offset(), kValue); + + EXPECT_FALSE(lhs == rhs); + EXPECT_TRUE(lhs != rhs); + + lhs = rhs; + + EXPECT_TRUE(lhs == rhs); + EXPECT_FALSE(lhs != rhs); + + rhs = RtpPacketInfo(); + EXPECT_EQ(rhs.local_capture_clock_offset(), absl::nullopt); + + rhs = RtpPacketInfo(/*ssrc=*/{}, /*csrcs=*/{}, /*rtp_timestamp=*/{}, + /*receive_time=*/Timestamp::Zero()); + rhs.set_local_capture_clock_offset(kValue); + EXPECT_EQ(rhs.local_capture_clock_offset(), kValue); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtp_packet_infos.h b/third_party/libwebrtc/api/rtp_packet_infos.h new file mode 100644 index 0000000000..7445729fbb --- /dev/null +++ b/third_party/libwebrtc/api/rtp_packet_infos.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019 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 API_RTP_PACKET_INFOS_H_ +#define API_RTP_PACKET_INFOS_H_ + +#include <cstdint> +#include <utility> +#include <vector> + +#include "api/make_ref_counted.h" +#include "api/ref_counted_base.h" +#include "api/rtp_packet_info.h" +#include "api/scoped_refptr.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Semi-immutable structure to hold information about packets used to assemble +// an audio or video frame. Uses internal reference counting to make it very +// cheap to copy. +// +// We should ideally just use `std::vector<RtpPacketInfo>` and have it +// `std::move()`-ed as the per-packet information is transferred from one object +// to another. But moving the info, instead of copying it, is not easily done +// for the current video code. +class RTC_EXPORT RtpPacketInfos { + public: + using vector_type = std::vector<RtpPacketInfo>; + + using value_type = vector_type::value_type; + using size_type = vector_type::size_type; + using difference_type = vector_type::difference_type; + using const_reference = vector_type::const_reference; + using const_pointer = vector_type::const_pointer; + using const_iterator = vector_type::const_iterator; + using const_reverse_iterator = vector_type::const_reverse_iterator; + + using reference = const_reference; + using pointer = const_pointer; + using iterator = const_iterator; + using reverse_iterator = const_reverse_iterator; + + RtpPacketInfos() {} + explicit RtpPacketInfos(const vector_type& entries) + : data_(Data::Create(entries)) {} + + explicit RtpPacketInfos(vector_type&& entries) + : data_(Data::Create(std::move(entries))) {} + + RtpPacketInfos(const RtpPacketInfos& other) = default; + RtpPacketInfos(RtpPacketInfos&& other) = default; + RtpPacketInfos& operator=(const RtpPacketInfos& other) = default; + RtpPacketInfos& operator=(RtpPacketInfos&& other) = default; + + const_reference operator[](size_type pos) const { return entries()[pos]; } + + const_reference at(size_type pos) const { return entries().at(pos); } + const_reference front() const { return entries().front(); } + const_reference back() const { return entries().back(); } + + const_iterator begin() const { return entries().begin(); } + const_iterator end() const { return entries().end(); } + const_reverse_iterator rbegin() const { return entries().rbegin(); } + const_reverse_iterator rend() const { return entries().rend(); } + + const_iterator cbegin() const { return entries().cbegin(); } + const_iterator cend() const { return entries().cend(); } + const_reverse_iterator crbegin() const { return entries().crbegin(); } + const_reverse_iterator crend() const { return entries().crend(); } + + bool empty() const { return entries().empty(); } + size_type size() const { return entries().size(); } + + private: + class Data final : public rtc::RefCountedNonVirtual<Data> { + public: + static rtc::scoped_refptr<Data> Create(const vector_type& entries) { + // Performance optimization for the empty case. + if (entries.empty()) { + return nullptr; + } + + return rtc::make_ref_counted<Data>(entries); + } + + static rtc::scoped_refptr<Data> Create(vector_type&& entries) { + // Performance optimization for the empty case. + if (entries.empty()) { + return nullptr; + } + + return rtc::make_ref_counted<Data>(std::move(entries)); + } + + const vector_type& entries() const { return entries_; } + + explicit Data(const vector_type& entries) : entries_(entries) {} + explicit Data(vector_type&& entries) : entries_(std::move(entries)) {} + ~Data() = default; + + private: + const vector_type entries_; + }; + + static const vector_type& empty_entries() { + static const vector_type& value = *new vector_type(); + return value; + } + + const vector_type& entries() const { + if (data_ != nullptr) { + return data_->entries(); + } else { + return empty_entries(); + } + } + + rtc::scoped_refptr<Data> data_; +}; + +} // namespace webrtc + +#endif // API_RTP_PACKET_INFOS_H_ diff --git a/third_party/libwebrtc/api/rtp_packet_infos_unittest.cc b/third_party/libwebrtc/api/rtp_packet_infos_unittest.cc new file mode 100644 index 0000000000..a90cfa03e2 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_packet_infos_unittest.cc @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2019 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 "api/rtp_packet_infos.h" + +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +using ::testing::ElementsAre; +using ::testing::SizeIs; + +template <typename Iterator> +RtpPacketInfos::vector_type ToVector(Iterator begin, Iterator end) { + return RtpPacketInfos::vector_type(begin, end); +} + +} // namespace + +TEST(RtpPacketInfosTest, BasicFunctionality) { + RtpPacketInfo p0(/*ssrc=*/123, /*csrcs=*/{1, 2}, /*rtp_timestamp=*/89, + /*receive_time=*/Timestamp::Millis(7)); + p0.set_audio_level(5); + p0.set_absolute_capture_time(AbsoluteCaptureTime{ + .absolute_capture_timestamp = 45, .estimated_capture_clock_offset = 78}); + + RtpPacketInfo p1(/*ssrc=*/456, /*csrcs=*/{3, 4}, /*rtp_timestamp=*/89, + /*receive_time=*/Timestamp::Millis(1)); + p1.set_audio_level(4); + p1.set_absolute_capture_time(AbsoluteCaptureTime{ + .absolute_capture_timestamp = 13, .estimated_capture_clock_offset = 21}); + + RtpPacketInfo p2(/*ssrc=*/789, /*csrcs=*/{5, 6}, /*rtp_timestamp=*/88, + /*receive_time=*/Timestamp::Millis(7)); + p2.set_audio_level(1); + p2.set_absolute_capture_time(AbsoluteCaptureTime{ + .absolute_capture_timestamp = 99, .estimated_capture_clock_offset = 78}); + + RtpPacketInfos x({p0, p1, p2}); + + ASSERT_THAT(x, SizeIs(3)); + + EXPECT_EQ(x[0], p0); + EXPECT_EQ(x[1], p1); + EXPECT_EQ(x[2], p2); + + EXPECT_EQ(x.front(), p0); + EXPECT_EQ(x.back(), p2); + + EXPECT_THAT(ToVector(x.begin(), x.end()), ElementsAre(p0, p1, p2)); + EXPECT_THAT(ToVector(x.rbegin(), x.rend()), ElementsAre(p2, p1, p0)); + + EXPECT_THAT(ToVector(x.cbegin(), x.cend()), ElementsAre(p0, p1, p2)); + EXPECT_THAT(ToVector(x.crbegin(), x.crend()), ElementsAre(p2, p1, p0)); + + EXPECT_FALSE(x.empty()); +} + +TEST(RtpPacketInfosTest, CopyShareData) { + RtpPacketInfo p0(/*ssrc=*/123, /*csrcs=*/{1, 2}, /*rtp_timestamp=*/89, + /*receive_time=*/Timestamp::Millis(7)); + p0.set_audio_level(5); + p0.set_absolute_capture_time(AbsoluteCaptureTime{ + .absolute_capture_timestamp = 45, .estimated_capture_clock_offset = 78}); + + RtpPacketInfo p1(/*ssrc=*/456, /*csrcs=*/{3, 4}, /*rtp_timestamp=*/89, + /*receive_time=*/Timestamp::Millis(1)); + p1.set_audio_level(4); + p1.set_absolute_capture_time(AbsoluteCaptureTime{ + .absolute_capture_timestamp = 13, .estimated_capture_clock_offset = 21}); + + RtpPacketInfo p2(/*ssrc=*/789, /*csrcs=*/{5, 6}, /*rtp_timestamp=*/88, + /*receive_time=*/Timestamp::Millis(7)); + p2.set_audio_level(1); + p2.set_absolute_capture_time(AbsoluteCaptureTime{ + .absolute_capture_timestamp = 99, .estimated_capture_clock_offset = 78}); + + RtpPacketInfos lhs({p0, p1, p2}); + RtpPacketInfos rhs = lhs; + + ASSERT_THAT(lhs, SizeIs(3)); + ASSERT_THAT(rhs, SizeIs(3)); + + for (size_t i = 0; i < lhs.size(); ++i) { + EXPECT_EQ(lhs[i], rhs[i]); + } + + EXPECT_EQ(lhs.front(), rhs.front()); + EXPECT_EQ(lhs.back(), rhs.back()); + + EXPECT_EQ(lhs.begin(), rhs.begin()); + EXPECT_EQ(lhs.end(), rhs.end()); + EXPECT_EQ(lhs.rbegin(), rhs.rbegin()); + EXPECT_EQ(lhs.rend(), rhs.rend()); + + EXPECT_EQ(lhs.cbegin(), rhs.cbegin()); + EXPECT_EQ(lhs.cend(), rhs.cend()); + EXPECT_EQ(lhs.crbegin(), rhs.crbegin()); + EXPECT_EQ(lhs.crend(), rhs.crend()); + + EXPECT_EQ(lhs.empty(), rhs.empty()); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtp_parameters.cc b/third_party/libwebrtc/api/rtp_parameters.cc new file mode 100644 index 0000000000..c1d12e5d8d --- /dev/null +++ b/third_party/libwebrtc/api/rtp_parameters.cc @@ -0,0 +1,295 @@ +/* + * 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. + */ +#include "api/rtp_parameters.h" + +#include <algorithm> +#include <string> +#include <tuple> +#include <utility> + +#include "api/array_view.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +const char* DegradationPreferenceToString( + DegradationPreference degradation_preference) { + switch (degradation_preference) { + case DegradationPreference::DISABLED: + return "disabled"; + case DegradationPreference::MAINTAIN_FRAMERATE: + return "maintain-framerate"; + case DegradationPreference::MAINTAIN_RESOLUTION: + return "maintain-resolution"; + case DegradationPreference::BALANCED: + return "balanced"; + } + RTC_CHECK_NOTREACHED(); +} + +const double kDefaultBitratePriority = 1.0; + +RtcpFeedback::RtcpFeedback() = default; +RtcpFeedback::RtcpFeedback(RtcpFeedbackType type) : type(type) {} +RtcpFeedback::RtcpFeedback(RtcpFeedbackType type, + RtcpFeedbackMessageType message_type) + : type(type), message_type(message_type) {} +RtcpFeedback::RtcpFeedback(const RtcpFeedback& rhs) = default; +RtcpFeedback::~RtcpFeedback() = default; + +RtpCodecCapability::RtpCodecCapability() = default; +RtpCodecCapability::~RtpCodecCapability() = default; + +RtpHeaderExtensionCapability::RtpHeaderExtensionCapability() = default; +RtpHeaderExtensionCapability::RtpHeaderExtensionCapability( + absl::string_view uri) + : uri(uri) {} +RtpHeaderExtensionCapability::RtpHeaderExtensionCapability( + absl::string_view uri, + int preferred_id) + : uri(uri), preferred_id(preferred_id) {} +RtpHeaderExtensionCapability::RtpHeaderExtensionCapability( + absl::string_view uri, + int preferred_id, + RtpTransceiverDirection direction) + : uri(uri), preferred_id(preferred_id), direction(direction) {} +RtpHeaderExtensionCapability::~RtpHeaderExtensionCapability() = default; + +RtpExtension::RtpExtension() = default; +RtpExtension::RtpExtension(absl::string_view uri, int id) : uri(uri), id(id) {} +RtpExtension::RtpExtension(absl::string_view uri, int id, bool encrypt) + : uri(uri), id(id), encrypt(encrypt) {} +RtpExtension::~RtpExtension() = default; + +RtpFecParameters::RtpFecParameters() = default; +RtpFecParameters::RtpFecParameters(FecMechanism mechanism) + : mechanism(mechanism) {} +RtpFecParameters::RtpFecParameters(FecMechanism mechanism, uint32_t ssrc) + : ssrc(ssrc), mechanism(mechanism) {} +RtpFecParameters::RtpFecParameters(const RtpFecParameters& rhs) = default; +RtpFecParameters::~RtpFecParameters() = default; + +RtpRtxParameters::RtpRtxParameters() = default; +RtpRtxParameters::RtpRtxParameters(uint32_t ssrc) : ssrc(ssrc) {} +RtpRtxParameters::RtpRtxParameters(const RtpRtxParameters& rhs) = default; +RtpRtxParameters::~RtpRtxParameters() = default; + +RtpEncodingParameters::RtpEncodingParameters() = default; +RtpEncodingParameters::RtpEncodingParameters(const RtpEncodingParameters& rhs) = + default; +RtpEncodingParameters::~RtpEncodingParameters() = default; + +RtpCodecParameters::RtpCodecParameters() = default; +RtpCodecParameters::RtpCodecParameters(const RtpCodecParameters& rhs) = default; +RtpCodecParameters::~RtpCodecParameters() = default; + +RtpCapabilities::RtpCapabilities() = default; +RtpCapabilities::~RtpCapabilities() = default; + +RtcpParameters::RtcpParameters() = default; +RtcpParameters::RtcpParameters(const RtcpParameters& rhs) = default; +RtcpParameters::~RtcpParameters() = default; + +RtpParameters::RtpParameters() = default; +RtpParameters::RtpParameters(const RtpParameters& rhs) = default; +RtpParameters::~RtpParameters() = default; + +std::string RtpExtension::ToString() const { + char buf[256]; + rtc::SimpleStringBuilder sb(buf); + sb << "{uri: " << uri; + sb << ", id: " << id; + if (encrypt) { + sb << ", encrypt"; + } + sb << '}'; + return sb.str(); +} + +constexpr char RtpExtension::kEncryptHeaderExtensionsUri[]; +constexpr char RtpExtension::kAudioLevelUri[]; +constexpr char RtpExtension::kTimestampOffsetUri[]; +constexpr char RtpExtension::kAbsSendTimeUri[]; +constexpr char RtpExtension::kAbsoluteCaptureTimeUri[]; +constexpr char RtpExtension::kVideoRotationUri[]; +constexpr char RtpExtension::kVideoContentTypeUri[]; +constexpr char RtpExtension::kVideoTimingUri[]; +constexpr char RtpExtension::kGenericFrameDescriptorUri00[]; +constexpr char RtpExtension::kDependencyDescriptorUri[]; +constexpr char RtpExtension::kVideoLayersAllocationUri[]; +constexpr char RtpExtension::kTransportSequenceNumberUri[]; +constexpr char RtpExtension::kTransportSequenceNumberV2Uri[]; +constexpr char RtpExtension::kPlayoutDelayUri[]; +constexpr char RtpExtension::kColorSpaceUri[]; +constexpr char RtpExtension::kMidUri[]; +constexpr char RtpExtension::kRidUri[]; +constexpr char RtpExtension::kRepairedRidUri[]; +constexpr char RtpExtension::kVideoFrameTrackingIdUri[]; +constexpr char RtpExtension::kCsrcAudioLevelsUri[]; + +constexpr int RtpExtension::kMinId; +constexpr int RtpExtension::kMaxId; +constexpr int RtpExtension::kMaxValueSize; +constexpr int RtpExtension::kOneByteHeaderExtensionMaxId; +constexpr int RtpExtension::kOneByteHeaderExtensionMaxValueSize; + +bool RtpExtension::IsSupportedForAudio(absl::string_view uri) { + return uri == webrtc::RtpExtension::kAudioLevelUri || + uri == webrtc::RtpExtension::kAbsSendTimeUri || + uri == webrtc::RtpExtension::kAbsoluteCaptureTimeUri || + uri == webrtc::RtpExtension::kTransportSequenceNumberUri || + uri == webrtc::RtpExtension::kTransportSequenceNumberV2Uri || + uri == webrtc::RtpExtension::kMidUri || + uri == webrtc::RtpExtension::kRidUri || + uri == webrtc::RtpExtension::kRepairedRidUri || + uri == webrtc::RtpExtension::kCsrcAudioLevelsUri; +} + +bool RtpExtension::IsSupportedForVideo(absl::string_view uri) { + return uri == webrtc::RtpExtension::kTimestampOffsetUri || + uri == webrtc::RtpExtension::kAbsSendTimeUri || + uri == webrtc::RtpExtension::kAbsoluteCaptureTimeUri || + uri == webrtc::RtpExtension::kVideoRotationUri || + uri == webrtc::RtpExtension::kTransportSequenceNumberUri || + uri == webrtc::RtpExtension::kTransportSequenceNumberV2Uri || + uri == webrtc::RtpExtension::kPlayoutDelayUri || + uri == webrtc::RtpExtension::kVideoContentTypeUri || + uri == webrtc::RtpExtension::kVideoTimingUri || + uri == webrtc::RtpExtension::kMidUri || + uri == webrtc::RtpExtension::kGenericFrameDescriptorUri00 || + uri == webrtc::RtpExtension::kDependencyDescriptorUri || + uri == webrtc::RtpExtension::kColorSpaceUri || + uri == webrtc::RtpExtension::kRidUri || + uri == webrtc::RtpExtension::kRepairedRidUri || + uri == webrtc::RtpExtension::kVideoLayersAllocationUri || + uri == webrtc::RtpExtension::kVideoFrameTrackingIdUri; +} + +bool RtpExtension::IsEncryptionSupported(absl::string_view uri) { + return +#if defined(ENABLE_EXTERNAL_AUTH) + // TODO(jbauch): Figure out a way to always allow "kAbsSendTimeUri" + // here and filter out later if external auth is really used in + // srtpfilter. External auth is used by Chromium and replaces the + // extension header value of "kAbsSendTimeUri", so it must not be + // encrypted (which can't be done by Chromium). + uri != webrtc::RtpExtension::kAbsSendTimeUri && +#endif + uri != webrtc::RtpExtension::kEncryptHeaderExtensionsUri; +} + +// Returns whether a header extension with the given URI exists. +// Note: This does not differentiate between encrypted and non-encrypted +// extensions, so use with care! +static bool HeaderExtensionWithUriExists( + const std::vector<RtpExtension>& extensions, + absl::string_view uri) { + for (const auto& extension : extensions) { + if (extension.uri == uri) { + return true; + } + } + return false; +} + +const RtpExtension* RtpExtension::FindHeaderExtensionByUri( + const std::vector<RtpExtension>& extensions, + absl::string_view uri, + Filter filter) { + const webrtc::RtpExtension* fallback_extension = nullptr; + for (const auto& extension : extensions) { + if (extension.uri != uri) { + continue; + } + + switch (filter) { + case kDiscardEncryptedExtension: + // We only accept an unencrypted extension. + if (!extension.encrypt) { + return &extension; + } + break; + + case kPreferEncryptedExtension: + // We prefer an encrypted extension but we can fall back to an + // unencrypted extension. + if (extension.encrypt) { + return &extension; + } else { + fallback_extension = &extension; + } + break; + + case kRequireEncryptedExtension: + // We only accept an encrypted extension. + if (extension.encrypt) { + return &extension; + } + break; + } + } + + // Returning fallback extension (if any) + return fallback_extension; +} + +const RtpExtension* RtpExtension::FindHeaderExtensionByUriAndEncryption( + const std::vector<RtpExtension>& extensions, + absl::string_view uri, + bool encrypt) { + for (const auto& extension : extensions) { + if (extension.uri == uri && extension.encrypt == encrypt) { + return &extension; + } + } + return nullptr; +} + +const std::vector<RtpExtension> RtpExtension::DeduplicateHeaderExtensions( + const std::vector<RtpExtension>& extensions, + Filter filter) { + std::vector<RtpExtension> filtered; + + // If we do not discard encrypted extensions, add them first + if (filter != kDiscardEncryptedExtension) { + for (const auto& extension : extensions) { + if (!extension.encrypt) { + continue; + } + if (!HeaderExtensionWithUriExists(filtered, extension.uri)) { + filtered.push_back(extension); + } + } + } + + // If we do not require encrypted extensions, add missing, non-encrypted + // extensions. + if (filter != kRequireEncryptedExtension) { + for (const auto& extension : extensions) { + if (extension.encrypt) { + continue; + } + if (!HeaderExtensionWithUriExists(filtered, extension.uri)) { + filtered.push_back(extension); + } + } + } + + // Sort the returned vector to make comparisons of header extensions reliable. + // In order of priority, we sort by uri first, then encrypt and id last. + std::sort(filtered.begin(), filtered.end(), + [](const RtpExtension& a, const RtpExtension& b) { + return std::tie(a.uri, a.encrypt, a.id) < + std::tie(b.uri, b.encrypt, b.id); + }); + + return filtered; +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtp_parameters.h b/third_party/libwebrtc/api/rtp_parameters.h new file mode 100644 index 0000000000..0d3c9dfd22 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_parameters.h @@ -0,0 +1,719 @@ +/* + * Copyright 2015 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 API_RTP_PARAMETERS_H_ +#define API_RTP_PARAMETERS_H_ + +#include <stdint.h> + +#include <map> +#include <string> +#include <vector> + +#include "absl/container/inlined_vector.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/media_types.h" +#include "api/priority.h" +#include "api/rtp_transceiver_direction.h" +#include "api/video/resolution.h" +#include "api/video_codecs/scalability_mode.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// These structures are intended to mirror those defined by: +// http://draft.ortc.org/#rtcrtpdictionaries* +// Contains everything specified as of 2017 Jan 24. +// +// They are used when retrieving or modifying the parameters of an +// RtpSender/RtpReceiver, or retrieving capabilities. +// +// Note on conventions: Where ORTC may use "octet", "short" and "unsigned" +// types, we typically use "int", in keeping with our style guidelines. The +// parameter's actual valid range will be enforced when the parameters are set, +// rather than when the parameters struct is built. An exception is made for +// SSRCs, since they use the full unsigned 32-bit range, and aren't expected to +// be used for any numeric comparisons/operations. +// +// Additionally, where ORTC uses strings, we may use enums for things that have +// a fixed number of supported values. However, for things that can be extended +// (such as codecs, by providing an external encoder factory), a string +// identifier is used. + +enum class FecMechanism { + RED, + RED_AND_ULPFEC, + FLEXFEC, +}; + +// Used in RtcpFeedback struct. +enum class RtcpFeedbackType { + CCM, + LNTF, // "goog-lntf" + NACK, + REMB, // "goog-remb" + TRANSPORT_CC, +}; + +// Used in RtcpFeedback struct when type is NACK or CCM. +enum class RtcpFeedbackMessageType { + // Equivalent to {type: "nack", parameter: undefined} in ORTC. + GENERIC_NACK, + PLI, // Usable with NACK. + FIR, // Usable with CCM. +}; + +enum class DtxStatus { + DISABLED, + ENABLED, +}; + +// Based on the spec in +// https://w3c.github.io/webrtc-pc/#idl-def-rtcdegradationpreference. +// These options are enforced on a best-effort basis. For instance, all of +// these options may suffer some frame drops in order to avoid queuing. +// TODO(sprang): Look into possibility of more strictly enforcing the +// maintain-framerate option. +// TODO(deadbeef): Default to "balanced", as the spec indicates? +enum class DegradationPreference { + // Don't take any actions based on over-utilization signals. Not part of the + // web API. + DISABLED, + // On over-use, request lower resolution, possibly causing down-scaling. + MAINTAIN_FRAMERATE, + // On over-use, request lower frame rate, possibly causing frame drops. + MAINTAIN_RESOLUTION, + // Try to strike a "pleasing" balance between frame rate or resolution. + BALANCED, +}; + +RTC_EXPORT const char* DegradationPreferenceToString( + DegradationPreference degradation_preference); + +RTC_EXPORT extern const double kDefaultBitratePriority; + +struct RTC_EXPORT RtcpFeedback { + RtcpFeedbackType type = RtcpFeedbackType::CCM; + + // Equivalent to ORTC "parameter" field with slight differences: + // 1. It's an enum instead of a string. + // 2. Generic NACK feedback is represented by a GENERIC_NACK message type, + // rather than an unset "parameter" value. + absl::optional<RtcpFeedbackMessageType> message_type; + + // Constructors for convenience. + RtcpFeedback(); + explicit RtcpFeedback(RtcpFeedbackType type); + RtcpFeedback(RtcpFeedbackType type, RtcpFeedbackMessageType message_type); + RtcpFeedback(const RtcpFeedback&); + ~RtcpFeedback(); + + bool operator==(const RtcpFeedback& o) const { + return type == o.type && message_type == o.message_type; + } + bool operator!=(const RtcpFeedback& o) const { return !(*this == o); } +}; + +// RtpCodecCapability is to RtpCodecParameters as RtpCapabilities is to +// RtpParameters. This represents the static capabilities of an endpoint's +// implementation of a codec. +struct RTC_EXPORT RtpCodecCapability { + RtpCodecCapability(); + ~RtpCodecCapability(); + + // Build MIME "type/subtype" string from `name` and `kind`. + std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; } + + // Used to identify the codec. Equivalent to MIME subtype. + std::string name; + + // The media type of this codec. Equivalent to MIME top-level type. + cricket::MediaType kind = cricket::MEDIA_TYPE_AUDIO; + + // Clock rate in Hertz. If unset, the codec is applicable to any clock rate. + absl::optional<int> clock_rate; + + // Default payload type for this codec. Mainly needed for codecs that use + // that have statically assigned payload types. + absl::optional<int> preferred_payload_type; + + // Maximum packetization time supported by an RtpReceiver for this codec. + // TODO(deadbeef): Not implemented. + absl::optional<int> max_ptime; + + // Preferred packetization time for an RtpReceiver or RtpSender of this codec. + // TODO(deadbeef): Not implemented. + absl::optional<int> ptime; + + // The number of audio channels supported. Unused for video codecs. + absl::optional<int> num_channels; + + // Feedback mechanisms supported for this codec. + std::vector<RtcpFeedback> rtcp_feedback; + + // Codec-specific parameters that must be signaled to the remote party. + // + // Corresponds to "a=fmtp" parameters in SDP. + // + // Contrary to ORTC, these parameters are named using all lowercase strings. + // This helps make the mapping to SDP simpler, if an application is using SDP. + // Boolean values are represented by the string "1". + std::map<std::string, std::string> parameters; + + // Codec-specific parameters that may optionally be signaled to the remote + // party. + // TODO(deadbeef): Not implemented. + std::map<std::string, std::string> options; + + // Maximum number of temporal layer extensions supported by this codec. + // For example, a value of 1 indicates that 2 total layers are supported. + // TODO(deadbeef): Not implemented. + int max_temporal_layer_extensions = 0; + + // Maximum number of spatial layer extensions supported by this codec. + // For example, a value of 1 indicates that 2 total layers are supported. + // TODO(deadbeef): Not implemented. + int max_spatial_layer_extensions = 0; + + // Whether the implementation can send/receive SVC layers with distinct SSRCs. + // Always false for audio codecs. True for video codecs that support scalable + // video coding with MRST. + // TODO(deadbeef): Not implemented. + bool svc_multi_stream_support = false; + + // https://w3c.github.io/webrtc-svc/#dom-rtcrtpcodeccapability-scalabilitymodes + absl::InlinedVector<ScalabilityMode, kScalabilityModeCount> scalability_modes; + + bool operator==(const RtpCodecCapability& o) const { + return name == o.name && kind == o.kind && clock_rate == o.clock_rate && + preferred_payload_type == o.preferred_payload_type && + max_ptime == o.max_ptime && ptime == o.ptime && + num_channels == o.num_channels && rtcp_feedback == o.rtcp_feedback && + parameters == o.parameters && options == o.options && + max_temporal_layer_extensions == o.max_temporal_layer_extensions && + max_spatial_layer_extensions == o.max_spatial_layer_extensions && + svc_multi_stream_support == o.svc_multi_stream_support && + scalability_modes == o.scalability_modes; + } + bool operator!=(const RtpCodecCapability& o) const { return !(*this == o); } +}; + +// Used in RtpCapabilities and RtpTransceiverInterface's header extensions query +// and setup methods; represents the capabilities/preferences of an +// implementation for a header extension. +// +// Just called "RtpHeaderExtension" in ORTC, but the "Capability" suffix was +// added here for consistency and to avoid confusion with +// RtpHeaderExtensionParameters. +// +// Note that ORTC includes a "kind" field, but we omit this because it's +// redundant; if you call "RtpReceiver::GetCapabilities(MEDIA_TYPE_AUDIO)", +// you know you're getting audio capabilities. +struct RTC_EXPORT RtpHeaderExtensionCapability { + // URI of this extension, as defined in RFC8285. + std::string uri; + + // Preferred value of ID that goes in the packet. + absl::optional<int> preferred_id; + + // If true, it's preferred that the value in the header is encrypted. + // TODO(deadbeef): Not implemented. + bool preferred_encrypt = false; + + // The direction of the extension. The kStopped value is only used with + // RtpTransceiverInterface::HeaderExtensionsToOffer() and + // SetOfferedRtpHeaderExtensions(). + RtpTransceiverDirection direction = RtpTransceiverDirection::kSendRecv; + + // Constructors for convenience. + RtpHeaderExtensionCapability(); + explicit RtpHeaderExtensionCapability(absl::string_view uri); + RtpHeaderExtensionCapability(absl::string_view uri, int preferred_id); + RtpHeaderExtensionCapability(absl::string_view uri, + int preferred_id, + RtpTransceiverDirection direction); + ~RtpHeaderExtensionCapability(); + + bool operator==(const RtpHeaderExtensionCapability& o) const { + return uri == o.uri && preferred_id == o.preferred_id && + preferred_encrypt == o.preferred_encrypt && direction == o.direction; + } + bool operator!=(const RtpHeaderExtensionCapability& o) const { + return !(*this == o); + } +}; + +// RTP header extension, see RFC8285. +struct RTC_EXPORT RtpExtension { + enum Filter { + // Encrypted extensions will be ignored and only non-encrypted extensions + // will be considered. + kDiscardEncryptedExtension, + // Encrypted extensions will be preferred but will fall back to + // non-encrypted extensions if necessary. + kPreferEncryptedExtension, + // Encrypted extensions will be required, so any non-encrypted extensions + // will be discarded. + kRequireEncryptedExtension, + }; + + RtpExtension(); + RtpExtension(absl::string_view uri, int id); + RtpExtension(absl::string_view uri, int id, bool encrypt); + ~RtpExtension(); + + std::string ToString() const; + bool operator==(const RtpExtension& rhs) const { + return uri == rhs.uri && id == rhs.id && encrypt == rhs.encrypt; + } + static bool IsSupportedForAudio(absl::string_view uri); + static bool IsSupportedForVideo(absl::string_view uri); + // Return "true" if the given RTP header extension URI may be encrypted. + static bool IsEncryptionSupported(absl::string_view uri); + + // Returns the header extension with the given URI or nullptr if not found. + static const RtpExtension* FindHeaderExtensionByUri( + const std::vector<RtpExtension>& extensions, + absl::string_view uri, + Filter filter); + + // Returns the header extension with the given URI and encrypt parameter, + // if found, otherwise nullptr. + static const RtpExtension* FindHeaderExtensionByUriAndEncryption( + const std::vector<RtpExtension>& extensions, + absl::string_view uri, + bool encrypt); + + // Returns a list of extensions where any extension URI is unique. + // The returned list will be sorted by uri first, then encrypt and id last. + // Having the list sorted allows the caller fo compare filtered lists for + // equality to detect when changes have been made. + static const std::vector<RtpExtension> DeduplicateHeaderExtensions( + const std::vector<RtpExtension>& extensions, + Filter filter); + + // Encryption of Header Extensions, see RFC 6904 for details: + // https://tools.ietf.org/html/rfc6904 + static constexpr char kEncryptHeaderExtensionsUri[] = + "urn:ietf:params:rtp-hdrext:encrypt"; + + // Header extension for audio levels, as defined in: + // https://tools.ietf.org/html/rfc6464 + static constexpr char kAudioLevelUri[] = + "urn:ietf:params:rtp-hdrext:ssrc-audio-level"; + + // Header extension for RTP timestamp offset, see RFC 5450 for details: + // http://tools.ietf.org/html/rfc5450 + static constexpr char kTimestampOffsetUri[] = + "urn:ietf:params:rtp-hdrext:toffset"; + + // Header extension for absolute send time, see url for details: + // http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time + static constexpr char kAbsSendTimeUri[] = + "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time"; + + // Header extension for absolute capture time, see url for details: + // http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time + static constexpr char kAbsoluteCaptureTimeUri[] = + "http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time"; + + // Header extension for coordination of video orientation, see url for + // details: + // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ts_126114v120700p.pdf + static constexpr char kVideoRotationUri[] = "urn:3gpp:video-orientation"; + + // Header extension for video content type. E.g. default or screenshare. + static constexpr char kVideoContentTypeUri[] = + "http://www.webrtc.org/experiments/rtp-hdrext/video-content-type"; + + // Header extension for video timing. + static constexpr char kVideoTimingUri[] = + "http://www.webrtc.org/experiments/rtp-hdrext/video-timing"; + + // Experimental codec agnostic frame descriptor. + static constexpr char kGenericFrameDescriptorUri00[] = + "http://www.webrtc.org/experiments/rtp-hdrext/" + "generic-frame-descriptor-00"; + static constexpr char kDependencyDescriptorUri[] = + "https://aomediacodec.github.io/av1-rtp-spec/" + "#dependency-descriptor-rtp-header-extension"; + + // Experimental extension for signalling target bitrate per layer. + static constexpr char kVideoLayersAllocationUri[] = + "http://www.webrtc.org/experiments/rtp-hdrext/video-layers-allocation00"; + + // Header extension for transport sequence number, see url for details: + // http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions + static constexpr char kTransportSequenceNumberUri[] = + "http://www.ietf.org/id/" + "draft-holmer-rmcat-transport-wide-cc-extensions-01"; + static constexpr char kTransportSequenceNumberV2Uri[] = + "http://www.webrtc.org/experiments/rtp-hdrext/transport-wide-cc-02"; + + // This extension allows applications to adaptively limit the playout delay + // on frames as per the current needs. For example, a gaming application + // has very different needs on end-to-end delay compared to a video-conference + // application. + static constexpr char kPlayoutDelayUri[] = + "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay"; + + // Header extension for color space information. + static constexpr char kColorSpaceUri[] = + "http://www.webrtc.org/experiments/rtp-hdrext/color-space"; + + // Header extension for identifying media section within a transport. + // https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-49#section-15 + static constexpr char kMidUri[] = "urn:ietf:params:rtp-hdrext:sdes:mid"; + + // Header extension for RIDs and Repaired RIDs + // https://tools.ietf.org/html/draft-ietf-avtext-rid-09 + // https://tools.ietf.org/html/draft-ietf-mmusic-rid-15 + static constexpr char kRidUri[] = + "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id"; + static constexpr char kRepairedRidUri[] = + "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id"; + + // Header extension to propagate webrtc::VideoFrame id field + static constexpr char kVideoFrameTrackingIdUri[] = + "http://www.webrtc.org/experiments/rtp-hdrext/video-frame-tracking-id"; + + // Header extension for Mixer-to-Client audio levels per CSRC as defined in + // https://tools.ietf.org/html/rfc6465 + static constexpr char kCsrcAudioLevelsUri[] = + "urn:ietf:params:rtp-hdrext:csrc-audio-level"; + + // Inclusive min and max IDs for two-byte header extensions and one-byte + // header extensions, per RFC8285 Section 4.2-4.3. + static constexpr int kMinId = 1; + static constexpr int kMaxId = 255; + static constexpr int kMaxValueSize = 255; + static constexpr int kOneByteHeaderExtensionMaxId = 14; + static constexpr int kOneByteHeaderExtensionMaxValueSize = 16; + + std::string uri; + int id = 0; + bool encrypt = false; +}; + +struct RTC_EXPORT RtpFecParameters { + // If unset, a value is chosen by the implementation. + // Works just like RtpEncodingParameters::ssrc. + absl::optional<uint32_t> ssrc; + + FecMechanism mechanism = FecMechanism::RED; + + // Constructors for convenience. + RtpFecParameters(); + explicit RtpFecParameters(FecMechanism mechanism); + RtpFecParameters(FecMechanism mechanism, uint32_t ssrc); + RtpFecParameters(const RtpFecParameters&); + ~RtpFecParameters(); + + bool operator==(const RtpFecParameters& o) const { + return ssrc == o.ssrc && mechanism == o.mechanism; + } + bool operator!=(const RtpFecParameters& o) const { return !(*this == o); } +}; + +struct RTC_EXPORT RtpRtxParameters { + // If unset, a value is chosen by the implementation. + // Works just like RtpEncodingParameters::ssrc. + absl::optional<uint32_t> ssrc; + + // Constructors for convenience. + RtpRtxParameters(); + explicit RtpRtxParameters(uint32_t ssrc); + RtpRtxParameters(const RtpRtxParameters&); + ~RtpRtxParameters(); + + bool operator==(const RtpRtxParameters& o) const { return ssrc == o.ssrc; } + bool operator!=(const RtpRtxParameters& o) const { return !(*this == o); } +}; + +struct RTC_EXPORT RtpEncodingParameters { + RtpEncodingParameters(); + RtpEncodingParameters(const RtpEncodingParameters&); + ~RtpEncodingParameters(); + + // If unset, a value is chosen by the implementation. + // + // Note that the chosen value is NOT returned by GetParameters, because it + // may change due to an SSRC conflict, in which case the conflict is handled + // internally without any event. Another way of looking at this is that an + // unset SSRC acts as a "wildcard" SSRC. + absl::optional<uint32_t> ssrc; + + // The relative bitrate priority of this encoding. Currently this is + // implemented for the entire rtp sender by using the value of the first + // encoding parameter. + // See: https://w3c.github.io/webrtc-priority/#enumdef-rtcprioritytype + // "very-low" = 0.5 + // "low" = 1.0 + // "medium" = 2.0 + // "high" = 4.0 + // TODO(webrtc.bugs.org/8630): Implement this per encoding parameter. + // Currently there is logic for how bitrate is distributed per simulcast layer + // in the VideoBitrateAllocator. This must be updated to incorporate relative + // bitrate priority. + double bitrate_priority = kDefaultBitratePriority; + + // The relative DiffServ Code Point priority for this encoding, allowing + // packets to be marked relatively higher or lower without affecting + // bandwidth allocations. See https://w3c.github.io/webrtc-dscp-exp/ . + // TODO(http://crbug.com/webrtc/8630): Implement this per encoding parameter. + // TODO(http://crbug.com/webrtc/11379): TCP connections should use a single + // DSCP value even if shared by multiple senders; this is not implemented. + Priority network_priority = Priority::kLow; + + // If set, this represents the Transport Independent Application Specific + // maximum bandwidth defined in RFC3890. If unset, there is no maximum + // bitrate. Currently this is implemented for the entire rtp sender by using + // the value of the first encoding parameter. + // + // Just called "maxBitrate" in ORTC spec. + // + // TODO(deadbeef): With ORTC RtpSenders, this currently sets the total + // bandwidth for the entire bandwidth estimator (audio and video). This is + // just always how "b=AS" was handled, but it's not correct and should be + // fixed. + absl::optional<int> max_bitrate_bps; + + // Specifies the minimum bitrate in bps for video. + absl::optional<int> min_bitrate_bps; + + // Specifies the maximum framerate in fps for video. + absl::optional<double> max_framerate; + + // Specifies the number of temporal layers for video (if the feature is + // supported by the codec implementation). + // Screencast support is experimental. + absl::optional<int> num_temporal_layers; + + // For video, scale the resolution down by this factor. + absl::optional<double> scale_resolution_down_by; + + // https://w3c.github.io/webrtc-svc/#rtcrtpencodingparameters + absl::optional<std::string> scalability_mode; + + // Requested encode resolution. + // + // This field provides an alternative to `scale_resolution_down_by` + // that is not dependent on the video source. + // + // When setting requested_resolution it is not necessary to adapt the + // video source using OnOutputFormatRequest, since the VideoStreamEncoder + // will apply downscaling if necessary. requested_resolution will also be + // propagated to the video source, this allows downscaling earlier in the + // pipeline which can be beneficial if the source is consumed by multiple + // encoders, but is not strictly necessary. + // + // The `requested_resolution` is subject to resource adaptation. + // + // It is an error to set both `requested_resolution` and + // `scale_resolution_down_by`. + absl::optional<Resolution> requested_resolution; + + // For an RtpSender, set to true to cause this encoding to be encoded and + // sent, and false for it not to be encoded and sent. This allows control + // across multiple encodings of a sender for turning simulcast layers on and + // off. + // TODO(webrtc.bugs.org/8807): Updating this parameter will trigger an encoder + // reset, but this isn't necessarily required. + bool active = true; + + // Value to use for RID RTP header extension. + // Called "encodingId" in ORTC. + std::string rid; + + // Allow dynamic frame length changes for audio: + // https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-adaptiveptime + bool adaptive_ptime = false; + + bool operator==(const RtpEncodingParameters& o) const { + return ssrc == o.ssrc && bitrate_priority == o.bitrate_priority && + network_priority == o.network_priority && + max_bitrate_bps == o.max_bitrate_bps && + min_bitrate_bps == o.min_bitrate_bps && + max_framerate == o.max_framerate && + num_temporal_layers == o.num_temporal_layers && + scale_resolution_down_by == o.scale_resolution_down_by && + active == o.active && rid == o.rid && + adaptive_ptime == o.adaptive_ptime && + requested_resolution == o.requested_resolution; + } + bool operator!=(const RtpEncodingParameters& o) const { + return !(*this == o); + } +}; + +struct RTC_EXPORT RtpCodecParameters { + RtpCodecParameters(); + RtpCodecParameters(const RtpCodecParameters&); + ~RtpCodecParameters(); + + // Build MIME "type/subtype" string from `name` and `kind`. + std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; } + + // Used to identify the codec. Equivalent to MIME subtype. + std::string name; + + // The media type of this codec. Equivalent to MIME top-level type. + cricket::MediaType kind = cricket::MEDIA_TYPE_AUDIO; + + // Payload type used to identify this codec in RTP packets. + // This must always be present, and must be unique across all codecs using + // the same transport. + int payload_type = 0; + + // If unset, the implementation default is used. + absl::optional<int> clock_rate; + + // The number of audio channels used. Unset for video codecs. If unset for + // audio, the implementation default is used. + // TODO(deadbeef): The "implementation default" part isn't fully implemented. + // Only defaults to 1, even though some codecs (such as opus) should really + // default to 2. + absl::optional<int> num_channels; + + // The maximum packetization time to be used by an RtpSender. + // If `ptime` is also set, this will be ignored. + // TODO(deadbeef): Not implemented. + absl::optional<int> max_ptime; + + // The packetization time to be used by an RtpSender. + // If unset, will use any time up to max_ptime. + // TODO(deadbeef): Not implemented. + absl::optional<int> ptime; + + // Feedback mechanisms to be used for this codec. + // TODO(deadbeef): Not implemented with PeerConnection senders/receivers. + std::vector<RtcpFeedback> rtcp_feedback; + + // Codec-specific parameters that must be signaled to the remote party. + // + // Corresponds to "a=fmtp" parameters in SDP. + // + // Contrary to ORTC, these parameters are named using all lowercase strings. + // This helps make the mapping to SDP simpler, if an application is using SDP. + // Boolean values are represented by the string "1". + std::map<std::string, std::string> parameters; + + bool operator==(const RtpCodecParameters& o) const { + return name == o.name && kind == o.kind && payload_type == o.payload_type && + clock_rate == o.clock_rate && num_channels == o.num_channels && + max_ptime == o.max_ptime && ptime == o.ptime && + rtcp_feedback == o.rtcp_feedback && parameters == o.parameters; + } + bool operator!=(const RtpCodecParameters& o) const { return !(*this == o); } +}; + +// RtpCapabilities is used to represent the static capabilities of an endpoint. +// An application can use these capabilities to construct an RtpParameters. +struct RTC_EXPORT RtpCapabilities { + RtpCapabilities(); + ~RtpCapabilities(); + + // Supported codecs. + std::vector<RtpCodecCapability> codecs; + + // Supported RTP header extensions. + std::vector<RtpHeaderExtensionCapability> header_extensions; + + // Supported Forward Error Correction (FEC) mechanisms. Note that the RED, + // ulpfec and flexfec codecs used by these mechanisms will still appear in + // `codecs`. + std::vector<FecMechanism> fec; + + bool operator==(const RtpCapabilities& o) const { + return codecs == o.codecs && header_extensions == o.header_extensions && + fec == o.fec; + } + bool operator!=(const RtpCapabilities& o) const { return !(*this == o); } +}; + +struct RtcpParameters final { + RtcpParameters(); + RtcpParameters(const RtcpParameters&); + ~RtcpParameters(); + + // The SSRC to be used in the "SSRC of packet sender" field. If not set, one + // will be chosen by the implementation. + // TODO(deadbeef): Not implemented. + absl::optional<uint32_t> ssrc; + + // The Canonical Name (CNAME) used by RTCP (e.g. in SDES messages). + // + // If empty in the construction of the RtpTransport, one will be generated by + // the implementation, and returned in GetRtcpParameters. Multiple + // RtpTransports created by the same OrtcFactory will use the same generated + // CNAME. + // + // If empty when passed into SetParameters, the CNAME simply won't be + // modified. + std::string cname; + + // Send reduced-size RTCP? + bool reduced_size = false; + + // Send RTCP multiplexed on the RTP transport? + // Not used with PeerConnection senders/receivers + bool mux = true; + + bool operator==(const RtcpParameters& o) const { + return ssrc == o.ssrc && cname == o.cname && + reduced_size == o.reduced_size && mux == o.mux; + } + bool operator!=(const RtcpParameters& o) const { return !(*this == o); } +}; + +struct RTC_EXPORT RtpParameters { + RtpParameters(); + RtpParameters(const RtpParameters&); + ~RtpParameters(); + + // Used when calling getParameters/setParameters with a PeerConnection + // RtpSender, to ensure that outdated parameters are not unintentionally + // applied successfully. + std::string transaction_id; + + // Value to use for MID RTP header extension. + // Called "muxId" in ORTC. + // TODO(deadbeef): Not implemented. + std::string mid; + + std::vector<RtpCodecParameters> codecs; + + std::vector<RtpExtension> header_extensions; + + std::vector<RtpEncodingParameters> encodings; + + // Only available with a Peerconnection RtpSender. + // In ORTC, our API includes an additional "RtpTransport" + // abstraction on which RTCP parameters are set. + RtcpParameters rtcp; + + // When bandwidth is constrained and the RtpSender needs to choose between + // degrading resolution or degrading framerate, degradationPreference + // indicates which is preferred. Only for video tracks. + absl::optional<DegradationPreference> degradation_preference; + + bool operator==(const RtpParameters& o) const { + return mid == o.mid && codecs == o.codecs && + header_extensions == o.header_extensions && + encodings == o.encodings && rtcp == o.rtcp && + degradation_preference == o.degradation_preference; + } + bool operator!=(const RtpParameters& o) const { return !(*this == o); } +}; + +} // namespace webrtc + +#endif // API_RTP_PARAMETERS_H_ diff --git a/third_party/libwebrtc/api/rtp_parameters_gn/moz.build b/third_party/libwebrtc/api/rtp_parameters_gn/moz.build new file mode 100644 index 0000000000..4dc6e4a743 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_parameters_gn/moz.build @@ -0,0 +1,222 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/media_types.cc", + "/third_party/libwebrtc/api/rtp_parameters.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rtp_parameters_gn") diff --git a/third_party/libwebrtc/api/rtp_parameters_unittest.cc b/third_party/libwebrtc/api/rtp_parameters_unittest.cc new file mode 100644 index 0000000000..234c3c9b6d --- /dev/null +++ b/third_party/libwebrtc/api/rtp_parameters_unittest.cc @@ -0,0 +1,303 @@ +/* + * 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. + */ + +#include "api/rtp_parameters.h" + +#include "test/gtest.h" + +namespace webrtc { + +using webrtc::RtpExtension; + +static const char kExtensionUri1[] = "extension-uri1"; +static const char kExtensionUri2[] = "extension-uri2"; + +static const RtpExtension kExtension1(kExtensionUri1, 1); +static const RtpExtension kExtension1Encrypted(kExtensionUri1, 10, true); +static const RtpExtension kExtension2(kExtensionUri2, 2); + +TEST(RtpExtensionTest, DeduplicateHeaderExtensions) { + std::vector<RtpExtension> extensions; + std::vector<RtpExtension> filtered; + + extensions.clear(); + extensions.push_back(kExtension1); + extensions.push_back(kExtension1Encrypted); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kDiscardEncryptedExtension); + EXPECT_EQ(1u, filtered.size()); + EXPECT_EQ(std::vector<RtpExtension>{kExtension1}, filtered); + + extensions.clear(); + extensions.push_back(kExtension1); + extensions.push_back(kExtension1Encrypted); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kPreferEncryptedExtension); + EXPECT_EQ(1u, filtered.size()); + EXPECT_EQ(std::vector<RtpExtension>{kExtension1Encrypted}, filtered); + + extensions.clear(); + extensions.push_back(kExtension1); + extensions.push_back(kExtension1Encrypted); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kRequireEncryptedExtension); + EXPECT_EQ(1u, filtered.size()); + EXPECT_EQ(std::vector<RtpExtension>{kExtension1Encrypted}, filtered); + + extensions.clear(); + extensions.push_back(kExtension1Encrypted); + extensions.push_back(kExtension1); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kDiscardEncryptedExtension); + EXPECT_EQ(1u, filtered.size()); + EXPECT_EQ(std::vector<RtpExtension>{kExtension1}, filtered); + + extensions.clear(); + extensions.push_back(kExtension1Encrypted); + extensions.push_back(kExtension1); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kPreferEncryptedExtension); + EXPECT_EQ(1u, filtered.size()); + EXPECT_EQ(std::vector<RtpExtension>{kExtension1Encrypted}, filtered); + + extensions.clear(); + extensions.push_back(kExtension1Encrypted); + extensions.push_back(kExtension1); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kRequireEncryptedExtension); + EXPECT_EQ(1u, filtered.size()); + EXPECT_EQ(std::vector<RtpExtension>{kExtension1Encrypted}, filtered); + + extensions.clear(); + extensions.push_back(kExtension1); + extensions.push_back(kExtension2); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kDiscardEncryptedExtension); + EXPECT_EQ(2u, filtered.size()); + EXPECT_EQ(extensions, filtered); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kPreferEncryptedExtension); + EXPECT_EQ(2u, filtered.size()); + EXPECT_EQ(extensions, filtered); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kRequireEncryptedExtension); + EXPECT_EQ(0u, filtered.size()); + + extensions.clear(); + extensions.push_back(kExtension1); + extensions.push_back(kExtension2); + extensions.push_back(kExtension1Encrypted); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kDiscardEncryptedExtension); + EXPECT_EQ(2u, filtered.size()); + EXPECT_EQ((std::vector<RtpExtension>{kExtension1, kExtension2}), filtered); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kPreferEncryptedExtension); + EXPECT_EQ(2u, filtered.size()); + EXPECT_EQ((std::vector<RtpExtension>{kExtension1Encrypted, kExtension2}), + filtered); + filtered = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kRequireEncryptedExtension); + EXPECT_EQ(1u, filtered.size()); + EXPECT_EQ((std::vector<RtpExtension>{kExtension1Encrypted}), filtered); +} + +// Test that the filtered vector is sorted so that for a given unsorted array of +// extensions, the filtered vector will always be laied out the same (for easy +// comparison). +TEST(RtpExtensionTest, DeduplicateHeaderExtensionsSorted) { + const std::vector<RtpExtension> extensions = { + RtpExtension("cde1", 11, false), RtpExtension("cde2", 12, true), + RtpExtension("abc1", 3, false), RtpExtension("abc2", 4, true), + RtpExtension("cde3", 9, true), RtpExtension("cde4", 10, false), + RtpExtension("abc3", 1, true), RtpExtension("abc4", 2, false), + RtpExtension("bcd3", 7, false), RtpExtension("bcd1", 8, true), + RtpExtension("bcd2", 5, true), RtpExtension("bcd4", 6, false), + }; + + auto encrypted = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kRequireEncryptedExtension); + + const std::vector<RtpExtension> expected_sorted_encrypted = { + RtpExtension("abc2", 4, true), RtpExtension("abc3", 1, true), + RtpExtension("bcd1", 8, true), RtpExtension("bcd2", 5, true), + RtpExtension("cde2", 12, true), RtpExtension("cde3", 9, true)}; + EXPECT_EQ(expected_sorted_encrypted, encrypted); + + auto unencypted = RtpExtension::DeduplicateHeaderExtensions( + extensions, RtpExtension::Filter::kDiscardEncryptedExtension); + + const std::vector<RtpExtension> expected_sorted_unencrypted = { + RtpExtension("abc1", 3, false), RtpExtension("abc4", 2, false), + RtpExtension("bcd3", 7, false), RtpExtension("bcd4", 6, false), + RtpExtension("cde1", 11, false), RtpExtension("cde4", 10, false)}; + EXPECT_EQ(expected_sorted_unencrypted, unencypted); +} + +TEST(RtpExtensionTest, FindHeaderExtensionByUriAndEncryption) { + std::vector<RtpExtension> extensions; + + extensions.clear(); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUriAndEncryption( + extensions, kExtensionUri1, false)); + + extensions.clear(); + extensions.push_back(kExtension1); + EXPECT_EQ(kExtension1, *RtpExtension::FindHeaderExtensionByUriAndEncryption( + extensions, kExtensionUri1, false)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUriAndEncryption( + extensions, kExtensionUri1, true)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUriAndEncryption( + extensions, kExtensionUri2, false)); + + extensions.clear(); + extensions.push_back(kExtension1); + extensions.push_back(kExtension2); + extensions.push_back(kExtension1Encrypted); + EXPECT_EQ(kExtension1, *RtpExtension::FindHeaderExtensionByUriAndEncryption( + extensions, kExtensionUri1, false)); + EXPECT_EQ(kExtension2, *RtpExtension::FindHeaderExtensionByUriAndEncryption( + extensions, kExtensionUri2, false)); + EXPECT_EQ(kExtension1Encrypted, + *RtpExtension::FindHeaderExtensionByUriAndEncryption( + extensions, kExtensionUri1, true)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUriAndEncryption( + extensions, kExtensionUri2, true)); +} + +TEST(RtpExtensionTest, FindHeaderExtensionByUri) { + std::vector<RtpExtension> extensions; + + extensions.clear(); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kDiscardEncryptedExtension)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kPreferEncryptedExtension)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kRequireEncryptedExtension)); + + extensions.clear(); + extensions.push_back(kExtension1); + EXPECT_EQ(kExtension1, *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kDiscardEncryptedExtension)); + EXPECT_EQ(kExtension1, *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kPreferEncryptedExtension)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kRequireEncryptedExtension)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri2, + RtpExtension::Filter::kDiscardEncryptedExtension)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri2, + RtpExtension::Filter::kPreferEncryptedExtension)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri2, + RtpExtension::Filter::kRequireEncryptedExtension)); + + extensions.clear(); + extensions.push_back(kExtension1); + extensions.push_back(kExtension1Encrypted); + EXPECT_EQ(kExtension1, *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kDiscardEncryptedExtension)); + + extensions.clear(); + extensions.push_back(kExtension1); + extensions.push_back(kExtension1Encrypted); + EXPECT_EQ(kExtension1Encrypted, + *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kPreferEncryptedExtension)); + + extensions.clear(); + extensions.push_back(kExtension1); + extensions.push_back(kExtension1Encrypted); + EXPECT_EQ(kExtension1Encrypted, + *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kRequireEncryptedExtension)); + + extensions.clear(); + extensions.push_back(kExtension1Encrypted); + extensions.push_back(kExtension1); + EXPECT_EQ(kExtension1, *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kDiscardEncryptedExtension)); + + extensions.clear(); + extensions.push_back(kExtension1Encrypted); + extensions.push_back(kExtension1); + EXPECT_EQ(kExtension1Encrypted, + *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kPreferEncryptedExtension)); + + extensions.clear(); + extensions.push_back(kExtension1Encrypted); + extensions.push_back(kExtension1); + EXPECT_EQ(kExtension1Encrypted, + *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kRequireEncryptedExtension)); + + extensions.clear(); + extensions.push_back(kExtension1); + extensions.push_back(kExtension2); + EXPECT_EQ(kExtension1, *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kDiscardEncryptedExtension)); + EXPECT_EQ(kExtension1, *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kPreferEncryptedExtension)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kRequireEncryptedExtension)); + EXPECT_EQ(kExtension2, *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri2, + RtpExtension::Filter::kDiscardEncryptedExtension)); + EXPECT_EQ(kExtension2, *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri2, + RtpExtension::Filter::kPreferEncryptedExtension)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri2, + RtpExtension::Filter::kRequireEncryptedExtension)); + + extensions.clear(); + extensions.push_back(kExtension1); + extensions.push_back(kExtension2); + extensions.push_back(kExtension1Encrypted); + EXPECT_EQ(kExtension1, *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kDiscardEncryptedExtension)); + EXPECT_EQ(kExtension1Encrypted, + *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kPreferEncryptedExtension)); + EXPECT_EQ(kExtension1Encrypted, + *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri1, + RtpExtension::Filter::kRequireEncryptedExtension)); + EXPECT_EQ(kExtension2, *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri2, + RtpExtension::Filter::kDiscardEncryptedExtension)); + EXPECT_EQ(kExtension2, *RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri2, + RtpExtension::Filter::kPreferEncryptedExtension)); + EXPECT_EQ(nullptr, RtpExtension::FindHeaderExtensionByUri( + extensions, kExtensionUri2, + RtpExtension::Filter::kRequireEncryptedExtension)); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtp_receiver_interface.cc b/third_party/libwebrtc/api/rtp_receiver_interface.cc new file mode 100644 index 0000000000..bc9aef5aef --- /dev/null +++ b/third_party/libwebrtc/api/rtp_receiver_interface.cc @@ -0,0 +1,44 @@ +/* + * Copyright 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 "api/rtp_receiver_interface.h" + +namespace webrtc { + +std::vector<std::string> RtpReceiverInterface::stream_ids() const { + return {}; +} + +std::vector<rtc::scoped_refptr<MediaStreamInterface>> +RtpReceiverInterface::streams() const { + return {}; +} + +std::vector<RtpSource> RtpReceiverInterface::GetSources() const { + return {}; +} + +void RtpReceiverInterface::SetFrameDecryptor( + rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {} + +rtc::scoped_refptr<FrameDecryptorInterface> +RtpReceiverInterface::GetFrameDecryptor() const { + return nullptr; +} + +rtc::scoped_refptr<DtlsTransportInterface> +RtpReceiverInterface::dtls_transport() const { + return nullptr; +} + +void RtpReceiverInterface::SetDepacketizerToDecoderFrameTransformer( + rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtp_receiver_interface.h b/third_party/libwebrtc/api/rtp_receiver_interface.h new file mode 100644 index 0000000000..e4ec9b5986 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_receiver_interface.h @@ -0,0 +1,123 @@ +/* + * Copyright 2015 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 file contains interfaces for RtpReceivers +// http://w3c.github.io/webrtc-pc/#rtcrtpreceiver-interface + +#ifndef API_RTP_RECEIVER_INTERFACE_H_ +#define API_RTP_RECEIVER_INTERFACE_H_ + +#include <string> +#include <vector> + +#include "api/crypto/frame_decryptor_interface.h" +#include "api/dtls_transport_interface.h" +#include "api/frame_transformer_interface.h" +#include "api/media_stream_interface.h" +#include "api/media_types.h" +#include "api/rtp_parameters.h" +#include "api/scoped_refptr.h" +#include "api/transport/rtp/rtp_source.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +class RtpReceiverObserverInterface { + public: + // Note: Currently if there are multiple RtpReceivers of the same media type, + // they will all call OnFirstPacketReceived at once. + // + // In the future, it's likely that an RtpReceiver will only call + // OnFirstPacketReceived when a packet is received specifically for its + // SSRC/mid. + virtual void OnFirstPacketReceived(cricket::MediaType media_type) = 0; + + protected: + virtual ~RtpReceiverObserverInterface() {} +}; + +class RTC_EXPORT RtpReceiverInterface : public rtc::RefCountInterface { + public: + virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0; + + // The dtlsTransport attribute exposes the DTLS transport on which the + // media is received. It may be null. + // https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-transport + // TODO(https://bugs.webrtc.org/907849) remove default implementation + virtual rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const; + + // The list of streams that `track` is associated with. This is the same as + // the [[AssociatedRemoteMediaStreams]] internal slot in the spec. + // https://w3c.github.io/webrtc-pc/#dfn-associatedremotemediastreams + // TODO(hbos): Make pure virtual as soon as Chromium's mock implements this. + // TODO(https://crbug.com/webrtc/9480): Remove streams() in favor of + // stream_ids() as soon as downstream projects are no longer dependent on + // stream objects. + virtual std::vector<std::string> stream_ids() const; + virtual std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams() const; + + // Audio or video receiver? + virtual cricket::MediaType media_type() const = 0; + + // Not to be confused with "mid", this is a field we can temporarily use + // to uniquely identify a receiver until we implement Unified Plan SDP. + virtual std::string id() const = 0; + + // The WebRTC specification only defines RTCRtpParameters in terms of senders, + // but this API also applies them to receivers, similar to ORTC: + // http://ortc.org/wp-content/uploads/2016/03/ortc.html#rtcrtpparameters*. + virtual RtpParameters GetParameters() const = 0; + // TODO(dinosaurav): Delete SetParameters entirely after rolling to Chromium. + // Currently, doesn't support changing any parameters. + virtual bool SetParameters(const RtpParameters& parameters) { return false; } + + // Does not take ownership of observer. + // Must call SetObserver(nullptr) before the observer is destroyed. + virtual void SetObserver(RtpReceiverObserverInterface* observer) = 0; + + // Sets the jitter buffer minimum delay until media playout. Actual observed + // delay may differ depending on the congestion control. `delay_seconds` is a + // positive value including 0.0 measured in seconds. `nullopt` means default + // value must be used. + virtual void SetJitterBufferMinimumDelay( + absl::optional<double> delay_seconds) = 0; + + // TODO(zhihuang): Remove the default implementation once the subclasses + // implement this. Currently, the only relevant subclass is the + // content::FakeRtpReceiver in Chromium. + virtual std::vector<RtpSource> GetSources() const; + + // Sets a user defined frame decryptor that will decrypt the entire frame + // before it is sent across the network. This will decrypt the entire frame + // using the user provided decryption mechanism regardless of whether SRTP is + // enabled or not. + // TODO(bugs.webrtc.org/12772): Remove. + virtual void SetFrameDecryptor( + rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor); + + // Returns a pointer to the frame decryptor set previously by the + // user. This can be used to update the state of the object. + // TODO(bugs.webrtc.org/12772): Remove. + virtual rtc::scoped_refptr<FrameDecryptorInterface> GetFrameDecryptor() const; + + // Sets a frame transformer between the depacketizer and the decoder to enable + // client code to transform received frames according to their own processing + // logic. + virtual void SetDepacketizerToDecoderFrameTransformer( + rtc::scoped_refptr<FrameTransformerInterface> frame_transformer); + + protected: + ~RtpReceiverInterface() override = default; +}; + +} // namespace webrtc + +#endif // API_RTP_RECEIVER_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/rtp_sender_interface.cc b/third_party/libwebrtc/api/rtp_sender_interface.cc new file mode 100644 index 0000000000..f1ca5c2203 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_sender_interface.cc @@ -0,0 +1,22 @@ +/* + * Copyright 2022 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 "api/rtp_sender_interface.h" + +#include "rtc_base/checks.h" + +namespace webrtc { + +void RtpSenderInterface::SetParametersAsync(const RtpParameters& parameters, + SetParametersCallback callback) { + RTC_DCHECK_NOTREACHED() << "Default implementation called"; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtp_sender_interface.h b/third_party/libwebrtc/api/rtp_sender_interface.h new file mode 100644 index 0000000000..98ee91b1cc --- /dev/null +++ b/third_party/libwebrtc/api/rtp_sender_interface.h @@ -0,0 +1,123 @@ +/* + * Copyright 2015 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 file contains interfaces for RtpSenders +// http://w3c.github.io/webrtc-pc/#rtcrtpsender-interface + +#ifndef API_RTP_SENDER_INTERFACE_H_ +#define API_RTP_SENDER_INTERFACE_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "absl/functional/any_invocable.h" +#include "api/crypto/frame_encryptor_interface.h" +#include "api/dtls_transport_interface.h" +#include "api/dtmf_sender_interface.h" +#include "api/frame_transformer_interface.h" +#include "api/media_stream_interface.h" +#include "api/media_types.h" +#include "api/rtc_error.h" +#include "api/rtp_parameters.h" +#include "api/scoped_refptr.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/system/rtc_export.h" + +#include "api/rtp_sender_setparameters_callback.h" + +namespace webrtc { + +class RTC_EXPORT RtpSenderInterface : public rtc::RefCountInterface { + public: + // Returns true if successful in setting the track. + // Fails if an audio track is set on a video RtpSender, or vice-versa. + virtual bool SetTrack(MediaStreamTrackInterface* track) = 0; + virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0; + + // The dtlsTransport attribute exposes the DTLS transport on which the + // media is sent. It may be null. + // https://w3c.github.io/webrtc-pc/#dom-rtcrtpsender-transport + virtual rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const = 0; + + // Returns primary SSRC used by this sender for sending media. + // Returns 0 if not yet determined. + // TODO(deadbeef): Change to absl::optional. + // TODO(deadbeef): Remove? With GetParameters this should be redundant. + virtual uint32_t ssrc() const = 0; + + // Audio or video sender? + virtual cricket::MediaType media_type() const = 0; + + // Not to be confused with "mid", this is a field we can temporarily use + // to uniquely identify a receiver until we implement Unified Plan SDP. + virtual std::string id() const = 0; + + // Returns a list of media stream ids associated with this sender's track. + // These are signalled in the SDP so that the remote side can associate + // tracks. + virtual std::vector<std::string> stream_ids() const = 0; + + // Sets the IDs of the media streams associated with this sender's track. + // These are signalled in the SDP so that the remote side can associate + // tracks. + virtual void SetStreams(const std::vector<std::string>& stream_ids) = 0; + + // Returns the list of encoding parameters that will be applied when the SDP + // local description is set. These initial encoding parameters can be set by + // PeerConnection::AddTransceiver, and later updated with Get/SetParameters. + // TODO(orphis): Make it pure virtual once Chrome has updated + virtual std::vector<RtpEncodingParameters> init_send_encodings() const = 0; + + virtual RtpParameters GetParameters() const = 0; + // Note that only a subset of the parameters can currently be changed. See + // rtpparameters.h + // The encodings are in increasing quality order for simulcast. + virtual RTCError SetParameters(const RtpParameters& parameters) = 0; + virtual void SetParametersAsync(const RtpParameters& parameters, + SetParametersCallback callback); + + // Returns null for a video sender. + virtual rtc::scoped_refptr<DtmfSenderInterface> GetDtmfSender() const = 0; + + // Sets a user defined frame encryptor that will encrypt the entire frame + // before it is sent across the network. This will encrypt the entire frame + // using the user provided encryption mechanism regardless of whether SRTP is + // enabled or not. + virtual void SetFrameEncryptor( + rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) = 0; + + // Returns a pointer to the frame encryptor set previously by the + // user. This can be used to update the state of the object. + virtual rtc::scoped_refptr<FrameEncryptorInterface> GetFrameEncryptor() + const = 0; + + virtual void SetEncoderToPacketizerFrameTransformer( + rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) = 0; + + // Sets a user defined encoder selector. + // Overrides selector that is (optionally) provided by VideoEncoderFactory. + virtual void SetEncoderSelector( + std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface> + encoder_selector) = 0; + + // TODO(crbug.com/1354101): make pure virtual again after Chrome roll. + virtual RTCError GenerateKeyFrame(const std::vector<std::string>& rids) { + return RTCError::OK(); + } + + protected: + ~RtpSenderInterface() override = default; +}; + +} // namespace webrtc + +#endif // API_RTP_SENDER_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/rtp_sender_interface_gn/moz.build b/third_party/libwebrtc/api/rtp_sender_interface_gn/moz.build new file mode 100644 index 0000000000..9712e13ddd --- /dev/null +++ b/third_party/libwebrtc/api/rtp_sender_interface_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rtp_sender_interface_gn") diff --git a/third_party/libwebrtc/api/rtp_sender_setparameters_callback.cc b/third_party/libwebrtc/api/rtp_sender_setparameters_callback.cc new file mode 100644 index 0000000000..99728ef95e --- /dev/null +++ b/third_party/libwebrtc/api/rtp_sender_setparameters_callback.cc @@ -0,0 +1,27 @@ +/* + * Copyright 2015 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. + */ + +// File added by mozilla, to decouple this from libwebrtc's implementation of +// RTCRtpSender. + +#include "api/rtp_sender_setparameters_callback.h" + +namespace webrtc { + +webrtc::RTCError InvokeSetParametersCallback(SetParametersCallback& callback, + RTCError error) { + if (callback) { + std::move(callback)(error); + callback = nullptr; + } + return error; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtp_sender_setparameters_callback.h b/third_party/libwebrtc/api/rtp_sender_setparameters_callback.h new file mode 100644 index 0000000000..45194f5ace --- /dev/null +++ b/third_party/libwebrtc/api/rtp_sender_setparameters_callback.h @@ -0,0 +1,28 @@ +/* + * Copyright 2015 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. + */ + +// File added by mozilla, to decouple this from libwebrtc's implementation of +// RTCRtpSender. + +#ifndef API_RTP_SENDER_SETPARAMETERS_CALLBACK_H_ +#define API_RTP_SENDER_SETPARAMETERS_CALLBACK_H_ + +#include "api/rtc_error.h" +#include "absl/functional/any_invocable.h" + +namespace webrtc { + +using SetParametersCallback = absl::AnyInvocable<void(RTCError) &&>; + +webrtc::RTCError InvokeSetParametersCallback(SetParametersCallback& callback, + RTCError error); +} // namespace webrtc + +#endif // API_RTP_SENDER_SETPARAMETERS_CALLBACK_H_ diff --git a/third_party/libwebrtc/api/rtp_sender_setparameters_callback_gn/moz.build b/third_party/libwebrtc/api/rtp_sender_setparameters_callback_gn/moz.build new file mode 100644 index 0000000000..5cc94b1d99 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_sender_setparameters_callback_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/rtp_sender_setparameters_callback.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rtp_sender_setparameters_callback_gn") diff --git a/third_party/libwebrtc/api/rtp_transceiver_direction.h b/third_party/libwebrtc/api/rtp_transceiver_direction.h new file mode 100644 index 0000000000..3c7d4cb0ad --- /dev/null +++ b/third_party/libwebrtc/api/rtp_transceiver_direction.h @@ -0,0 +1,27 @@ +/* + * Copyright 2020 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 API_RTP_TRANSCEIVER_DIRECTION_H_ +#define API_RTP_TRANSCEIVER_DIRECTION_H_ + +namespace webrtc { + +// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverdirection +enum class RtpTransceiverDirection { + kSendRecv, + kSendOnly, + kRecvOnly, + kInactive, + kStopped, +}; + +} // namespace webrtc + +#endif // API_RTP_TRANSCEIVER_DIRECTION_H_ diff --git a/third_party/libwebrtc/api/rtp_transceiver_direction_gn/moz.build b/third_party/libwebrtc/api/rtp_transceiver_direction_gn/moz.build new file mode 100644 index 0000000000..1ca9b4be66 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_transceiver_direction_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rtp_transceiver_direction_gn") diff --git a/third_party/libwebrtc/api/rtp_transceiver_interface.cc b/third_party/libwebrtc/api/rtp_transceiver_interface.cc new file mode 100644 index 0000000000..7267b286be --- /dev/null +++ b/third_party/libwebrtc/api/rtp_transceiver_interface.cc @@ -0,0 +1,60 @@ +/* + * Copyright 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 "api/rtp_transceiver_interface.h" + +#include "rtc_base/checks.h" + +namespace webrtc { + +RtpTransceiverInit::RtpTransceiverInit() = default; + +RtpTransceiverInit::RtpTransceiverInit(const RtpTransceiverInit& rhs) = default; + +RtpTransceiverInit::~RtpTransceiverInit() = default; + +absl::optional<RtpTransceiverDirection> +RtpTransceiverInterface::fired_direction() const { + return absl::nullopt; +} + +bool RtpTransceiverInterface::stopping() const { + return false; +} + +void RtpTransceiverInterface::Stop() { + StopInternal(); +} + +RTCError RtpTransceiverInterface::StopStandard() { + RTC_DCHECK_NOTREACHED() + << "DEBUG: RtpTransceiverInterface::StopStandard called"; + return RTCError::OK(); +} + +void RtpTransceiverInterface::StopInternal() { + RTC_DCHECK_NOTREACHED() + << "DEBUG: RtpTransceiverInterface::StopInternal called"; +} + +// TODO(bugs.webrtc.org/11839) Remove default implementations when clients +// are updated. +void RtpTransceiverInterface::SetDirection( + RtpTransceiverDirection new_direction) { + SetDirectionWithError(new_direction); +} + +RTCError RtpTransceiverInterface::SetDirectionWithError( + RtpTransceiverDirection new_direction) { + RTC_DCHECK_NOTREACHED() << "Default implementation called"; + return RTCError::OK(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/rtp_transceiver_interface.h b/third_party/libwebrtc/api/rtp_transceiver_interface.h new file mode 100644 index 0000000000..c9d911fac1 --- /dev/null +++ b/third_party/libwebrtc/api/rtp_transceiver_interface.h @@ -0,0 +1,178 @@ +/* + * Copyright 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. + */ + +#ifndef API_RTP_TRANSCEIVER_INTERFACE_H_ +#define API_RTP_TRANSCEIVER_INTERFACE_H_ + +#include <string> +#include <vector> + +#include "absl/base/attributes.h" +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/media_types.h" +#include "api/rtp_parameters.h" +#include "api/rtp_receiver_interface.h" +#include "api/rtp_sender_interface.h" +#include "api/rtp_transceiver_direction.h" +#include "api/scoped_refptr.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Structure for initializing an RtpTransceiver in a call to +// PeerConnectionInterface::AddTransceiver. +// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverinit +struct RTC_EXPORT RtpTransceiverInit final { + RtpTransceiverInit(); + RtpTransceiverInit(const RtpTransceiverInit&); + ~RtpTransceiverInit(); + // Direction of the RtpTransceiver. See RtpTransceiverInterface::direction(). + RtpTransceiverDirection direction = RtpTransceiverDirection::kSendRecv; + + // The added RtpTransceiver will be added to these streams. + std::vector<std::string> stream_ids; + + // TODO(bugs.webrtc.org/7600): Not implemented. + std::vector<RtpEncodingParameters> send_encodings; +}; + +// The RtpTransceiverInterface maps to the RTCRtpTransceiver defined by the +// WebRTC specification. A transceiver represents a combination of an RtpSender +// and an RtpReceiver than share a common mid. As defined in JSEP, an +// RtpTransceiver is said to be associated with a media description if its mid +// property is non-null; otherwise, it is said to be disassociated. +// JSEP: https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24 +// +// Note that RtpTransceivers are only supported when using PeerConnection with +// Unified Plan SDP. +// +// This class is thread-safe. +// +// WebRTC specification for RTCRtpTransceiver, the JavaScript analog: +// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver +class RTC_EXPORT RtpTransceiverInterface : public rtc::RefCountInterface { + public: + // Media type of the transceiver. Any sender(s)/receiver(s) will have this + // type as well. + virtual cricket::MediaType media_type() const = 0; + + // The mid attribute is the mid negotiated and present in the local and + // remote descriptions. Before negotiation is complete, the mid value may be + // null. After rollbacks, the value may change from a non-null value to null. + // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-mid + virtual absl::optional<std::string> mid() const = 0; + + // The sender attribute exposes the RtpSender corresponding to the RTP media + // that may be sent with the transceiver's mid. The sender is always present, + // regardless of the direction of media. + // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-sender + virtual rtc::scoped_refptr<RtpSenderInterface> sender() const = 0; + + // The receiver attribute exposes the RtpReceiver corresponding to the RTP + // media that may be received with the transceiver's mid. The receiver is + // always present, regardless of the direction of media. + // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-receiver + virtual rtc::scoped_refptr<RtpReceiverInterface> receiver() const = 0; + + // The stopped attribute indicates that the sender of this transceiver will no + // longer send, and that the receiver will no longer receive. It is true if + // either stop has been called or if setting the local or remote description + // has caused the RtpTransceiver to be stopped. + // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stopped + virtual bool stopped() const = 0; + + // The stopping attribute indicates that the user has indicated that the + // sender of this transceiver will stop sending, and that the receiver will + // no longer receive. It is always true if stopped() is true. + // If stopping() is true and stopped() is false, it means that the + // transceiver's stop() method has been called, but the negotiation with + // the other end for shutting down the transceiver is not yet done. + // https://w3c.github.io/webrtc-pc/#dfn-stopping-0 + virtual bool stopping() const = 0; + + // The direction attribute indicates the preferred direction of this + // transceiver, which will be used in calls to CreateOffer and CreateAnswer. + // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction + virtual RtpTransceiverDirection direction() const = 0; + + // Sets the preferred direction of this transceiver. An update of + // directionality does not take effect immediately. Instead, future calls to + // CreateOffer and CreateAnswer mark the corresponding media descriptions as + // sendrecv, sendonly, recvonly, or inactive. + // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction + // TODO(hta): Deprecate SetDirection without error and rename + // SetDirectionWithError to SetDirection, remove default implementations. + ABSL_DEPRECATED("Use SetDirectionWithError instead") + virtual void SetDirection(RtpTransceiverDirection new_direction); + virtual RTCError SetDirectionWithError(RtpTransceiverDirection new_direction); + + // The current_direction attribute indicates the current direction negotiated + // for this transceiver. If this transceiver has never been represented in an + // offer/answer exchange, or if the transceiver is stopped, the value is null. + // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-currentdirection + virtual absl::optional<RtpTransceiverDirection> current_direction() const = 0; + + // An internal slot designating for which direction the relevant + // PeerConnection events have been fired. This is to ensure that events like + // OnAddTrack only get fired once even if the same session description is + // applied again. + // Exposed in the public interface for use by Chromium. + virtual absl::optional<RtpTransceiverDirection> fired_direction() const; + + // Initiates a stop of the transceiver. + // The stop is complete when stopped() returns true. + // A stopped transceiver can be reused for a different track. + // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stop + // TODO(hta): Rename to Stop() when users of the non-standard Stop() are + // updated. + virtual RTCError StopStandard(); + + // Stops a transceiver immediately, without waiting for signalling. + // This is an internal function, and is exposed for historical reasons. + // https://w3c.github.io/webrtc-pc/#dfn-stop-the-rtcrtptransceiver + virtual void StopInternal(); + ABSL_DEPRECATED("Use StopStandard instead") virtual void Stop(); + + // The SetCodecPreferences method overrides the default codec preferences used + // by WebRTC for this transceiver. + // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-setcodecpreferences + virtual RTCError SetCodecPreferences( + rtc::ArrayView<RtpCodecCapability> codecs) = 0; + virtual std::vector<RtpCodecCapability> codec_preferences() const = 0; + + // Readonly attribute which contains the set of header extensions that was set + // with SetOfferedRtpHeaderExtensions, or a default set if it has not been + // called. + // https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface + virtual std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer() + const = 0; + + // Readonly attribute which is either empty if negotation has not yet + // happened, or a vector of the negotiated header extensions. + // https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface + virtual std::vector<RtpHeaderExtensionCapability> HeaderExtensionsNegotiated() + const = 0; + + // The SetOfferedRtpHeaderExtensions method modifies the next SDP negotiation + // so that it negotiates use of header extensions which are not kStopped. + // https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface + virtual webrtc::RTCError SetOfferedRtpHeaderExtensions( + rtc::ArrayView<const RtpHeaderExtensionCapability> + header_extensions_to_offer) = 0; + + protected: + ~RtpTransceiverInterface() override = default; +}; + +} // namespace webrtc + +#endif // API_RTP_TRANSCEIVER_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/scoped_refptr.h b/third_party/libwebrtc/api/scoped_refptr.h new file mode 100644 index 0000000000..e145509127 --- /dev/null +++ b/third_party/libwebrtc/api/scoped_refptr.h @@ -0,0 +1,222 @@ +/* + * Copyright 2011 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. + */ + +// Originally these classes are from Chromium. +// http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/ref_counted.h?view=markup + +// +// A smart pointer class for reference counted objects. Use this class instead +// of calling AddRef and Release manually on a reference counted object to +// avoid common memory leaks caused by forgetting to Release an object +// reference. Sample usage: +// +// class MyFoo : public RefCounted<MyFoo> { +// ... +// }; +// +// void some_function() { +// scoped_refptr<MyFoo> foo = new MyFoo(); +// foo->Method(param); +// // `foo` is released when this function returns +// } +// +// void some_other_function() { +// scoped_refptr<MyFoo> foo = new MyFoo(); +// ... +// foo = nullptr; // explicitly releases `foo` +// ... +// if (foo) +// foo->Method(param); +// } +// +// The above examples show how scoped_refptr<T> acts like a pointer to T. +// Given two scoped_refptr<T> classes, it is also possible to exchange +// references between the two objects, like so: +// +// { +// scoped_refptr<MyFoo> a = new MyFoo(); +// scoped_refptr<MyFoo> b; +// +// b.swap(a); +// // now, `b` references the MyFoo object, and `a` references null. +// } +// +// To make both `a` and `b` in the above example reference the same MyFoo +// object, simply use the assignment operator: +// +// { +// scoped_refptr<MyFoo> a = new MyFoo(); +// scoped_refptr<MyFoo> b; +// +// b = a; +// // now, `a` and `b` each own a reference to the same MyFoo object. +// } +// + +#ifndef API_SCOPED_REFPTR_H_ +#define API_SCOPED_REFPTR_H_ + +#include <memory> +#include <utility> + +namespace rtc { + +template <class T> +class scoped_refptr { + public: + typedef T element_type; + + scoped_refptr() : ptr_(nullptr) {} + scoped_refptr(std::nullptr_t) : ptr_(nullptr) {} // NOLINT(runtime/explicit) + + explicit scoped_refptr(T* p) : ptr_(p) { + if (ptr_) + ptr_->AddRef(); + } + + scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { + if (ptr_) + ptr_->AddRef(); + } + + template <typename U> + scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { + if (ptr_) + ptr_->AddRef(); + } + + // Move constructors. + scoped_refptr(scoped_refptr<T>&& r) noexcept : ptr_(r.release()) {} + + template <typename U> + scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.release()) {} + + ~scoped_refptr() { + if (ptr_) + ptr_->Release(); + } + + T* get() const { return ptr_; } + explicit operator bool() const { return ptr_ != nullptr; } + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + + // Returns the (possibly null) raw pointer, and makes the scoped_refptr hold a + // null pointer, all without touching the reference count of the underlying + // pointed-to object. The object is still reference counted, and the caller of + // release() is now the proud owner of one reference, so it is responsible for + // calling Release() once on the object when no longer using it. + T* release() { + T* retVal = ptr_; + ptr_ = nullptr; + return retVal; + } + + scoped_refptr<T>& operator=(T* p) { + // AddRef first so that self assignment should work + if (p) + p->AddRef(); + if (ptr_) + ptr_->Release(); + ptr_ = p; + return *this; + } + + scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { + return *this = r.ptr_; + } + + template <typename U> + scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { + return *this = r.get(); + } + + scoped_refptr<T>& operator=(scoped_refptr<T>&& r) noexcept { + scoped_refptr<T>(std::move(r)).swap(*this); + return *this; + } + + template <typename U> + scoped_refptr<T>& operator=(scoped_refptr<U>&& r) noexcept { + scoped_refptr<T>(std::move(r)).swap(*this); + return *this; + } + + void swap(T** pp) noexcept { + T* p = ptr_; + ptr_ = *pp; + *pp = p; + } + + void swap(scoped_refptr<T>& r) noexcept { swap(&r.ptr_); } + + protected: + T* ptr_; +}; + +template <typename T, typename U> +bool operator==(const rtc::scoped_refptr<T>& a, + const rtc::scoped_refptr<U>& b) { + return a.get() == b.get(); +} +template <typename T, typename U> +bool operator!=(const rtc::scoped_refptr<T>& a, + const rtc::scoped_refptr<U>& b) { + return !(a == b); +} + +template <typename T> +bool operator==(const rtc::scoped_refptr<T>& a, std::nullptr_t) { + return a.get() == nullptr; +} + +template <typename T> +bool operator!=(const rtc::scoped_refptr<T>& a, std::nullptr_t) { + return !(a == nullptr); +} + +template <typename T> +bool operator==(std::nullptr_t, const rtc::scoped_refptr<T>& a) { + return a.get() == nullptr; +} + +template <typename T> +bool operator!=(std::nullptr_t, const rtc::scoped_refptr<T>& a) { + return !(a == nullptr); +} + +// Comparison with raw pointer. +template <typename T, typename U> +bool operator==(const rtc::scoped_refptr<T>& a, const U* b) { + return a.get() == b; +} +template <typename T, typename U> +bool operator!=(const rtc::scoped_refptr<T>& a, const U* b) { + return !(a == b); +} + +template <typename T, typename U> +bool operator==(const T* a, const rtc::scoped_refptr<U>& b) { + return a == b.get(); +} +template <typename T, typename U> +bool operator!=(const T* a, const rtc::scoped_refptr<U>& b) { + return !(a == b); +} + +// Ordered comparison, needed for use as a std::map key. +template <typename T, typename U> +bool operator<(const rtc::scoped_refptr<T>& a, const rtc::scoped_refptr<U>& b) { + return a.get() < b.get(); +} + +} // namespace rtc + +#endif // API_SCOPED_REFPTR_H_ diff --git a/third_party/libwebrtc/api/scoped_refptr_gn/moz.build b/third_party/libwebrtc/api/scoped_refptr_gn/moz.build new file mode 100644 index 0000000000..d4dbda2c18 --- /dev/null +++ b/third_party/libwebrtc/api/scoped_refptr_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("scoped_refptr_gn") diff --git a/third_party/libwebrtc/api/scoped_refptr_unittest.cc b/third_party/libwebrtc/api/scoped_refptr_unittest.cc new file mode 100644 index 0000000000..22b61209cd --- /dev/null +++ b/third_party/libwebrtc/api/scoped_refptr_unittest.cc @@ -0,0 +1,111 @@ +/* + * Copyright 2019 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 "api/scoped_refptr.h" + +#include <utility> +#include <vector> + +#include "test/gtest.h" + +namespace rtc { +namespace { + +struct FunctionsCalled { + int addref = 0; + int release = 0; +}; + +class ScopedRefCounted { + public: + explicit ScopedRefCounted(FunctionsCalled* called) : called_(*called) {} + ScopedRefCounted(const ScopedRefCounted&) = delete; + ScopedRefCounted& operator=(const ScopedRefCounted&) = delete; + + void AddRef() { + ++called_.addref; + ++ref_count_; + } + void Release() { + ++called_.release; + if (0 == --ref_count_) + delete this; + } + + private: + ~ScopedRefCounted() = default; + + FunctionsCalled& called_; + int ref_count_ = 0; +}; + +TEST(ScopedRefptrTest, IsCopyConstructable) { + FunctionsCalled called; + scoped_refptr<ScopedRefCounted> ptr(new ScopedRefCounted(&called)); + scoped_refptr<ScopedRefCounted> another_ptr = ptr; + + EXPECT_TRUE(ptr); + EXPECT_TRUE(another_ptr); + EXPECT_EQ(called.addref, 2); +} + +TEST(ScopedRefptrTest, IsCopyAssignable) { + FunctionsCalled called; + scoped_refptr<ScopedRefCounted> another_ptr; + scoped_refptr<ScopedRefCounted> ptr(new ScopedRefCounted(&called)); + another_ptr = ptr; + + EXPECT_TRUE(ptr); + EXPECT_TRUE(another_ptr); + EXPECT_EQ(called.addref, 2); +} + +TEST(ScopedRefptrTest, IsMoveConstructableWithoutExtraAddRefRelease) { + FunctionsCalled called; + scoped_refptr<ScopedRefCounted> ptr(new ScopedRefCounted(&called)); + scoped_refptr<ScopedRefCounted> another_ptr = std::move(ptr); + + EXPECT_FALSE(ptr); + EXPECT_TRUE(another_ptr); + EXPECT_EQ(called.addref, 1); + EXPECT_EQ(called.release, 0); +} + +TEST(ScopedRefptrTest, IsMoveAssignableWithoutExtraAddRefRelease) { + FunctionsCalled called; + scoped_refptr<ScopedRefCounted> another_ptr; + scoped_refptr<ScopedRefCounted> ptr(new ScopedRefCounted(&called)); + another_ptr = std::move(ptr); + + EXPECT_FALSE(ptr); + EXPECT_TRUE(another_ptr); + EXPECT_EQ(called.addref, 1); + EXPECT_EQ(called.release, 0); +} + +TEST(ScopedRefptrTest, MovableDuringVectorReallocation) { + static_assert( + std::is_nothrow_move_constructible<scoped_refptr<ScopedRefCounted>>(), + ""); + // Test below describes a scenario where it is helpful for move constructor + // to be noexcept. + FunctionsCalled called; + std::vector<scoped_refptr<ScopedRefCounted>> ptrs; + ptrs.reserve(1); + // Insert more elements than reserved to provoke reallocation. + ptrs.emplace_back(new ScopedRefCounted(&called)); + ptrs.emplace_back(new ScopedRefCounted(&called)); + + EXPECT_EQ(called.addref, 2); + EXPECT_EQ(called.release, 0); +} + +} // namespace +} // namespace rtc diff --git a/third_party/libwebrtc/api/sctp_transport_interface.cc b/third_party/libwebrtc/api/sctp_transport_interface.cc new file mode 100644 index 0000000000..8a0a866e85 --- /dev/null +++ b/third_party/libwebrtc/api/sctp_transport_interface.cc @@ -0,0 +1,32 @@ +/* + * Copyright 2019 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 "api/sctp_transport_interface.h" + +#include <utility> + +namespace webrtc { + +SctpTransportInformation::SctpTransportInformation(SctpTransportState state) + : state_(state) {} + +SctpTransportInformation::SctpTransportInformation( + SctpTransportState state, + rtc::scoped_refptr<DtlsTransportInterface> dtls_transport, + absl::optional<double> max_message_size, + absl::optional<int> max_channels) + : state_(state), + dtls_transport_(std::move(dtls_transport)), + max_message_size_(max_message_size), + max_channels_(max_channels) {} + +SctpTransportInformation::~SctpTransportInformation() {} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/sctp_transport_interface.h b/third_party/libwebrtc/api/sctp_transport_interface.h new file mode 100644 index 0000000000..7080889fcf --- /dev/null +++ b/third_party/libwebrtc/api/sctp_transport_interface.h @@ -0,0 +1,92 @@ +/* + * Copyright 2019 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 API_SCTP_TRANSPORT_INTERFACE_H_ +#define API_SCTP_TRANSPORT_INTERFACE_H_ + +#include "absl/types/optional.h" +#include "api/dtls_transport_interface.h" +#include "api/rtc_error.h" +#include "api/scoped_refptr.h" +#include "rtc_base/ref_count.h" + +namespace webrtc { + +// States of a SCTP transport, corresponding to the JS API specification. +// http://w3c.github.io/webrtc-pc/#dom-rtcsctptransportstate +enum class SctpTransportState { + kNew, // Has not started negotiating yet. Non-standard state. + kConnecting, // In the process of negotiating an association. + kConnected, // Completed negotiation of an association. + kClosed, // Closed by local or remote party. + kNumValues +}; + +// This object gives snapshot information about the changeable state of a +// SctpTransport. +// It reflects the readonly attributes of the object in the specification. +// http://w3c.github.io/webrtc-pc/#rtcsctptransport-interface +class RTC_EXPORT SctpTransportInformation { + public: + SctpTransportInformation() = default; + SctpTransportInformation(const SctpTransportInformation&) = default; + explicit SctpTransportInformation(SctpTransportState state); + SctpTransportInformation( + SctpTransportState state, + rtc::scoped_refptr<DtlsTransportInterface> dtls_transport, + absl::optional<double> max_message_size, + absl::optional<int> max_channels); + ~SctpTransportInformation(); + // The DTLS transport that supports this SCTP transport. + rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const { + return dtls_transport_; + } + SctpTransportState state() const { return state_; } + absl::optional<double> MaxMessageSize() const { return max_message_size_; } + absl::optional<int> MaxChannels() const { return max_channels_; } + + private: + SctpTransportState state_; + rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_; + absl::optional<double> max_message_size_; + absl::optional<int> max_channels_; +}; + +class SctpTransportObserverInterface { + public: + // This callback carries information about the state of the transport. + // The argument is a pass-by-value snapshot of the state. + // The callback will be called on the network thread. + virtual void OnStateChange(SctpTransportInformation info) = 0; + + protected: + virtual ~SctpTransportObserverInterface() = default; +}; + +// A SCTP transport, as represented to the outside world. +// This object is created on the network thread, and can only be +// accessed on that thread, except for functions explicitly marked otherwise. +// References can be held by other threads, and destruction can therefore +// be initiated by other threads. +class SctpTransportInterface : public rtc::RefCountInterface { + public: + // This function can be called from other threads. + virtual rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const = 0; + // Returns information on the state of the SctpTransport. + // This function can be called from other threads. + virtual SctpTransportInformation Information() const = 0; + // Observer management. + virtual void RegisterObserver(SctpTransportObserverInterface* observer) = 0; + virtual void UnregisterObserver() = 0; +}; + +} // namespace webrtc + +#endif // API_SCTP_TRANSPORT_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/sequence_checker.h b/third_party/libwebrtc/api/sequence_checker.h new file mode 100644 index 0000000000..33e0f3c074 --- /dev/null +++ b/third_party/libwebrtc/api/sequence_checker.h @@ -0,0 +1,126 @@ +/* + * Copyright 2019 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 API_SEQUENCE_CHECKER_H_ +#define API_SEQUENCE_CHECKER_H_ + +#include "rtc_base/checks.h" +#include "rtc_base/synchronization/sequence_checker_internal.h" +#include "rtc_base/thread_annotations.h" + +namespace webrtc { + +// SequenceChecker is a helper class used to help verify that some methods +// of a class are called on the same task queue or thread. A +// SequenceChecker is bound to a a task queue if the object is +// created on a task queue, or a thread otherwise. +// +// +// Example: +// class MyClass { +// public: +// void Foo() { +// RTC_DCHECK_RUN_ON(&sequence_checker_); +// ... (do stuff) ... +// } +// +// private: +// SequenceChecker sequence_checker_; +// } +// +// In Release mode, IsCurrent will always return true. +class RTC_LOCKABLE SequenceChecker +#if RTC_DCHECK_IS_ON + : public webrtc_sequence_checker_internal::SequenceCheckerImpl { + using Impl = webrtc_sequence_checker_internal::SequenceCheckerImpl; +#else + : public webrtc_sequence_checker_internal::SequenceCheckerDoNothing { + using Impl = webrtc_sequence_checker_internal::SequenceCheckerDoNothing; +#endif + public: + enum InitialState : bool { kDetached = false, kAttached = true }; + + explicit SequenceChecker(InitialState initial_state = kAttached) + : Impl(initial_state) {} + + // Returns true if sequence checker is attached to the current sequence. + bool IsCurrent() const { return Impl::IsCurrent(); } + // Detaches checker from sequence to which it is attached. Next attempt + // to do a check with this checker will result in attaching this checker + // to the sequence on which check was performed. + void Detach() { Impl::Detach(); } +}; + +} // namespace webrtc + +// RTC_RUN_ON/RTC_GUARDED_BY/RTC_DCHECK_RUN_ON macros allows to annotate +// variables are accessed from same thread/task queue. +// Using tools designed to check mutexes, it checks at compile time everywhere +// variable is access, there is a run-time dcheck thread/task queue is correct. +// +// class SequenceCheckerExample { +// public: +// int CalledFromPacer() RTC_RUN_ON(pacer_sequence_checker_) { +// return var2_; +// } +// +// void CallMeFromPacer() { +// RTC_DCHECK_RUN_ON(&pacer_sequence_checker_) +// << "Should be called from pacer"; +// CalledFromPacer(); +// } +// +// private: +// int pacer_var_ RTC_GUARDED_BY(pacer_sequence_checker_); +// SequenceChecker pacer_sequence_checker_; +// }; +// +// class TaskQueueExample { +// public: +// class Encoder { +// public: +// rtc::TaskQueueBase& Queue() { return encoder_queue_; } +// void Encode() { +// RTC_DCHECK_RUN_ON(&encoder_queue_); +// DoSomething(var_); +// } +// +// private: +// rtc::TaskQueueBase& encoder_queue_; +// Frame var_ RTC_GUARDED_BY(encoder_queue_); +// }; +// +// void Encode() { +// // Will fail at runtime when DCHECK is enabled: +// // encoder_->Encode(); +// // Will work: +// rtc::scoped_refptr<Encoder> encoder = encoder_; +// encoder_->Queue().PostTask([encoder] { encoder->Encode(); }); +// } +// +// private: +// rtc::scoped_refptr<Encoder> encoder_; +// } + +// Document if a function expected to be called from same thread/task queue. +#define RTC_RUN_ON(x) \ + RTC_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x)) + +// Checks current code is running on the desired sequence. +// +// First statement validates it is running on the sequence `x`. +// Second statement annotates for the thread safety analyzer the check was done. +// Such annotation has to be attached to a function, and that function has to be +// called. Thus current implementation creates a noop lambda and calls it. +#define RTC_DCHECK_RUN_ON(x) \ + RTC_DCHECK((x)->IsCurrent()) \ + << webrtc::webrtc_sequence_checker_internal::ExpectationToString(x); \ + []() RTC_ASSERT_EXCLUSIVE_LOCK(x) {}() + +#endif // API_SEQUENCE_CHECKER_H_ diff --git a/third_party/libwebrtc/api/sequence_checker_gn/moz.build b/third_party/libwebrtc/api/sequence_checker_gn/moz.build new file mode 100644 index 0000000000..d3dd3980f8 --- /dev/null +++ b/third_party/libwebrtc/api/sequence_checker_gn/moz.build @@ -0,0 +1,205 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("sequence_checker_gn") diff --git a/third_party/libwebrtc/api/sequence_checker_unittest.cc b/third_party/libwebrtc/api/sequence_checker_unittest.cc new file mode 100644 index 0000000000..f117926d73 --- /dev/null +++ b/third_party/libwebrtc/api/sequence_checker_unittest.cc @@ -0,0 +1,224 @@ +/* + * 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. + */ + +#include "api/sequence_checker.h" + +#include <memory> +#include <utility> + +#include "api/function_view.h" +#include "api/units/time_delta.h" +#include "rtc_base/event.h" +#include "rtc_base/platform_thread.h" +#include "rtc_base/task_queue_for_test.h" +#include "test/gmock.h" +#include "test/gtest.h" + +using testing::HasSubstr; + +namespace webrtc { +namespace { + +// This class is dead code, but its purpose is to make sure that +// SequenceChecker is compatible with the RTC_GUARDED_BY and RTC_RUN_ON +// attributes that are checked at compile-time. +class CompileTimeTestForGuardedBy { + public: + int CalledOnSequence() RTC_RUN_ON(sequence_checker_) { return guarded_; } + + void CallMeFromSequence() { + RTC_DCHECK_RUN_ON(&sequence_checker_); + guarded_ = 41; + } + + private: + int guarded_ RTC_GUARDED_BY(sequence_checker_); + ::webrtc::SequenceChecker sequence_checker_; +}; + +void RunOnDifferentThread(rtc::FunctionView<void()> run) { + rtc::Event thread_has_run_event; + rtc::PlatformThread::SpawnJoinable( + [&] { + run(); + thread_has_run_event.Set(); + }, + "thread"); + EXPECT_TRUE(thread_has_run_event.Wait(TimeDelta::Seconds(1))); +} + +} // namespace + +TEST(SequenceCheckerTest, CallsAllowedOnSameThread) { + SequenceChecker sequence_checker; + EXPECT_TRUE(sequence_checker.IsCurrent()); +} + +TEST(SequenceCheckerTest, DestructorAllowedOnDifferentThread) { + auto sequence_checker = std::make_unique<SequenceChecker>(); + RunOnDifferentThread([&] { + // Verify that the destructor doesn't assert when called on a different + // thread. + sequence_checker.reset(); + }); +} + +TEST(SequenceCheckerTest, Detach) { + SequenceChecker sequence_checker; + sequence_checker.Detach(); + RunOnDifferentThread([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); }); +} + +TEST(SequenceCheckerTest, DetachFromThreadAndUseOnTaskQueue) { + SequenceChecker sequence_checker; + sequence_checker.Detach(); + TaskQueueForTest queue; + queue.SendTask([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); }); +} + +TEST(SequenceCheckerTest, DetachFromTaskQueueAndUseOnThread) { + TaskQueueForTest queue; + queue.SendTask([] { + SequenceChecker sequence_checker; + sequence_checker.Detach(); + RunOnDifferentThread([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); }); + }); +} + +TEST(SequenceCheckerTest, MethodNotAllowedOnDifferentThreadInDebug) { + SequenceChecker sequence_checker; + RunOnDifferentThread( + [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); }); +} + +#if RTC_DCHECK_IS_ON +TEST(SequenceCheckerTest, OnlyCurrentOnOneThread) { + SequenceChecker sequence_checker(SequenceChecker::kDetached); + RunOnDifferentThread([&] { + EXPECT_TRUE(sequence_checker.IsCurrent()); + // Spawn a new thread from within the first one to guarantee that we have + // two concurrently active threads (and that there's no chance of the + // thread ref being reused). + RunOnDifferentThread([&] { EXPECT_FALSE(sequence_checker.IsCurrent()); }); + }); +} +#endif + +TEST(SequenceCheckerTest, MethodNotAllowedOnDifferentTaskQueueInDebug) { + SequenceChecker sequence_checker; + TaskQueueForTest queue; + queue.SendTask( + [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); }); +} + +TEST(SequenceCheckerTest, DetachFromTaskQueueInDebug) { + SequenceChecker sequence_checker; + sequence_checker.Detach(); + + TaskQueueForTest queue1; + queue1.SendTask([&] { EXPECT_TRUE(sequence_checker.IsCurrent()); }); + + // IsCurrent should return false in debug builds after moving to + // another task queue. + TaskQueueForTest queue2; + queue2.SendTask( + [&] { EXPECT_EQ(sequence_checker.IsCurrent(), !RTC_DCHECK_IS_ON); }); +} + +TEST(SequenceCheckerTest, ExpectationToString) { + TaskQueueForTest queue1; + + SequenceChecker sequence_checker(SequenceChecker::kDetached); + + rtc::Event blocker; + queue1.PostTask([&blocker, &sequence_checker]() { + (void)sequence_checker.IsCurrent(); + blocker.Set(); + }); + + blocker.Wait(rtc::Event::kForever); + +#if RTC_DCHECK_IS_ON + + EXPECT_THAT(ExpectationToString(&sequence_checker), + HasSubstr("# Expected: TQ:")); + + // Test for the base class + webrtc_sequence_checker_internal::SequenceCheckerImpl* sequence_checker_base = + &sequence_checker; + EXPECT_THAT(ExpectationToString(sequence_checker_base), + HasSubstr("# Expected: TQ:")); + +#else + GTEST_ASSERT_EQ(ExpectationToString(&sequence_checker), ""); +#endif +} + +TEST(SequenceCheckerTest, InitiallyDetached) { + TaskQueueForTest queue1; + + SequenceChecker sequence_checker(SequenceChecker::kDetached); + + rtc::Event blocker; + queue1.PostTask([&blocker, &sequence_checker]() { + EXPECT_TRUE(sequence_checker.IsCurrent()); + blocker.Set(); + }); + + blocker.Wait(rtc::Event::kForever); + +#if RTC_DCHECK_IS_ON + EXPECT_FALSE(sequence_checker.IsCurrent()); +#endif +} + +class TestAnnotations { + public: + TestAnnotations() : test_var_(false) {} + + void ModifyTestVar() { + RTC_DCHECK_RUN_ON(&checker_); + test_var_ = true; + } + + private: + bool test_var_ RTC_GUARDED_BY(&checker_); + SequenceChecker checker_; +}; + +TEST(SequenceCheckerTest, TestAnnotations) { + TestAnnotations annotations; + annotations.ModifyTestVar(); +} + +#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) + +void TestAnnotationsOnWrongQueue() { + TestAnnotations annotations; + TaskQueueForTest queue; + queue.SendTask([&] { annotations.ModifyTestVar(); }); +} + +#if RTC_DCHECK_IS_ON +// Note: Ending the test suite name with 'DeathTest' is important as it causes +// gtest to order this test before any other non-death-tests, to avoid potential +// global process state pollution such as shared worker threads being started +// (e.g. a side effect of calling InitCocoaMultiThreading() on Mac causes one or +// two additional threads to be created). +TEST(SequenceCheckerDeathTest, TestAnnotationsOnWrongQueueDebug) { + ASSERT_DEATH({ TestAnnotationsOnWrongQueue(); }, ""); +} +#else +TEST(SequenceCheckerTest, TestAnnotationsOnWrongQueueRelease) { + TestAnnotationsOnWrongQueue(); +} +#endif +#endif // GTEST_HAS_DEATH_TEST +} // namespace webrtc diff --git a/third_party/libwebrtc/api/set_local_description_observer_interface.h b/third_party/libwebrtc/api/set_local_description_observer_interface.h new file mode 100644 index 0000000000..8e7b6258d3 --- /dev/null +++ b/third_party/libwebrtc/api/set_local_description_observer_interface.h @@ -0,0 +1,30 @@ +/* + * Copyright 2020 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 API_SET_LOCAL_DESCRIPTION_OBSERVER_INTERFACE_H_ +#define API_SET_LOCAL_DESCRIPTION_OBSERVER_INTERFACE_H_ + +#include "api/rtc_error.h" +#include "rtc_base/ref_count.h" + +namespace webrtc { + +// OnSetLocalDescriptionComplete() invokes as soon as +// PeerConnectionInterface::SetLocalDescription() operation completes, allowing +// the observer to examine the effects of the operation without delay. +class SetLocalDescriptionObserverInterface : public rtc::RefCountInterface { + public: + // On success, `error.ok()` is true. + virtual void OnSetLocalDescriptionComplete(RTCError error) = 0; +}; + +} // namespace webrtc + +#endif // API_SET_LOCAL_DESCRIPTION_OBSERVER_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/set_remote_description_observer_interface.h b/third_party/libwebrtc/api/set_remote_description_observer_interface.h new file mode 100644 index 0000000000..d1c075309f --- /dev/null +++ b/third_party/libwebrtc/api/set_remote_description_observer_interface.h @@ -0,0 +1,31 @@ +/* + * Copyright 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. + */ + +#ifndef API_SET_REMOTE_DESCRIPTION_OBSERVER_INTERFACE_H_ +#define API_SET_REMOTE_DESCRIPTION_OBSERVER_INTERFACE_H_ + +#include "api/rtc_error.h" +#include "rtc_base/ref_count.h" + +namespace webrtc { + +// An observer for PeerConnectionInterface::SetRemoteDescription(). The +// callback is invoked such that the state of the peer connection can be +// examined to accurately reflect the effects of the SetRemoteDescription +// operation. +class SetRemoteDescriptionObserverInterface : public rtc::RefCountInterface { + public: + // On success, `error.ok()` is true. + virtual void OnSetRemoteDescriptionComplete(RTCError error) = 0; +}; + +} // namespace webrtc + +#endif // API_SET_REMOTE_DESCRIPTION_OBSERVER_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/simulated_network_api_gn/moz.build b/third_party/libwebrtc/api/simulated_network_api_gn/moz.build new file mode 100644 index 0000000000..0867200479 --- /dev/null +++ b/third_party/libwebrtc/api/simulated_network_api_gn/moz.build @@ -0,0 +1,205 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("simulated_network_api_gn") diff --git a/third_party/libwebrtc/api/stats/OWNERS b/third_party/libwebrtc/api/stats/OWNERS new file mode 100644 index 0000000000..7e98070d5d --- /dev/null +++ b/third_party/libwebrtc/api/stats/OWNERS @@ -0,0 +1,2 @@ +hbos@webrtc.org +hta@webrtc.org diff --git a/third_party/libwebrtc/api/stats/rtc_stats.h b/third_party/libwebrtc/api/stats/rtc_stats.h new file mode 100644 index 0000000000..72775243c7 --- /dev/null +++ b/third_party/libwebrtc/api/stats/rtc_stats.h @@ -0,0 +1,580 @@ +/* + * Copyright 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. + */ + +#ifndef API_STATS_RTC_STATS_H_ +#define API_STATS_RTC_STATS_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "absl/types/optional.h" +#include "api/units/timestamp.h" +#include "rtc_base/checks.h" +#include "rtc_base/system/rtc_export.h" +#include "rtc_base/system/rtc_export_template.h" + +namespace webrtc { + +class RTCStatsMemberInterface; + +// Abstract base class for RTCStats-derived dictionaries, see +// https://w3c.github.io/webrtc-stats/. +// +// All derived classes must have the following static variable defined: +// static const char kType[]; +// It is used as a unique class identifier and a string representation of the +// class type, see https://w3c.github.io/webrtc-stats/#rtcstatstype-str*. +// Use the `WEBRTC_RTCSTATS_IMPL` macro when implementing subclasses, see macro +// for details. +// +// Derived classes list their dictionary members, RTCStatsMember<T>, as public +// fields, allowing the following: +// +// RTCFooStats foo("fooId", Timestamp::Micros(GetCurrentTime())); +// foo.bar = 42; +// foo.baz = std::vector<std::string>(); +// foo.baz->push_back("hello world"); +// uint32_t x = *foo.bar; +// +// Pointers to all the members are available with `Members`, allowing iteration: +// +// for (const RTCStatsMemberInterface* member : foo.Members()) { +// printf("%s = %s\n", member->name(), member->ValueToString().c_str()); +// } +class RTC_EXPORT RTCStats { + public: + RTCStats(const std::string& id, Timestamp timestamp) + : id_(id), timestamp_(timestamp) {} + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCStats(std::string id, int64_t timestamp_us) + : RTCStats(std::move(id), Timestamp::Micros(timestamp_us)) {} + + virtual ~RTCStats() {} + + virtual std::unique_ptr<RTCStats> copy() const = 0; + + const std::string& id() const { return id_; } + // Time relative to the UNIX epoch (Jan 1, 1970, UTC), in microseconds. + ABSL_DEPRECATED("Use .timestamp().us() instead") + int64_t timestamp_us() const { return timestamp_.us(); } + Timestamp timestamp() const { return timestamp_; } + + // Returns the static member variable `kType` of the implementing class. + virtual const char* type() const = 0; + // Returns a vector of pointers to all the `RTCStatsMemberInterface` members + // of this class. This allows for iteration of members. For a given class, + // `Members` always returns the same members in the same order. + std::vector<const RTCStatsMemberInterface*> Members() const; + // Checks if the two stats objects are of the same type and have the same + // member values. Timestamps are not compared. These operators are exposed for + // testing. + bool operator==(const RTCStats& other) const; + bool operator!=(const RTCStats& other) const; + + // Creates a JSON readable string representation of the stats + // object, listing all of its members (names and values). + std::string ToJson() const; + + // Downcasts the stats object to an `RTCStats` subclass `T`. DCHECKs that the + // object is of type `T`. + template <typename T> + const T& cast_to() const { + RTC_DCHECK_EQ(type(), T::kType); + return static_cast<const T&>(*this); + } + + protected: + // Gets a vector of all members of this `RTCStats` object, including members + // derived from parent classes. `additional_capacity` is how many more members + // shall be reserved in the vector (so that subclasses can allocate a vector + // with room for both parent and child members without it having to resize). + virtual std::vector<const RTCStatsMemberInterface*> + MembersOfThisObjectAndAncestors(size_t additional_capacity) const; + + std::string const id_; + Timestamp timestamp_; +}; + +// All `RTCStats` classes should use these macros. +// `WEBRTC_RTCSTATS_DECL` is placed in a public section of the class definition. +// `WEBRTC_RTCSTATS_IMPL` is placed outside the class definition (in a .cc). +// +// These macros declare (in _DECL) and define (in _IMPL) the static `kType` and +// overrides methods as required by subclasses of `RTCStats`: `copy`, `type` and +// `MembersOfThisObjectAndAncestors`. The |...| argument is a list of addresses +// to each member defined in the implementing class. The list must have at least +// one member. +// +// (Since class names need to be known to implement these methods this cannot be +// part of the base `RTCStats`. While these methods could be implemented using +// templates, that would only work for immediate subclasses. Subclasses of +// subclasses also have to override these methods, resulting in boilerplate +// code. Using a macro avoids this and works for any `RTCStats` class, including +// grandchildren.) +// +// Sample usage: +// +// rtcfoostats.h: +// class RTCFooStats : public RTCStats { +// public: +// WEBRTC_RTCSTATS_DECL(); +// +// RTCFooStats(const std::string& id, int64_t timestamp_us); +// +// RTCStatsMember<int32_t> foo; +// RTCStatsMember<int32_t> bar; +// }; +// +// rtcfoostats.cc: +// WEBRTC_RTCSTATS_IMPL(RTCFooStats, RTCStats, "foo-stats" +// &foo, +// &bar); +// +// RTCFooStats::RTCFooStats(const std::string& id, int64_t timestamp_us) +// : RTCStats(id, timestamp_us), +// foo("foo"), +// bar("bar") { +// } +// +#define WEBRTC_RTCSTATS_DECL() \ + protected: \ + std::vector<const webrtc::RTCStatsMemberInterface*> \ + MembersOfThisObjectAndAncestors(size_t local_var_additional_capacity) \ + const override; \ + \ + public: \ + static const char kType[]; \ + \ + std::unique_ptr<webrtc::RTCStats> copy() const override; \ + const char* type() const override + +#define WEBRTC_RTCSTATS_IMPL(this_class, parent_class, type_str, ...) \ + const char this_class::kType[] = type_str; \ + \ + std::unique_ptr<webrtc::RTCStats> this_class::copy() const { \ + return std::make_unique<this_class>(*this); \ + } \ + \ + const char* this_class::type() const { return this_class::kType; } \ + \ + std::vector<const webrtc::RTCStatsMemberInterface*> \ + this_class::MembersOfThisObjectAndAncestors( \ + size_t local_var_additional_capacity) const { \ + const webrtc::RTCStatsMemberInterface* local_var_members[] = { \ + __VA_ARGS__}; \ + size_t local_var_members_count = \ + sizeof(local_var_members) / sizeof(local_var_members[0]); \ + std::vector<const webrtc::RTCStatsMemberInterface*> \ + local_var_members_vec = parent_class::MembersOfThisObjectAndAncestors( \ + local_var_members_count + local_var_additional_capacity); \ + RTC_DCHECK_GE( \ + local_var_members_vec.capacity() - local_var_members_vec.size(), \ + local_var_members_count + local_var_additional_capacity); \ + local_var_members_vec.insert(local_var_members_vec.end(), \ + &local_var_members[0], \ + &local_var_members[local_var_members_count]); \ + return local_var_members_vec; \ + } + +// A version of WEBRTC_RTCSTATS_IMPL() where "..." is omitted, used to avoid a +// compile error on windows. This is used if the stats dictionary does not +// declare any members of its own (but perhaps its parent dictionary does). +#define WEBRTC_RTCSTATS_IMPL_NO_MEMBERS(this_class, parent_class, type_str) \ + const char this_class::kType[] = type_str; \ + \ + std::unique_ptr<webrtc::RTCStats> this_class::copy() const { \ + return std::make_unique<this_class>(*this); \ + } \ + \ + const char* this_class::type() const { return this_class::kType; } \ + \ + std::vector<const webrtc::RTCStatsMemberInterface*> \ + this_class::MembersOfThisObjectAndAncestors( \ + size_t local_var_additional_capacity) const { \ + return parent_class::MembersOfThisObjectAndAncestors(0); \ + } + +// Non-standard stats members can be exposed to the JavaScript API in Chrome +// e.g. through origin trials. The group ID can be used by the blink layer to +// determine if a stats member should be exposed or not. Multiple non-standard +// stats members can share the same group ID so that they are exposed together. +enum class NonStandardGroupId { + // Group ID used for testing purposes only. + kGroupIdForTesting, + // I2E: + // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/hE2B1iItPDk + kRtcAudioJitterBufferMaxPackets, + // I2E: + // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/YbhMyqLXXXo + kRtcStatsRelativePacketArrivalDelay, +}; + +// Certain stat members should only be exposed to the JavaScript API in +// certain circumstances as to avoid passive fingerprinting. +enum class StatExposureCriteria : uint8_t { + // The stat should always be exposed. This is the default. + kAlways, + // The stat exposes hardware capabilities and thus should has limited exposure + // to JavaScript. The requirements for exposure are written in the spec at + // https://w3c.github.io/webrtc-stats/#limiting-exposure-of-hardware-capabilities. + kHardwareCapability, + // The stat is non-standard so user agents should filter these. + kNonStandard, +}; + +// Interface for `RTCStats` members, which have a name and a value of a type +// defined in a subclass. Only the types listed in `Type` are supported, these +// are implemented by `RTCStatsMember<T>`. The value of a member may be +// undefined, the value can only be read if `is_defined`. +class RTCStatsMemberInterface { + public: + // Member value types. + enum Type { + kBool, // bool + kInt32, // int32_t + kUint32, // uint32_t + kInt64, // int64_t + kUint64, // uint64_t + kDouble, // double + kString, // std::string + + kSequenceBool, // std::vector<bool> + kSequenceInt32, // std::vector<int32_t> + kSequenceUint32, // std::vector<uint32_t> + kSequenceInt64, // std::vector<int64_t> + kSequenceUint64, // std::vector<uint64_t> + kSequenceDouble, // std::vector<double> + kSequenceString, // std::vector<std::string> + + kMapStringUint64, // std::map<std::string, uint64_t> + kMapStringDouble, // std::map<std::string, double> + }; + + virtual ~RTCStatsMemberInterface() {} + + const char* name() const { return name_; } + virtual Type type() const = 0; + virtual bool is_sequence() const = 0; + virtual bool is_string() const = 0; + virtual bool is_defined() const = 0; + // Is this part of the stats spec? Used so that chromium can easily filter + // out anything unstandardized. + bool is_standardized() const { + return exposure_criteria() != StatExposureCriteria::kNonStandard; + } + // Non-standard stats members can have group IDs in order to be exposed in + // JavaScript through experiments. Standardized stats have no group IDs. + virtual std::vector<NonStandardGroupId> group_ids() const { return {}; } + // The conditions for exposing the statistic to JavaScript. Stats with + // criteria that is not kAlways has some restriction and should be filtered + // in accordance to the spec. + virtual StatExposureCriteria exposure_criteria() const { + return StatExposureCriteria::kAlways; + } + // Type and value comparator. The names are not compared. These operators are + // exposed for testing. + bool operator==(const RTCStatsMemberInterface& other) const { + return IsEqual(other); + } + bool operator!=(const RTCStatsMemberInterface& other) const { + return !(*this == other); + } + virtual std::string ValueToString() const = 0; + // This is the same as ValueToString except for kInt64 and kUint64 types, + // where the value is represented as a double instead of as an integer. + // Since JSON stores numbers as floating point numbers, very large integers + // cannot be accurately represented, so we prefer to display them as doubles + // instead. + virtual std::string ValueToJson() const = 0; + + template <typename T> + const T& cast_to() const { + RTC_DCHECK_EQ(type(), T::StaticType()); + return static_cast<const T&>(*this); + } + + protected: + explicit RTCStatsMemberInterface(const char* name) : name_(name) {} + + virtual bool IsEqual(const RTCStatsMemberInterface& other) const = 0; + + const char* const name_; +}; + +// Template implementation of `RTCStatsMemberInterface`. +// The supported types are the ones described by +// `RTCStatsMemberInterface::Type`. +template <typename T> +class RTCStatsMember : public RTCStatsMemberInterface { + public: + explicit RTCStatsMember(const char* name) + : RTCStatsMemberInterface(name), value_() {} + RTCStatsMember(const char* name, const T& value) + : RTCStatsMemberInterface(name), value_(value) {} + RTCStatsMember(const char* name, T&& value) + : RTCStatsMemberInterface(name), value_(std::move(value)) {} + explicit RTCStatsMember(const RTCStatsMember<T>& other) + : RTCStatsMemberInterface(other.name_), value_(other.value_) {} + explicit RTCStatsMember(RTCStatsMember<T>&& other) + : RTCStatsMemberInterface(other.name_), value_(std::move(other.value_)) {} + + static Type StaticType(); + Type type() const override { return StaticType(); } + bool is_sequence() const override; + bool is_string() const override; + bool is_defined() const override { return value_.has_value(); } + std::string ValueToString() const override; + std::string ValueToJson() const override; + + template <typename U> + inline T ValueOrDefault(U default_value) const { + return value_.value_or(default_value); + } + + // Assignment operators. + T& operator=(const T& value) { + value_ = value; + return value_.value(); + } + T& operator=(const T&& value) { + value_ = std::move(value); + return value_.value(); + } + + // Value getters. + T& operator*() { + RTC_DCHECK(value_); + return *value_; + } + const T& operator*() const { + RTC_DCHECK(value_); + return *value_; + } + + // Value getters, arrow operator. + T* operator->() { + RTC_DCHECK(value_); + return &(*value_); + } + const T* operator->() const { + RTC_DCHECK(value_); + return &(*value_); + } + + protected: + bool IsEqual(const RTCStatsMemberInterface& other) const override { + if (type() != other.type() || + is_standardized() != other.is_standardized() || + exposure_criteria() != other.exposure_criteria()) + return false; + const RTCStatsMember<T>& other_t = + static_cast<const RTCStatsMember<T>&>(other); + return value_ == other_t.value_; + } + + private: + absl::optional<T> value_; +}; + +namespace rtc_stats_internal { + +typedef std::map<std::string, uint64_t> MapStringUint64; +typedef std::map<std::string, double> MapStringDouble; + +} // namespace rtc_stats_internal + +#define WEBRTC_DECLARE_RTCSTATSMEMBER(T) \ + template <> \ + RTC_EXPORT RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType(); \ + template <> \ + RTC_EXPORT bool RTCStatsMember<T>::is_sequence() const; \ + template <> \ + RTC_EXPORT bool RTCStatsMember<T>::is_string() const; \ + template <> \ + RTC_EXPORT std::string RTCStatsMember<T>::ValueToString() const; \ + template <> \ + RTC_EXPORT std::string RTCStatsMember<T>::ValueToJson() const; \ + extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) \ + RTCStatsMember<T> + +WEBRTC_DECLARE_RTCSTATSMEMBER(bool); +WEBRTC_DECLARE_RTCSTATSMEMBER(int32_t); +WEBRTC_DECLARE_RTCSTATSMEMBER(uint32_t); +WEBRTC_DECLARE_RTCSTATSMEMBER(int64_t); +WEBRTC_DECLARE_RTCSTATSMEMBER(uint64_t); +WEBRTC_DECLARE_RTCSTATSMEMBER(double); +WEBRTC_DECLARE_RTCSTATSMEMBER(std::string); +WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<bool>); +WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int32_t>); +WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint32_t>); +WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int64_t>); +WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint64_t>); +WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<double>); +WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<std::string>); +WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64); +WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble); + +// For stats with restricted exposure. +template <typename T, StatExposureCriteria E> +class RTCRestrictedStatsMember : public RTCStatsMember<T> { + public: + explicit RTCRestrictedStatsMember(const char* name) + : RTCStatsMember<T>(name) {} + RTCRestrictedStatsMember(const char* name, const T& value) + : RTCStatsMember<T>(name, value) {} + RTCRestrictedStatsMember(const char* name, T&& value) + : RTCStatsMember<T>(name, std::move(value)) {} + RTCRestrictedStatsMember(const RTCRestrictedStatsMember<T, E>& other) + : RTCStatsMember<T>(other) {} + RTCRestrictedStatsMember(RTCRestrictedStatsMember<T, E>&& other) + : RTCStatsMember<T>(std::move(other)) {} + + StatExposureCriteria exposure_criteria() const override { return E; } + + T& operator=(const T& value) { return RTCStatsMember<T>::operator=(value); } + T& operator=(const T&& value) { + return RTCStatsMember<T>::operator=(std::move(value)); + } + + private: + static_assert(E != StatExposureCriteria::kAlways, + "kAlways is the default exposure criteria. Use " + "RTCStatMember<T> instead."); +}; + +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<bool, StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<int32_t, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<uint32_t, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<int64_t, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<uint64_t, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<double, StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<std::string, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<std::vector<bool>, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<std::vector<int32_t>, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<std::vector<uint32_t>, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<std::vector<int64_t>, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<std::vector<uint64_t>, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<std::vector<double>, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<std::vector<std::string>, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<std::map<std::string, uint64_t>, + StatExposureCriteria::kHardwareCapability>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCRestrictedStatsMember<std::map<std::string, double>, + StatExposureCriteria::kHardwareCapability>; + +// Using inheritance just so that it's obvious from the member's declaration +// whether it's standardized or not. +template <typename T> +class RTCNonStandardStatsMember + : public RTCRestrictedStatsMember<T, StatExposureCriteria::kNonStandard> { + public: + explicit RTCNonStandardStatsMember(const char* name) + : RTCRestrictedStatsBase(name) {} + RTCNonStandardStatsMember(const char* name, + std::initializer_list<NonStandardGroupId> group_ids) + : RTCRestrictedStatsBase(name), group_ids_(group_ids) {} + RTCNonStandardStatsMember(const char* name, const T& value) + : RTCRestrictedStatsBase(name, value) {} + RTCNonStandardStatsMember(const char* name, T&& value) + : RTCRestrictedStatsBase(name, std::move(value)) {} + RTCNonStandardStatsMember(const RTCNonStandardStatsMember<T>& other) + : RTCRestrictedStatsBase(other), group_ids_(other.group_ids_) {} + RTCNonStandardStatsMember(RTCNonStandardStatsMember<T>&& other) + : RTCRestrictedStatsBase(std::move(other)), + group_ids_(std::move(other.group_ids_)) {} + + std::vector<NonStandardGroupId> group_ids() const override { + return group_ids_; + } + + T& operator=(const T& value) { + return RTCRestrictedStatsMember< + T, StatExposureCriteria::kNonStandard>::operator=(value); + } + T& operator=(const T&& value) { + return RTCRestrictedStatsMember< + T, StatExposureCriteria::kNonStandard>::operator=(std::move(value)); + } + + private: + using RTCRestrictedStatsBase = + RTCRestrictedStatsMember<T, StatExposureCriteria::kNonStandard>; + std::vector<NonStandardGroupId> group_ids_; +}; + +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<bool>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<int32_t>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<uint32_t>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<int64_t>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<uint64_t>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<double>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<std::string>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<std::vector<bool>>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<std::vector<int32_t>>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<std::vector<uint32_t>>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<std::vector<int64_t>>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<std::vector<uint64_t>>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<std::vector<double>>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<std::vector<std::string>>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<std::map<std::string, uint64_t>>; +extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) + RTCNonStandardStatsMember<std::map<std::string, double>>; + +} // namespace webrtc + +#endif // API_STATS_RTC_STATS_H_ diff --git a/third_party/libwebrtc/api/stats/rtc_stats_collector_callback.h b/third_party/libwebrtc/api/stats/rtc_stats_collector_callback.h new file mode 100644 index 0000000000..506cc63e6f --- /dev/null +++ b/third_party/libwebrtc/api/stats/rtc_stats_collector_callback.h @@ -0,0 +1,30 @@ +/* + * Copyright 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. + */ + +#ifndef API_STATS_RTC_STATS_COLLECTOR_CALLBACK_H_ +#define API_STATS_RTC_STATS_COLLECTOR_CALLBACK_H_ + +#include "api/scoped_refptr.h" +#include "api/stats/rtc_stats_report.h" +#include "rtc_base/ref_count.h" + +namespace webrtc { + +class RTCStatsCollectorCallback : public rtc::RefCountInterface { + public: + ~RTCStatsCollectorCallback() override = default; + + virtual void OnStatsDelivered( + const rtc::scoped_refptr<const RTCStatsReport>& report) = 0; +}; + +} // namespace webrtc + +#endif // API_STATS_RTC_STATS_COLLECTOR_CALLBACK_H_ diff --git a/third_party/libwebrtc/api/stats/rtc_stats_report.h b/third_party/libwebrtc/api/stats/rtc_stats_report.h new file mode 100644 index 0000000000..1cc6293fec --- /dev/null +++ b/third_party/libwebrtc/api/stats/rtc_stats_report.h @@ -0,0 +1,144 @@ +/* + * Copyright 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. + */ + +#ifndef API_STATS_RTC_STATS_REPORT_H_ +#define API_STATS_RTC_STATS_REPORT_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "api/ref_counted_base.h" +#include "api/scoped_refptr.h" +#include "api/stats/rtc_stats.h" +#include "api/units/timestamp.h" +// TODO(tommi): Remove this include after fixing iwyu issue in chromium. +// See: third_party/blink/renderer/platform/peerconnection/rtc_stats.cc +#include "rtc_base/ref_counted_object.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// A collection of stats. +// This is accessible as a map from `RTCStats::id` to `RTCStats`. +class RTC_EXPORT RTCStatsReport final + : public rtc::RefCountedNonVirtual<RTCStatsReport> { + public: + typedef std::map<std::string, std::unique_ptr<const RTCStats>> StatsMap; + + class RTC_EXPORT ConstIterator { + public: + ConstIterator(ConstIterator&& other); + ~ConstIterator(); + + ConstIterator& operator++(); + ConstIterator& operator++(int); + const RTCStats& operator*() const; + const RTCStats* operator->() const; + bool operator==(const ConstIterator& other) const; + bool operator!=(const ConstIterator& other) const; + + private: + friend class RTCStatsReport; + ConstIterator(const rtc::scoped_refptr<const RTCStatsReport>& report, + StatsMap::const_iterator it); + + // Reference report to make sure it is kept alive. + rtc::scoped_refptr<const RTCStatsReport> report_; + StatsMap::const_iterator it_; + }; + + // TODO(bugs.webrtc.org/13756): deprecate this in favor of Timestamp. + // TODO(hbos): Remove "= 0" once downstream has been updated to call with a + // parameter. + static rtc::scoped_refptr<RTCStatsReport> Create(int64_t timestamp_us = 0); + static rtc::scoped_refptr<RTCStatsReport> Create(Timestamp timestamp); + + // TODO(bugs.webrtc.org/13756): deprecate this in favor of Timestamp. + explicit RTCStatsReport(int64_t timestamp_us); + explicit RTCStatsReport(Timestamp timestamp); + + RTCStatsReport(const RTCStatsReport& other) = delete; + rtc::scoped_refptr<RTCStatsReport> Copy() const; + + int64_t timestamp_us() const { return timestamp_.us_or(-1); } + Timestamp timestamp() const { return timestamp_; } + void AddStats(std::unique_ptr<const RTCStats> stats); + // On success, returns a non-owning pointer to `stats`. If the stats ID is not + // unique, `stats` is not inserted and nullptr is returned. + template <typename T> + T* TryAddStats(std::unique_ptr<T> stats) { + T* stats_ptr = stats.get(); + if (!stats_ + .insert(std::make_pair(std::string(stats->id()), std::move(stats))) + .second) { + return nullptr; + } + return stats_ptr; + } + const RTCStats* Get(const std::string& id) const; + size_t size() const { return stats_.size(); } + + // Gets the stat object of type `T` by ID, where `T` is any class descending + // from `RTCStats`. + // Returns null if there is no stats object for the given ID or it is the + // wrong type. + template <typename T> + const T* GetAs(const std::string& id) const { + const RTCStats* stats = Get(id); + if (!stats || stats->type() != T::kType) { + return nullptr; + } + return &stats->cast_to<const T>(); + } + + // Removes the stats object from the report, returning ownership of it or null + // if there is no object with `id`. + std::unique_ptr<const RTCStats> Take(const std::string& id); + // Takes ownership of all the stats in `other`, leaving it empty. + void TakeMembersFrom(rtc::scoped_refptr<RTCStatsReport> other); + + // Stats iterators. Stats are ordered lexicographically on `RTCStats::id`. + ConstIterator begin() const; + ConstIterator end() const; + + // Gets the subset of stats that are of type `T`, where `T` is any class + // descending from `RTCStats`. + template <typename T> + std::vector<const T*> GetStatsOfType() const { + std::vector<const T*> stats_of_type; + for (const RTCStats& stats : *this) { + if (stats.type() == T::kType) + stats_of_type.push_back(&stats.cast_to<const T>()); + } + return stats_of_type; + } + + // Creates a JSON readable string representation of the report, + // listing all of its stats objects. + std::string ToJson() const; + + protected: + friend class rtc::RefCountedNonVirtual<RTCStatsReport>; + ~RTCStatsReport() = default; + + private: + Timestamp timestamp_; + StatsMap stats_; +}; + +} // namespace webrtc + +#endif // API_STATS_RTC_STATS_REPORT_H_ diff --git a/third_party/libwebrtc/api/stats/rtcstats_objects.h b/third_party/libwebrtc/api/stats/rtcstats_objects.h new file mode 100644 index 0000000000..e5de2100bb --- /dev/null +++ b/third_party/libwebrtc/api/stats/rtcstats_objects.h @@ -0,0 +1,722 @@ +/* + * Copyright 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. + */ + +#ifndef API_STATS_RTCSTATS_OBJECTS_H_ +#define API_STATS_RTCSTATS_OBJECTS_H_ + +#include <stdint.h> + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "api/stats/rtc_stats.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// https://w3c.github.io/webrtc-pc/#idl-def-rtcdatachannelstate +struct RTCDataChannelState { + static const char* const kConnecting; + static const char* const kOpen; + static const char* const kClosing; + static const char* const kClosed; +}; + +// https://w3c.github.io/webrtc-stats/#dom-rtcstatsicecandidatepairstate +struct RTCStatsIceCandidatePairState { + static const char* const kFrozen; + static const char* const kWaiting; + static const char* const kInProgress; + static const char* const kFailed; + static const char* const kSucceeded; +}; + +// https://w3c.github.io/webrtc-pc/#rtcicecandidatetype-enum +struct RTCIceCandidateType { + static const char* const kHost; + static const char* const kSrflx; + static const char* const kPrflx; + static const char* const kRelay; +}; + +// https://w3c.github.io/webrtc-pc/#idl-def-rtcdtlstransportstate +struct RTCDtlsTransportState { + static const char* const kNew; + static const char* const kConnecting; + static const char* const kConnected; + static const char* const kClosed; + static const char* const kFailed; +}; + +// `RTCMediaStreamTrackStats::kind` is not an enum in the spec but the only +// valid values are "audio" and "video". +// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-kind +struct RTCMediaStreamTrackKind { + static const char* const kAudio; + static const char* const kVideo; +}; + +// https://w3c.github.io/webrtc-stats/#dom-rtcnetworktype +struct RTCNetworkType { + static const char* const kBluetooth; + static const char* const kCellular; + static const char* const kEthernet; + static const char* const kWifi; + static const char* const kWimax; + static const char* const kVpn; + static const char* const kUnknown; +}; + +// https://w3c.github.io/webrtc-stats/#dom-rtcqualitylimitationreason +struct RTCQualityLimitationReason { + static const char* const kNone; + static const char* const kCpu; + static const char* const kBandwidth; + static const char* const kOther; +}; + +// https://webrtc.org/experiments/rtp-hdrext/video-content-type/ +struct RTCContentType { + static const char* const kUnspecified; + static const char* const kScreenshare; +}; + +// https://w3c.github.io/webrtc-stats/#dom-rtcdtlsrole +struct RTCDtlsRole { + static const char* const kUnknown; + static const char* const kClient; + static const char* const kServer; +}; + +// https://www.w3.org/TR/webrtc/#rtcicerole +struct RTCIceRole { + static const char* const kUnknown; + static const char* const kControlled; + static const char* const kControlling; +}; + +// https://www.w3.org/TR/webrtc/#dom-rtcicetransportstate +struct RTCIceTransportState { + static const char* const kNew; + static const char* const kChecking; + static const char* const kConnected; + static const char* const kCompleted; + static const char* const kDisconnected; + static const char* const kFailed; + static const char* const kClosed; +}; + +// https://w3c.github.io/webrtc-stats/#certificatestats-dict* +class RTC_EXPORT RTCCertificateStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCCertificateStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCCertificateStats(std::string id, int64_t timestamp_us); + RTCCertificateStats(const RTCCertificateStats& other); + ~RTCCertificateStats() override; + + RTCStatsMember<std::string> fingerprint; + RTCStatsMember<std::string> fingerprint_algorithm; + RTCStatsMember<std::string> base64_certificate; + RTCStatsMember<std::string> issuer_certificate_id; +}; + +// Non standard extension mapping to rtc::AdapterType +struct RTCNetworkAdapterType { + static constexpr char kUnknown[] = "unknown"; + static constexpr char kEthernet[] = "ethernet"; + static constexpr char kWifi[] = "wifi"; + static constexpr char kCellular[] = "cellular"; + static constexpr char kLoopback[] = "loopback"; + static constexpr char kAny[] = "any"; + static constexpr char kCellular2g[] = "cellular2g"; + static constexpr char kCellular3g[] = "cellular3g"; + static constexpr char kCellular4g[] = "cellular4g"; + static constexpr char kCellular5g[] = "cellular5g"; +}; + +// https://w3c.github.io/webrtc-stats/#codec-dict* +class RTC_EXPORT RTCCodecStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCCodecStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCCodecStats(std::string id, int64_t timestamp_us); + RTCCodecStats(const RTCCodecStats& other); + ~RTCCodecStats() override; + + RTCStatsMember<std::string> transport_id; + RTCStatsMember<uint32_t> payload_type; + RTCStatsMember<std::string> mime_type; + RTCStatsMember<uint32_t> clock_rate; + RTCStatsMember<uint32_t> channels; + RTCStatsMember<std::string> sdp_fmtp_line; +}; + +// https://w3c.github.io/webrtc-stats/#dcstats-dict* +class RTC_EXPORT RTCDataChannelStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCDataChannelStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCDataChannelStats(std::string id, int64_t timestamp_us); + RTCDataChannelStats(const RTCDataChannelStats& other); + ~RTCDataChannelStats() override; + + RTCStatsMember<std::string> label; + RTCStatsMember<std::string> protocol; + RTCStatsMember<int32_t> data_channel_identifier; + // Enum type RTCDataChannelState. + RTCStatsMember<std::string> state; + RTCStatsMember<uint32_t> messages_sent; + RTCStatsMember<uint64_t> bytes_sent; + RTCStatsMember<uint32_t> messages_received; + RTCStatsMember<uint64_t> bytes_received; +}; + +// https://w3c.github.io/webrtc-stats/#candidatepair-dict* +class RTC_EXPORT RTCIceCandidatePairStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCIceCandidatePairStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCIceCandidatePairStats(std::string id, int64_t timestamp_us); + RTCIceCandidatePairStats(const RTCIceCandidatePairStats& other); + ~RTCIceCandidatePairStats() override; + + RTCStatsMember<std::string> transport_id; + RTCStatsMember<std::string> local_candidate_id; + RTCStatsMember<std::string> remote_candidate_id; + // Enum type RTCStatsIceCandidatePairState. + RTCStatsMember<std::string> state; + // Obsolete: priority + RTCStatsMember<uint64_t> priority; + RTCStatsMember<bool> nominated; + // `writable` does not exist in the spec and old comments suggest it used to + // exist but was incorrectly implemented. + // TODO(https://crbug.com/webrtc/14171): Standardize and/or modify + // implementation. + RTCStatsMember<bool> writable; + RTCStatsMember<uint64_t> packets_sent; + RTCStatsMember<uint64_t> packets_received; + RTCStatsMember<uint64_t> bytes_sent; + RTCStatsMember<uint64_t> bytes_received; + RTCStatsMember<double> total_round_trip_time; + RTCStatsMember<double> current_round_trip_time; + RTCStatsMember<double> available_outgoing_bitrate; + RTCStatsMember<double> available_incoming_bitrate; + RTCStatsMember<uint64_t> requests_received; + RTCStatsMember<uint64_t> requests_sent; + RTCStatsMember<uint64_t> responses_received; + RTCStatsMember<uint64_t> responses_sent; + RTCStatsMember<uint64_t> consent_requests_sent; + RTCStatsMember<uint64_t> packets_discarded_on_send; + RTCStatsMember<uint64_t> bytes_discarded_on_send; + RTCStatsMember<double> last_packet_received_timestamp; + RTCStatsMember<double> last_packet_sent_timestamp; +}; + +// https://w3c.github.io/webrtc-stats/#icecandidate-dict* +class RTC_EXPORT RTCIceCandidateStats : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCIceCandidateStats(const RTCIceCandidateStats& other); + ~RTCIceCandidateStats() override; + + RTCStatsMember<std::string> transport_id; + // Obsolete: is_remote + RTCStatsMember<bool> is_remote; + RTCStatsMember<std::string> network_type; + RTCStatsMember<std::string> ip; + RTCStatsMember<std::string> address; + RTCStatsMember<int32_t> port; + RTCStatsMember<std::string> protocol; + RTCStatsMember<std::string> relay_protocol; + // Enum type RTCIceCandidateType. + RTCStatsMember<std::string> candidate_type; + RTCStatsMember<int32_t> priority; + RTCStatsMember<std::string> url; + RTCStatsMember<std::string> foundation; + RTCStatsMember<std::string> related_address; + RTCStatsMember<int32_t> related_port; + RTCStatsMember<std::string> username_fragment; + // Enum type RTCIceTcpCandidateType. + RTCStatsMember<std::string> tcp_type; + + RTCNonStandardStatsMember<bool> vpn; + RTCNonStandardStatsMember<std::string> network_adapter_type; + + protected: + RTCIceCandidateStats(std::string id, Timestamp timestamp, bool is_remote); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCIceCandidateStats(std::string id, int64_t timestamp_us, bool is_remote); +}; + +// In the spec both local and remote varieties are of type RTCIceCandidateStats. +// But here we define them as subclasses of `RTCIceCandidateStats` because the +// `kType` need to be different ("RTCStatsType type") in the local/remote case. +// https://w3c.github.io/webrtc-stats/#rtcstatstype-str* +// This forces us to have to override copy() and type(). +class RTC_EXPORT RTCLocalIceCandidateStats final : public RTCIceCandidateStats { + public: + static const char kType[]; + RTCLocalIceCandidateStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCLocalIceCandidateStats(std::string id, int64_t timestamp_us); + std::unique_ptr<RTCStats> copy() const override; + const char* type() const override; +}; + +class RTC_EXPORT RTCRemoteIceCandidateStats final + : public RTCIceCandidateStats { + public: + static const char kType[]; + RTCRemoteIceCandidateStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCRemoteIceCandidateStats(std::string id, int64_t timestamp_us); + std::unique_ptr<RTCStats> copy() const override; + const char* type() const override; +}; + +// TODO(https://crbug.com/webrtc/14419): Delete this class, it's deprecated. +class RTC_EXPORT DEPRECATED_RTCMediaStreamStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + DEPRECATED_RTCMediaStreamStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + DEPRECATED_RTCMediaStreamStats(std::string id, int64_t timestamp_us); + DEPRECATED_RTCMediaStreamStats(const DEPRECATED_RTCMediaStreamStats& other); + ~DEPRECATED_RTCMediaStreamStats() override; + + RTCStatsMember<std::string> stream_identifier; + RTCStatsMember<std::vector<std::string>> track_ids; +}; +using RTCMediaStreamStats [[deprecated("bugs.webrtc.org/14419")]] = + DEPRECATED_RTCMediaStreamStats; + +// TODO(https://crbug.com/webrtc/14175): Delete this class, it's deprecated. +class RTC_EXPORT DEPRECATED_RTCMediaStreamTrackStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + DEPRECATED_RTCMediaStreamTrackStats(std::string id, + Timestamp timestamp, + const char* kind); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + DEPRECATED_RTCMediaStreamTrackStats(std::string id, + int64_t timestamp_us, + const char* kind); + DEPRECATED_RTCMediaStreamTrackStats( + const DEPRECATED_RTCMediaStreamTrackStats& other); + ~DEPRECATED_RTCMediaStreamTrackStats() override; + + RTCStatsMember<std::string> track_identifier; + RTCStatsMember<std::string> media_source_id; + RTCStatsMember<bool> remote_source; + RTCStatsMember<bool> ended; + // TODO(https://crbug.com/webrtc/14173): Remove this obsolete metric. + RTCStatsMember<bool> detached; + // Enum type RTCMediaStreamTrackKind. + RTCStatsMember<std::string> kind; + RTCStatsMember<double> jitter_buffer_delay; + RTCStatsMember<uint64_t> jitter_buffer_emitted_count; + // Video-only members + RTCStatsMember<uint32_t> frame_width; + RTCStatsMember<uint32_t> frame_height; + RTCStatsMember<uint32_t> frames_sent; + RTCStatsMember<uint32_t> huge_frames_sent; + RTCStatsMember<uint32_t> frames_received; + RTCStatsMember<uint32_t> frames_decoded; + RTCStatsMember<uint32_t> frames_dropped; + // Audio-only members + RTCStatsMember<double> audio_level; // Receive-only + RTCStatsMember<double> total_audio_energy; // Receive-only + RTCStatsMember<double> echo_return_loss; + RTCStatsMember<double> echo_return_loss_enhancement; + RTCStatsMember<uint64_t> total_samples_received; + RTCStatsMember<double> total_samples_duration; // Receive-only + RTCStatsMember<uint64_t> concealed_samples; + RTCStatsMember<uint64_t> silent_concealed_samples; + RTCStatsMember<uint64_t> concealment_events; + RTCStatsMember<uint64_t> inserted_samples_for_deceleration; + RTCStatsMember<uint64_t> removed_samples_for_acceleration; +}; +using RTCMediaStreamTrackStats [[deprecated("bugs.webrtc.org/14175")]] = + DEPRECATED_RTCMediaStreamTrackStats; + +// https://w3c.github.io/webrtc-stats/#pcstats-dict* +class RTC_EXPORT RTCPeerConnectionStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCPeerConnectionStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCPeerConnectionStats(std::string id, int64_t timestamp_us); + RTCPeerConnectionStats(const RTCPeerConnectionStats& other); + ~RTCPeerConnectionStats() override; + + RTCStatsMember<uint32_t> data_channels_opened; + RTCStatsMember<uint32_t> data_channels_closed; +}; + +// https://w3c.github.io/webrtc-stats/#streamstats-dict* +class RTC_EXPORT RTCRTPStreamStats : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCRTPStreamStats(const RTCRTPStreamStats& other); + ~RTCRTPStreamStats() override; + + RTCStatsMember<uint32_t> ssrc; + RTCStatsMember<std::string> kind; + // Obsolete: track_id + RTCStatsMember<std::string> track_id; + RTCStatsMember<std::string> transport_id; + RTCStatsMember<std::string> codec_id; + + // Obsolete + RTCStatsMember<std::string> media_type; // renamed to kind. + + protected: + RTCRTPStreamStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCRTPStreamStats(std::string id, int64_t timestamp_us); +}; + +// https://www.w3.org/TR/webrtc-stats/#receivedrtpstats-dict* +class RTC_EXPORT RTCReceivedRtpStreamStats : public RTCRTPStreamStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCReceivedRtpStreamStats(const RTCReceivedRtpStreamStats& other); + ~RTCReceivedRtpStreamStats() override; + + RTCStatsMember<double> jitter; + RTCStatsMember<int32_t> packets_lost; // Signed per RFC 3550 + + protected: + RTCReceivedRtpStreamStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCReceivedRtpStreamStats(std::string id, int64_t timestamp_us); +}; + +// https://www.w3.org/TR/webrtc-stats/#sentrtpstats-dict* +class RTC_EXPORT RTCSentRtpStreamStats : public RTCRTPStreamStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCSentRtpStreamStats(const RTCSentRtpStreamStats& other); + ~RTCSentRtpStreamStats() override; + + RTCStatsMember<uint32_t> packets_sent; + RTCStatsMember<uint64_t> bytes_sent; + + protected: + RTCSentRtpStreamStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCSentRtpStreamStats(std::string id, int64_t timestamp_us); +}; + +// https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict* +class RTC_EXPORT RTCInboundRTPStreamStats final + : public RTCReceivedRtpStreamStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCInboundRTPStreamStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCInboundRTPStreamStats(std::string id, int64_t timestamp_us); + RTCInboundRTPStreamStats(const RTCInboundRTPStreamStats& other); + ~RTCInboundRTPStreamStats() override; + + // TODO(https://crbug.com/webrtc/14174): Implement trackIdentifier and kind. + + RTCStatsMember<std::string> playout_id; + RTCStatsMember<std::string> track_identifier; + RTCStatsMember<std::string> mid; + RTCStatsMember<std::string> remote_id; + RTCStatsMember<uint32_t> packets_received; + RTCStatsMember<uint64_t> packets_discarded; + RTCStatsMember<uint64_t> fec_packets_received; + RTCStatsMember<uint64_t> fec_packets_discarded; + RTCStatsMember<uint64_t> bytes_received; + RTCStatsMember<uint64_t> header_bytes_received; + RTCStatsMember<double> last_packet_received_timestamp; + RTCStatsMember<double> jitter_buffer_delay; + RTCStatsMember<double> jitter_buffer_target_delay; + RTCStatsMember<double> jitter_buffer_minimum_delay; + RTCStatsMember<uint64_t> jitter_buffer_emitted_count; + RTCStatsMember<uint64_t> total_samples_received; + RTCStatsMember<uint64_t> concealed_samples; + RTCStatsMember<uint64_t> silent_concealed_samples; + RTCStatsMember<uint64_t> concealment_events; + RTCStatsMember<uint64_t> inserted_samples_for_deceleration; + RTCStatsMember<uint64_t> removed_samples_for_acceleration; + RTCStatsMember<double> audio_level; + RTCStatsMember<double> total_audio_energy; + RTCStatsMember<double> total_samples_duration; + // Stats below are only implemented or defined for video. + RTCStatsMember<int32_t> frames_received; + RTCStatsMember<uint32_t> frame_width; + RTCStatsMember<uint32_t> frame_height; + RTCStatsMember<double> frames_per_second; + RTCStatsMember<uint32_t> frames_decoded; + RTCStatsMember<uint32_t> key_frames_decoded; + RTCStatsMember<uint32_t> frames_dropped; + RTCStatsMember<double> total_decode_time; + RTCStatsMember<double> total_processing_delay; + RTCStatsMember<double> total_assembly_time; + RTCStatsMember<uint32_t> frames_assembled_from_multiple_packets; + RTCStatsMember<double> total_inter_frame_delay; + RTCStatsMember<double> total_squared_inter_frame_delay; + RTCStatsMember<uint32_t> pause_count; + RTCStatsMember<double> total_pauses_duration; + RTCStatsMember<uint32_t> freeze_count; + RTCStatsMember<double> total_freezes_duration; + // https://w3c.github.io/webrtc-provisional-stats/#dom-rtcinboundrtpstreamstats-contenttype + RTCStatsMember<std::string> content_type; + // Only populated if audio/video sync is enabled. + // TODO(https://crbug.com/webrtc/14177): Expose even if A/V sync is off? + RTCStatsMember<double> estimated_playout_timestamp; + // Only implemented for video. + // TODO(https://crbug.com/webrtc/14178): Also implement for audio. + RTCRestrictedStatsMember<std::string, + StatExposureCriteria::kHardwareCapability> + decoder_implementation; + // FIR and PLI counts are only defined for |kind == "video"|. + RTCStatsMember<uint32_t> fir_count; + RTCStatsMember<uint32_t> pli_count; + RTCStatsMember<uint32_t> nack_count; + RTCStatsMember<uint64_t> qp_sum; + // This is a remnant of the legacy getStats() API. When the "video-timing" + // header extension is used, + // https://webrtc.github.io/webrtc-org/experiments/rtp-hdrext/video-timing/, + // `googTimingFrameInfo` is exposed with the value of + // TimingFrameInfo::ToString(). + // TODO(https://crbug.com/webrtc/14586): Unship or standardize this metric. + RTCStatsMember<std::string> goog_timing_frame_info; + RTCRestrictedStatsMember<bool, StatExposureCriteria::kHardwareCapability> + power_efficient_decoder; + // Non-standard audio metrics. + RTCNonStandardStatsMember<uint64_t> jitter_buffer_flushes; + RTCNonStandardStatsMember<uint64_t> delayed_packet_outage_samples; + RTCNonStandardStatsMember<double> relative_packet_arrival_delay; + RTCNonStandardStatsMember<uint32_t> interruption_count; + RTCNonStandardStatsMember<double> total_interruption_duration; + + // The former googMinPlayoutDelayMs (in seconds). + RTCNonStandardStatsMember<double> min_playout_delay; +}; + +// https://w3c.github.io/webrtc-stats/#outboundrtpstats-dict* +class RTC_EXPORT RTCOutboundRTPStreamStats final : public RTCRTPStreamStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCOutboundRTPStreamStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCOutboundRTPStreamStats(std::string id, int64_t timestamp_us); + RTCOutboundRTPStreamStats(const RTCOutboundRTPStreamStats& other); + ~RTCOutboundRTPStreamStats() override; + + RTCStatsMember<std::string> media_source_id; + RTCStatsMember<std::string> remote_id; + RTCStatsMember<std::string> mid; + RTCStatsMember<std::string> rid; + RTCStatsMember<uint32_t> packets_sent; + RTCStatsMember<uint64_t> retransmitted_packets_sent; + RTCStatsMember<uint64_t> bytes_sent; + RTCStatsMember<uint64_t> header_bytes_sent; + RTCStatsMember<uint64_t> retransmitted_bytes_sent; + RTCStatsMember<double> target_bitrate; + RTCStatsMember<uint32_t> frames_encoded; + RTCStatsMember<uint32_t> key_frames_encoded; + RTCStatsMember<double> total_encode_time; + RTCStatsMember<uint64_t> total_encoded_bytes_target; + RTCStatsMember<uint32_t> frame_width; + RTCStatsMember<uint32_t> frame_height; + RTCStatsMember<double> frames_per_second; + RTCStatsMember<uint32_t> frames_sent; + RTCStatsMember<uint32_t> huge_frames_sent; + RTCStatsMember<double> total_packet_send_delay; + // Enum type RTCQualityLimitationReason + RTCStatsMember<std::string> quality_limitation_reason; + RTCStatsMember<std::map<std::string, double>> quality_limitation_durations; + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-qualitylimitationresolutionchanges + RTCStatsMember<uint32_t> quality_limitation_resolution_changes; + // https://w3c.github.io/webrtc-provisional-stats/#dom-rtcoutboundrtpstreamstats-contenttype + RTCStatsMember<std::string> content_type; + // Only implemented for video. + // TODO(https://crbug.com/webrtc/14178): Implement for audio as well. + RTCRestrictedStatsMember<std::string, + StatExposureCriteria::kHardwareCapability> + encoder_implementation; + // FIR and PLI counts are only defined for |kind == "video"|. + RTCStatsMember<uint32_t> fir_count; + RTCStatsMember<uint32_t> pli_count; + RTCStatsMember<uint32_t> nack_count; + RTCStatsMember<uint64_t> qp_sum; + RTCStatsMember<bool> active; + RTCRestrictedStatsMember<bool, StatExposureCriteria::kHardwareCapability> + power_efficient_encoder; + RTCStatsMember<std::string> scalability_mode; +}; + +// https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict* +class RTC_EXPORT RTCRemoteInboundRtpStreamStats final + : public RTCReceivedRtpStreamStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCRemoteInboundRtpStreamStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCRemoteInboundRtpStreamStats(std::string id, int64_t timestamp_us); + RTCRemoteInboundRtpStreamStats(const RTCRemoteInboundRtpStreamStats& other); + ~RTCRemoteInboundRtpStreamStats() override; + + RTCStatsMember<std::string> local_id; + RTCStatsMember<double> round_trip_time; + RTCStatsMember<double> fraction_lost; + RTCStatsMember<double> total_round_trip_time; + RTCStatsMember<int32_t> round_trip_time_measurements; +}; + +// https://w3c.github.io/webrtc-stats/#remoteoutboundrtpstats-dict* +class RTC_EXPORT RTCRemoteOutboundRtpStreamStats final + : public RTCSentRtpStreamStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCRemoteOutboundRtpStreamStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCRemoteOutboundRtpStreamStats(std::string id, int64_t timestamp_us); + RTCRemoteOutboundRtpStreamStats(const RTCRemoteOutboundRtpStreamStats& other); + ~RTCRemoteOutboundRtpStreamStats() override; + + RTCStatsMember<std::string> local_id; + RTCStatsMember<double> remote_timestamp; + RTCStatsMember<uint64_t> reports_sent; + RTCStatsMember<double> round_trip_time; + RTCStatsMember<uint64_t> round_trip_time_measurements; + RTCStatsMember<double> total_round_trip_time; +}; + +// https://w3c.github.io/webrtc-stats/#dom-rtcmediasourcestats +class RTC_EXPORT RTCMediaSourceStats : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCMediaSourceStats(const RTCMediaSourceStats& other); + ~RTCMediaSourceStats() override; + + RTCStatsMember<std::string> track_identifier; + RTCStatsMember<std::string> kind; + + protected: + RTCMediaSourceStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCMediaSourceStats(std::string id, int64_t timestamp_us); +}; + +// https://w3c.github.io/webrtc-stats/#dom-rtcaudiosourcestats +class RTC_EXPORT RTCAudioSourceStats final : public RTCMediaSourceStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCAudioSourceStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCAudioSourceStats(std::string id, int64_t timestamp_us); + RTCAudioSourceStats(const RTCAudioSourceStats& other); + ~RTCAudioSourceStats() override; + + RTCStatsMember<double> audio_level; + RTCStatsMember<double> total_audio_energy; + RTCStatsMember<double> total_samples_duration; + RTCStatsMember<double> echo_return_loss; + RTCStatsMember<double> echo_return_loss_enhancement; +}; + +// https://w3c.github.io/webrtc-stats/#dom-rtcvideosourcestats +class RTC_EXPORT RTCVideoSourceStats final : public RTCMediaSourceStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCVideoSourceStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCVideoSourceStats(std::string id, int64_t timestamp_us); + RTCVideoSourceStats(const RTCVideoSourceStats& other); + ~RTCVideoSourceStats() override; + + RTCStatsMember<uint32_t> width; + RTCStatsMember<uint32_t> height; + RTCStatsMember<uint32_t> frames; + RTCStatsMember<double> frames_per_second; +}; + +// https://w3c.github.io/webrtc-stats/#transportstats-dict* +class RTC_EXPORT RTCTransportStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCTransportStats(std::string id, Timestamp timestamp); + ABSL_DEPRECATED("Use constructor with Timestamp instead") + RTCTransportStats(std::string id, int64_t timestamp_us); + RTCTransportStats(const RTCTransportStats& other); + ~RTCTransportStats() override; + + RTCStatsMember<uint64_t> bytes_sent; + RTCStatsMember<uint64_t> packets_sent; + RTCStatsMember<uint64_t> bytes_received; + RTCStatsMember<uint64_t> packets_received; + RTCStatsMember<std::string> rtcp_transport_stats_id; + // Enum type RTCDtlsTransportState. + RTCStatsMember<std::string> dtls_state; + RTCStatsMember<std::string> selected_candidate_pair_id; + RTCStatsMember<std::string> local_certificate_id; + RTCStatsMember<std::string> remote_certificate_id; + RTCStatsMember<std::string> tls_version; + RTCStatsMember<std::string> dtls_cipher; + RTCStatsMember<std::string> dtls_role; + RTCStatsMember<std::string> srtp_cipher; + RTCStatsMember<uint32_t> selected_candidate_pair_changes; + RTCStatsMember<std::string> ice_role; + RTCStatsMember<std::string> ice_local_username_fragment; + RTCStatsMember<std::string> ice_state; +}; + +// https://w3c.github.io/webrtc-stats/#playoutstats-dict* +class RTC_EXPORT RTCAudioPlayoutStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCAudioPlayoutStats(const std::string& id, Timestamp timestamp); + RTCAudioPlayoutStats(const RTCAudioPlayoutStats& other); + ~RTCAudioPlayoutStats() override; + + RTCStatsMember<std::string> kind; + RTCStatsMember<double> synthesized_samples_duration; + RTCStatsMember<uint64_t> synthesized_samples_events; + RTCStatsMember<double> total_samples_duration; + RTCStatsMember<double> total_playout_delay; + RTCStatsMember<uint64_t> total_samples_count; +}; + +} // namespace webrtc + +#endif // API_STATS_RTCSTATS_OBJECTS_H_ diff --git a/third_party/libwebrtc/api/task_queue/BUILD.gn b/third_party/libwebrtc/api/task_queue/BUILD.gn new file mode 100644 index 0000000000..1c342cb57e --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/BUILD.gn @@ -0,0 +1,166 @@ +# 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. + +import("../../webrtc.gni") + +rtc_library("task_queue") { + visibility = [ "*" ] + public = [ + "task_queue_base.h", + "task_queue_factory.h", + ] + sources = [ "task_queue_base.cc" ] + + deps = [ + "../../rtc_base:checks", + "../../rtc_base:macromagic", + "../../rtc_base/system:rtc_export", + "../units:time_delta", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/base:config", + "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/functional:any_invocable", + "//third_party/abseil-cpp/absl/strings", + ] +} + +# Mozilla - we want to ensure that rtc_include_tests is set to false +# to guarantee that default_task_queue_factory is not used so we +# know that remaining win32k code in task_queue_win.cc is not built. +# See Bug 1797161 for more info. +assert(!rtc_include_tests, "Mozilla - verify rtc_include_tests is off") +if (rtc_include_tests) { +rtc_library("task_queue_test") { + visibility = [ "*" ] + testonly = true + sources = [ + "task_queue_test.cc", + "task_queue_test.h", + ] + + check_includes = false # no-presubmit-check TODO(bugs.webrtc.org/9419) + if (build_with_chromium) { + visibility = [] + visibility = webrtc_default_visibility + visibility += [ + # This is the only Chromium targets that can depend on this. The reason + # behind this is the fact that these are 'testonly' targets and as such + # it cannot be part of the WebRTC component. + "//components/webrtc:unit_tests", + "//third_party/blink/renderer/platform:blink_platform_unittests_sources", + ] + + # Don't depend on WebRTC code outside of webrtc_overrides:webrtc_component + # because this will break the WebRTC component build in Chromium. + deps = [ + "../../../webrtc_overrides:webrtc_component", + "../../test:test_support", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/cleanup", + "//third_party/abseil-cpp/absl/strings", + ] + } else { + deps = [ + ":default_task_queue_factory", + ":task_queue", + "../../api:field_trials_view", + "../../api:make_ref_counted", + "../../api/units:time_delta", + "../../rtc_base:refcount", + "../../rtc_base:rtc_event", + "../../rtc_base:timeutils", + "../../test:test_support", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/cleanup", + "//third_party/abseil-cpp/absl/strings", + ] + } +} +} + +rtc_library("default_task_queue_factory") { + visibility = [ "*" ] + if (!is_ios && !is_android) { + poisonous = [ "default_task_queue" ] + } + sources = [ "default_task_queue_factory.h" ] + deps = [ + ":task_queue", + "../../api:field_trials_view", + "../../rtc_base/memory:always_valid_pointer", + ] + + if (rtc_enable_libevent) { + if (is_android) { + sources += + [ "default_task_queue_factory_stdlib_or_libevent_experiment.cc" ] + deps += [ + "../../api/transport:field_trial_based_config", + "../../rtc_base:logging", + "../../rtc_base:rtc_task_queue_libevent", + "../../rtc_base:rtc_task_queue_stdlib", + ] + } else { + sources += [ "default_task_queue_factory_libevent.cc" ] + deps += [ "../../rtc_base:rtc_task_queue_libevent" ] + } + } else if (is_mac || is_ios) { + sources += [ "default_task_queue_factory_gcd.cc" ] + deps += [ "../../rtc_base:rtc_task_queue_gcd" ] + } else if (is_win && current_os != "winuwp") { + sources += [ "default_task_queue_factory_win.cc" ] + deps += [ "../../rtc_base:rtc_task_queue_win" ] + } else { + sources += [ "default_task_queue_factory_stdlib.cc" ] + deps += [ "../../rtc_base:rtc_task_queue_stdlib" ] + } +} + +rtc_library("pending_task_safety_flag") { + visibility = [ "*" ] + sources = [ + "pending_task_safety_flag.cc", + "pending_task_safety_flag.h", + ] + deps = [ + "../../api:refcountedbase", + "../../api:scoped_refptr", + "../../api:sequence_checker", + "../../rtc_base:checks", + "../../rtc_base/system:no_unique_address", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/functional:any_invocable" ] +} + +if (rtc_include_tests) { + rtc_library("task_queue_default_factory_unittests") { + testonly = true + sources = [ "default_task_queue_factory_unittest.cc" ] + deps = [ + ":default_task_queue_factory", + ":task_queue_test", + "../../test:test_support", + ] + } + + rtc_library("pending_task_safety_flag_unittests") { + testonly = true + sources = [ "pending_task_safety_flag_unittest.cc" ] + deps = [ + ":pending_task_safety_flag", + "../../rtc_base:logging", + "../../rtc_base:rtc_event", + "../../rtc_base:rtc_task_queue", + "../../rtc_base:task_queue_for_test", + "../../test:test_support", + ] + } +} diff --git a/third_party/libwebrtc/api/task_queue/DEPS b/third_party/libwebrtc/api/task_queue/DEPS new file mode 100644 index 0000000000..1365edb504 --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/DEPS @@ -0,0 +1,14 @@ +specific_include_rules = { + "task_queue_base\.h": [ + # Make TaskQueueBase RTC_LOCKABALE to allow annotate variables are only + # accessed on specific task queue. + "+rtc_base/thread_annotations.h", + ], + "task_queue_test\.h": [ + "+test/gtest.h", + ], + "pending_task_safety_flag.h": [ + "+rtc_base/checks.h", + "+rtc_base/system/no_unique_address.h", + ], +} diff --git a/third_party/libwebrtc/api/task_queue/default_task_queue_factory.h b/third_party/libwebrtc/api/task_queue/default_task_queue_factory.h new file mode 100644 index 0000000000..1d2dbd7ec2 --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/default_task_queue_factory.h @@ -0,0 +1,25 @@ +/* + * Copyright 2019 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 API_TASK_QUEUE_DEFAULT_TASK_QUEUE_FACTORY_H_ +#define API_TASK_QUEUE_DEFAULT_TASK_QUEUE_FACTORY_H_ + +#include <memory> + +#include "api/field_trials_view.h" +#include "api/task_queue/task_queue_factory.h" + +namespace webrtc { + +std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory( + const FieldTrialsView* field_trials = nullptr); + +} // namespace webrtc + +#endif // API_TASK_QUEUE_DEFAULT_TASK_QUEUE_FACTORY_H_ diff --git a/third_party/libwebrtc/api/task_queue/default_task_queue_factory_gcd.cc b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_gcd.cc new file mode 100644 index 0000000000..391f09b393 --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_gcd.cc @@ -0,0 +1,23 @@ +/* + * Copyright 2019 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 <memory> + +#include "api/field_trials_view.h" +#include "api/task_queue/task_queue_factory.h" +#include "rtc_base/task_queue_gcd.h" + +namespace webrtc { + +std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory( + const FieldTrialsView* field_trials) { + return CreateTaskQueueGcdFactory(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/task_queue/default_task_queue_factory_libevent.cc b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_libevent.cc new file mode 100644 index 0000000000..89079f51ca --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_libevent.cc @@ -0,0 +1,23 @@ +/* + * Copyright 2019 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 <memory> + +#include "api/field_trials_view.h" +#include "api/task_queue/task_queue_factory.h" +#include "rtc_base/task_queue_libevent.h" + +namespace webrtc { + +std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory( + const FieldTrialsView* field_trials) { + return CreateTaskQueueLibeventFactory(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/task_queue/default_task_queue_factory_stdlib.cc b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_stdlib.cc new file mode 100644 index 0000000000..10cda7c5ec --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_stdlib.cc @@ -0,0 +1,23 @@ +/* + * Copyright 2019 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 <memory> + +#include "api/field_trials_view.h" +#include "api/task_queue/task_queue_factory.h" +#include "rtc_base/task_queue_stdlib.h" + +namespace webrtc { + +std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory( + const FieldTrialsView* field_trials) { + return CreateTaskQueueStdlibFactory(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/task_queue/default_task_queue_factory_stdlib_or_libevent_experiment.cc b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_stdlib_or_libevent_experiment.cc new file mode 100644 index 0000000000..dc6e835907 --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_stdlib_or_libevent_experiment.cc @@ -0,0 +1,38 @@ +/* + * Copyright 2022 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 <memory> + +#include "api/field_trials_view.h" +#include "api/task_queue/task_queue_factory.h" +#include "api/transport/field_trial_based_config.h" +#include "rtc_base/logging.h" +#include "rtc_base/memory/always_valid_pointer.h" +#include "rtc_base/task_queue_libevent.h" +#include "rtc_base/task_queue_stdlib.h" + +namespace webrtc { + +std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory( + const FieldTrialsView* field_trials_view) { + AlwaysValidPointer<const FieldTrialsView, FieldTrialBasedConfig> field_trials( + field_trials_view); + if (field_trials->IsEnabled("WebRTC-TaskQueue-ReplaceLibeventWithStdlib")) { + RTC_LOG(LS_INFO) << "WebRTC-TaskQueue-ReplaceLibeventWithStdlib: " + << "using TaskQueueStdlibFactory."; + return CreateTaskQueueStdlibFactory(); + } + + RTC_LOG(LS_INFO) << "WebRTC-TaskQueue-ReplaceLibeventWithStdlib: " + << "using TaskQueueLibeventFactory."; + return CreateTaskQueueLibeventFactory(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/task_queue/default_task_queue_factory_unittest.cc b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_unittest.cc new file mode 100644 index 0000000000..92c17d8444 --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_unittest.cc @@ -0,0 +1,24 @@ +/* + * Copyright 2019 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 "api/task_queue/default_task_queue_factory.h" + +#include "api/task_queue/task_queue_test.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +INSTANTIATE_TEST_SUITE_P(Default, + TaskQueueTest, + ::testing::Values(CreateDefaultTaskQueueFactory)); + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/api/task_queue/default_task_queue_factory_win.cc b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_win.cc new file mode 100644 index 0000000000..e3adc07327 --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/default_task_queue_factory_win.cc @@ -0,0 +1,23 @@ +/* + * Copyright 2019 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 <memory> + +#include "api/field_trials_view.h" +#include "api/task_queue/task_queue_factory.h" +#include "rtc_base/task_queue_win.h" + +namespace webrtc { + +std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory( + const FieldTrialsView* field_trials) { + return CreateTaskQueueWinFactory(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/task_queue/pending_task_safety_flag.cc b/third_party/libwebrtc/api/task_queue/pending_task_safety_flag.cc new file mode 100644 index 0000000000..437ce0755d --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/pending_task_safety_flag.cc @@ -0,0 +1,57 @@ +/* + * Copyright 2020 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 "api/task_queue/pending_task_safety_flag.h" + +namespace webrtc { + +// static +rtc::scoped_refptr<PendingTaskSafetyFlag> PendingTaskSafetyFlag::CreateInternal( + bool alive) { + // Explicit new, to access private constructor. + return rtc::scoped_refptr<PendingTaskSafetyFlag>( + new PendingTaskSafetyFlag(alive)); +} + +// static +rtc::scoped_refptr<PendingTaskSafetyFlag> PendingTaskSafetyFlag::Create() { + return CreateInternal(true); +} + +rtc::scoped_refptr<PendingTaskSafetyFlag> +PendingTaskSafetyFlag::CreateDetached() { + rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag = CreateInternal(true); + safety_flag->main_sequence_.Detach(); + return safety_flag; +} + +rtc::scoped_refptr<PendingTaskSafetyFlag> +PendingTaskSafetyFlag::CreateDetachedInactive() { + rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag = CreateInternal(false); + safety_flag->main_sequence_.Detach(); + return safety_flag; +} + +void PendingTaskSafetyFlag::SetNotAlive() { + RTC_DCHECK_RUN_ON(&main_sequence_); + alive_ = false; +} + +void PendingTaskSafetyFlag::SetAlive() { + RTC_DCHECK_RUN_ON(&main_sequence_); + alive_ = true; +} + +bool PendingTaskSafetyFlag::alive() const { + RTC_DCHECK_RUN_ON(&main_sequence_); + return alive_; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/task_queue/pending_task_safety_flag.h b/third_party/libwebrtc/api/task_queue/pending_task_safety_flag.h new file mode 100644 index 0000000000..3b948ca8f1 --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/pending_task_safety_flag.h @@ -0,0 +1,168 @@ +/* + * Copyright 2020 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 API_TASK_QUEUE_PENDING_TASK_SAFETY_FLAG_H_ +#define API_TASK_QUEUE_PENDING_TASK_SAFETY_FLAG_H_ + +#include <utility> + +#include "absl/functional/any_invocable.h" +#include "api/ref_counted_base.h" +#include "api/scoped_refptr.h" +#include "api/sequence_checker.h" +#include "rtc_base/checks.h" +#include "rtc_base/system/no_unique_address.h" + +namespace webrtc { + +// The PendingTaskSafetyFlag and the ScopedTaskSafety are designed to address +// the issue where you have a task to be executed later that has references, +// but cannot guarantee that the referenced object is alive when the task is +// executed. + +// This mechanism can be used with tasks that are created and destroyed +// on a single thread / task queue, and with tasks posted to the same +// thread/task queue, but tasks can be posted from any thread/TQ. + +// Typical usage: +// When posting a task, post a copy (capture by-value in a lambda) of the flag +// reference and before performing the work, check the `alive()` state. Abort if +// alive() returns `false`: +// +// class ExampleClass { +// .... +// rtc::scoped_refptr<PendingTaskSafetyFlag> flag = safety_flag_; +// my_task_queue_->PostTask( +// [flag = std::move(flag), this] { +// // Now running on the main thread. +// if (!flag->alive()) +// return; +// MyMethod(); +// }); +// .... +// ~ExampleClass() { +// safety_flag_->SetNotAlive(); +// } +// scoped_refptr<PendingTaskSafetyFlag> safety_flag_ +// = PendingTaskSafetyFlag::Create(); +// } +// +// SafeTask makes this check automatic: +// +// my_task_queue_->PostTask(SafeTask(safety_flag_, [this] { MyMethod(); })); +// +class PendingTaskSafetyFlag final + : public rtc::RefCountedNonVirtual<PendingTaskSafetyFlag> { + public: + static rtc::scoped_refptr<PendingTaskSafetyFlag> Create(); + + // Creates a flag, but with its SequenceChecker initially detached. Hence, it + // may be created on a different thread than the flag will be used on. + static rtc::scoped_refptr<PendingTaskSafetyFlag> CreateDetached(); + + // Same as `CreateDetached()` except the initial state of the returned flag + // will be `!alive()`. + static rtc::scoped_refptr<PendingTaskSafetyFlag> CreateDetachedInactive(); + + ~PendingTaskSafetyFlag() = default; + + void SetNotAlive(); + // The SetAlive method is intended to support Start/Stop/Restart usecases. + // When a class has called SetNotAlive on a flag used for posted tasks, and + // decides it wants to post new tasks and have them run, there are two + // reasonable ways to do that: + // + // (i) Use the below SetAlive method. One subtlety is that any task posted + // prior to SetNotAlive, and still in the queue, is resurrected and will + // run. + // + // (ii) Create a fresh flag, and just drop the reference to the old one. This + // avoids the above problem, and ensures that tasks poster prior to + // SetNotAlive stay cancelled. Instead, there's a potential data race on + // the flag pointer itself. Some synchronization is required between the + // thread overwriting the flag pointer, and the threads that want to post + // tasks and therefore read that same pointer. + void SetAlive(); + bool alive() const; + + protected: + explicit PendingTaskSafetyFlag(bool alive) : alive_(alive) {} + + private: + static rtc::scoped_refptr<PendingTaskSafetyFlag> CreateInternal(bool alive); + + bool alive_ = true; + RTC_NO_UNIQUE_ADDRESS SequenceChecker main_sequence_; +}; + +// The ScopedTaskSafety makes using PendingTaskSafetyFlag very simple. +// It does automatic PTSF creation and signalling of destruction when the +// ScopedTaskSafety instance goes out of scope. +// +// Example usage: +// +// my_task_queue->PostTask(SafeTask(scoped_task_safety.flag(), +// [this] { +// // task goes here +// } +// +// This should be used by the class that wants tasks dropped after destruction. +// The requirement is that the instance has to be constructed and destructed on +// the same thread as the potentially dropped tasks would be running on. +class ScopedTaskSafety final { + public: + ScopedTaskSafety() = default; + explicit ScopedTaskSafety(rtc::scoped_refptr<PendingTaskSafetyFlag> flag) + : flag_(std::move(flag)) {} + ~ScopedTaskSafety() { flag_->SetNotAlive(); } + + // Returns a new reference to the safety flag. + rtc::scoped_refptr<PendingTaskSafetyFlag> flag() const { return flag_; } + + // Marks the current flag as not-alive and attaches to a new one. + void reset(rtc::scoped_refptr<PendingTaskSafetyFlag> new_flag = + PendingTaskSafetyFlag::Create()) { + flag_->SetNotAlive(); + flag_ = std::move(new_flag); + } + + private: + rtc::scoped_refptr<PendingTaskSafetyFlag> flag_ = + PendingTaskSafetyFlag::Create(); +}; + +// Like ScopedTaskSafety, but allows construction on a different thread than +// where the flag will be used. +class ScopedTaskSafetyDetached final { + public: + ScopedTaskSafetyDetached() = default; + ~ScopedTaskSafetyDetached() { flag_->SetNotAlive(); } + + // Returns a new reference to the safety flag. + rtc::scoped_refptr<PendingTaskSafetyFlag> flag() const { return flag_; } + + private: + rtc::scoped_refptr<PendingTaskSafetyFlag> flag_ = + PendingTaskSafetyFlag::CreateDetached(); +}; + +inline absl::AnyInvocable<void() &&> SafeTask( + rtc::scoped_refptr<PendingTaskSafetyFlag> flag, + absl::AnyInvocable<void() &&> task) { + return [flag = std::move(flag), task = std::move(task)]() mutable { + if (flag->alive()) { + std::move(task)(); + } + }; +} + +} // namespace webrtc + +#endif // API_TASK_QUEUE_PENDING_TASK_SAFETY_FLAG_H_ diff --git a/third_party/libwebrtc/api/task_queue/pending_task_safety_flag_gn/moz.build b/third_party/libwebrtc/api/task_queue/pending_task_safety_flag_gn/moz.build new file mode 100644 index 0000000000..d7e6a087fa --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/pending_task_safety_flag_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/task_queue/pending_task_safety_flag.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("pending_task_safety_flag_gn") diff --git a/third_party/libwebrtc/api/task_queue/pending_task_safety_flag_unittest.cc b/third_party/libwebrtc/api/task_queue/pending_task_safety_flag_unittest.cc new file mode 100644 index 0000000000..cedf0eb8df --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/pending_task_safety_flag_unittest.cc @@ -0,0 +1,188 @@ +/* + * Copyright 2019 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 "api/task_queue/pending_task_safety_flag.h" + +#include <memory> + +#include "rtc_base/event.h" +#include "rtc_base/logging.h" +#include "rtc_base/task_queue_for_test.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { + +TEST(PendingTaskSafetyFlagTest, Basic) { + rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag; + { + // Scope for the `owner` instance. + class Owner { + public: + Owner() = default; + ~Owner() { flag_->SetNotAlive(); } + + rtc::scoped_refptr<PendingTaskSafetyFlag> flag_ = + PendingTaskSafetyFlag::Create(); + } owner; + EXPECT_TRUE(owner.flag_->alive()); + safety_flag = owner.flag_; + EXPECT_TRUE(safety_flag->alive()); + } + // `owner` now out of scope. + EXPECT_FALSE(safety_flag->alive()); +} + +TEST(PendingTaskSafetyFlagTest, BasicScoped) { + rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag; + { + struct Owner { + ScopedTaskSafety safety; + } owner; + safety_flag = owner.safety.flag(); + EXPECT_TRUE(safety_flag->alive()); + } + // `owner` now out of scope. + EXPECT_FALSE(safety_flag->alive()); +} + +TEST(PendingTaskSafetyFlagTest, PendingTaskSuccess) { + TaskQueueForTest tq1("OwnerHere"); + TaskQueueForTest tq2("OwnerNotHere"); + + class Owner { + public: + Owner() : tq_main_(TaskQueueBase::Current()) { RTC_DCHECK(tq_main_); } + ~Owner() { + RTC_DCHECK(tq_main_->IsCurrent()); + flag_->SetNotAlive(); + } + + void DoStuff() { + RTC_DCHECK(!tq_main_->IsCurrent()); + rtc::scoped_refptr<PendingTaskSafetyFlag> safe = flag_; + tq_main_->PostTask([safe = std::move(safe), this]() { + if (!safe->alive()) + return; + stuff_done_ = true; + }); + } + + bool stuff_done() const { return stuff_done_; } + + private: + TaskQueueBase* const tq_main_; + bool stuff_done_ = false; + rtc::scoped_refptr<PendingTaskSafetyFlag> flag_ = + PendingTaskSafetyFlag::Create(); + }; + + std::unique_ptr<Owner> owner; + tq1.SendTask([&owner]() { + owner = std::make_unique<Owner>(); + EXPECT_FALSE(owner->stuff_done()); + }); + ASSERT_TRUE(owner); + tq2.SendTask([&owner]() { owner->DoStuff(); }); + tq1.SendTask([&owner]() { + EXPECT_TRUE(owner->stuff_done()); + owner.reset(); + }); + ASSERT_FALSE(owner); +} + +TEST(PendingTaskSafetyFlagTest, PendingTaskDropped) { + TaskQueueForTest tq1("OwnerHere"); + TaskQueueForTest tq2("OwnerNotHere"); + + class Owner { + public: + explicit Owner(bool* stuff_done) + : tq_main_(TaskQueueBase::Current()), stuff_done_(stuff_done) { + RTC_DCHECK(tq_main_); + *stuff_done_ = false; + } + ~Owner() { RTC_DCHECK(tq_main_->IsCurrent()); } + + void DoStuff() { + RTC_DCHECK(!tq_main_->IsCurrent()); + tq_main_->PostTask( + SafeTask(safety_.flag(), [this]() { *stuff_done_ = true; })); + } + + private: + TaskQueueBase* const tq_main_; + bool* const stuff_done_; + ScopedTaskSafety safety_; + }; + + std::unique_ptr<Owner> owner; + bool stuff_done = false; + tq1.SendTask([&owner, &stuff_done]() { + owner = std::make_unique<Owner>(&stuff_done); + }); + ASSERT_TRUE(owner); + // Queue up a task on tq1 that will execute before the 'DoStuff' task + // can, and delete the `owner` before the 'stuff' task can execute. + rtc::Event blocker; + tq1.PostTask([&blocker, &owner]() { + blocker.Wait(rtc::Event::kForever); + owner.reset(); + }); + + // Queue up a DoStuff... + tq2.SendTask([&owner]() { owner->DoStuff(); }); + + ASSERT_TRUE(owner); + blocker.Set(); + + // Run an empty task on tq1 to flush all the queued tasks. + tq1.WaitForPreviouslyPostedTasks(); + ASSERT_FALSE(owner); + EXPECT_FALSE(stuff_done); +} + +TEST(PendingTaskSafetyFlagTest, PendingTaskNotAliveInitialized) { + TaskQueueForTest tq("PendingTaskNotAliveInitialized"); + + // Create a new flag that initially not `alive`. + auto flag = PendingTaskSafetyFlag::CreateDetachedInactive(); + tq.SendTask([&flag]() { EXPECT_FALSE(flag->alive()); }); + + bool task_1_ran = false; + bool task_2_ran = false; + tq.PostTask(SafeTask(flag, [&task_1_ran]() { task_1_ran = true; })); + tq.PostTask([&flag]() { flag->SetAlive(); }); + tq.PostTask(SafeTask(flag, [&task_2_ran]() { task_2_ran = true; })); + + tq.WaitForPreviouslyPostedTasks(); + EXPECT_FALSE(task_1_ran); + EXPECT_TRUE(task_2_ran); +} + +TEST(PendingTaskSafetyFlagTest, SafeTask) { + rtc::scoped_refptr<PendingTaskSafetyFlag> flag = + PendingTaskSafetyFlag::Create(); + + int count = 0; + // Create two identical tasks that increment the `count`. + auto task1 = SafeTask(flag, [&count] { ++count; }); + auto task2 = SafeTask(flag, [&count] { ++count; }); + + EXPECT_EQ(count, 0); + std::move(task1)(); + EXPECT_EQ(count, 1); + flag->SetNotAlive(); + // Now task2 should actually not run. + std::move(task2)(); + EXPECT_EQ(count, 1); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/task_queue/task_queue_base.cc b/third_party/libwebrtc/api/task_queue/task_queue_base.cc new file mode 100644 index 0000000000..ecdc7f7691 --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/task_queue_base.cc @@ -0,0 +1,81 @@ +/* + * Copyright 2019 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 "api/task_queue/task_queue_base.h" + +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/functional/any_invocable.h" +#include "api/units/time_delta.h" +#include "rtc_base/checks.h" + +#if defined(ABSL_HAVE_THREAD_LOCAL) + +namespace webrtc { +namespace { + +ABSL_CONST_INIT thread_local TaskQueueBase* current = nullptr; + +} // namespace + +TaskQueueBase* TaskQueueBase::Current() { + return current; +} + +TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter( + TaskQueueBase* task_queue) + : previous_(current) { + current = task_queue; +} + +TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() { + current = previous_; +} +} // namespace webrtc + +#elif defined(WEBRTC_POSIX) + +#include <pthread.h> + +namespace webrtc { +namespace { + +ABSL_CONST_INIT pthread_key_t g_queue_ptr_tls = 0; + +void InitializeTls() { + RTC_CHECK(pthread_key_create(&g_queue_ptr_tls, nullptr) == 0); +} + +pthread_key_t GetQueuePtrTls() { + static pthread_once_t init_once = PTHREAD_ONCE_INIT; + RTC_CHECK(pthread_once(&init_once, &InitializeTls) == 0); + return g_queue_ptr_tls; +} + +} // namespace + +TaskQueueBase* TaskQueueBase::Current() { + return static_cast<TaskQueueBase*>(pthread_getspecific(GetQueuePtrTls())); +} + +TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter( + TaskQueueBase* task_queue) + : previous_(TaskQueueBase::Current()) { + pthread_setspecific(GetQueuePtrTls(), task_queue); +} + +TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() { + pthread_setspecific(GetQueuePtrTls(), previous_); +} + +} // namespace webrtc + +#else +#error Unsupported platform +#endif diff --git a/third_party/libwebrtc/api/task_queue/task_queue_base.h b/third_party/libwebrtc/api/task_queue/task_queue_base.h new file mode 100644 index 0000000000..f78600de60 --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/task_queue_base.h @@ -0,0 +1,156 @@ +/* + * Copyright 2019 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 API_TASK_QUEUE_TASK_QUEUE_BASE_H_ +#define API_TASK_QUEUE_TASK_QUEUE_BASE_H_ + +#include <memory> +#include <utility> + +#include "absl/functional/any_invocable.h" +#include "api/units/time_delta.h" +#include "rtc_base/system/rtc_export.h" +#include "rtc_base/thread_annotations.h" + +namespace webrtc { + +// Asynchronously executes tasks in a way that guarantees that they're executed +// in FIFO order and that tasks never overlap. Tasks may always execute on the +// same worker thread and they may not. To DCHECK that tasks are executing on a +// known task queue, use IsCurrent(). +class RTC_LOCKABLE RTC_EXPORT TaskQueueBase { + public: + enum class DelayPrecision { + // This may include up to a 17 ms leeway in addition to OS timer precision. + // See PostDelayedTask() for more information. + kLow, + // This does not have the additional delay that kLow has, but it is still + // limited by OS timer precision. See PostDelayedHighPrecisionTask() for + // more information. + kHigh, + }; + + // Starts destruction of the task queue. + // On return ensures no task are running and no new tasks are able to start + // on the task queue. + // Responsible for deallocation. Deallocation may happen synchronously during + // Delete or asynchronously after Delete returns. + // Code not running on the TaskQueue should not make any assumption when + // TaskQueue is deallocated and thus should not call any methods after Delete. + // Code running on the TaskQueue should not call Delete, but can assume + // TaskQueue still exists and may call other methods, e.g. PostTask. + // Should be called on the same task queue or thread that this task queue + // was created on. + virtual void Delete() = 0; + + // Schedules a `task` to execute. Tasks are executed in FIFO order. + // When a TaskQueue is deleted, pending tasks will not be executed but they + // will be deleted. + // + // As long as tasks are not posted from task destruction, posted tasks are + // guaranteed to be destroyed with Current() pointing to the task queue they + // were posted to, whether they're executed or not. That means SequenceChecker + // works during task destruction, a fact that can be used to guarantee + // thread-compatible object deletion happening on a particular task queue + // which can simplify class design. + // Note that this guarantee does not apply to delayed tasks. + // + // May be called on any thread or task queue, including this task queue. + virtual void PostTask(absl::AnyInvocable<void() &&> task) = 0; + + // Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever + // possible. + // + // Schedules a `task` to execute a specified `delay` from when the call is + // made, using "low" precision. All scheduling is affected by OS-specific + // leeway and current workloads which means that in terms of precision there + // are no hard guarantees, but in addition to the OS induced leeway, "low" + // precision adds up to a 17 ms additional leeway. The purpose of this leeway + // is to achieve more efficient CPU scheduling and reduce Idle Wake Up + // frequency. + // + // The task may execute with [-1, 17 + OS induced leeway) ms additional delay. + // + // Avoid making assumptions about the precision of the OS scheduler. On macOS, + // the OS induced leeway may be 10% of sleep interval. On Windows, 1 ms + // precision timers may be used but there are cases, such as when running on + // battery, when the timer precision can be as poor as 15 ms. + // + // "Low" precision is not implemented everywhere yet. Where not yet + // implemented, PostDelayedTask() has "high" precision. See + // https://crbug.com/webrtc/13583 for more information. + // + // May be called on any thread or task queue, including this task queue. + virtual void PostDelayedTask(absl::AnyInvocable<void() &&> task, + TimeDelta delay) = 0; + + // Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever + // possible. + // + // Schedules a `task` to execute a specified `delay` from when the call is + // made, using "high" precision. All scheduling is affected by OS-specific + // leeway and current workloads which means that in terms of precision there + // are no hard guarantees. + // + // The task may execute with [-1, OS induced leeway] ms additional delay. + // + // Avoid making assumptions about the precision of the OS scheduler. On macOS, + // the OS induced leeway may be 10% of sleep interval. On Windows, 1 ms + // precision timers may be used but there are cases, such as when running on + // battery, when the timer precision can be as poor as 15 ms. + // + // May be called on any thread or task queue, including this task queue. + virtual void PostDelayedHighPrecisionTask(absl::AnyInvocable<void() &&> task, + TimeDelta delay) = 0; + + // As specified by `precision`, calls either PostDelayedTask() or + // PostDelayedHighPrecisionTask(). + void PostDelayedTaskWithPrecision(DelayPrecision precision, + absl::AnyInvocable<void() &&> task, + TimeDelta delay) { + switch (precision) { + case DelayPrecision::kLow: + PostDelayedTask(std::move(task), delay); + break; + case DelayPrecision::kHigh: + PostDelayedHighPrecisionTask(std::move(task), delay); + break; + } + } + + // Returns the task queue that is running the current thread. + // Returns nullptr if this thread is not associated with any task queue. + // May be called on any thread or task queue, including this task queue. + static TaskQueueBase* Current(); + bool IsCurrent() const { return Current() == this; } + + protected: + class RTC_EXPORT CurrentTaskQueueSetter { + public: + explicit CurrentTaskQueueSetter(TaskQueueBase* task_queue); + CurrentTaskQueueSetter(const CurrentTaskQueueSetter&) = delete; + CurrentTaskQueueSetter& operator=(const CurrentTaskQueueSetter&) = delete; + ~CurrentTaskQueueSetter(); + + private: + TaskQueueBase* const previous_; + }; + + // Users of the TaskQueue should call Delete instead of directly deleting + // this object. + virtual ~TaskQueueBase() = default; +}; + +struct TaskQueueDeleter { + void operator()(TaskQueueBase* task_queue) const { task_queue->Delete(); } +}; + +} // namespace webrtc + +#endif // API_TASK_QUEUE_TASK_QUEUE_BASE_H_ diff --git a/third_party/libwebrtc/api/task_queue/task_queue_factory.h b/third_party/libwebrtc/api/task_queue/task_queue_factory.h new file mode 100644 index 0000000000..b68ab33f69 --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/task_queue_factory.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 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 API_TASK_QUEUE_TASK_QUEUE_FACTORY_H_ +#define API_TASK_QUEUE_TASK_QUEUE_FACTORY_H_ + +#include <memory> + +#include "absl/strings/string_view.h" +#include "api/task_queue/task_queue_base.h" + +namespace webrtc { + +// The implementation of this interface must be thread-safe. +class TaskQueueFactory { + public: + // TaskQueue priority levels. On some platforms these will map to thread + // priorities, on others such as Mac and iOS, GCD queue priorities. + enum class Priority { NORMAL = 0, HIGH, LOW }; + + virtual ~TaskQueueFactory() = default; + virtual std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue( + absl::string_view name, + Priority priority) const = 0; +}; + +} // namespace webrtc + +#endif // API_TASK_QUEUE_TASK_QUEUE_FACTORY_H_ diff --git a/third_party/libwebrtc/api/task_queue/task_queue_gn/moz.build b/third_party/libwebrtc/api/task_queue/task_queue_gn/moz.build new file mode 100644 index 0000000000..c4d9c9d67d --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/task_queue_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/task_queue/task_queue_base.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("task_queue_gn") diff --git a/third_party/libwebrtc/api/task_queue/task_queue_test.cc b/third_party/libwebrtc/api/task_queue/task_queue_test.cc new file mode 100644 index 0000000000..7849f4273d --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/task_queue_test.cc @@ -0,0 +1,333 @@ +/* + * Copyright 2019 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 "api/task_queue/task_queue_test.h" + +#include <memory> + +#include "absl/cleanup/cleanup.h" +#include "absl/strings/string_view.h" +#include "api/task_queue/task_queue_base.h" +#include "api/units/time_delta.h" +#include "rtc_base/event.h" +#include "rtc_base/ref_counter.h" +#include "rtc_base/time_utils.h" + +namespace webrtc { +namespace { + +// Avoids a dependency to system_wrappers. +void SleepFor(TimeDelta duration) { + rtc::ScopedAllowBaseSyncPrimitivesForTesting allow; + rtc::Event event; + event.Wait(duration); +} + +std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue( + const std::unique_ptr<webrtc::TaskQueueFactory>& factory, + absl::string_view task_queue_name, + TaskQueueFactory::Priority priority = TaskQueueFactory::Priority::NORMAL) { + return factory->CreateTaskQueue(task_queue_name, priority); +} + +TEST_P(TaskQueueTest, Construct) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + auto queue = CreateTaskQueue(factory, "Construct"); + EXPECT_FALSE(queue->IsCurrent()); +} + +TEST_P(TaskQueueTest, PostAndCheckCurrent) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + rtc::Event event; + auto queue = CreateTaskQueue(factory, "PostAndCheckCurrent"); + + // We're not running a task, so `queue` shouldn't be current. + // Note that because rtc::Thread also supports the TQ interface and + // TestMainImpl::Init wraps the main test thread (bugs.webrtc.org/9714), that + // means that TaskQueueBase::Current() will still return a valid value. + EXPECT_FALSE(queue->IsCurrent()); + + queue->PostTask([&event, &queue] { + EXPECT_TRUE(queue->IsCurrent()); + event.Set(); + }); + EXPECT_TRUE(event.Wait(TimeDelta::Seconds(1))); +} + +TEST_P(TaskQueueTest, PostCustomTask) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + rtc::Event ran; + auto queue = CreateTaskQueue(factory, "PostCustomImplementation"); + + class CustomTask { + public: + explicit CustomTask(rtc::Event* ran) : ran_(ran) {} + + void operator()() { ran_->Set(); } + + private: + rtc::Event* const ran_; + } my_task(&ran); + + queue->PostTask(my_task); + EXPECT_TRUE(ran.Wait(TimeDelta::Seconds(1))); +} + +TEST_P(TaskQueueTest, PostDelayedZero) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + rtc::Event event; + auto queue = CreateTaskQueue(factory, "PostDelayedZero"); + + queue->PostDelayedTask([&event] { event.Set(); }, TimeDelta::Zero()); + EXPECT_TRUE(event.Wait(TimeDelta::Seconds(1))); +} + +TEST_P(TaskQueueTest, PostFromQueue) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + rtc::Event event; + auto queue = CreateTaskQueue(factory, "PostFromQueue"); + + queue->PostTask( + [&event, &queue] { queue->PostTask([&event] { event.Set(); }); }); + EXPECT_TRUE(event.Wait(TimeDelta::Seconds(1))); +} + +TEST_P(TaskQueueTest, PostDelayed) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + rtc::Event event; + auto queue = + CreateTaskQueue(factory, "PostDelayed", TaskQueueFactory::Priority::HIGH); + + int64_t start = rtc::TimeMillis(); + queue->PostDelayedTask( + [&event, &queue] { + EXPECT_TRUE(queue->IsCurrent()); + event.Set(); + }, + TimeDelta::Millis(100)); + EXPECT_TRUE(event.Wait(TimeDelta::Seconds(1))); + int64_t end = rtc::TimeMillis(); + // These tests are a little relaxed due to how "powerful" our test bots can + // be. Most recently we've seen windows bots fire the callback after 94-99ms, + // which is why we have a little bit of leeway backwards as well. + EXPECT_GE(end - start, 90u); + EXPECT_NEAR(end - start, 190u, 100u); // Accept 90-290. +} + +TEST_P(TaskQueueTest, PostMultipleDelayed) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + auto queue = CreateTaskQueue(factory, "PostMultipleDelayed"); + + std::vector<rtc::Event> events(100); + for (int i = 0; i < 100; ++i) { + rtc::Event* event = &events[i]; + queue->PostDelayedTask( + [event, &queue] { + EXPECT_TRUE(queue->IsCurrent()); + event->Set(); + }, + TimeDelta::Millis(i)); + } + + for (rtc::Event& e : events) + EXPECT_TRUE(e.Wait(TimeDelta::Seconds(1))); +} + +TEST_P(TaskQueueTest, PostDelayedAfterDestruct) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + rtc::Event run; + rtc::Event deleted; + auto queue = CreateTaskQueue(factory, "PostDelayedAfterDestruct"); + absl::Cleanup cleanup = [&deleted] { deleted.Set(); }; + queue->PostDelayedTask([&run, cleanup = std::move(cleanup)] { run.Set(); }, + TimeDelta::Millis(100)); + // Destroy the queue. + queue = nullptr; + // Task might outlive the TaskQueue, but still should be deleted. + EXPECT_TRUE(deleted.Wait(TimeDelta::Seconds(1))); + EXPECT_FALSE(run.Wait(TimeDelta::Zero())); // and should not run. +} + +TEST_P(TaskQueueTest, PostDelayedHighPrecisionAfterDestruct) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + rtc::Event run; + rtc::Event deleted; + auto queue = + CreateTaskQueue(factory, "PostDelayedHighPrecisionAfterDestruct"); + absl::Cleanup cleanup = [&deleted] { deleted.Set(); }; + queue->PostDelayedHighPrecisionTask( + [&run, cleanup = std::move(cleanup)] { run.Set(); }, + TimeDelta::Millis(100)); + // Destroy the queue. + queue = nullptr; + // Task might outlive the TaskQueue, but still should be deleted. + EXPECT_TRUE(deleted.Wait(TimeDelta::Seconds(1))); + EXPECT_FALSE(run.Wait(TimeDelta::Zero())); // and should not run. +} + +TEST_P(TaskQueueTest, PostedUnexecutedClosureDestroyedOnTaskQueue) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + auto queue = + CreateTaskQueue(factory, "PostedUnexecutedClosureDestroyedOnTaskQueue"); + TaskQueueBase* queue_ptr = queue.get(); + queue->PostTask([] { SleepFor(TimeDelta::Millis(100)); }); + // Give the task queue a chance to start executing the first lambda. + SleepFor(TimeDelta::Millis(10)); + // Then ensure the next lambda (which is likely not executing yet) is + // destroyed in the task queue context when the queue is deleted. + auto cleanup = absl::Cleanup( + [queue_ptr] { EXPECT_EQ(queue_ptr, TaskQueueBase::Current()); }); + queue->PostTask([cleanup = std::move(cleanup)] {}); + queue = nullptr; +} + +TEST_P(TaskQueueTest, PostedExecutedClosureDestroyedOnTaskQueue) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + auto queue = + CreateTaskQueue(factory, "PostedExecutedClosureDestroyedOnTaskQueue"); + TaskQueueBase* queue_ptr = queue.get(); + // Ensure an executed lambda is destroyed on the task queue. + rtc::Event finished; + queue->PostTask([cleanup = absl::Cleanup([queue_ptr, &finished] { + EXPECT_EQ(queue_ptr, TaskQueueBase::Current()); + finished.Set(); + })] {}); + finished.Wait(rtc::Event::kForever); +} + +TEST_P(TaskQueueTest, PostAndReuse) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + rtc::Event event; + auto post_queue = CreateTaskQueue(factory, "PostQueue"); + auto reply_queue = CreateTaskQueue(factory, "ReplyQueue"); + + int call_count = 0; + + class ReusedTask { + public: + ReusedTask(int* counter, TaskQueueBase* reply_queue, rtc::Event* event) + : counter_(*counter), reply_queue_(reply_queue), event_(*event) { + EXPECT_EQ(counter_, 0); + } + ReusedTask(ReusedTask&&) = default; + ReusedTask& operator=(ReusedTask&&) = delete; + + void operator()() && { + if (++counter_ == 1) { + reply_queue_->PostTask(std::move(*this)); + // At this point, the object is in the moved-from state. + } else { + EXPECT_EQ(counter_, 2); + EXPECT_TRUE(reply_queue_->IsCurrent()); + event_.Set(); + } + } + + private: + int& counter_; + TaskQueueBase* const reply_queue_; + rtc::Event& event_; + }; + + ReusedTask task(&call_count, reply_queue.get(), &event); + post_queue->PostTask(std::move(task)); + EXPECT_TRUE(event.Wait(TimeDelta::Seconds(1))); +} + +TEST_P(TaskQueueTest, PostALot) { + // Waits until DecrementCount called `count` times. Thread safe. + class BlockingCounter { + public: + explicit BlockingCounter(int initial_count) : count_(initial_count) {} + + void DecrementCount() { + if (count_.DecRef() == rtc::RefCountReleaseStatus::kDroppedLastRef) { + event_.Set(); + } + } + bool Wait(TimeDelta give_up_after) { return event_.Wait(give_up_after); } + + private: + webrtc_impl::RefCounter count_; + rtc::Event event_; + }; + + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + static constexpr int kTaskCount = 0xffff; + rtc::Event posting_done; + BlockingCounter all_destroyed(kTaskCount); + + int tasks_executed = 0; + auto task_queue = CreateTaskQueue(factory, "PostALot"); + + task_queue->PostTask([&] { + // Post tasks from the queue to guarantee that the 1st task won't be + // executed before the last one is posted. + for (int i = 0; i < kTaskCount; ++i) { + absl::Cleanup cleanup = [&] { all_destroyed.DecrementCount(); }; + task_queue->PostTask([&tasks_executed, cleanup = std::move(cleanup)] { + ++tasks_executed; + }); + } + + posting_done.Set(); + }); + + // Before destroying the task queue wait until all child tasks are posted. + posting_done.Wait(rtc::Event::kForever); + // Destroy the task queue. + task_queue = nullptr; + + // Expect all tasks are destroyed eventually. In some task queue + // implementations that might happen on a different thread after task queue is + // destroyed. + EXPECT_TRUE(all_destroyed.Wait(TimeDelta::Minutes(1))); + EXPECT_LE(tasks_executed, kTaskCount); +} + +// Test posting two tasks that have shared state not protected by a +// lock. The TaskQueue should guarantee memory read-write order and +// FIFO task execution order, so the second task should always see the +// changes that were made by the first task. +// +// If the TaskQueue doesn't properly synchronize the execution of +// tasks, there will be a data race, which is undefined behavior. The +// EXPECT calls may randomly catch this, but to make the most of this +// unit test, run it under TSan or some other tool that is able to +// directly detect data races. +TEST_P(TaskQueueTest, PostTwoWithSharedUnprotectedState) { + std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()(nullptr); + struct SharedState { + // First task will set this value to 1 and second will assert it. + int state = 0; + } state; + + auto queue = CreateTaskQueue(factory, "PostTwoWithSharedUnprotectedState"); + rtc::Event done; + queue->PostTask([&state, &queue, &done] { + // Post tasks from queue to guarantee, that 1st task won't be + // executed before the second one will be posted. + queue->PostTask([&state] { state.state = 1; }); + queue->PostTask([&state, &done] { + EXPECT_EQ(state.state, 1); + done.Set(); + }); + // Check, that state changing tasks didn't start yet. + EXPECT_EQ(state.state, 0); + }); + EXPECT_TRUE(done.Wait(TimeDelta::Seconds(1))); +} + +// TaskQueueTest is a set of tests for any implementation of the TaskQueueBase. +// Tests are instantiated next to the concrete implementation(s). +// https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#creating-value-parameterized-abstract-tests +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TaskQueueTest); + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/api/task_queue/task_queue_test.h b/third_party/libwebrtc/api/task_queue/task_queue_test.h new file mode 100644 index 0000000000..214f95008f --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/task_queue_test.h @@ -0,0 +1,41 @@ +/* + * Copyright 2019 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 API_TASK_QUEUE_TASK_QUEUE_TEST_H_ +#define API_TASK_QUEUE_TASK_QUEUE_TEST_H_ + +#include <functional> +#include <memory> + +#include "api/field_trials_view.h" +#include "api/task_queue/task_queue_factory.h" +#include "test/gtest.h" + +namespace webrtc { + +// Suite of tests to verify TaskQueue implementation with. +// Example usage: +// +// namespace { +// +// using ::testing::Values; +// using ::webrtc::TaskQueueTest; +// +// std::unique_ptr<webrtc::TaskQueueFactory> CreateMyFactory(); +// +// INSTANTIATE_TEST_SUITE_P(My, TaskQueueTest, Values(CreateMyFactory)); +// +// } // namespace +class TaskQueueTest + : public ::testing::TestWithParam<std::function< + std::unique_ptr<TaskQueueFactory>(const FieldTrialsView*)>> {}; + +} // namespace webrtc + +#endif // API_TASK_QUEUE_TASK_QUEUE_TEST_H_ diff --git a/third_party/libwebrtc/api/task_queue/test/BUILD.gn b/third_party/libwebrtc/api/task_queue/test/BUILD.gn new file mode 100644 index 0000000000..25f7ed0c7f --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/test/BUILD.gn @@ -0,0 +1,20 @@ +# 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. + +import("../../../webrtc.gni") + +rtc_library("mock_task_queue_base") { + testonly = true + sources = [ "mock_task_queue_base.h" ] + deps = [ + "../../../api/task_queue:task_queue", + "../../../api/units:time_delta", + "../../../test:test_support", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/functional:any_invocable" ] +} diff --git a/third_party/libwebrtc/api/task_queue/test/mock_task_queue_base.h b/third_party/libwebrtc/api/task_queue/test/mock_task_queue_base.h new file mode 100644 index 0000000000..2e99be7e82 --- /dev/null +++ b/third_party/libwebrtc/api/task_queue/test/mock_task_queue_base.h @@ -0,0 +1,37 @@ +/* + * Copyright 2022 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 API_TASK_QUEUE_TEST_MOCK_TASK_QUEUE_BASE_H_ +#define API_TASK_QUEUE_TEST_MOCK_TASK_QUEUE_BASE_H_ + +#include "absl/functional/any_invocable.h" +#include "api/task_queue/task_queue_base.h" +#include "api/units/time_delta.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockTaskQueueBase : public TaskQueueBase { + public: + MOCK_METHOD(void, Delete, (), (override)); + MOCK_METHOD(void, PostTask, (absl::AnyInvocable<void() &&>), (override)); + MOCK_METHOD(void, + PostDelayedTask, + (absl::AnyInvocable<void() &&>, TimeDelta), + (override)); + MOCK_METHOD(void, + PostDelayedHighPrecisionTask, + (absl::AnyInvocable<void() &&>, TimeDelta), + (override)); +}; + +} // namespace webrtc + +#endif // API_TASK_QUEUE_TEST_MOCK_TASK_QUEUE_BASE_H_ diff --git a/third_party/libwebrtc/api/test/DEPS b/third_party/libwebrtc/api/test/DEPS new file mode 100644 index 0000000000..270b274c5f --- /dev/null +++ b/third_party/libwebrtc/api/test/DEPS @@ -0,0 +1,39 @@ +specific_include_rules = { + ".*": [ + "+modules/video_coding", + ], + ".*": [ + "+video" + ], + "dummy_peer_connection\.h": [ + "+rtc_base/ref_counted_object.h", + ], + "neteq_factory_with_codecs\.h": [ + "+system_wrappers/include/clock.h", + ], + "network_emulation_manager\.h": [ + "+rtc_base/thread.h", + "+rtc_base/network.h", + "+rtc_base/network_constants.h", + ], + "peer_network_dependencies\.h": [ + "+rtc_base/network.h", + "+rtc_base/thread.h", + ], + "peerconnection_quality_test_fixture\.h": [ + "+logging/rtc_event_log/rtc_event_log_factory_interface.h", + "+rtc_base/network.h", + "+rtc_base/rtc_certificate_generator.h", + "+rtc_base/ssl_certificate.h", + "+rtc_base/thread.h", + "+media/base/media_constants.h", + "+modules/audio_processing/include/audio_processing.h", + ], + "time_controller\.h": [ + "+rtc_base/synchronization/yield_policy.h", + "+system_wrappers/include/clock.h", + ], + "create_frame_generator\.h": [ + "+system_wrappers/include/clock.h", + ], +} diff --git a/third_party/libwebrtc/api/test/OWNERS b/third_party/libwebrtc/api/test/OWNERS new file mode 100644 index 0000000000..a7392abe31 --- /dev/null +++ b/third_party/libwebrtc/api/test/OWNERS @@ -0,0 +1,5 @@ +mbonadei@webrtc.org +sprang@webrtc.org +srte@webrtc.org +titovartem@webrtc.org + diff --git a/third_party/libwebrtc/api/test/audio_quality_analyzer_interface.h b/third_party/libwebrtc/api/test/audio_quality_analyzer_interface.h new file mode 100644 index 0000000000..2eb7817445 --- /dev/null +++ b/third_party/libwebrtc/api/test/audio_quality_analyzer_interface.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef API_TEST_AUDIO_QUALITY_ANALYZER_INTERFACE_H_ +#define API_TEST_AUDIO_QUALITY_ANALYZER_INTERFACE_H_ + +#include <string> + +#include "api/test/stats_observer_interface.h" +#include "api/test/track_id_stream_info_map.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +// API is in development. Can be changed/removed without notice. +class AudioQualityAnalyzerInterface : public StatsObserverInterface { + public: + ~AudioQualityAnalyzerInterface() override = default; + + // Will be called by the framework before the test. + // `test_case_name` is name of test case, that should be used to report all + // audio metrics. + // `analyzer_helper` is a pointer to a class that will allow track_id to + // stream_id matching. The caller is responsible for ensuring the + // AnalyzerHelper outlives the instance of the AudioQualityAnalyzerInterface. + virtual void Start(std::string test_case_name, + TrackIdStreamInfoMap* analyzer_helper) = 0; + + // Will be called by the framework at the end of the test. The analyzer + // has to finalize all its stats and it should report them. + virtual void Stop() = 0; +}; + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // API_TEST_AUDIO_QUALITY_ANALYZER_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/test/audioproc_float.cc b/third_party/libwebrtc/api/test/audioproc_float.cc new file mode 100644 index 0000000000..c8d7ff7193 --- /dev/null +++ b/third_party/libwebrtc/api/test/audioproc_float.cc @@ -0,0 +1,44 @@ +/* + * 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 "api/test/audioproc_float.h" + +#include <utility> + +#include "modules/audio_processing/test/audioproc_float_impl.h" + +namespace webrtc { +namespace test { + +int AudioprocFloat(rtc::scoped_refptr<AudioProcessing> audio_processing, + int argc, + char* argv[]) { + return AudioprocFloatImpl(std::move(audio_processing), argc, argv); +} + +int AudioprocFloat(std::unique_ptr<AudioProcessingBuilder> ap_builder, + int argc, + char* argv[]) { + return AudioprocFloatImpl(std::move(ap_builder), argc, argv, + /*input_aecdump=*/"", + /*processed_capture_samples=*/nullptr); +} + +int AudioprocFloat(std::unique_ptr<AudioProcessingBuilder> ap_builder, + int argc, + char* argv[], + absl::string_view input_aecdump, + std::vector<float>* processed_capture_samples) { + return AudioprocFloatImpl(std::move(ap_builder), argc, argv, input_aecdump, + processed_capture_samples); +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/audioproc_float.h b/third_party/libwebrtc/api/test/audioproc_float.h new file mode 100644 index 0000000000..1ef1c9828f --- /dev/null +++ b/third_party/libwebrtc/api/test/audioproc_float.h @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#ifndef API_TEST_AUDIOPROC_FLOAT_H_ +#define API_TEST_AUDIOPROC_FLOAT_H_ + +#include <memory> +#include <vector> + +#include "modules/audio_processing/include/audio_processing.h" + +namespace webrtc { +namespace test { + +// This is an interface for the audio processing simulation utility. This +// utility can be used to simulate the audioprocessing module using a recording +// (either an AEC dump or wav files), and generate the output as a wav file. +// Any audio_processing object specified in the input is used for the +// simulation. The optional `audio_processing` object provides the +// AudioProcessing instance that is used during the simulation. Note that when +// the audio_processing object is specified all functionality that relies on +// using the AudioProcessingBuilder is deactivated, since the AudioProcessing +// object is already created and the builder is not used in the simulation. It +// is needed to pass the command line flags as `argc` and `argv`, so these can +// be interpreted properly by the utility. To see a list of all supported +// command line flags, run the executable with the '--help' flag. +int AudioprocFloat(rtc::scoped_refptr<AudioProcessing> audio_processing, + int argc, + char* argv[]); + +// This is an interface for the audio processing simulation utility. This +// utility can be used to simulate the audioprocessing module using a recording +// (either an AEC dump or wav files), and generate the output as a wav file. +// The `ap_builder` object will be used to create the AudioProcessing instance +// that is used during the simulation. The `ap_builder` supports setting of +// injectable components, which will be passed on to the created AudioProcessing +// instance. It is needed to pass the command line flags as `argc` and `argv`, +// so these can be interpreted properly by the utility. +// To get a fully-working audioproc_f utility, all that is needed is to write a +// main function, create an AudioProcessingBuilder, optionally set custom +// processing components on it, and pass the builder together with the command +// line arguments into this function. +// To see a list of all supported command line flags, run the executable with +// the '--help' flag. +int AudioprocFloat(std::unique_ptr<AudioProcessingBuilder> ap_builder, + int argc, + char* argv[]); + +// Interface for the audio processing simulation utility, which is similar to +// the one above, but which adds the option of receiving the input as a string +// and returning the output as an array. The first three arguments fulfill the +// same purpose as above. Pass the `input_aecdump` to provide the content of an +// AEC dump file as a string. After the simulation is completed, +// `processed_capture_samples` will contain the the samples processed on the +// capture side. +int AudioprocFloat(std::unique_ptr<AudioProcessingBuilder> ap_builder, + int argc, + char* argv[], + absl::string_view input_aecdump, + std::vector<float>* processed_capture_samples); +} // namespace test +} // namespace webrtc + +#endif // API_TEST_AUDIOPROC_FLOAT_H_ diff --git a/third_party/libwebrtc/api/test/compile_all_headers.cc b/third_party/libwebrtc/api/test/compile_all_headers.cc new file mode 100644 index 0000000000..1fcf63e97b --- /dev/null +++ b/third_party/libwebrtc/api/test/compile_all_headers.cc @@ -0,0 +1,53 @@ +/* + * Copyright 2019 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 file verifies that all include files in this directory can be +// compiled without errors or other required includes. + +// Note: The following header files are not not tested here, as their +// associated targets are not included in all configurations. +// "api/test/audioproc_float.h" +// "api/test/create_video_quality_test_fixture.h" +// "api/test/neteq_simulator_factory.h" +// "api/test/video_quality_test_fixture.h" +// The following header files are also not tested: +// "api/test/create_simulcast_test_fixture.h" +// "api/test/create_videocodec_test_fixture.h" +// "api/test/neteq_simulator.h" +// "api/test/simulated_network.h" +// "api/test/simulcast_test_fixture.h" +// "api/test/test_dependency_factory.h" +// "api/test/videocodec_test_fixture.h" +// "api/test/videocodec_test_stats.h" + +#include "api/test/fake_frame_decryptor.h" +#include "api/test/fake_frame_encryptor.h" +#include "api/test/mock_async_dns_resolver.h" +#include "api/test/mock_audio_mixer.h" +#include "api/test/mock_audio_sink.h" +#include "api/test/mock_data_channel.h" +#include "api/test/mock_dtmf_sender.h" +#include "api/test/mock_frame_decryptor.h" +#include "api/test/mock_frame_encryptor.h" +#include "api/test/mock_media_stream_interface.h" +#include "api/test/mock_peer_connection_factory_interface.h" +#include "api/test/mock_peerconnectioninterface.h" +#include "api/test/mock_rtp_transceiver.h" +#include "api/test/mock_rtpreceiver.h" +#include "api/test/mock_rtpsender.h" +#include "api/test/mock_session_description_interface.h" +#include "api/test/mock_transformable_video_frame.h" +#include "api/test/mock_video_bitrate_allocator.h" +#include "api/test/mock_video_bitrate_allocator_factory.h" +#include "api/test/mock_video_decoder.h" +#include "api/test/mock_video_decoder_factory.h" +#include "api/test/mock_video_encoder.h" +#include "api/test/mock_video_encoder_factory.h" +#include "api/test/mock_video_track.h" diff --git a/third_party/libwebrtc/api/test/create_frame_generator.cc b/third_party/libwebrtc/api/test/create_frame_generator.cc new file mode 100644 index 0000000000..5e6fb3228b --- /dev/null +++ b/third_party/libwebrtc/api/test/create_frame_generator.cc @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2019 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 "api/test/create_frame_generator.h" + +#include <cstdio> +#include <utility> + +#include "rtc_base/checks.h" +#include "test/frame_generator.h" +#include "test/testsupport/ivf_video_frame_generator.h" + +namespace webrtc { +namespace test { + +std::unique_ptr<FrameGeneratorInterface> CreateSquareFrameGenerator( + int width, + int height, + absl::optional<FrameGeneratorInterface::OutputType> type, + absl::optional<int> num_squares) { + return std::make_unique<SquareGenerator>( + width, height, type.value_or(FrameGeneratorInterface::OutputType::kI420), + num_squares.value_or(10)); +} + +std::unique_ptr<FrameGeneratorInterface> CreateFromYuvFileFrameGenerator( + std::vector<std::string> filenames, + size_t width, + size_t height, + int frame_repeat_count) { + RTC_DCHECK(!filenames.empty()); + std::vector<FILE*> files; + for (const std::string& filename : filenames) { + FILE* file = fopen(filename.c_str(), "rb"); + RTC_DCHECK(file != nullptr) << "Failed to open: '" << filename << "'\n"; + files.push_back(file); + } + + return std::make_unique<YuvFileGenerator>(files, width, height, + frame_repeat_count); +} + +std::unique_ptr<FrameGeneratorInterface> CreateFromNV12FileFrameGenerator( + std::vector<std::string> filenames, + size_t width, + size_t height, + int frame_repeat_count) { + RTC_DCHECK(!filenames.empty()); + std::vector<FILE*> files; + for (const std::string& filename : filenames) { + FILE* file = fopen(filename.c_str(), "rb"); + RTC_DCHECK(file != nullptr) << "Failed to open: '" << filename << "'\n"; + files.push_back(file); + } + + return std::make_unique<NV12FileGenerator>(files, width, height, + frame_repeat_count); +} + +std::unique_ptr<FrameGeneratorInterface> CreateFromIvfFileFrameGenerator( + std::string filename) { + return std::make_unique<IvfVideoFrameGenerator>(std::move(filename)); +} + +std::unique_ptr<FrameGeneratorInterface> +CreateScrollingInputFromYuvFilesFrameGenerator( + Clock* clock, + std::vector<std::string> filenames, + size_t source_width, + size_t source_height, + size_t target_width, + size_t target_height, + int64_t scroll_time_ms, + int64_t pause_time_ms) { + RTC_DCHECK(!filenames.empty()); + std::vector<FILE*> files; + for (const std::string& filename : filenames) { + FILE* file = fopen(filename.c_str(), "rb"); + RTC_DCHECK(file != nullptr); + files.push_back(file); + } + + return std::make_unique<ScrollingImageFrameGenerator>( + clock, files, source_width, source_height, target_width, target_height, + scroll_time_ms, pause_time_ms); +} + +std::unique_ptr<FrameGeneratorInterface> +CreateSlideFrameGenerator(int width, int height, int frame_repeat_count) { + return std::make_unique<SlideGenerator>(width, height, frame_repeat_count); +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/create_frame_generator.h b/third_party/libwebrtc/api/test/create_frame_generator.h new file mode 100644 index 0000000000..70be0c4e8e --- /dev/null +++ b/third_party/libwebrtc/api/test/create_frame_generator.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2019 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 API_TEST_CREATE_FRAME_GENERATOR_H_ +#define API_TEST_CREATE_FRAME_GENERATOR_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/test/frame_generator_interface.h" +#include "system_wrappers/include/clock.h" + +namespace webrtc { +namespace test { + +// Creates a frame generator that produces frames with small squares that +// move randomly towards the lower right corner. +// `type` has the default value FrameGeneratorInterface::OutputType::I420. +// `num_squares` has the default value 10. +std::unique_ptr<FrameGeneratorInterface> CreateSquareFrameGenerator( + int width, + int height, + absl::optional<FrameGeneratorInterface::OutputType> type, + absl::optional<int> num_squares); + +// Creates a frame generator that repeatedly plays a set of yuv files. +// The frame_repeat_count determines how many times each frame is shown, +// with 1 = show each frame once, etc. +std::unique_ptr<FrameGeneratorInterface> CreateFromYuvFileFrameGenerator( + std::vector<std::string> filenames, + size_t width, + size_t height, + int frame_repeat_count); + +// Creates a frame generator that repeatedly plays a set of nv12 files. +// The frame_repeat_count determines how many times each frame is shown, +// with 1 = show each frame once, etc. +std::unique_ptr<FrameGeneratorInterface> CreateFromNV12FileFrameGenerator( + std::vector<std::string> filenames, + size_t width, + size_t height, + int frame_repeat_count = 1); + +// Creates a frame generator that repeatedly plays an ivf file. +std::unique_ptr<FrameGeneratorInterface> CreateFromIvfFileFrameGenerator( + std::string filename); + +// Creates a frame generator which takes a set of yuv files (wrapping a +// frame generator created by CreateFromYuvFile() above), but outputs frames +// that have been cropped to specified resolution: source_width/source_height +// is the size of the source images, target_width/target_height is the size of +// the cropped output. For each source image read, the cropped viewport will +// be scrolled top to bottom/left to right for scroll_tim_ms milliseconds. +// After that the image will stay in place for pause_time_ms milliseconds, +// and then this will be repeated with the next file from the input set. +std::unique_ptr<FrameGeneratorInterface> +CreateScrollingInputFromYuvFilesFrameGenerator( + Clock* clock, + std::vector<std::string> filenames, + size_t source_width, + size_t source_height, + size_t target_width, + size_t target_height, + int64_t scroll_time_ms, + int64_t pause_time_ms); + +// Creates a frame generator that produces randomly generated slides. It fills +// the frames with randomly sized and colored squares. +// `frame_repeat_count` determines how many times each slide is shown. +std::unique_ptr<FrameGeneratorInterface> +CreateSlideFrameGenerator(int width, int height, int frame_repeat_count); + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_CREATE_FRAME_GENERATOR_H_ diff --git a/third_party/libwebrtc/api/test/create_network_emulation_manager.cc b/third_party/libwebrtc/api/test/create_network_emulation_manager.cc new file mode 100644 index 0000000000..f5d5a1bc88 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_network_emulation_manager.cc @@ -0,0 +1,27 @@ + +/* + * Copyright (c) 2019 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 "api/test/create_network_emulation_manager.h" + +#include <memory> + +#include "test/network/network_emulation_manager.h" + +namespace webrtc { + +std::unique_ptr<NetworkEmulationManager> CreateNetworkEmulationManager( + TimeMode time_mode, + EmulatedNetworkStatsGatheringMode stats_gathering_mode) { + return std::make_unique<test::NetworkEmulationManagerImpl>( + time_mode, stats_gathering_mode); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/create_network_emulation_manager.h b/third_party/libwebrtc/api/test/create_network_emulation_manager.h new file mode 100644 index 0000000000..941b2b1c52 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_network_emulation_manager.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019 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 API_TEST_CREATE_NETWORK_EMULATION_MANAGER_H_ +#define API_TEST_CREATE_NETWORK_EMULATION_MANAGER_H_ + +#include <memory> + +#include "api/test/network_emulation_manager.h" + +namespace webrtc { + +// Returns a non-null NetworkEmulationManager instance. +std::unique_ptr<NetworkEmulationManager> CreateNetworkEmulationManager( + TimeMode time_mode = TimeMode::kRealTime, + EmulatedNetworkStatsGatheringMode stats_gathering_mode = + EmulatedNetworkStatsGatheringMode::kDefault); + +} // namespace webrtc + +#endif // API_TEST_CREATE_NETWORK_EMULATION_MANAGER_H_ diff --git a/third_party/libwebrtc/api/test/create_peer_connection_quality_test_frame_generator.cc b/third_party/libwebrtc/api/test/create_peer_connection_quality_test_frame_generator.cc new file mode 100644 index 0000000000..a1c53635f9 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_peer_connection_quality_test_frame_generator.cc @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2020 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 "api/test/create_peer_connection_quality_test_frame_generator.h" + +#include <utility> +#include <vector> + +#include "api/test/create_frame_generator.h" +#include "api/test/pclf/media_configuration.h" +#include "rtc_base/checks.h" +#include "test/testsupport/file_utils.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +void ValidateScreenShareConfig(const VideoConfig& video_config, + const ScreenShareConfig& screen_share_config) { + if (screen_share_config.slides_yuv_file_names.empty()) { + if (screen_share_config.scrolling_params) { + // If we have scrolling params, then its `source_width` and `source_heigh` + // will be used as width and height of video input, so we have to validate + // it against width and height of default input. + RTC_CHECK_EQ(screen_share_config.scrolling_params->source_width, + kDefaultSlidesWidth); + RTC_CHECK_EQ(screen_share_config.scrolling_params->source_height, + kDefaultSlidesHeight); + } else { + RTC_CHECK_EQ(video_config.width, kDefaultSlidesWidth); + RTC_CHECK_EQ(video_config.height, kDefaultSlidesHeight); + } + } + if (screen_share_config.scrolling_params) { + RTC_CHECK_LE(screen_share_config.scrolling_params->duration, + screen_share_config.slide_change_interval); + RTC_CHECK_GE(screen_share_config.scrolling_params->source_width, + video_config.width); + RTC_CHECK_GE(screen_share_config.scrolling_params->source_height, + video_config.height); + } +} + +std::unique_ptr<test::FrameGeneratorInterface> CreateSquareFrameGenerator( + const VideoConfig& video_config, + absl::optional<test::FrameGeneratorInterface::OutputType> type) { + return test::CreateSquareFrameGenerator( + video_config.width, video_config.height, std::move(type), absl::nullopt); +} + +std::unique_ptr<test::FrameGeneratorInterface> CreateFromYuvFileFrameGenerator( + const VideoConfig& video_config, + std::string filename) { + return test::CreateFromYuvFileFrameGenerator( + {std::move(filename)}, video_config.width, video_config.height, + /*frame_repeat_count=*/1); +} + +std::unique_ptr<test::FrameGeneratorInterface> CreateScreenShareFrameGenerator( + const VideoConfig& video_config, + const ScreenShareConfig& screen_share_config) { + ValidateScreenShareConfig(video_config, screen_share_config); + if (screen_share_config.generate_slides) { + return test::CreateSlideFrameGenerator( + video_config.width, video_config.height, + screen_share_config.slide_change_interval.seconds() * video_config.fps); + } + std::vector<std::string> slides = screen_share_config.slides_yuv_file_names; + if (slides.empty()) { + // If slides is empty we need to add default slides as source. In such case + // video width and height is validated to be equal to kDefaultSlidesWidth + // and kDefaultSlidesHeight. + slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv")); + slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv")); + slides.push_back(test::ResourcePath("photo_1850_1110", "yuv")); + slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv")); + } + if (!screen_share_config.scrolling_params) { + // Cycle image every slide_change_interval seconds. + return test::CreateFromYuvFileFrameGenerator( + slides, video_config.width, video_config.height, + screen_share_config.slide_change_interval.seconds() * video_config.fps); + } + + TimeDelta pause_duration = screen_share_config.slide_change_interval - + screen_share_config.scrolling_params->duration; + RTC_DCHECK(pause_duration >= TimeDelta::Zero()); + return test::CreateScrollingInputFromYuvFilesFrameGenerator( + Clock::GetRealTimeClock(), slides, + screen_share_config.scrolling_params->source_width, + screen_share_config.scrolling_params->source_height, video_config.width, + video_config.height, screen_share_config.scrolling_params->duration.ms(), + pause_duration.ms()); +} + +} // namespace webrtc_pc_e2e +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/create_peer_connection_quality_test_frame_generator.h b/third_party/libwebrtc/api/test/create_peer_connection_quality_test_frame_generator.h new file mode 100644 index 0000000000..62043d140a --- /dev/null +++ b/third_party/libwebrtc/api/test/create_peer_connection_quality_test_frame_generator.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020 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 API_TEST_CREATE_PEER_CONNECTION_QUALITY_TEST_FRAME_GENERATOR_H_ +#define API_TEST_CREATE_PEER_CONNECTION_QUALITY_TEST_FRAME_GENERATOR_H_ + +#include <memory> +#include <string> + +#include "absl/types/optional.h" +#include "api/test/frame_generator_interface.h" +#include "api/test/pclf/media_configuration.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +// Creates a frame generator that produces frames with small squares that move +// randomly towards the lower right corner. `type` has the default value +// FrameGeneratorInterface::OutputType::I420. video_config specifies frame +// weight and height. +std::unique_ptr<test::FrameGeneratorInterface> CreateSquareFrameGenerator( + const VideoConfig& video_config, + absl::optional<test::FrameGeneratorInterface::OutputType> type); + +// Creates a frame generator that plays frames from the yuv file. +std::unique_ptr<test::FrameGeneratorInterface> CreateFromYuvFileFrameGenerator( + const VideoConfig& video_config, + std::string filename); + +// Creates a proper frame generator for testing screen sharing. +std::unique_ptr<test::FrameGeneratorInterface> CreateScreenShareFrameGenerator( + const VideoConfig& video_config, + const ScreenShareConfig& screen_share_config); + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // API_TEST_CREATE_PEER_CONNECTION_QUALITY_TEST_FRAME_GENERATOR_H_ diff --git a/third_party/libwebrtc/api/test/create_peerconnection_quality_test_fixture.cc b/third_party/libwebrtc/api/test/create_peerconnection_quality_test_fixture.cc new file mode 100644 index 0000000000..e156991ed4 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_peerconnection_quality_test_fixture.cc @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019 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 "api/test/create_peerconnection_quality_test_fixture.h" + +#include <memory> +#include <utility> + +#include "api/test/metrics/global_metrics_logger_and_exporter.h" +#include "api/test/time_controller.h" +#include "test/pc/e2e/peer_connection_quality_test.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +std::unique_ptr<PeerConnectionE2EQualityTestFixture> +CreatePeerConnectionE2EQualityTestFixture( + std::string test_case_name, + TimeController& time_controller, + std::unique_ptr<AudioQualityAnalyzerInterface> audio_quality_analyzer, + std::unique_ptr<VideoQualityAnalyzerInterface> video_quality_analyzer) { + return std::make_unique<PeerConnectionE2EQualityTest>( + std::move(test_case_name), time_controller, + std::move(audio_quality_analyzer), std::move(video_quality_analyzer), + test::GetGlobalMetricsLogger()); +} + +} // namespace webrtc_pc_e2e +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/create_peerconnection_quality_test_fixture.h b/third_party/libwebrtc/api/test/create_peerconnection_quality_test_fixture.h new file mode 100644 index 0000000000..a0b0d08dd4 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_peerconnection_quality_test_fixture.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 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 API_TEST_CREATE_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_ +#define API_TEST_CREATE_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_ + +#include <memory> +#include <string> + +#include "api/test/audio_quality_analyzer_interface.h" +#include "api/test/peerconnection_quality_test_fixture.h" +#include "api/test/time_controller.h" +#include "api/test/video_quality_analyzer_interface.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +// API is in development. Can be changed/removed without notice. + +// Create test fixture to establish test call between Alice and Bob. +// During the test Alice will be caller and Bob will answer the call. +// `test_case_name` is a name of test case, that will be used for all metrics +// reporting. +// `time_controller` is used to manage all rtc::Thread's and TaskQueue +// instances. Instance of `time_controller` have to outlive created fixture. +// Returns a non-null PeerConnectionE2EQualityTestFixture instance. +std::unique_ptr<PeerConnectionE2EQualityTestFixture> +CreatePeerConnectionE2EQualityTestFixture( + std::string test_case_name, + TimeController& time_controller, + std::unique_ptr<AudioQualityAnalyzerInterface> audio_quality_analyzer, + std::unique_ptr<VideoQualityAnalyzerInterface> video_quality_analyzer); + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // API_TEST_CREATE_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_ diff --git a/third_party/libwebrtc/api/test/create_simulcast_test_fixture.cc b/third_party/libwebrtc/api/test/create_simulcast_test_fixture.cc new file mode 100644 index 0000000000..024145dff0 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_simulcast_test_fixture.cc @@ -0,0 +1,31 @@ +/* + * 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 "api/test/create_simulcast_test_fixture.h" + +#include <memory> +#include <utility> + +#include "api/test/simulcast_test_fixture.h" +#include "modules/video_coding/utility/simulcast_test_fixture_impl.h" + +namespace webrtc { +namespace test { + +std::unique_ptr<SimulcastTestFixture> CreateSimulcastTestFixture( + std::unique_ptr<VideoEncoderFactory> encoder_factory, + std::unique_ptr<VideoDecoderFactory> decoder_factory, + SdpVideoFormat video_format) { + return std::make_unique<SimulcastTestFixtureImpl>( + std::move(encoder_factory), std::move(decoder_factory), video_format); +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/create_simulcast_test_fixture.h b/third_party/libwebrtc/api/test/create_simulcast_test_fixture.h new file mode 100644 index 0000000000..87f229c009 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_simulcast_test_fixture.h @@ -0,0 +1,32 @@ +/* + * 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. + */ + +#ifndef API_TEST_CREATE_SIMULCAST_TEST_FIXTURE_H_ +#define API_TEST_CREATE_SIMULCAST_TEST_FIXTURE_H_ + +#include <memory> + +#include "api/test/simulcast_test_fixture.h" +#include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder_factory.h" + +namespace webrtc { +namespace test { + +std::unique_ptr<SimulcastTestFixture> CreateSimulcastTestFixture( + std::unique_ptr<VideoEncoderFactory> encoder_factory, + std::unique_ptr<VideoDecoderFactory> decoder_factory, + SdpVideoFormat video_format); + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_CREATE_SIMULCAST_TEST_FIXTURE_H_ diff --git a/third_party/libwebrtc/api/test/create_time_controller.cc b/third_party/libwebrtc/api/test/create_time_controller.cc new file mode 100644 index 0000000000..d198f2b0fe --- /dev/null +++ b/third_party/libwebrtc/api/test/create_time_controller.cc @@ -0,0 +1,53 @@ +/* + * Copyright 2019 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 "api/test/create_time_controller.h" + +#include <memory> + +#include "call/call.h" +#include "call/rtp_transport_config.h" +#include "call/rtp_transport_controller_send_factory_interface.h" +#include "test/time_controller/external_time_controller.h" +#include "test/time_controller/simulated_time_controller.h" + +namespace webrtc { + +std::unique_ptr<TimeController> CreateTimeController( + ControlledAlarmClock* alarm) { + return std::make_unique<ExternalTimeController>(alarm); +} + +std::unique_ptr<TimeController> CreateSimulatedTimeController() { + return std::make_unique<GlobalSimulatedTimeController>( + Timestamp::Seconds(10000)); +} + +std::unique_ptr<CallFactoryInterface> CreateTimeControllerBasedCallFactory( + TimeController* time_controller) { + class TimeControllerBasedCallFactory : public CallFactoryInterface { + public: + explicit TimeControllerBasedCallFactory(TimeController* time_controller) + : time_controller_(time_controller) {} + Call* CreateCall(const Call::Config& config) override { + RtpTransportConfig transportConfig = config.ExtractTransportConfig(); + + return Call::Create(config, time_controller_->GetClock(), + config.rtp_transport_controller_send_factory->Create( + transportConfig, time_controller_->GetClock())); + } + + private: + TimeController* time_controller_; + }; + return std::make_unique<TimeControllerBasedCallFactory>(time_controller); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/create_time_controller.h b/third_party/libwebrtc/api/test/create_time_controller.h new file mode 100644 index 0000000000..e7bc9cb465 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_time_controller.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 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 API_TEST_CREATE_TIME_CONTROLLER_H_ +#define API_TEST_CREATE_TIME_CONTROLLER_H_ + +#include <memory> + +#include "api/call/call_factory_interface.h" +#include "api/test/time_controller.h" + +namespace webrtc { + +// Creates a time coltroller that wraps `alarm`. +std::unique_ptr<TimeController> CreateTimeController( + ControlledAlarmClock* alarm); + +// Creates a time controller that runs in simulated time. +std::unique_ptr<TimeController> CreateSimulatedTimeController(); + +// This is creates a call factory that creates Call instances that are backed by +// a time controller. +std::unique_ptr<CallFactoryInterface> CreateTimeControllerBasedCallFactory( + TimeController* time_controller); + +} // namespace webrtc + +#endif // API_TEST_CREATE_TIME_CONTROLLER_H_ diff --git a/third_party/libwebrtc/api/test/create_time_controller_unittest.cc b/third_party/libwebrtc/api/test/create_time_controller_unittest.cc new file mode 100644 index 0000000000..0ea868c5cc --- /dev/null +++ b/third_party/libwebrtc/api/test/create_time_controller_unittest.cc @@ -0,0 +1,76 @@ +/* + * Copyright 2019 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 "api/test/create_time_controller.h" + +#include "api/test/time_controller.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +class FakeAlarm : public ControlledAlarmClock { + public: + explicit FakeAlarm(Timestamp start_time); + + Clock* GetClock() override; + bool ScheduleAlarmAt(Timestamp deadline) override; + void SetCallback(std::function<void()> callback) override; + void Sleep(TimeDelta duration) override; + + private: + SimulatedClock clock_; + Timestamp deadline_; + std::function<void()> callback_; +}; + +FakeAlarm::FakeAlarm(Timestamp start_time) + : clock_(start_time), + deadline_(Timestamp::PlusInfinity()), + callback_([] {}) {} + +Clock* FakeAlarm::GetClock() { + return &clock_; +} + +bool FakeAlarm::ScheduleAlarmAt(Timestamp deadline) { + if (deadline < deadline_) { + deadline_ = deadline; + return true; + } + return false; +} + +void FakeAlarm::SetCallback(std::function<void()> callback) { + callback_ = callback; +} + +void FakeAlarm::Sleep(TimeDelta duration) { + Timestamp end_time = clock_.CurrentTime() + duration; + + while (deadline_ <= end_time) { + clock_.AdvanceTime(deadline_ - clock_.CurrentTime()); + deadline_ = Timestamp::PlusInfinity(); + callback_(); + } + + clock_.AdvanceTime(end_time - clock_.CurrentTime()); +} + +TEST(CreateTimeControllerTest, CreatesNonNullController) { + FakeAlarm alarm(Timestamp::Millis(100)); + EXPECT_NE(CreateTimeController(&alarm), nullptr); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/create_video_codec_tester.cc b/third_party/libwebrtc/api/test/create_video_codec_tester.cc new file mode 100644 index 0000000000..a1efefdb48 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_video_codec_tester.cc @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 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 "api/test/create_video_codec_tester.h" + +#include <memory> +#include <utility> + +#include "api/test/video_codec_tester.h" +#include "modules/video_coding/codecs/test/video_codec_tester_impl.h" + +namespace webrtc { +namespace test { + +std::unique_ptr<VideoCodecTester> CreateVideoCodecTester() { + return std::make_unique<VideoCodecTesterImpl>(); +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/create_video_codec_tester.h b/third_party/libwebrtc/api/test/create_video_codec_tester.h new file mode 100644 index 0000000000..c68864ce85 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_video_codec_tester.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 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 API_TEST_CREATE_VIDEO_CODEC_TESTER_H_ +#define API_TEST_CREATE_VIDEO_CODEC_TESTER_H_ + +#include <memory> + +#include "api/test/video_codec_tester.h" + +namespace webrtc { +namespace test { + +std::unique_ptr<VideoCodecTester> CreateVideoCodecTester(); + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_CREATE_VIDEO_CODEC_TESTER_H_ diff --git a/third_party/libwebrtc/api/test/create_video_quality_test_fixture.cc b/third_party/libwebrtc/api/test/create_video_quality_test_fixture.cc new file mode 100644 index 0000000000..1fa7d243cc --- /dev/null +++ b/third_party/libwebrtc/api/test/create_video_quality_test_fixture.cc @@ -0,0 +1,40 @@ +/* + * 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 "api/test/create_video_quality_test_fixture.h" + +#include <memory> +#include <utility> + +#include "video/video_quality_test.h" + +namespace webrtc { + +std::unique_ptr<VideoQualityTestFixtureInterface> +CreateVideoQualityTestFixture() { + // By default, we don't override the FEC module, so pass an empty factory. + return std::make_unique<VideoQualityTest>(nullptr); +} + +std::unique_ptr<VideoQualityTestFixtureInterface> CreateVideoQualityTestFixture( + std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory) { + auto components = + std::make_unique<VideoQualityTestFixtureInterface::InjectionComponents>(); + components->fec_controller_factory = std::move(fec_controller_factory); + return std::make_unique<VideoQualityTest>(std::move(components)); +} + +std::unique_ptr<VideoQualityTestFixtureInterface> CreateVideoQualityTestFixture( + std::unique_ptr<VideoQualityTestFixtureInterface::InjectionComponents> + components) { + return std::make_unique<VideoQualityTest>(std::move(components)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/create_video_quality_test_fixture.h b/third_party/libwebrtc/api/test/create_video_quality_test_fixture.h new file mode 100644 index 0000000000..ed618fefc8 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_video_quality_test_fixture.h @@ -0,0 +1,31 @@ +/* + * 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. + */ +#ifndef API_TEST_CREATE_VIDEO_QUALITY_TEST_FIXTURE_H_ +#define API_TEST_CREATE_VIDEO_QUALITY_TEST_FIXTURE_H_ + +#include <memory> + +#include "api/fec_controller.h" +#include "api/test/video_quality_test_fixture.h" + +namespace webrtc { + +std::unique_ptr<VideoQualityTestFixtureInterface> +CreateVideoQualityTestFixture(); + +std::unique_ptr<VideoQualityTestFixtureInterface> CreateVideoQualityTestFixture( + std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory); + +std::unique_ptr<VideoQualityTestFixtureInterface> CreateVideoQualityTestFixture( + std::unique_ptr<VideoQualityTestFixtureInterface::InjectionComponents> + components); +} // namespace webrtc + +#endif // API_TEST_CREATE_VIDEO_QUALITY_TEST_FIXTURE_H_ diff --git a/third_party/libwebrtc/api/test/create_videocodec_test_fixture.cc b/third_party/libwebrtc/api/test/create_videocodec_test_fixture.cc new file mode 100644 index 0000000000..1f618e5db8 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_videocodec_test_fixture.cc @@ -0,0 +1,38 @@ +/* + * 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 "api/test/create_videocodec_test_fixture.h" + +#include <memory> +#include <utility> + +#include "api/test/videocodec_test_fixture.h" +#include "modules/video_coding/codecs/test/videocodec_test_fixture_impl.h" + +namespace webrtc { +namespace test { + +using Config = VideoCodecTestFixture::Config; + +std::unique_ptr<VideoCodecTestFixture> CreateVideoCodecTestFixture( + const Config& config) { + return std::make_unique<VideoCodecTestFixtureImpl>(config); +} + +std::unique_ptr<VideoCodecTestFixture> CreateVideoCodecTestFixture( + const Config& config, + std::unique_ptr<VideoDecoderFactory> decoder_factory, + std::unique_ptr<VideoEncoderFactory> encoder_factory) { + return std::make_unique<VideoCodecTestFixtureImpl>( + config, std::move(decoder_factory), std::move(encoder_factory)); +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/create_videocodec_test_fixture.h b/third_party/libwebrtc/api/test/create_videocodec_test_fixture.h new file mode 100644 index 0000000000..7a44f6b058 --- /dev/null +++ b/third_party/libwebrtc/api/test/create_videocodec_test_fixture.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef API_TEST_CREATE_VIDEOCODEC_TEST_FIXTURE_H_ +#define API_TEST_CREATE_VIDEOCODEC_TEST_FIXTURE_H_ + +#include <memory> + +#include "api/test/videocodec_test_fixture.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder_factory.h" + +namespace webrtc { +namespace test { + +std::unique_ptr<VideoCodecTestFixture> CreateVideoCodecTestFixture( + const VideoCodecTestFixture::Config& config); + +std::unique_ptr<VideoCodecTestFixture> CreateVideoCodecTestFixture( + const VideoCodecTestFixture::Config& config, + std::unique_ptr<VideoDecoderFactory> decoder_factory, + std::unique_ptr<VideoEncoderFactory> encoder_factory); + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_CREATE_VIDEOCODEC_TEST_FIXTURE_H_ diff --git a/third_party/libwebrtc/api/test/fake_frame_decryptor.cc b/third_party/libwebrtc/api/test/fake_frame_decryptor.cc new file mode 100644 index 0000000000..16cb1bd3b6 --- /dev/null +++ b/third_party/libwebrtc/api/test/fake_frame_decryptor.cc @@ -0,0 +1,71 @@ +/* + * Copyright 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 "api/test/fake_frame_decryptor.h" + +#include <vector> + +#include "rtc_base/checks.h" + +namespace webrtc { + +FakeFrameDecryptor::FakeFrameDecryptor(uint8_t fake_key, + uint8_t expected_postfix_byte) + : fake_key_(fake_key), expected_postfix_byte_(expected_postfix_byte) {} + +FakeFrameDecryptor::Result FakeFrameDecryptor::Decrypt( + cricket::MediaType media_type, + const std::vector<uint32_t>& csrcs, + rtc::ArrayView<const uint8_t> additional_data, + rtc::ArrayView<const uint8_t> encrypted_frame, + rtc::ArrayView<uint8_t> frame) { + if (fail_decryption_) { + return Result(Status::kFailedToDecrypt, 0); + } + + RTC_CHECK_EQ(frame.size() + 1, encrypted_frame.size()); + for (size_t i = 0; i < frame.size(); i++) { + frame[i] = encrypted_frame[i] ^ fake_key_; + } + + if (encrypted_frame[frame.size()] != expected_postfix_byte_) { + return Result(Status::kFailedToDecrypt, 0); + } + + return Result(Status::kOk, frame.size()); +} + +size_t FakeFrameDecryptor::GetMaxPlaintextByteSize( + cricket::MediaType media_type, + size_t encrypted_frame_size) { + return encrypted_frame_size - 1; +} + +void FakeFrameDecryptor::SetFakeKey(uint8_t fake_key) { + fake_key_ = fake_key; +} + +uint8_t FakeFrameDecryptor::GetFakeKey() const { + return fake_key_; +} + +void FakeFrameDecryptor::SetExpectedPostfixByte(uint8_t expected_postfix_byte) { + expected_postfix_byte_ = expected_postfix_byte; +} + +uint8_t FakeFrameDecryptor::GetExpectedPostfixByte() const { + return expected_postfix_byte_; +} + +void FakeFrameDecryptor::SetFailDecryption(bool fail_decryption) { + fail_decryption_ = fail_decryption; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/fake_frame_decryptor.h b/third_party/libwebrtc/api/test/fake_frame_decryptor.h new file mode 100644 index 0000000000..783bc805c4 --- /dev/null +++ b/third_party/libwebrtc/api/test/fake_frame_decryptor.h @@ -0,0 +1,70 @@ +/* + * Copyright 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. + */ + +#ifndef API_TEST_FAKE_FRAME_DECRYPTOR_H_ +#define API_TEST_FAKE_FRAME_DECRYPTOR_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <vector> + +#include "api/array_view.h" +#include "api/crypto/frame_decryptor_interface.h" +#include "api/media_types.h" + +namespace webrtc { + +// The FakeFrameDecryptor is a TEST ONLY fake implementation of the +// FrameDecryptorInterface. It is constructed with a simple single digit key and +// a fixed postfix byte. This is just to validate that the core code works +// as expected. +class FakeFrameDecryptor : public FrameDecryptorInterface { + public: + // Provide a key (0,255) and some postfix byte (0,255) this should match the + // byte you expect from the FakeFrameEncryptor. + explicit FakeFrameDecryptor(uint8_t fake_key = 0xAA, + uint8_t expected_postfix_byte = 255); + // Fake decryption that just xors the payload with the 1 byte key and checks + // the postfix byte. This will always fail if fail_decryption_ is set to true. + Result Decrypt(cricket::MediaType media_type, + const std::vector<uint32_t>& csrcs, + rtc::ArrayView<const uint8_t> additional_data, + rtc::ArrayView<const uint8_t> encrypted_frame, + rtc::ArrayView<uint8_t> frame) override; + // Always returns 1 less than the size of the encrypted frame. + size_t GetMaxPlaintextByteSize(cricket::MediaType media_type, + size_t encrypted_frame_size) override; + // Sets the fake key to use for encryption. + void SetFakeKey(uint8_t fake_key); + // Returns the fake key used for encryption. + uint8_t GetFakeKey() const; + // Set the Postfix byte that is expected in the encrypted payload. + void SetExpectedPostfixByte(uint8_t expected_postfix_byte); + // Returns the postfix byte that will be checked for in the encrypted payload. + uint8_t GetExpectedPostfixByte() const; + // If set to true will force all encryption to fail. + void SetFailDecryption(bool fail_decryption); + // Simple error codes for tests to validate against. + enum class FakeDecryptStatus : int { + OK = 0, + FORCED_FAILURE = 1, + INVALID_POSTFIX = 2 + }; + + private: + uint8_t fake_key_ = 0; + uint8_t expected_postfix_byte_ = 0; + bool fail_decryption_ = false; +}; + +} // namespace webrtc + +#endif // API_TEST_FAKE_FRAME_DECRYPTOR_H_ diff --git a/third_party/libwebrtc/api/test/fake_frame_encryptor.cc b/third_party/libwebrtc/api/test/fake_frame_encryptor.cc new file mode 100644 index 0000000000..89d14aab88 --- /dev/null +++ b/third_party/libwebrtc/api/test/fake_frame_encryptor.cc @@ -0,0 +1,66 @@ +/* + * Copyright 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 "api/test/fake_frame_encryptor.h" + +#include "rtc_base/checks.h" + +namespace webrtc { +FakeFrameEncryptor::FakeFrameEncryptor(uint8_t fake_key, uint8_t postfix_byte) + : fake_key_(fake_key), postfix_byte_(postfix_byte) {} + +// FrameEncryptorInterface implementation +int FakeFrameEncryptor::Encrypt(cricket::MediaType media_type, + uint32_t ssrc, + rtc::ArrayView<const uint8_t> additional_data, + rtc::ArrayView<const uint8_t> frame, + rtc::ArrayView<uint8_t> encrypted_frame, + size_t* bytes_written) { + if (fail_encryption_) { + return static_cast<int>(FakeEncryptionStatus::FORCED_FAILURE); + } + + RTC_CHECK_EQ(frame.size() + 1, encrypted_frame.size()); + for (size_t i = 0; i < frame.size(); i++) { + encrypted_frame[i] = frame[i] ^ fake_key_; + } + + encrypted_frame[frame.size()] = postfix_byte_; + *bytes_written = encrypted_frame.size(); + return static_cast<int>(FakeEncryptionStatus::OK); +} + +size_t FakeFrameEncryptor::GetMaxCiphertextByteSize( + cricket::MediaType media_type, + size_t frame_size) { + return frame_size + 1; +} + +void FakeFrameEncryptor::SetFakeKey(uint8_t fake_key) { + fake_key_ = fake_key; +} + +uint8_t FakeFrameEncryptor::GetFakeKey() const { + return fake_key_; +} + +void FakeFrameEncryptor::SetPostfixByte(uint8_t postfix_byte) { + postfix_byte_ = postfix_byte; +} + +uint8_t FakeFrameEncryptor::GetPostfixByte() const { + return postfix_byte_; +} + +void FakeFrameEncryptor::SetFailEncryption(bool fail_encryption) { + fail_encryption_ = fail_encryption; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/fake_frame_encryptor.h b/third_party/libwebrtc/api/test/fake_frame_encryptor.h new file mode 100644 index 0000000000..074981b183 --- /dev/null +++ b/third_party/libwebrtc/api/test/fake_frame_encryptor.h @@ -0,0 +1,69 @@ +/* + * Copyright 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. + */ + +#ifndef API_TEST_FAKE_FRAME_ENCRYPTOR_H_ +#define API_TEST_FAKE_FRAME_ENCRYPTOR_H_ + +#include <stddef.h> +#include <stdint.h> + +#include "api/array_view.h" +#include "api/crypto/frame_encryptor_interface.h" +#include "api/media_types.h" +#include "rtc_base/ref_counted_object.h" + +namespace webrtc { + +// The FakeFrameEncryptor is a TEST ONLY fake implementation of the +// FrameEncryptorInterface. It is constructed with a simple single digit key and +// a fixed postfix byte. This is just to validate that the core code works +// as expected. +class FakeFrameEncryptor + : public rtc::RefCountedObject<FrameEncryptorInterface> { + public: + // Provide a key (0,255) and some postfix byte (0,255). + explicit FakeFrameEncryptor(uint8_t fake_key = 0xAA, + uint8_t postfix_byte = 255); + // Simply xors each payload with the provided fake key and adds the postfix + // bit to the end. This will always fail if fail_encryption_ is set to true. + int Encrypt(cricket::MediaType media_type, + uint32_t ssrc, + rtc::ArrayView<const uint8_t> additional_data, + rtc::ArrayView<const uint8_t> frame, + rtc::ArrayView<uint8_t> encrypted_frame, + size_t* bytes_written) override; + // Always returns 1 more than the size of the frame. + size_t GetMaxCiphertextByteSize(cricket::MediaType media_type, + size_t frame_size) override; + // Sets the fake key to use during encryption. + void SetFakeKey(uint8_t fake_key); + // Returns the fake key used during encryption. + uint8_t GetFakeKey() const; + // Set the postfix byte to use. + void SetPostfixByte(uint8_t expected_postfix_byte); + // Return a postfix byte added to each outgoing payload. + uint8_t GetPostfixByte() const; + // Force all encryptions to fail. + void SetFailEncryption(bool fail_encryption); + + enum class FakeEncryptionStatus : int { + OK = 0, + FORCED_FAILURE = 1, + }; + + private: + uint8_t fake_key_ = 0; + uint8_t postfix_byte_ = 0; + bool fail_encryption_ = false; +}; + +} // namespace webrtc + +#endif // API_TEST_FAKE_FRAME_ENCRYPTOR_H_ diff --git a/third_party/libwebrtc/api/test/frame_generator_interface.cc b/third_party/libwebrtc/api/test/frame_generator_interface.cc new file mode 100644 index 0000000000..fe7b1e883d --- /dev/null +++ b/third_party/libwebrtc/api/test/frame_generator_interface.cc @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 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 "api/test/frame_generator_interface.h" + +namespace webrtc { +namespace test { + +// static +const char* FrameGeneratorInterface::OutputTypeToString( + FrameGeneratorInterface::OutputType type) { + switch (type) { + case OutputType::kI420: + return "I420"; + case OutputType::kI420A: + return "I420A"; + case OutputType::kI010: + return "I010"; + case OutputType::kNV12: + return "NV12"; + default: + RTC_DCHECK_NOTREACHED(); + } +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/frame_generator_interface.h b/third_party/libwebrtc/api/test/frame_generator_interface.h new file mode 100644 index 0000000000..90e60debac --- /dev/null +++ b/third_party/libwebrtc/api/test/frame_generator_interface.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019 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 API_TEST_FRAME_GENERATOR_INTERFACE_H_ +#define API_TEST_FRAME_GENERATOR_INTERFACE_H_ + +#include <utility> + +#include "absl/types/optional.h" +#include "api/scoped_refptr.h" +#include "api/video/video_frame.h" +#include "api/video/video_frame_buffer.h" + +namespace webrtc { +namespace test { + +class FrameGeneratorInterface { + public: + struct VideoFrameData { + VideoFrameData(rtc::scoped_refptr<VideoFrameBuffer> buffer, + absl::optional<VideoFrame::UpdateRect> update_rect) + : buffer(std::move(buffer)), update_rect(update_rect) {} + + rtc::scoped_refptr<VideoFrameBuffer> buffer; + absl::optional<VideoFrame::UpdateRect> update_rect; + }; + + enum class OutputType { kI420, kI420A, kI010, kNV12 }; + static const char* OutputTypeToString(OutputType type); + + virtual ~FrameGeneratorInterface() = default; + + // Returns VideoFrameBuffer and area where most of update was done to set them + // on the VideoFrame object. + virtual VideoFrameData NextFrame() = 0; + + // Change the capture resolution. + virtual void ChangeResolution(size_t width, size_t height) = 0; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_FRAME_GENERATOR_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/test/metrics/BUILD.gn b/third_party/libwebrtc/api/test/metrics/BUILD.gn new file mode 100644 index 0000000000..309b699329 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/BUILD.gn @@ -0,0 +1,281 @@ +# Copyright (c) 2022 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("metrics") { + deps = [ + ":global_metrics_logger_and_exporter", + ":metric", + ":metrics_accumulator", + ":metrics_exporter", + ":metrics_logger", + ":stdout_metrics_exporter", + ] +} + +if (rtc_include_tests) { + group("metrics_unittests") { + testonly = true + + deps = [ + ":global_metrics_logger_and_exporter_test", + ":metrics_accumulator_test", + ":metrics_logger_test", + ":print_result_proxy_metrics_exporter_test", + ":stdout_metrics_exporter_test", + ] + + if (rtc_enable_protobuf) { + deps += [ + ":chrome_perf_dashboard_metrics_exporter_test", + ":metrics_set_proto_file_exporter_test", + ] + } + } +} + +rtc_library("metric") { + visibility = [ "*" ] + sources = [ + "metric.cc", + "metric.h", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + deps = [ "../../../api/units:timestamp" ] +} + +rtc_library("metrics_logger") { + visibility = [ "*" ] + sources = [ + "metrics_logger.cc", + "metrics_logger.h", + ] + deps = [ + ":metric", + ":metrics_accumulator", + "../..:array_view", + "../../../rtc_base/synchronization:mutex", + "../../../system_wrappers", + "../../numerics", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} + +rtc_library("metrics_accumulator") { + visibility = [ "*" ] + sources = [ + "metrics_accumulator.cc", + "metrics_accumulator.h", + ] + deps = [ + ":metric", + "../../../rtc_base:macromagic", + "../../../rtc_base/synchronization:mutex", + "../../numerics", + "../../units:timestamp", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} + +rtc_library("metrics_exporter") { + visibility = [ "*" ] + sources = [ "metrics_exporter.h" ] + deps = [ + ":metric", + "../..:array_view", + ] +} + +rtc_library("stdout_metrics_exporter") { + visibility = [ "*" ] + sources = [ + "stdout_metrics_exporter.cc", + "stdout_metrics_exporter.h", + ] + deps = [ + ":metric", + ":metrics_exporter", + "../..:array_view", + "../../../rtc_base:stringutils", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("chrome_perf_dashboard_metrics_exporter") { + visibility = [ "*" ] + testonly = true + sources = [ + "chrome_perf_dashboard_metrics_exporter.cc", + "chrome_perf_dashboard_metrics_exporter.h", + ] + deps = [ + ":metric", + ":metrics_exporter", + "../../../api:array_view", + "../../../test:fileutils", + "../../../test:perf_test", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/strings", + ] +} + +if (rtc_enable_protobuf) { + proto_library("metric_proto") { + visibility = [ "*" ] + sources = [ "proto/metric.proto" ] + proto_out_dir = "api/test/metrics/proto" + cc_generator_options = "lite" + } +} + +rtc_library("metrics_set_proto_file_exporter") { + visibility = [ "*" ] + testonly = true + sources = [ + "metrics_set_proto_file_exporter.cc", + "metrics_set_proto_file_exporter.h", + ] + deps = [ + ":metric", + ":metrics_exporter", + "../..:array_view", + "../../../rtc_base:logging", + "../../../test:fileutils", + ] + + if (rtc_enable_protobuf) { + deps += [ ":metric_proto" ] + } +} + +rtc_library("print_result_proxy_metrics_exporter") { + visibility = [ "*" ] + testonly = true + sources = [ + "print_result_proxy_metrics_exporter.cc", + "print_result_proxy_metrics_exporter.h", + ] + deps = [ + ":metric", + ":metrics_exporter", + "../..:array_view", + "../../../test:perf_test", + ] +} + +rtc_library("global_metrics_logger_and_exporter") { + visibility = [ "*" ] + sources = [ + "global_metrics_logger_and_exporter.cc", + "global_metrics_logger_and_exporter.h", + ] + deps = [ + ":metrics_exporter", + ":metrics_logger", + "../../../rtc_base:checks", + "../../../system_wrappers", + ] +} + +if (rtc_include_tests) { + rtc_library("metrics_logger_test") { + testonly = true + sources = [ "metrics_logger_test.cc" ] + deps = [ + ":metric", + ":metrics_logger", + "../../../system_wrappers", + "../../../test:test_support", + "../../numerics", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + } + + rtc_library("metrics_accumulator_test") { + testonly = true + sources = [ "metrics_accumulator_test.cc" ] + deps = [ + ":metric", + ":metrics_accumulator", + "../../../test:test_support", + "../../units:timestamp", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + } + + rtc_library("stdout_metrics_exporter_test") { + testonly = true + sources = [ "stdout_metrics_exporter_test.cc" ] + deps = [ + ":metric", + ":stdout_metrics_exporter", + "../../../test:test_support", + "../../units:timestamp", + ] + } + + rtc_library("print_result_proxy_metrics_exporter_test") { + testonly = true + sources = [ "print_result_proxy_metrics_exporter_test.cc" ] + deps = [ + ":metric", + ":print_result_proxy_metrics_exporter", + "../../../test:test_support", + "../../units:timestamp", + ] + } + + rtc_library("global_metrics_logger_and_exporter_test") { + testonly = true + sources = [ "global_metrics_logger_and_exporter_test.cc" ] + deps = [ + ":global_metrics_logger_and_exporter", + ":metric", + ":metrics_exporter", + ":metrics_logger", + "../../../system_wrappers", + "../../../test:test_support", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + } + + if (rtc_enable_protobuf) { + rtc_library("metrics_set_proto_file_exporter_test") { + testonly = true + sources = [ "metrics_set_proto_file_exporter_test.cc" ] + deps = [ + ":metric", + ":metric_proto", + ":metrics_set_proto_file_exporter", + "../../../rtc_base:protobuf_utils", + "../../../test:fileutils", + "../../../test:test_support", + "../../units:timestamp", + ] + } + + rtc_library("chrome_perf_dashboard_metrics_exporter_test") { + testonly = true + sources = [ "chrome_perf_dashboard_metrics_exporter_test.cc" ] + deps = [ + ":chrome_perf_dashboard_metrics_exporter", + ":metric", + "../../../api/units:timestamp", + "../../../test:fileutils", + "../../../test:test_support", + "//third_party/catapult/tracing/tracing:histogram", + ] + } + } +} diff --git a/third_party/libwebrtc/api/test/metrics/DEPS b/third_party/libwebrtc/api/test/metrics/DEPS new file mode 100644 index 0000000000..74889c61c7 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/DEPS @@ -0,0 +1,14 @@ +specific_include_rules = { + "metrics_logger_and_exporter\.h": [ + "+rtc_base/synchronization/mutex.h", + "+system_wrappers/include/clock.h", + ], + "metrics_logger\.h": [ + "+rtc_base/synchronization/mutex.h", + "+system_wrappers/include/clock.h", + ], + "metrics_accumulator\.h": [ + "+rtc_base/synchronization/mutex.h", + "+rtc_base/thread_annotations.h", + ], +} diff --git a/third_party/libwebrtc/api/test/metrics/chrome_perf_dashboard_metrics_exporter.cc b/third_party/libwebrtc/api/test/metrics/chrome_perf_dashboard_metrics_exporter.cc new file mode 100644 index 0000000000..018d110b12 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/chrome_perf_dashboard_metrics_exporter.cc @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/chrome_perf_dashboard_metrics_exporter.h" + +#include <stdio.h> + +#include <memory> +#include <string> +#include <vector> + +#include "absl/memory/memory.h" +#include "absl/strings/string_view.h" +#include "api/array_view.h" +#include "api/test/metrics/metric.h" +#include "test/testsupport/file_utils.h" +#include "test/testsupport/perf_test_histogram_writer.h" +#include "test/testsupport/perf_test_result_writer.h" + +namespace webrtc { +namespace test { +namespace { + +std::string ToChromePerfDashboardUnit(Unit unit) { + switch (unit) { + case Unit::kMilliseconds: + return "msBestFitFormat"; + case Unit::kPercent: + return "n%"; + case Unit::kBytes: + return "sizeInBytes"; + case Unit::kKilobitsPerSecond: + // Chrome Perf Dashboard doesn't have kpbs units, so we change the unit + // and value accordingly. + return "bytesPerSecond"; + case Unit::kHertz: + return "Hz"; + case Unit::kUnitless: + return "unitless"; + case Unit::kCount: + return "count"; + } +} + +double ToChromePerfDashboardValue(double value, Unit unit) { + switch (unit) { + case Unit::kKilobitsPerSecond: + // Chrome Perf Dashboard doesn't have kpbs units, so we change the unit + // and value accordingly. + return value * 1000 / 8; + default: + return value; + } +} + +ImproveDirection ToChromePerfDashboardImproveDirection( + ImprovementDirection direction) { + switch (direction) { + case ImprovementDirection::kBiggerIsBetter: + return ImproveDirection::kBiggerIsBetter; + case ImprovementDirection::kNeitherIsBetter: + return ImproveDirection::kNone; + case ImprovementDirection::kSmallerIsBetter: + return ImproveDirection::kSmallerIsBetter; + } +} + +bool WriteMetricsToFile(const std::string& path, const std::string& data) { + CreateDir(DirName(path)); + FILE* output = fopen(path.c_str(), "wb"); + if (output == NULL) { + printf("Failed to write to %s.\n", path.c_str()); + return false; + } + size_t written = fwrite(data.c_str(), sizeof(char), data.size(), output); + fclose(output); + + if (written != data.size()) { + size_t expected = data.size(); + printf("Wrote %zu, tried to write %zu\n", written, expected); + return false; + } + return true; +} + +bool IsEmpty(const Metric::Stats& stats) { + return !stats.mean.has_value() && !stats.stddev.has_value() && + !stats.min.has_value() && !stats.max.has_value(); +} + +} // namespace + +ChromePerfDashboardMetricsExporter::ChromePerfDashboardMetricsExporter( + absl::string_view export_file_path) + : export_file_path_(export_file_path) {} + +bool ChromePerfDashboardMetricsExporter::Export( + rtc::ArrayView<const Metric> metrics) { + std::unique_ptr<PerfTestResultWriter> writer = + absl::WrapUnique<PerfTestResultWriter>(CreateHistogramWriter()); + for (const Metric& metric : metrics) { + if (metric.time_series.samples.empty() && IsEmpty(metric.stats)) { + // If there were no data collected for the metric it is expected that 0 + // will be exported, so add 0 to the samples. + writer->LogResult( + metric.name, metric.test_case, + ToChromePerfDashboardValue(0, metric.unit), + ToChromePerfDashboardUnit(metric.unit), + /*important=*/false, + ToChromePerfDashboardImproveDirection(metric.improvement_direction)); + continue; + } + + if (metric.time_series.samples.empty()) { + writer->LogResultMeanAndError( + metric.name, metric.test_case, + ToChromePerfDashboardValue(*metric.stats.mean, metric.unit), + ToChromePerfDashboardValue(*metric.stats.stddev, metric.unit), + ToChromePerfDashboardUnit(metric.unit), + /*important=*/false, + ToChromePerfDashboardImproveDirection(metric.improvement_direction)); + continue; + } + + std::vector<double> samples(metric.time_series.samples.size()); + for (size_t i = 0; i < metric.time_series.samples.size(); ++i) { + samples[i] = ToChromePerfDashboardValue( + metric.time_series.samples[i].value, metric.unit); + } + writer->LogResultList( + metric.name, metric.test_case, samples, + ToChromePerfDashboardUnit(metric.unit), + /*important=*/false, + ToChromePerfDashboardImproveDirection(metric.improvement_direction)); + } + return WriteMetricsToFile(export_file_path_, writer->Serialize()); +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/chrome_perf_dashboard_metrics_exporter.h b/third_party/libwebrtc/api/test/metrics/chrome_perf_dashboard_metrics_exporter.h new file mode 100644 index 0000000000..dda17a08c6 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/chrome_perf_dashboard_metrics_exporter.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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 API_TEST_METRICS_CHROME_PERF_DASHBOARD_METRICS_EXPORTER_H_ +#define API_TEST_METRICS_CHROME_PERF_DASHBOARD_METRICS_EXPORTER_H_ + +#include <string> + +#include "absl/strings/string_view.h" +#include "api/array_view.h" +#include "api/test/metrics/metric.h" +#include "api/test/metrics/metrics_exporter.h" + +namespace webrtc { +namespace test { + +// Exports all collected metrics in the Chrome Perf Dashboard proto format. +class ChromePerfDashboardMetricsExporter : public MetricsExporter { + public: + // `export_file_path` - path where the proto file will be written. + explicit ChromePerfDashboardMetricsExporter( + absl::string_view export_file_path); + ~ChromePerfDashboardMetricsExporter() override = default; + + bool Export(rtc::ArrayView<const Metric> metrics) override; + + private: + const std::string export_file_path_; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_METRICS_CHROME_PERF_DASHBOARD_METRICS_EXPORTER_H_ diff --git a/third_party/libwebrtc/api/test/metrics/chrome_perf_dashboard_metrics_exporter_test.cc b/third_party/libwebrtc/api/test/metrics/chrome_perf_dashboard_metrics_exporter_test.cc new file mode 100644 index 0000000000..5d3136f49a --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/chrome_perf_dashboard_metrics_exporter_test.cc @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/chrome_perf_dashboard_metrics_exporter.h" + +#include <fstream> +#include <map> +#include <vector> + +#include "api/test/metrics/metric.h" +#include "api/units/timestamp.h" +#include "test/gmock.h" +#include "test/gtest.h" +#include "test/testsupport/file_utils.h" +#include "third_party/catapult/tracing/tracing/value/histogram.h" + +namespace webrtc { +namespace test { +namespace { + +using ::testing::DoubleNear; +using ::testing::Eq; +using ::testing::Test; + +namespace proto = ::catapult::tracing::tracing::proto; + +std::map<std::string, std::string> DefaultMetadata() { + return std::map<std::string, std::string>{{"key", "value"}}; +} + +Metric::TimeSeries::Sample Sample(double value) { + return Metric::TimeSeries::Sample{.timestamp = Timestamp::Seconds(1), + .value = value, + .sample_metadata = DefaultMetadata()}; +} + +std::string ReadFileAsString(const std::string& filename) { + std::ifstream infile(filename, std::ios_base::binary); + auto buffer = std::vector<char>(std::istreambuf_iterator<char>(infile), + std::istreambuf_iterator<char>()); + return std::string(buffer.begin(), buffer.end()); +} + +class ChromePerfDashboardMetricsExporterTest : public Test { + protected: + ~ChromePerfDashboardMetricsExporterTest() override = default; + + void SetUp() override { + temp_filename_ = webrtc::test::TempFilename( + webrtc::test::OutputPath(), + "chrome_perf_dashboard_metrics_exporter_test"); + } + + void TearDown() override { + ASSERT_TRUE(webrtc::test::RemoveFile(temp_filename_)); + } + + std::string temp_filename_; +}; + +TEST_F(ChromePerfDashboardMetricsExporterTest, ExportMetricFormatCorrect) { + Metric metric1{ + .name = "test_metric1", + .unit = Unit::kMilliseconds, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case_name1", + .metric_metadata = DefaultMetadata(), + .time_series = + Metric::TimeSeries{.samples = std::vector{Sample(10), Sample(20)}}, + .stats = + Metric::Stats{.mean = 15.0, .stddev = 5.0, .min = 10.0, .max = 20.0}}; + Metric metric2{ + .name = "test_metric2", + .unit = Unit::kKilobitsPerSecond, + .improvement_direction = ImprovementDirection::kSmallerIsBetter, + .test_case = "test_case_name2", + .metric_metadata = DefaultMetadata(), + .time_series = + Metric::TimeSeries{.samples = std::vector{Sample(20), Sample(40)}}, + .stats = Metric::Stats{ + .mean = 30.0, .stddev = 10.0, .min = 20.0, .max = 40.0}}; + + ChromePerfDashboardMetricsExporter exporter(temp_filename_); + + ASSERT_TRUE(exporter.Export(std::vector<Metric>{metric1, metric2})); + proto::HistogramSet actual_histogram_set; + actual_histogram_set.ParseFromString(ReadFileAsString(temp_filename_)); + EXPECT_THAT(actual_histogram_set.histograms().size(), Eq(2)); + + // Validate output for `metric1` + EXPECT_THAT(actual_histogram_set.histograms(0).name(), Eq("test_metric1")); + EXPECT_THAT(actual_histogram_set.histograms(0).unit().unit(), + Eq(proto::Unit::MS_BEST_FIT_FORMAT)); + EXPECT_THAT(actual_histogram_set.histograms(0).unit().improvement_direction(), + Eq(proto::ImprovementDirection::BIGGER_IS_BETTER)); + EXPECT_THAT( + actual_histogram_set.histograms(0).diagnostics().diagnostic_map().size(), + Eq(1lu)); + EXPECT_THAT(actual_histogram_set.histograms(0) + .diagnostics() + .diagnostic_map() + .at("stories") + .generic_set() + .values(0), + Eq("\"test_case_name1\"")); + EXPECT_THAT(actual_histogram_set.histograms(0).sample_values().size(), Eq(2)); + EXPECT_THAT(actual_histogram_set.histograms(0).sample_values(0), Eq(10.0)); + EXPECT_THAT(actual_histogram_set.histograms(0).sample_values(1), Eq(20.0)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().count(), Eq(2)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().max(), Eq(20)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().meanlogs(), + DoubleNear(2.64916, 0.1)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().mean(), Eq(15)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().min(), Eq(10)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().sum(), Eq(30)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().variance(), Eq(50)); + + // Validate output for `metric2` + EXPECT_THAT(actual_histogram_set.histograms(1).name(), Eq("test_metric2")); + EXPECT_THAT(actual_histogram_set.histograms(1).unit().unit(), + Eq(proto::Unit::BYTES_PER_SECOND)); + EXPECT_THAT(actual_histogram_set.histograms(1).unit().improvement_direction(), + Eq(proto::ImprovementDirection::SMALLER_IS_BETTER)); + EXPECT_THAT( + actual_histogram_set.histograms(1).diagnostics().diagnostic_map().size(), + Eq(1lu)); + EXPECT_THAT(actual_histogram_set.histograms(1) + .diagnostics() + .diagnostic_map() + .at("stories") + .generic_set() + .values(0), + Eq("\"test_case_name2\"")); + EXPECT_THAT(actual_histogram_set.histograms(1).sample_values().size(), Eq(2)); + EXPECT_THAT(actual_histogram_set.histograms(1).sample_values(0), Eq(2500.0)); + EXPECT_THAT(actual_histogram_set.histograms(1).sample_values(1), Eq(5000.0)); + EXPECT_THAT(actual_histogram_set.histograms(1).running().count(), Eq(2)); + EXPECT_THAT(actual_histogram_set.histograms(1).running().max(), Eq(5000)); + EXPECT_THAT(actual_histogram_set.histograms(1).running().meanlogs(), + DoubleNear(8.17062, 0.1)); + EXPECT_THAT(actual_histogram_set.histograms(1).running().mean(), Eq(3750)); + EXPECT_THAT(actual_histogram_set.histograms(1).running().min(), Eq(2500)); + EXPECT_THAT(actual_histogram_set.histograms(1).running().sum(), Eq(7500)); + EXPECT_THAT(actual_histogram_set.histograms(1).running().variance(), + Eq(3125000)); +} + +TEST_F(ChromePerfDashboardMetricsExporterTest, + ExportEmptyMetricExportsZeroValue) { + Metric metric{.name = "test_metric", + .unit = Unit::kMilliseconds, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case_name", + .metric_metadata = DefaultMetadata(), + .time_series = Metric::TimeSeries{.samples = {}}, + .stats = Metric::Stats{}}; + + ChromePerfDashboardMetricsExporter exporter(temp_filename_); + + ASSERT_TRUE(exporter.Export(std::vector<Metric>{metric})); + proto::HistogramSet actual_histogram_set; + actual_histogram_set.ParseFromString(ReadFileAsString(temp_filename_)); + EXPECT_THAT(actual_histogram_set.histograms().size(), Eq(1)); + + // Validate values for `metric` + EXPECT_THAT(actual_histogram_set.histograms(0).sample_values().size(), Eq(1)); + EXPECT_THAT(actual_histogram_set.histograms(0).sample_values(0), Eq(0.0)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().count(), Eq(1)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().max(), + DoubleNear(0, 1e-6)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().meanlogs(), Eq(0)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().mean(), Eq(0)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().min(), Eq(0)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().sum(), Eq(0)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().variance(), Eq(0)); +} + +TEST_F(ChromePerfDashboardMetricsExporterTest, + ExportMetricWithOnlyStatsExportsMeanValues) { + Metric metric{.name = "test_metric", + .unit = Unit::kMilliseconds, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case_name", + .metric_metadata = DefaultMetadata(), + .time_series = Metric::TimeSeries{.samples = {}}, + .stats = Metric::Stats{ + .mean = 15.0, .stddev = 5.0, .min = 10.0, .max = 20.0}}; + + ChromePerfDashboardMetricsExporter exporter(temp_filename_); + + ASSERT_TRUE(exporter.Export(std::vector<Metric>{metric})); + proto::HistogramSet actual_histogram_set; + actual_histogram_set.ParseFromString(ReadFileAsString(temp_filename_)); + EXPECT_THAT(actual_histogram_set.histograms().size(), Eq(1)); + + // Validate values for `metric` + EXPECT_THAT(actual_histogram_set.histograms(0).sample_values().size(), Eq(1)); + EXPECT_THAT(actual_histogram_set.histograms(0).sample_values(0), Eq(15.0)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().count(), Eq(1)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().max(), Eq(15)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().meanlogs(), + DoubleNear(2.70805, 0.1)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().mean(), Eq(15)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().min(), Eq(15)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().sum(), Eq(15)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().variance(), Eq(0)); +} + +TEST_F(ChromePerfDashboardMetricsExporterTest, + ExportMetricWithOnlyStatsConvertsMeanValuesWhenRequired) { + Metric metric{.name = "test_metric", + .unit = Unit::kKilobitsPerSecond, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case_name", + .metric_metadata = DefaultMetadata(), + .time_series = Metric::TimeSeries{.samples = {}}, + .stats = Metric::Stats{ + .mean = 15.0, .stddev = 5.0, .min = 10.0, .max = 20.0}}; + + ChromePerfDashboardMetricsExporter exporter(temp_filename_); + + ASSERT_TRUE(exporter.Export(std::vector<Metric>{metric})); + proto::HistogramSet actual_histogram_set; + actual_histogram_set.ParseFromString(ReadFileAsString(temp_filename_)); + EXPECT_THAT(actual_histogram_set.histograms().size(), Eq(1)); + + // Validate values for `metric` + EXPECT_THAT(actual_histogram_set.histograms(0).sample_values().size(), Eq(1)); + EXPECT_THAT(actual_histogram_set.histograms(0).sample_values(0), Eq(1875.0)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().count(), Eq(1)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().max(), Eq(1875)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().meanlogs(), + DoubleNear(7.53636, 0.1)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().mean(), Eq(1875)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().min(), Eq(1875)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().sum(), Eq(1875)); + EXPECT_THAT(actual_histogram_set.histograms(0).running().variance(), Eq(0)); +} + +} // namespace +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/global_metrics_logger_and_exporter.cc b/third_party/libwebrtc/api/test/metrics/global_metrics_logger_and_exporter.cc new file mode 100644 index 0000000000..2d42a976aa --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/global_metrics_logger_and_exporter.cc @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/global_metrics_logger_and_exporter.h" + +#include <memory> +#include <utility> +#include <vector> + +#include "api/test/metrics/metrics_exporter.h" +#include "api/test/metrics/metrics_logger.h" +#include "rtc_base/checks.h" +#include "system_wrappers/include/clock.h" + +namespace webrtc { +namespace test { + +DefaultMetricsLogger* GetGlobalMetricsLogger() { + static DefaultMetricsLogger* logger_ = + new DefaultMetricsLogger(Clock::GetRealTimeClock()); + return logger_; +} + +bool ExportPerfMetric(MetricsLogger& logger, + std::vector<std::unique_ptr<MetricsExporter>> exporters) { + std::vector<Metric> metrics = logger.GetCollectedMetrics(); + bool success = true; + for (auto& exporter : exporters) { + bool export_result = exporter->Export(metrics); + success = success && export_result; + } + return success; +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/global_metrics_logger_and_exporter.h b/third_party/libwebrtc/api/test/metrics/global_metrics_logger_and_exporter.h new file mode 100644 index 0000000000..f77ff1c737 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/global_metrics_logger_and_exporter.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 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 API_TEST_METRICS_GLOBAL_METRICS_LOGGER_AND_EXPORTER_H_ +#define API_TEST_METRICS_GLOBAL_METRICS_LOGGER_AND_EXPORTER_H_ + +#include <memory> +#include <vector> + +#include "api/test/metrics/metrics_exporter.h" +#include "api/test/metrics/metrics_logger.h" + +namespace webrtc { +namespace test { + +// Returns non-null global `MetricsLogger` to log metrics. +DefaultMetricsLogger* GetGlobalMetricsLogger(); + +bool ExportPerfMetric(MetricsLogger& logger, + std::vector<std::unique_ptr<MetricsExporter>> exporters); + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_METRICS_GLOBAL_METRICS_LOGGER_AND_EXPORTER_H_ diff --git a/third_party/libwebrtc/api/test/metrics/global_metrics_logger_and_exporter_test.cc b/third_party/libwebrtc/api/test/metrics/global_metrics_logger_and_exporter_test.cc new file mode 100644 index 0000000000..567b3da9e3 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/global_metrics_logger_and_exporter_test.cc @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/global_metrics_logger_and_exporter.h" + +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "absl/types/optional.h" +#include "api/test/metrics/metric.h" +#include "api/test/metrics/metrics_exporter.h" +#include "api/test/metrics/metrics_logger.h" +#include "system_wrappers/include/clock.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { +namespace { + +using ::testing::Eq; +using ::testing::IsEmpty; + +std::map<std::string, std::string> DefaultMetadata() { + return std::map<std::string, std::string>{{"key", "value"}}; +} + +struct TestMetricsExporterFactory { + public: + std::unique_ptr<MetricsExporter> CreateExporter() { + return std::make_unique<TestMetricsExporter>(this, /*export_result=*/true); + } + + std::unique_ptr<MetricsExporter> CreateFailureExporter() { + return std::make_unique<TestMetricsExporter>(this, /*export_result=*/false); + } + + std::vector<Metric> exported_metrics; + + private: + class TestMetricsExporter : public MetricsExporter { + public: + TestMetricsExporter(TestMetricsExporterFactory* factory, bool export_result) + : factory_(factory), export_result_(export_result) {} + ~TestMetricsExporter() override = default; + + bool Export(rtc::ArrayView<const Metric> metrics) override { + factory_->exported_metrics = + std::vector<Metric>(metrics.begin(), metrics.end()); + return export_result_; + } + + TestMetricsExporterFactory* factory_; + bool export_result_; + }; +}; + +TEST(ExportPerfMetricTest, CollectedMetricsAreExporter) { + TestMetricsExporterFactory exporter_factory; + + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + logger.LogSingleValueMetric( + "metric_name", "test_case_name", + /*value=*/10, Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, + std::map<std::string, std::string>{{"key", "value"}}); + + std::vector<std::unique_ptr<MetricsExporter>> exporters; + exporters.push_back(exporter_factory.CreateExporter()); + ASSERT_TRUE(ExportPerfMetric(logger, std::move(exporters))); + + std::vector<Metric> metrics = exporter_factory.exported_metrics; + ASSERT_THAT(metrics.size(), Eq(1lu)); + const Metric& metric = metrics[0]; + EXPECT_THAT(metric.name, Eq("metric_name")); + EXPECT_THAT(metric.test_case, Eq("test_case_name")); + EXPECT_THAT(metric.unit, Eq(Unit::kMilliseconds)); + EXPECT_THAT(metric.improvement_direction, + Eq(ImprovementDirection::kBiggerIsBetter)); + EXPECT_THAT(metric.metric_metadata, + Eq(std::map<std::string, std::string>{{"key", "value"}})); + ASSERT_THAT(metric.time_series.samples.size(), Eq(1lu)); + EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0)); + EXPECT_THAT(metric.time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{})); + ASSERT_THAT(metric.stats.mean, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.stddev, absl::nullopt); + ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.max, absl::optional<double>(10.0)); +} + +TEST(ExportPerfMetricTest, OneFailedExporterDoesNotPreventExportToOthers) { + TestMetricsExporterFactory exporter_factory1; + TestMetricsExporterFactory exporter_factory2; + TestMetricsExporterFactory exporter_factory3; + + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + logger.LogSingleValueMetric("metric_name", "test_case_name", + /*value=*/10, Unit::kMilliseconds, + ImprovementDirection::kBiggerIsBetter, + DefaultMetadata()); + + std::vector<std::unique_ptr<MetricsExporter>> exporters; + exporters.push_back(exporter_factory1.CreateExporter()); + exporters.push_back(exporter_factory2.CreateFailureExporter()); + exporters.push_back(exporter_factory3.CreateExporter()); + ASSERT_FALSE(ExportPerfMetric(logger, std::move(exporters))); + + std::vector<Metric> metrics1 = exporter_factory1.exported_metrics; + std::vector<Metric> metrics2 = exporter_factory2.exported_metrics; + std::vector<Metric> metrics3 = exporter_factory3.exported_metrics; + ASSERT_THAT(metrics1.size(), Eq(1lu)) + << metrics1[0].name << "; " << metrics1[1].name; + EXPECT_THAT(metrics1[0].name, Eq("metric_name")); + ASSERT_THAT(metrics2.size(), Eq(1lu)); + EXPECT_THAT(metrics2[0].name, Eq("metric_name")); + ASSERT_THAT(metrics3.size(), Eq(1lu)); + EXPECT_THAT(metrics3[0].name, Eq("metric_name")); +} + +} // namespace +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/metric.cc b/third_party/libwebrtc/api/test/metrics/metric.cc new file mode 100644 index 0000000000..3c30f36f49 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metric.cc @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/metric.h" + +#include <string> + +namespace webrtc { +namespace test { + +absl::string_view ToString(Unit unit) { + switch (unit) { + case Unit::kMilliseconds: + return "Milliseconds"; + case Unit::kPercent: + return "Percent"; + case Unit::kBytes: + return "Bytes"; + case Unit::kKilobitsPerSecond: + return "KilobitsPerSecond"; + case Unit::kHertz: + return "Hertz"; + case Unit::kUnitless: + return "Unitless"; + case Unit::kCount: + return "Count"; + } +} + +absl::string_view ToString(ImprovementDirection direction) { + switch (direction) { + case ImprovementDirection::kBiggerIsBetter: + return "BiggerIsBetter"; + case ImprovementDirection::kNeitherIsBetter: + return "NeitherIsBetter"; + case ImprovementDirection::kSmallerIsBetter: + return "SmallerIsBetter"; + } +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/metric.h b/third_party/libwebrtc/api/test/metrics/metric.h new file mode 100644 index 0000000000..17c1755f95 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metric.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2022 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 API_TEST_METRICS_METRIC_H_ +#define API_TEST_METRICS_METRIC_H_ + +#include <map> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/units/timestamp.h" + +namespace webrtc { +namespace test { + +enum class Unit { + kMilliseconds, + kPercent, + kBytes, + kKilobitsPerSecond, + kHertz, + // General unitless value. Can be used either for dimensionless quantities + // (ex ratio) or for units not presented in this enum and too specific to add + // to this enum. + kUnitless, + kCount +}; + +absl::string_view ToString(Unit unit); + +enum class ImprovementDirection { + kBiggerIsBetter, + kNeitherIsBetter, + kSmallerIsBetter +}; + +absl::string_view ToString(ImprovementDirection direction); + +struct Metric { + struct TimeSeries { + struct Sample { + // Timestamp in microseconds associated with a sample. For example, + // the timestamp when the sample was collected. + webrtc::Timestamp timestamp; + double value; + // Metadata associated with this particular sample. + std::map<std::string, std::string> sample_metadata; + }; + + // All samples collected for this metric. It can be empty if the Metric + // object only contains `stats`. + std::vector<Sample> samples; + }; + + // Contains metric's precomputed statistics based on the `time_series` or if + // `time_series` is omitted (has 0 samples) contains precomputed statistics + // provided by the metric's calculator. + struct Stats { + // Sample mean of the metric + // (https://en.wikipedia.org/wiki/Sample_mean_and_covariance). + absl::optional<double> mean; + // Standard deviation (https://en.wikipedia.org/wiki/Standard_deviation). + // Is undefined if `time_series` contains only a single value. + absl::optional<double> stddev; + absl::optional<double> min; + absl::optional<double> max; + }; + + // Metric name, for example PSNR, SSIM, decode_time, etc. + std::string name; + Unit unit; + ImprovementDirection improvement_direction; + // If the metric is generated by a test, this field can be used to specify + // this information. + std::string test_case; + // Metadata associated with the whole metric. + std::map<std::string, std::string> metric_metadata; + // Contains all samples of the metric collected during test execution. + // It can be empty if the user only stores precomputed statistics into + // `stats`. + TimeSeries time_series; + Stats stats; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_METRICS_METRIC_H_ diff --git a/third_party/libwebrtc/api/test/metrics/metrics_accumulator.cc b/third_party/libwebrtc/api/test/metrics/metrics_accumulator.cc new file mode 100644 index 0000000000..c34396be97 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metrics_accumulator.cc @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/metrics_accumulator.h" + +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "absl/strings/string_view.h" +#include "api/numerics/samples_stats_counter.h" +#include "api/test/metrics/metric.h" +#include "api/units/timestamp.h" +#include "rtc_base/synchronization/mutex.h" + +namespace webrtc { +namespace test { +namespace { + +Metric::Stats ToStats(const SamplesStatsCounter& values) { + if (values.IsEmpty()) { + return Metric::Stats(); + } + return Metric::Stats{.mean = values.GetAverage(), + .stddev = values.GetStandardDeviation(), + .min = values.GetMin(), + .max = values.GetMax()}; +} + +Metric SetTimeseries(const Metric& prototype, + const SamplesStatsCounter& counter) { + Metric output(prototype); + Metric::TimeSeries time_series; + for (const SamplesStatsCounter::StatsSample& sample : + counter.GetTimedSamples()) { + time_series.samples.push_back( + Metric::TimeSeries::Sample{.timestamp = sample.time, + .value = sample.value, + .sample_metadata = sample.metadata}); + } + output.time_series = std::move(time_series); + output.stats = ToStats(counter); + return output; +} + +} // namespace + +bool operator<(const MetricsAccumulator::MetricKey& a, + const MetricsAccumulator::MetricKey& b) { + if (a.test_case_name < b.test_case_name) { + return true; + } else if (a.test_case_name > b.test_case_name) { + return false; + } else { + return a.metric_name < b.metric_name; + } +} + +bool MetricsAccumulator::AddSample( + absl::string_view metric_name, + absl::string_view test_case_name, + double value, + Timestamp timestamp, + std::map<std::string, std::string> point_metadata) { + MutexLock lock(&mutex_); + bool created; + MetricValue* metric_value = + GetOrCreateMetric(metric_name, test_case_name, &created); + metric_value->counter.AddSample( + SamplesStatsCounter::StatsSample{.value = value, + .time = timestamp, + .metadata = std::move(point_metadata)}); + return created; +} + +bool MetricsAccumulator::AddMetricMetadata( + absl::string_view metric_name, + absl::string_view test_case_name, + Unit unit, + ImprovementDirection improvement_direction, + std::map<std::string, std::string> metric_metadata) { + MutexLock lock(&mutex_); + bool created; + MetricValue* metric_value = + GetOrCreateMetric(metric_name, test_case_name, &created); + metric_value->metric.unit = unit; + metric_value->metric.improvement_direction = improvement_direction; + metric_value->metric.metric_metadata = std::move(metric_metadata); + return created; +} + +std::vector<Metric> MetricsAccumulator::GetCollectedMetrics() const { + MutexLock lock(&mutex_); + std::vector<Metric> out; + out.reserve(metrics_.size()); + for (const auto& [unused_key, metric_value] : metrics_) { + out.push_back(SetTimeseries(metric_value.metric, metric_value.counter)); + } + return out; +} + +MetricsAccumulator::MetricValue* MetricsAccumulator::GetOrCreateMetric( + absl::string_view metric_name, + absl::string_view test_case_name, + bool* created) { + MetricKey key(metric_name, test_case_name); + auto it = metrics_.find(key); + if (it != metrics_.end()) { + *created = false; + return &it->second; + } + *created = true; + + Metric metric{ + .name = key.metric_name, + .unit = Unit::kUnitless, + .improvement_direction = ImprovementDirection::kNeitherIsBetter, + .test_case = key.test_case_name, + }; + return &metrics_.emplace(key, MetricValue{.metric = std::move(metric)}) + .first->second; +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/metrics_accumulator.h b/third_party/libwebrtc/api/test/metrics/metrics_accumulator.h new file mode 100644 index 0000000000..c75bd9429c --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metrics_accumulator.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2022 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 API_TEST_METRICS_METRICS_ACCUMULATOR_H_ +#define API_TEST_METRICS_METRICS_ACCUMULATOR_H_ + +#include <map> +#include <string> +#include <vector> + +#include "absl/strings/string_view.h" +#include "api/numerics/samples_stats_counter.h" +#include "api/test/metrics/metric.h" +#include "api/units/timestamp.h" +#include "rtc_base/synchronization/mutex.h" +#include "rtc_base/thread_annotations.h" + +namespace webrtc { +namespace test { + +// Accumulates metrics' samples internally and provides API to get collected +// ones. +// +// This object is thread safe. +class MetricsAccumulator { + public: + MetricsAccumulator() = default; + + // Adds sample for the specified `metric_name` within specified + // `test_case_name`. If it is the first time when this combination of + // `metric_name` and `test_case_name` is used, creates a new Metric to collect + // samples, otherwise adds a sample to the previously created Metric. + // + // By default metric will use `Unit::kUnitless` and + // `ImprovementDirection::kNeitherIsBetter`. + // + // `point_metadata` - the metadata to be added to the single data point that + // this method adds to the Metric (it is not a metric global metadata). + // + // Returns true if a new metric was created and false otherwise. + bool AddSample(absl::string_view metric_name, + absl::string_view test_case_name, + double value, + Timestamp timestamp, + std::map<std::string, std::string> point_metadata = {}); + + // Adds metadata to the metric specified by `metric_name` within specified + // `test_case_name`. If such a metric doesn't exist, creates a new one, + // otherwise overrides previously recorded values. + // + // Returns true if a new metric was created and false otherwise. + bool AddMetricMetadata( + absl::string_view metric_name, + absl::string_view test_case_name, + Unit unit, + ImprovementDirection improvement_direction, + std::map<std::string, std::string> metric_metadata = {}); + + // Returns all metrics collected by this accumulator. No order guarantees + // provided. + std::vector<Metric> GetCollectedMetrics() const; + + private: + struct MetricKey { + MetricKey(absl::string_view metric_name, absl::string_view test_case_name) + : metric_name(metric_name), test_case_name(test_case_name) {} + + std::string metric_name; + std::string test_case_name; + }; + friend bool operator<(const MetricKey& a, const MetricKey& b); + + struct MetricValue { + SamplesStatsCounter counter; + Metric metric; + }; + + // Gets existing metrics or creates a new one. If metric was created `created` + // will be set to true. + MetricValue* GetOrCreateMetric(absl::string_view metric_name, + absl::string_view test_case_name, + bool* created) + RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + mutable Mutex mutex_; + std::map<MetricKey, MetricValue> metrics_ RTC_GUARDED_BY(mutex_); +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_METRICS_METRICS_ACCUMULATOR_H_ diff --git a/third_party/libwebrtc/api/test/metrics/metrics_accumulator_test.cc b/third_party/libwebrtc/api/test/metrics/metrics_accumulator_test.cc new file mode 100644 index 0000000000..677f523339 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metrics_accumulator_test.cc @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/metrics_accumulator.h" + +#include <map> +#include <vector> + +#include "api/test/metrics/metric.h" +#include "api/units/timestamp.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { +namespace { + +using ::testing::Eq; +using ::testing::IsEmpty; +using ::testing::SizeIs; + +TEST(MetricsAccumulatorTest, AddSampleToTheNewMetricWillCreateOne) { + MetricsAccumulator accumulator; + ASSERT_TRUE(accumulator.AddSample( + "metric_name", "test_case_name", + /*value=*/10, Timestamp::Seconds(1), + /*point_metadata=*/std::map<std::string, std::string>{{"key", "value"}})); + + std::vector<Metric> metrics = accumulator.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(1)); + const Metric& metric = metrics[0]; + EXPECT_THAT(metric.name, Eq("metric_name")); + EXPECT_THAT(metric.test_case, Eq("test_case_name")); + EXPECT_THAT(metric.unit, Eq(Unit::kUnitless)); + EXPECT_THAT(metric.improvement_direction, + Eq(ImprovementDirection::kNeitherIsBetter)); + EXPECT_THAT(metric.metric_metadata, IsEmpty()); + ASSERT_THAT(metric.time_series.samples, SizeIs(1)); + EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0)); + EXPECT_THAT(metric.time_series.samples[0].timestamp, + Eq(Timestamp::Seconds(1))); + EXPECT_THAT(metric.time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{{"key", "value"}})); + ASSERT_THAT(metric.stats.mean, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.stddev, absl::optional<double>(0.0)); + ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.max, absl::optional<double>(10.0)); +} + +TEST(MetricsAccumulatorTest, AddSamplesToExistingMetricWontCreateNewOne) { + MetricsAccumulator accumulator; + ASSERT_TRUE(accumulator.AddSample( + "metric_name", "test_case_name", + /*value=*/10, Timestamp::Seconds(1), + /*point_metadata=*/ + std::map<std::string, std::string>{{"key1", "value1"}})); + ASSERT_FALSE(accumulator.AddSample( + "metric_name", "test_case_name", + /*value=*/20, Timestamp::Seconds(2), + /*point_metadata=*/ + std::map<std::string, std::string>{{"key2", "value2"}})); + + std::vector<Metric> metrics = accumulator.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(1)); + const Metric& metric = metrics[0]; + EXPECT_THAT(metric.name, Eq("metric_name")); + EXPECT_THAT(metric.test_case, Eq("test_case_name")); + EXPECT_THAT(metric.unit, Eq(Unit::kUnitless)); + EXPECT_THAT(metric.improvement_direction, + Eq(ImprovementDirection::kNeitherIsBetter)); + EXPECT_THAT(metric.metric_metadata, IsEmpty()); + ASSERT_THAT(metric.time_series.samples, SizeIs(2)); + EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0)); + EXPECT_THAT(metric.time_series.samples[0].timestamp, + Eq(Timestamp::Seconds(1))); + EXPECT_THAT(metric.time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{{"key1", "value1"}})); + EXPECT_THAT(metric.time_series.samples[1].value, Eq(20.0)); + EXPECT_THAT(metric.time_series.samples[1].timestamp, + Eq(Timestamp::Seconds(2))); + EXPECT_THAT(metric.time_series.samples[1].sample_metadata, + Eq(std::map<std::string, std::string>{{"key2", "value2"}})); + ASSERT_THAT(metric.stats.mean, absl::optional<double>(15.0)); + ASSERT_THAT(metric.stats.stddev, absl::optional<double>(5.0)); + ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.max, absl::optional<double>(20.0)); +} + +TEST(MetricsAccumulatorTest, AddSampleToDifferentMetricsWillCreateBoth) { + MetricsAccumulator accumulator; + ASSERT_TRUE(accumulator.AddSample( + "metric_name1", "test_case_name1", + /*value=*/10, Timestamp::Seconds(1), + /*point_metadata=*/ + std::map<std::string, std::string>{{"key1", "value1"}})); + ASSERT_TRUE(accumulator.AddSample( + "metric_name2", "test_case_name2", + /*value=*/20, Timestamp::Seconds(2), + /*point_metadata=*/ + std::map<std::string, std::string>{{"key2", "value2"}})); + + std::vector<Metric> metrics = accumulator.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(2)); + EXPECT_THAT(metrics[0].name, Eq("metric_name1")); + EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1")); + EXPECT_THAT(metrics[0].unit, Eq(Unit::kUnitless)); + EXPECT_THAT(metrics[0].improvement_direction, + Eq(ImprovementDirection::kNeitherIsBetter)); + EXPECT_THAT(metrics[0].metric_metadata, IsEmpty()); + ASSERT_THAT(metrics[0].time_series.samples, SizeIs(1)); + EXPECT_THAT(metrics[0].time_series.samples[0].value, Eq(10.0)); + EXPECT_THAT(metrics[0].time_series.samples[0].timestamp, + Eq(Timestamp::Seconds(1))); + EXPECT_THAT(metrics[0].time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{{"key1", "value1"}})); + ASSERT_THAT(metrics[0].stats.mean, absl::optional<double>(10.0)); + ASSERT_THAT(metrics[0].stats.stddev, absl::optional<double>(0.0)); + ASSERT_THAT(metrics[0].stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metrics[0].stats.max, absl::optional<double>(10.0)); + EXPECT_THAT(metrics[1].name, Eq("metric_name2")); + EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2")); + EXPECT_THAT(metrics[1].unit, Eq(Unit::kUnitless)); + EXPECT_THAT(metrics[1].improvement_direction, + Eq(ImprovementDirection::kNeitherIsBetter)); + EXPECT_THAT(metrics[1].metric_metadata, IsEmpty()); + ASSERT_THAT(metrics[1].time_series.samples, SizeIs(1)); + EXPECT_THAT(metrics[1].time_series.samples[0].value, Eq(20.0)); + EXPECT_THAT(metrics[1].time_series.samples[0].timestamp, + Eq(Timestamp::Seconds(2))); + EXPECT_THAT(metrics[1].time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{{"key2", "value2"}})); + ASSERT_THAT(metrics[1].stats.mean, absl::optional<double>(20.0)); + ASSERT_THAT(metrics[1].stats.stddev, absl::optional<double>(0.0)); + ASSERT_THAT(metrics[1].stats.min, absl::optional<double>(20.0)); + ASSERT_THAT(metrics[1].stats.max, absl::optional<double>(20.0)); +} + +TEST(MetricsAccumulatorTest, AddMetadataToTheNewMetricWillCreateOne) { + MetricsAccumulator accumulator; + ASSERT_TRUE(accumulator.AddMetricMetadata( + "metric_name", "test_case_name", Unit::kMilliseconds, + ImprovementDirection::kBiggerIsBetter, + /*metric_metadata=*/ + std::map<std::string, std::string>{{"key", "value"}})); + + std::vector<Metric> metrics = accumulator.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(1)); + const Metric& metric = metrics[0]; + EXPECT_THAT(metric.name, Eq("metric_name")); + EXPECT_THAT(metric.test_case, Eq("test_case_name")); + EXPECT_THAT(metric.unit, Eq(Unit::kMilliseconds)); + EXPECT_THAT(metric.improvement_direction, + Eq(ImprovementDirection::kBiggerIsBetter)); + EXPECT_THAT(metric.metric_metadata, + Eq(std::map<std::string, std::string>{{"key", "value"}})); + ASSERT_THAT(metric.time_series.samples, IsEmpty()); + ASSERT_THAT(metric.stats.mean, absl::nullopt); + ASSERT_THAT(metric.stats.stddev, absl::nullopt); + ASSERT_THAT(metric.stats.min, absl::nullopt); + ASSERT_THAT(metric.stats.max, absl::nullopt); +} + +TEST(MetricsAccumulatorTest, + AddMetadataToTheExistingMetricWillOverwriteValues) { + MetricsAccumulator accumulator; + ASSERT_TRUE(accumulator.AddMetricMetadata( + "metric_name", "test_case_name", Unit::kMilliseconds, + ImprovementDirection::kBiggerIsBetter, + /*metric_metadata=*/ + std::map<std::string, std::string>{{"key1", "value1"}})); + + ASSERT_FALSE(accumulator.AddMetricMetadata( + "metric_name", "test_case_name", Unit::kBytes, + ImprovementDirection::kSmallerIsBetter, + /*metric_metadata=*/ + std::map<std::string, std::string>{{"key2", "value2"}})); + + std::vector<Metric> metrics = accumulator.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(1)); + const Metric& metric = metrics[0]; + EXPECT_THAT(metric.name, Eq("metric_name")); + EXPECT_THAT(metric.test_case, Eq("test_case_name")); + EXPECT_THAT(metric.unit, Eq(Unit::kBytes)); + EXPECT_THAT(metric.improvement_direction, + Eq(ImprovementDirection::kSmallerIsBetter)); + EXPECT_THAT(metric.metric_metadata, + Eq(std::map<std::string, std::string>{{"key2", "value2"}})); + ASSERT_THAT(metric.time_series.samples, IsEmpty()); + ASSERT_THAT(metric.stats.mean, absl::nullopt); + ASSERT_THAT(metric.stats.stddev, absl::nullopt); + ASSERT_THAT(metric.stats.min, absl::nullopt); + ASSERT_THAT(metric.stats.max, absl::nullopt); +} + +TEST(MetricsAccumulatorTest, AddMetadataToDifferentMetricsWillCreateBoth) { + MetricsAccumulator accumulator; + ASSERT_TRUE(accumulator.AddMetricMetadata( + "metric_name1", "test_case_name1", Unit::kMilliseconds, + ImprovementDirection::kBiggerIsBetter, + /*metric_metadata=*/ + std::map<std::string, std::string>{{"key1", "value1"}})); + + ASSERT_TRUE(accumulator.AddMetricMetadata( + "metric_name2", "test_case_name2", Unit::kBytes, + ImprovementDirection::kSmallerIsBetter, + /*metric_metadata=*/ + std::map<std::string, std::string>{{"key2", "value2"}})); + + std::vector<Metric> metrics = accumulator.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(2)); + EXPECT_THAT(metrics[0].name, Eq("metric_name1")); + EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1")); + EXPECT_THAT(metrics[0].unit, Eq(Unit::kMilliseconds)); + EXPECT_THAT(metrics[0].improvement_direction, + Eq(ImprovementDirection::kBiggerIsBetter)); + EXPECT_THAT(metrics[0].metric_metadata, + Eq(std::map<std::string, std::string>{{"key1", "value1"}})); + ASSERT_THAT(metrics[0].time_series.samples, IsEmpty()); + ASSERT_THAT(metrics[0].stats.mean, absl::nullopt); + ASSERT_THAT(metrics[0].stats.stddev, absl::nullopt); + ASSERT_THAT(metrics[0].stats.min, absl::nullopt); + ASSERT_THAT(metrics[0].stats.max, absl::nullopt); + EXPECT_THAT(metrics[1].name, Eq("metric_name2")); + EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2")); + EXPECT_THAT(metrics[1].unit, Eq(Unit::kBytes)); + EXPECT_THAT(metrics[1].improvement_direction, + Eq(ImprovementDirection::kSmallerIsBetter)); + EXPECT_THAT(metrics[1].metric_metadata, + Eq(std::map<std::string, std::string>{{"key2", "value2"}})); + ASSERT_THAT(metrics[1].time_series.samples, IsEmpty()); + ASSERT_THAT(metrics[1].stats.mean, absl::nullopt); + ASSERT_THAT(metrics[1].stats.stddev, absl::nullopt); + ASSERT_THAT(metrics[1].stats.min, absl::nullopt); + ASSERT_THAT(metrics[1].stats.max, absl::nullopt); +} + +TEST(MetricsAccumulatorTest, AddMetadataAfterAddingSampleWontCreateNewMetric) { + MetricsAccumulator accumulator; + ASSERT_TRUE(accumulator.AddSample( + "metric_name", "test_case_name", + /*value=*/10, Timestamp::Seconds(1), + /*point_metadata=*/ + std::map<std::string, std::string>{{"key_s", "value_s"}})); + ASSERT_FALSE(accumulator.AddMetricMetadata( + "metric_name", "test_case_name", Unit::kMilliseconds, + ImprovementDirection::kBiggerIsBetter, + /*metric_metadata=*/ + std::map<std::string, std::string>{{"key_m", "value_m"}})); + + std::vector<Metric> metrics = accumulator.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(1)); + const Metric& metric = metrics[0]; + EXPECT_THAT(metric.name, Eq("metric_name")); + EXPECT_THAT(metric.test_case, Eq("test_case_name")); + EXPECT_THAT(metric.unit, Eq(Unit::kMilliseconds)); + EXPECT_THAT(metric.improvement_direction, + Eq(ImprovementDirection::kBiggerIsBetter)); + EXPECT_THAT(metric.metric_metadata, + Eq(std::map<std::string, std::string>{{"key_m", "value_m"}})); + ASSERT_THAT(metric.time_series.samples, SizeIs(1)); + EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0)); + EXPECT_THAT(metric.time_series.samples[0].timestamp, + Eq(Timestamp::Seconds(1))); + EXPECT_THAT(metric.time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{{"key_s", "value_s"}})); + ASSERT_THAT(metric.stats.mean, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.stddev, absl::optional<double>(0.0)); + ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.max, absl::optional<double>(10.0)); +} + +TEST(MetricsAccumulatorTest, AddSampleAfterAddingMetadataWontCreateNewMetric) { + MetricsAccumulator accumulator; + ASSERT_TRUE(accumulator.AddMetricMetadata( + "metric_name", "test_case_name", Unit::kMilliseconds, + ImprovementDirection::kBiggerIsBetter, + /*metric_metadata=*/ + std::map<std::string, std::string>{{"key_m", "value_m"}})); + ASSERT_FALSE(accumulator.AddSample( + "metric_name", "test_case_name", + /*value=*/10, Timestamp::Seconds(1), + /*point_metadata=*/ + std::map<std::string, std::string>{{"key_s", "value_s"}})); + + std::vector<Metric> metrics = accumulator.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(1)); + const Metric& metric = metrics[0]; + EXPECT_THAT(metric.name, Eq("metric_name")); + EXPECT_THAT(metric.test_case, Eq("test_case_name")); + EXPECT_THAT(metric.unit, Eq(Unit::kMilliseconds)); + EXPECT_THAT(metric.improvement_direction, + Eq(ImprovementDirection::kBiggerIsBetter)); + EXPECT_THAT(metric.metric_metadata, + Eq(std::map<std::string, std::string>{{"key_m", "value_m"}})); + ASSERT_THAT(metric.time_series.samples, SizeIs(1)); + EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0)); + EXPECT_THAT(metric.time_series.samples[0].timestamp, + Eq(Timestamp::Seconds(1))); + EXPECT_THAT(metric.time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{{"key_s", "value_s"}})); + ASSERT_THAT(metric.stats.mean, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.stddev, absl::optional<double>(0.0)); + ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.max, absl::optional<double>(10.0)); +} + +} // namespace +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/metrics_exporter.h b/third_party/libwebrtc/api/test/metrics/metrics_exporter.h new file mode 100644 index 0000000000..23954b6b1f --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metrics_exporter.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 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 API_TEST_METRICS_METRICS_EXPORTER_H_ +#define API_TEST_METRICS_METRICS_EXPORTER_H_ + +#include "api/array_view.h" +#include "api/test/metrics/metric.h" + +namespace webrtc { +namespace test { + +// Exports metrics in the requested format. +class MetricsExporter { + public: + virtual ~MetricsExporter() = default; + + // Exports specified metrics in a format that depends on the implementation. + // Returns true if export succeeded, false otherwise. + virtual bool Export(rtc::ArrayView<const Metric> metrics) = 0; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_METRICS_METRICS_EXPORTER_H_ diff --git a/third_party/libwebrtc/api/test/metrics/metrics_logger.cc b/third_party/libwebrtc/api/test/metrics/metrics_logger.cc new file mode 100644 index 0000000000..1e24400367 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metrics_logger.cc @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/metrics_logger.h" + +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "absl/strings/string_view.h" +#include "api/numerics/samples_stats_counter.h" +#include "api/test/metrics/metric.h" +#include "rtc_base/synchronization/mutex.h" + +namespace webrtc { +namespace test { +namespace { + +Metric::Stats ToStats(const SamplesStatsCounter& values) { + if (values.IsEmpty()) { + return Metric::Stats(); + } + return Metric::Stats{.mean = values.GetAverage(), + .stddev = values.GetStandardDeviation(), + .min = values.GetMin(), + .max = values.GetMax()}; +} + +} // namespace + +void DefaultMetricsLogger::LogSingleValueMetric( + absl::string_view name, + absl::string_view test_case_name, + double value, + Unit unit, + ImprovementDirection improvement_direction, + std::map<std::string, std::string> metadata) { + MutexLock lock(&mutex_); + metrics_.push_back(Metric{ + .name = std::string(name), + .unit = unit, + .improvement_direction = improvement_direction, + .test_case = std::string(test_case_name), + .metric_metadata = std::move(metadata), + .time_series = + Metric::TimeSeries{.samples = std::vector{Metric::TimeSeries::Sample{ + .timestamp = Now(), .value = value}}}, + .stats = Metric::Stats{ + .mean = value, .stddev = absl::nullopt, .min = value, .max = value}}); +} + +void DefaultMetricsLogger::LogMetric( + absl::string_view name, + absl::string_view test_case_name, + const SamplesStatsCounter& values, + Unit unit, + ImprovementDirection improvement_direction, + std::map<std::string, std::string> metadata) { + MutexLock lock(&mutex_); + Metric::TimeSeries time_series; + for (const SamplesStatsCounter::StatsSample& sample : + values.GetTimedSamples()) { + time_series.samples.push_back( + Metric::TimeSeries::Sample{.timestamp = sample.time, + .value = sample.value, + .sample_metadata = sample.metadata}); + } + + metrics_.push_back(Metric{.name = std::string(name), + .unit = unit, + .improvement_direction = improvement_direction, + .test_case = std::string(test_case_name), + .metric_metadata = std::move(metadata), + .time_series = std::move(time_series), + .stats = ToStats(values)}); +} + +void DefaultMetricsLogger::LogMetric( + absl::string_view name, + absl::string_view test_case_name, + const Metric::Stats& metric_stats, + Unit unit, + ImprovementDirection improvement_direction, + std::map<std::string, std::string> metadata) { + MutexLock lock(&mutex_); + metrics_.push_back(Metric{.name = std::string(name), + .unit = unit, + .improvement_direction = improvement_direction, + .test_case = std::string(test_case_name), + .metric_metadata = std::move(metadata), + .time_series = Metric::TimeSeries{.samples = {}}, + .stats = std::move(metric_stats)}); +} + +std::vector<Metric> DefaultMetricsLogger::GetCollectedMetrics() const { + std::vector<Metric> out = metrics_accumulator_.GetCollectedMetrics(); + MutexLock lock(&mutex_); + out.insert(out.end(), metrics_.begin(), metrics_.end()); + return out; +} + +Timestamp DefaultMetricsLogger::Now() { + return clock_->CurrentTime(); +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/metrics_logger.h b/third_party/libwebrtc/api/test/metrics/metrics_logger.h new file mode 100644 index 0000000000..66f9e55b95 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metrics_logger.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2022 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 API_TEST_METRICS_METRICS_LOGGER_H_ +#define API_TEST_METRICS_METRICS_LOGGER_H_ + +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "absl/strings/string_view.h" +#include "api/numerics/samples_stats_counter.h" +#include "api/test/metrics/metric.h" +#include "api/test/metrics/metrics_accumulator.h" +#include "rtc_base/synchronization/mutex.h" +#include "system_wrappers/include/clock.h" + +namespace webrtc { +namespace test { + +// Provides API to log and collect performance metrics. +class MetricsLogger { + public: + virtual ~MetricsLogger() = default; + + // Adds a metric with a single value. + // `metadata` - metric's level metadata to add. + virtual void LogSingleValueMetric( + absl::string_view name, + absl::string_view test_case_name, + double value, + Unit unit, + ImprovementDirection improvement_direction, + std::map<std::string, std::string> metadata = {}) = 0; + + // Adds metrics with a time series created based on the provided `values`. + // `metadata` - metric's level metadata to add. + virtual void LogMetric(absl::string_view name, + absl::string_view test_case_name, + const SamplesStatsCounter& values, + Unit unit, + ImprovementDirection improvement_direction, + std::map<std::string, std::string> metadata = {}) = 0; + + // Adds metric with a time series with only stats object and without actual + // collected values. + // `metadata` - metric's level metadata to add. + virtual void LogMetric(absl::string_view name, + absl::string_view test_case_name, + const Metric::Stats& metric_stats, + Unit unit, + ImprovementDirection improvement_direction, + std::map<std::string, std::string> metadata = {}) = 0; + + // Returns all metrics collected by this logger. + virtual std::vector<Metric> GetCollectedMetrics() const = 0; +}; + +class DefaultMetricsLogger : public MetricsLogger { + public: + explicit DefaultMetricsLogger(webrtc::Clock* clock) : clock_(clock) {} + ~DefaultMetricsLogger() override = default; + + void LogSingleValueMetric( + absl::string_view name, + absl::string_view test_case_name, + double value, + Unit unit, + ImprovementDirection improvement_direction, + std::map<std::string, std::string> metadata = {}) override; + + void LogMetric(absl::string_view name, + absl::string_view test_case_name, + const SamplesStatsCounter& values, + Unit unit, + ImprovementDirection improvement_direction, + std::map<std::string, std::string> metadata = {}) override; + + void LogMetric(absl::string_view name, + absl::string_view test_case_name, + const Metric::Stats& metric_stats, + Unit unit, + ImprovementDirection improvement_direction, + std::map<std::string, std::string> metadata = {}) override; + + // Returns all metrics collected by this logger and its `MetricsAccumulator`. + std::vector<Metric> GetCollectedMetrics() const override; + + MetricsAccumulator* GetMetricsAccumulator() { return &metrics_accumulator_; } + + private: + webrtc::Timestamp Now(); + + webrtc::Clock* const clock_; + MetricsAccumulator metrics_accumulator_; + + mutable Mutex mutex_; + std::vector<Metric> metrics_ RTC_GUARDED_BY(mutex_); +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_METRICS_METRICS_LOGGER_H_ diff --git a/third_party/libwebrtc/api/test/metrics/metrics_logger_test.cc b/third_party/libwebrtc/api/test/metrics/metrics_logger_test.cc new file mode 100644 index 0000000000..de4501ca36 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metrics_logger_test.cc @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/metrics_logger.h" + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/numerics/samples_stats_counter.h" +#include "api/test/metrics/metric.h" +#include "system_wrappers/include/clock.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { +namespace { + +using ::testing::Eq; +using ::testing::IsEmpty; +using ::testing::SizeIs; + +std::map<std::string, std::string> DefaultMetadata() { + return std::map<std::string, std::string>{{"key", "value"}}; +} + +TEST(DefaultMetricsLoggerTest, LogSingleValueMetricRecordsMetric) { + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + logger.LogSingleValueMetric( + "metric_name", "test_case_name", + /*value=*/10, Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, + std::map<std::string, std::string>{{"key", "value"}}); + + std::vector<Metric> metrics = logger.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(1)); + const Metric& metric = metrics[0]; + EXPECT_THAT(metric.name, Eq("metric_name")); + EXPECT_THAT(metric.test_case, Eq("test_case_name")); + EXPECT_THAT(metric.unit, Eq(Unit::kMilliseconds)); + EXPECT_THAT(metric.improvement_direction, + Eq(ImprovementDirection::kBiggerIsBetter)); + EXPECT_THAT(metric.metric_metadata, + Eq(std::map<std::string, std::string>{{"key", "value"}})); + ASSERT_THAT(metric.time_series.samples, SizeIs(1)); + EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0)); + EXPECT_THAT(metric.time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{})); + ASSERT_THAT(metric.stats.mean, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.stddev, absl::nullopt); + ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.max, absl::optional<double>(10.0)); +} + +TEST(DefaultMetricsLoggerTest, LogMetricWithSamplesStatsCounterRecordsMetric) { + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + + SamplesStatsCounter values; + values.AddSample(SamplesStatsCounter::StatsSample{ + .value = 10, + .time = Clock::GetRealTimeClock()->CurrentTime(), + .metadata = + std::map<std::string, std::string>{{"point_key1", "value1"}}}); + values.AddSample(SamplesStatsCounter::StatsSample{ + .value = 20, + .time = Clock::GetRealTimeClock()->CurrentTime(), + .metadata = + std::map<std::string, std::string>{{"point_key2", "value2"}}}); + logger.LogMetric("metric_name", "test_case_name", values, Unit::kMilliseconds, + ImprovementDirection::kBiggerIsBetter, + std::map<std::string, std::string>{{"key", "value"}}); + + std::vector<Metric> metrics = logger.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(1)); + const Metric& metric = metrics[0]; + EXPECT_THAT(metric.name, Eq("metric_name")); + EXPECT_THAT(metric.test_case, Eq("test_case_name")); + EXPECT_THAT(metric.unit, Eq(Unit::kMilliseconds)); + EXPECT_THAT(metric.improvement_direction, + Eq(ImprovementDirection::kBiggerIsBetter)); + EXPECT_THAT(metric.metric_metadata, + Eq(std::map<std::string, std::string>{{"key", "value"}})); + ASSERT_THAT(metric.time_series.samples, SizeIs(2)); + EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0)); + EXPECT_THAT(metric.time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{{"point_key1", "value1"}})); + EXPECT_THAT(metric.time_series.samples[1].value, Eq(20.0)); + EXPECT_THAT(metric.time_series.samples[1].sample_metadata, + Eq(std::map<std::string, std::string>{{"point_key2", "value2"}})); + ASSERT_THAT(metric.stats.mean, absl::optional<double>(15.0)); + ASSERT_THAT(metric.stats.stddev, absl::optional<double>(5.0)); + ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.max, absl::optional<double>(20.0)); +} + +TEST(DefaultMetricsLoggerTest, + LogMetricWithEmptySamplesStatsCounterRecordsEmptyMetric) { + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + SamplesStatsCounter values; + logger.LogMetric("metric_name", "test_case_name", values, Unit::kUnitless, + ImprovementDirection::kBiggerIsBetter, DefaultMetadata()); + + std::vector<Metric> metrics = logger.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(1)); + EXPECT_THAT(metrics[0].name, Eq("metric_name")); + EXPECT_THAT(metrics[0].test_case, Eq("test_case_name")); + EXPECT_THAT(metrics[0].time_series.samples, IsEmpty()); + ASSERT_THAT(metrics[0].stats.mean, Eq(absl::nullopt)); + ASSERT_THAT(metrics[0].stats.stddev, Eq(absl::nullopt)); + ASSERT_THAT(metrics[0].stats.min, Eq(absl::nullopt)); + ASSERT_THAT(metrics[0].stats.max, Eq(absl::nullopt)); +} + +TEST(DefaultMetricsLoggerTest, LogMetricWithStatsRecordsMetric) { + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + Metric::Stats metric_stats{.mean = 15, .stddev = 5, .min = 10, .max = 20}; + logger.LogMetric("metric_name", "test_case_name", metric_stats, + Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, + std::map<std::string, std::string>{{"key", "value"}}); + + std::vector<Metric> metrics = logger.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(1)); + const Metric& metric = metrics[0]; + EXPECT_THAT(metric.name, Eq("metric_name")); + EXPECT_THAT(metric.test_case, Eq("test_case_name")); + EXPECT_THAT(metric.unit, Eq(Unit::kMilliseconds)); + EXPECT_THAT(metric.improvement_direction, + Eq(ImprovementDirection::kBiggerIsBetter)); + EXPECT_THAT(metric.metric_metadata, + Eq(std::map<std::string, std::string>{{"key", "value"}})); + ASSERT_THAT(metric.time_series.samples, IsEmpty()); + ASSERT_THAT(metric.stats.mean, absl::optional<double>(15.0)); + ASSERT_THAT(metric.stats.stddev, absl::optional<double>(5.0)); + ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.max, absl::optional<double>(20.0)); +} + +TEST(DefaultMetricsLoggerTest, LogSingleValueMetricRecordsMultipleMetrics) { + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + + logger.LogSingleValueMetric("metric_name1", "test_case_name1", + /*value=*/10, Unit::kMilliseconds, + ImprovementDirection::kBiggerIsBetter, + DefaultMetadata()); + logger.LogSingleValueMetric("metric_name2", "test_case_name2", + /*value=*/10, Unit::kMilliseconds, + ImprovementDirection::kBiggerIsBetter, + DefaultMetadata()); + + std::vector<Metric> metrics = logger.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(2)); + EXPECT_THAT(metrics[0].name, Eq("metric_name1")); + EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1")); + EXPECT_THAT(metrics[1].name, Eq("metric_name2")); + EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2")); +} + +TEST(DefaultMetricsLoggerTest, + LogMetricWithSamplesStatsCounterRecordsMultipleMetrics) { + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + SamplesStatsCounter values; + values.AddSample(SamplesStatsCounter::StatsSample{ + .value = 10, + .time = Clock::GetRealTimeClock()->CurrentTime(), + .metadata = DefaultMetadata()}); + values.AddSample(SamplesStatsCounter::StatsSample{ + .value = 20, + .time = Clock::GetRealTimeClock()->CurrentTime(), + .metadata = DefaultMetadata()}); + + logger.LogMetric("metric_name1", "test_case_name1", values, + Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, + DefaultMetadata()); + logger.LogMetric("metric_name2", "test_case_name2", values, + Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, + DefaultMetadata()); + + std::vector<Metric> metrics = logger.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(2)); + EXPECT_THAT(metrics[0].name, Eq("metric_name1")); + EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1")); + EXPECT_THAT(metrics[1].name, Eq("metric_name2")); + EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2")); +} + +TEST(DefaultMetricsLoggerTest, LogMetricWithStatsRecordsMultipleMetrics) { + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + Metric::Stats metric_stats{.mean = 15, .stddev = 5, .min = 10, .max = 20}; + + logger.LogMetric("metric_name1", "test_case_name1", metric_stats, + Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, + DefaultMetadata()); + logger.LogMetric("metric_name2", "test_case_name2", metric_stats, + Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, + DefaultMetadata()); + + std::vector<Metric> metrics = logger.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(2)); + EXPECT_THAT(metrics[0].name, Eq("metric_name1")); + EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1")); + EXPECT_THAT(metrics[1].name, Eq("metric_name2")); + EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2")); +} + +TEST(DefaultMetricsLoggerTest, + LogMetricThroughtAllMethodsAccumulateAllMetrics) { + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + SamplesStatsCounter values; + values.AddSample(SamplesStatsCounter::StatsSample{ + .value = 10, + .time = Clock::GetRealTimeClock()->CurrentTime(), + .metadata = DefaultMetadata()}); + values.AddSample(SamplesStatsCounter::StatsSample{ + .value = 20, + .time = Clock::GetRealTimeClock()->CurrentTime(), + .metadata = DefaultMetadata()}); + Metric::Stats metric_stats{.mean = 15, .stddev = 5, .min = 10, .max = 20}; + + logger.LogSingleValueMetric("metric_name1", "test_case_name1", + /*value=*/10, Unit::kMilliseconds, + ImprovementDirection::kBiggerIsBetter, + DefaultMetadata()); + logger.LogMetric("metric_name2", "test_case_name2", values, + Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, + DefaultMetadata()); + logger.LogMetric("metric_name3", "test_case_name3", metric_stats, + Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, + DefaultMetadata()); + + std::vector<Metric> metrics = logger.GetCollectedMetrics(); + ASSERT_THAT(metrics.size(), Eq(3lu)); + EXPECT_THAT(metrics[0].name, Eq("metric_name1")); + EXPECT_THAT(metrics[0].test_case, Eq("test_case_name1")); + EXPECT_THAT(metrics[1].name, Eq("metric_name2")); + EXPECT_THAT(metrics[1].test_case, Eq("test_case_name2")); + EXPECT_THAT(metrics[2].name, Eq("metric_name3")); + EXPECT_THAT(metrics[2].test_case, Eq("test_case_name3")); +} + +TEST(DefaultMetricsLoggerTest, AccumulatedMetricsReturnedInCollectedMetrics) { + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + logger.GetMetricsAccumulator()->AddSample( + "metric_name", "test_case_name", + /*value=*/10, Timestamp::Seconds(1), + /*point_metadata=*/std::map<std::string, std::string>{{"key", "value"}}); + + std::vector<Metric> metrics = logger.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(1)); + const Metric& metric = metrics[0]; + EXPECT_THAT(metric.name, Eq("metric_name")); + EXPECT_THAT(metric.test_case, Eq("test_case_name")); + EXPECT_THAT(metric.unit, Eq(Unit::kUnitless)); + EXPECT_THAT(metric.improvement_direction, + Eq(ImprovementDirection::kNeitherIsBetter)); + EXPECT_THAT(metric.metric_metadata, IsEmpty()); + ASSERT_THAT(metric.time_series.samples, SizeIs(1)); + EXPECT_THAT(metric.time_series.samples[0].value, Eq(10.0)); + EXPECT_THAT(metric.time_series.samples[0].timestamp, + Eq(Timestamp::Seconds(1))); + EXPECT_THAT(metric.time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{{"key", "value"}})); + ASSERT_THAT(metric.stats.mean, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.stddev, absl::optional<double>(0.0)); + ASSERT_THAT(metric.stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metric.stats.max, absl::optional<double>(10.0)); +} + +TEST(DefaultMetricsLoggerTest, + AccumulatedMetricsReturnedTogetherWithLoggedMetrics) { + DefaultMetricsLogger logger(Clock::GetRealTimeClock()); + logger.LogSingleValueMetric( + "metric_name1", "test_case_name1", + /*value=*/10, Unit::kMilliseconds, ImprovementDirection::kBiggerIsBetter, + std::map<std::string, std::string>{{"key_m", "value_m"}}); + logger.GetMetricsAccumulator()->AddSample( + "metric_name2", "test_case_name2", + /*value=*/10, Timestamp::Seconds(1), + /*point_metadata=*/ + std::map<std::string, std::string>{{"key_s", "value_s"}}); + + std::vector<Metric> metrics = logger.GetCollectedMetrics(); + ASSERT_THAT(metrics, SizeIs(2)); + EXPECT_THAT(metrics[0].name, Eq("metric_name2")); + EXPECT_THAT(metrics[0].test_case, Eq("test_case_name2")); + EXPECT_THAT(metrics[0].unit, Eq(Unit::kUnitless)); + EXPECT_THAT(metrics[0].improvement_direction, + Eq(ImprovementDirection::kNeitherIsBetter)); + EXPECT_THAT(metrics[0].metric_metadata, IsEmpty()); + ASSERT_THAT(metrics[0].time_series.samples, SizeIs(1)); + EXPECT_THAT(metrics[0].time_series.samples[0].value, Eq(10.0)); + EXPECT_THAT(metrics[0].time_series.samples[0].timestamp, + Eq(Timestamp::Seconds(1))); + EXPECT_THAT(metrics[0].time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{{"key_s", "value_s"}})); + ASSERT_THAT(metrics[0].stats.mean, absl::optional<double>(10.0)); + ASSERT_THAT(metrics[0].stats.stddev, absl::optional<double>(0.0)); + ASSERT_THAT(metrics[0].stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metrics[0].stats.max, absl::optional<double>(10.0)); + EXPECT_THAT(metrics[1].name, Eq("metric_name1")); + EXPECT_THAT(metrics[1].test_case, Eq("test_case_name1")); + EXPECT_THAT(metrics[1].unit, Eq(Unit::kMilliseconds)); + EXPECT_THAT(metrics[1].improvement_direction, + Eq(ImprovementDirection::kBiggerIsBetter)); + EXPECT_THAT(metrics[1].metric_metadata, + Eq(std::map<std::string, std::string>{{"key_m", "value_m"}})); + ASSERT_THAT(metrics[1].time_series.samples, SizeIs(1)); + EXPECT_THAT(metrics[1].time_series.samples[0].value, Eq(10.0)); + EXPECT_THAT(metrics[1].time_series.samples[0].sample_metadata, + Eq(std::map<std::string, std::string>{})); + ASSERT_THAT(metrics[1].stats.mean, absl::optional<double>(10.0)); + ASSERT_THAT(metrics[1].stats.stddev, absl::nullopt); + ASSERT_THAT(metrics[1].stats.min, absl::optional<double>(10.0)); + ASSERT_THAT(metrics[1].stats.max, absl::optional<double>(10.0)); +} + +} // namespace +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/metrics_set_proto_file_exporter.cc b/third_party/libwebrtc/api/test/metrics/metrics_set_proto_file_exporter.cc new file mode 100644 index 0000000000..86e6f2e136 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metrics_set_proto_file_exporter.cc @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/metrics_set_proto_file_exporter.h" + +#include <stdio.h> + +#include <string> + +#include "api/test/metrics/metric.h" +#include "rtc_base/logging.h" +#include "test/testsupport/file_utils.h" + +#if WEBRTC_ENABLE_PROTOBUF +#include "api/test/metrics/proto/metric.pb.h" +#endif + +namespace webrtc { +namespace test { +namespace { + +#if WEBRTC_ENABLE_PROTOBUF +webrtc::test_metrics::Unit ToProtoUnit(Unit unit) { + switch (unit) { + case Unit::kMilliseconds: + return webrtc::test_metrics::Unit::MILLISECONDS; + case Unit::kPercent: + return webrtc::test_metrics::Unit::PERCENT; + case Unit::kBytes: + return webrtc::test_metrics::Unit::BYTES; + case Unit::kKilobitsPerSecond: + return webrtc::test_metrics::Unit::KILOBITS_PER_SECOND; + case Unit::kHertz: + return webrtc::test_metrics::Unit::HERTZ; + case Unit::kUnitless: + return webrtc::test_metrics::Unit::UNITLESS; + case Unit::kCount: + return webrtc::test_metrics::Unit::COUNT; + } +} + +webrtc::test_metrics::ImprovementDirection ToProtoImprovementDirection( + ImprovementDirection direction) { + switch (direction) { + case ImprovementDirection::kBiggerIsBetter: + return webrtc::test_metrics::ImprovementDirection::BIGGER_IS_BETTER; + case ImprovementDirection::kNeitherIsBetter: + return webrtc::test_metrics::ImprovementDirection::NEITHER_IS_BETTER; + case ImprovementDirection::kSmallerIsBetter: + return webrtc::test_metrics::ImprovementDirection::SMALLER_IS_BETTER; + } +} + +void SetTimeSeries( + const Metric::TimeSeries& time_series, + webrtc::test_metrics::Metric::TimeSeries* proto_time_series) { + for (const Metric::TimeSeries::Sample& sample : time_series.samples) { + webrtc::test_metrics::Metric::TimeSeries::Sample* proto_sample = + proto_time_series->add_samples(); + proto_sample->set_value(sample.value); + proto_sample->set_timestamp_us(sample.timestamp.us()); + for (const auto& [key, value] : sample.sample_metadata) { + proto_sample->mutable_sample_metadata()->insert({key, value}); + } + } +} + +void SetStats(const Metric::Stats& stats, + webrtc::test_metrics::Metric::Stats* proto_stats) { + if (stats.mean.has_value()) { + proto_stats->set_mean(*stats.mean); + } + if (stats.stddev.has_value()) { + proto_stats->set_stddev(*stats.stddev); + } + if (stats.min.has_value()) { + proto_stats->set_min(*stats.min); + } + if (stats.max.has_value()) { + proto_stats->set_max(*stats.max); + } +} + +bool WriteMetricsToFile(const std::string& path, + const webrtc::test_metrics::MetricsSet& metrics_set) { + std::string data; + bool ok = metrics_set.SerializeToString(&data); + if (!ok) { + RTC_LOG(LS_ERROR) << "Failed to serialize histogram set to string"; + return false; + } + + CreateDir(DirName(path)); + FILE* output = fopen(path.c_str(), "wb"); + if (output == NULL) { + RTC_LOG(LS_ERROR) << "Failed to write to " << path; + return false; + } + size_t written = fwrite(data.c_str(), sizeof(char), data.size(), output); + fclose(output); + + if (written != data.size()) { + size_t expected = data.size(); + RTC_LOG(LS_ERROR) << "Wrote " << written << ", tried to write " << expected; + return false; + } + return true; +} +#endif // WEBRTC_ENABLE_PROTOBUF + +} // namespace + +MetricsSetProtoFileExporter::Options::Options( + absl::string_view export_file_path) + : export_file_path(export_file_path) {} +MetricsSetProtoFileExporter::Options::Options( + absl::string_view export_file_path, + bool export_whole_time_series) + : export_file_path(export_file_path), + export_whole_time_series(export_whole_time_series) {} + +bool MetricsSetProtoFileExporter::Export(rtc::ArrayView<const Metric> metrics) { +#if WEBRTC_ENABLE_PROTOBUF + webrtc::test_metrics::MetricsSet metrics_set; + for (const Metric& metric : metrics) { + webrtc::test_metrics::Metric* metric_proto = metrics_set.add_metrics(); + metric_proto->set_name(metric.name); + metric_proto->set_unit(ToProtoUnit(metric.unit)); + metric_proto->set_improvement_direction( + ToProtoImprovementDirection(metric.improvement_direction)); + metric_proto->set_test_case(metric.test_case); + for (const auto& [key, value] : metric.metric_metadata) { + metric_proto->mutable_metric_metadata()->insert({key, value}); + } + + if (options_.export_whole_time_series) { + SetTimeSeries(metric.time_series, metric_proto->mutable_time_series()); + } + SetStats(metric.stats, metric_proto->mutable_stats()); + } + + return WriteMetricsToFile(options_.export_file_path, metrics_set); +#else + RTC_LOG(LS_ERROR) + << "Compile with protobuf support to properly use this class"; + return false; +#endif +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/metrics_set_proto_file_exporter.h b/third_party/libwebrtc/api/test/metrics/metrics_set_proto_file_exporter.h new file mode 100644 index 0000000000..f996e9e7b0 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metrics_set_proto_file_exporter.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 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 API_TEST_METRICS_METRICS_SET_PROTO_FILE_EXPORTER_H_ +#define API_TEST_METRICS_METRICS_SET_PROTO_FILE_EXPORTER_H_ + +#include <string> + +#include "api/array_view.h" +#include "api/test/metrics/metric.h" +#include "api/test/metrics/metrics_exporter.h" + +namespace webrtc { +namespace test { + +// Exports all collected metrics to the proto file using +// `webrtc::test_metrics::MetricsSet` format. +class MetricsSetProtoFileExporter : public MetricsExporter { + public: + struct Options { + explicit Options(absl::string_view export_file_path); + Options(absl::string_view export_file_path, bool export_whole_time_series); + + // File to export proto. + std::string export_file_path; + // If true will write all time series values to the output proto file, + // otherwise will write stats only. + bool export_whole_time_series = true; + }; + + explicit MetricsSetProtoFileExporter(const Options& options) + : options_(options) {} + + MetricsSetProtoFileExporter(const MetricsSetProtoFileExporter&) = delete; + MetricsSetProtoFileExporter& operator=(const MetricsSetProtoFileExporter&) = + delete; + + bool Export(rtc::ArrayView<const Metric> metrics) override; + + private: + const Options options_; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_METRICS_METRICS_SET_PROTO_FILE_EXPORTER_H_ diff --git a/third_party/libwebrtc/api/test/metrics/metrics_set_proto_file_exporter_test.cc b/third_party/libwebrtc/api/test/metrics/metrics_set_proto_file_exporter_test.cc new file mode 100644 index 0000000000..eb4d483068 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/metrics_set_proto_file_exporter_test.cc @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/metrics_set_proto_file_exporter.h" + +#include <fstream> +#include <map> +#include <string> +#include <vector> + +#include "api/test/metrics/metric.h" +#include "api/test/metrics/proto/metric.pb.h" +#include "api/units/timestamp.h" +#include "rtc_base/protobuf_utils.h" +#include "test/gmock.h" +#include "test/gtest.h" +#include "test/testsupport/file_utils.h" + +namespace webrtc { +namespace test { +namespace { + +using ::testing::Eq; +using ::testing::Test; + +namespace proto = ::webrtc::test_metrics; + +std::string ReadFileAsString(const std::string& filename) { + std::ifstream infile(filename, std::ios_base::binary); + auto buffer = std::vector<char>(std::istreambuf_iterator<char>(infile), + std::istreambuf_iterator<char>()); + return std::string(buffer.begin(), buffer.end()); +} + +std::map<std::string, std::string> DefaultMetadata() { + return std::map<std::string, std::string>{{"key", "value"}}; +} + +Metric::TimeSeries::Sample Sample(double value) { + return Metric::TimeSeries::Sample{.timestamp = Timestamp::Seconds(1), + .value = value, + .sample_metadata = DefaultMetadata()}; +} + +void AssertSamplesEqual(const proto::Metric::TimeSeries::Sample& actual_sample, + const Metric::TimeSeries::Sample& expected_sample) { + EXPECT_THAT(actual_sample.value(), Eq(expected_sample.value)); + EXPECT_THAT(actual_sample.timestamp_us(), Eq(expected_sample.timestamp.us())); + EXPECT_THAT(actual_sample.sample_metadata().size(), + Eq(expected_sample.sample_metadata.size())); + for (const auto& [key, value] : expected_sample.sample_metadata) { + EXPECT_THAT(actual_sample.sample_metadata().at(key), Eq(value)); + } +} + +class MetricsSetProtoFileExporterTest : public Test { + protected: + ~MetricsSetProtoFileExporterTest() override = default; + + void SetUp() override { + temp_filename_ = webrtc::test::TempFilename( + webrtc::test::OutputPath(), "metrics_set_proto_file_exporter_test"); + } + + void TearDown() override { + ASSERT_TRUE(webrtc::test::RemoveFile(temp_filename_)); + } + + std::string temp_filename_; +}; + +TEST_F(MetricsSetProtoFileExporterTest, MetricsAreExportedCorrectly) { + MetricsSetProtoFileExporter::Options options(temp_filename_); + MetricsSetProtoFileExporter exporter(options); + + Metric metric1{ + .name = "test_metric1", + .unit = Unit::kMilliseconds, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case_name1", + .metric_metadata = DefaultMetadata(), + .time_series = + Metric::TimeSeries{.samples = std::vector{Sample(10), Sample(20)}}, + .stats = + Metric::Stats{.mean = 15.0, .stddev = 5.0, .min = 10.0, .max = 20.0}}; + Metric metric2{ + .name = "test_metric2", + .unit = Unit::kKilobitsPerSecond, + .improvement_direction = ImprovementDirection::kSmallerIsBetter, + .test_case = "test_case_name2", + .metric_metadata = DefaultMetadata(), + .time_series = + Metric::TimeSeries{.samples = std::vector{Sample(20), Sample(40)}}, + .stats = Metric::Stats{ + .mean = 30.0, .stddev = 10.0, .min = 20.0, .max = 40.0}}; + + ASSERT_TRUE(exporter.Export(std::vector<Metric>{metric1, metric2})); + webrtc::test_metrics::MetricsSet actual_metrics_set; + actual_metrics_set.ParseFromString(ReadFileAsString(temp_filename_)); + EXPECT_THAT(actual_metrics_set.metrics().size(), Eq(2)); + + EXPECT_THAT(actual_metrics_set.metrics(0).name(), Eq("test_metric1")); + EXPECT_THAT(actual_metrics_set.metrics(0).test_case(), Eq("test_case_name1")); + EXPECT_THAT(actual_metrics_set.metrics(0).unit(), + Eq(proto::Unit::MILLISECONDS)); + EXPECT_THAT(actual_metrics_set.metrics(0).improvement_direction(), + Eq(proto::ImprovementDirection::BIGGER_IS_BETTER)); + EXPECT_THAT(actual_metrics_set.metrics(0).metric_metadata().size(), Eq(1lu)); + EXPECT_THAT(actual_metrics_set.metrics(0).metric_metadata().at("key"), + Eq("value")); + EXPECT_THAT(actual_metrics_set.metrics(0).time_series().samples().size(), + Eq(2)); + AssertSamplesEqual(actual_metrics_set.metrics(0).time_series().samples(0), + Sample(10.0)); + AssertSamplesEqual(actual_metrics_set.metrics(0).time_series().samples(1), + Sample(20.0)); + EXPECT_THAT(actual_metrics_set.metrics(0).stats().mean(), Eq(15.0)); + EXPECT_THAT(actual_metrics_set.metrics(0).stats().stddev(), Eq(5.0)); + EXPECT_THAT(actual_metrics_set.metrics(0).stats().min(), Eq(10.0)); + EXPECT_THAT(actual_metrics_set.metrics(0).stats().max(), Eq(20.0)); + + EXPECT_THAT(actual_metrics_set.metrics(1).name(), Eq("test_metric2")); + EXPECT_THAT(actual_metrics_set.metrics(1).test_case(), Eq("test_case_name2")); + EXPECT_THAT(actual_metrics_set.metrics(1).unit(), + Eq(proto::Unit::KILOBITS_PER_SECOND)); + EXPECT_THAT(actual_metrics_set.metrics(1).improvement_direction(), + Eq(proto::ImprovementDirection::SMALLER_IS_BETTER)); + EXPECT_THAT(actual_metrics_set.metrics(1).metric_metadata().size(), Eq(1lu)); + EXPECT_THAT(actual_metrics_set.metrics(1).metric_metadata().at("key"), + Eq("value")); + EXPECT_THAT(actual_metrics_set.metrics(1).time_series().samples().size(), + Eq(2)); + AssertSamplesEqual(actual_metrics_set.metrics(1).time_series().samples(0), + Sample(20.0)); + AssertSamplesEqual(actual_metrics_set.metrics(1).time_series().samples(1), + Sample(40.0)); + EXPECT_THAT(actual_metrics_set.metrics(1).stats().mean(), Eq(30.0)); + EXPECT_THAT(actual_metrics_set.metrics(1).stats().stddev(), Eq(10.0)); + EXPECT_THAT(actual_metrics_set.metrics(1).stats().min(), Eq(20.0)); + EXPECT_THAT(actual_metrics_set.metrics(1).stats().max(), Eq(40.0)); +} + +} // namespace +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/print_result_proxy_metrics_exporter.cc b/third_party/libwebrtc/api/test/metrics/print_result_proxy_metrics_exporter.cc new file mode 100644 index 0000000000..1ce1e63892 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/print_result_proxy_metrics_exporter.cc @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/print_result_proxy_metrics_exporter.h" + +#include <string> +#include <unordered_set> + +#include "api/array_view.h" +#include "api/test/metrics/metric.h" +#include "test/testsupport/perf_test.h" + +namespace webrtc { +namespace test { +namespace { + +std::string ToPrintResultUnit(Unit unit) { + switch (unit) { + case Unit::kMilliseconds: + return "msBestFitFormat"; + case Unit::kPercent: + return "n%"; + case Unit::kBytes: + return "sizeInBytes"; + case Unit::kKilobitsPerSecond: + // PrintResults prefer Chrome Perf Dashboard units, which doesn't have + // kpbs units, so we change the unit and value accordingly. + return "bytesPerSecond"; + case Unit::kHertz: + return "Hz"; + case Unit::kUnitless: + return "unitless"; + case Unit::kCount: + return "count"; + } +} + +double ToPrintResultValue(double value, Unit unit) { + switch (unit) { + case Unit::kKilobitsPerSecond: + // PrintResults prefer Chrome Perf Dashboard units, which doesn't have + // kpbs units, so we change the unit and value accordingly. + return value * 1000 / 8; + default: + return value; + } +} + +ImproveDirection ToPrintResultImproveDirection(ImprovementDirection direction) { + switch (direction) { + case ImprovementDirection::kBiggerIsBetter: + return ImproveDirection::kBiggerIsBetter; + case ImprovementDirection::kNeitherIsBetter: + return ImproveDirection::kNone; + case ImprovementDirection::kSmallerIsBetter: + return ImproveDirection::kSmallerIsBetter; + } +} + +bool IsEmpty(const Metric::Stats& stats) { + return !stats.mean.has_value() && !stats.stddev.has_value() && + !stats.min.has_value() && !stats.max.has_value(); +} + +bool NameEndsWithConnected(const std::string& name) { + static const std::string suffix = "_connected"; + return name.size() >= suffix.size() && + 0 == name.compare(name.size() - suffix.size(), suffix.size(), suffix); +} + +} // namespace + +bool PrintResultProxyMetricsExporter::Export( + rtc::ArrayView<const Metric> metrics) { + static const std::unordered_set<std::string> per_call_metrics{ + "actual_encode_bitrate", + "encode_frame_rate", + "harmonic_framerate", + "max_skipped", + "min_psnr_dB", + "retransmission_bitrate", + "sent_packets_loss", + "transmission_bitrate", + "dropped_frames", + "frames_in_flight", + "rendered_frames", + "average_receive_rate", + "average_send_rate", + "bytes_discarded_no_receiver", + "bytes_received", + "bytes_sent", + "packets_discarded_no_receiver", + "packets_received", + "packets_sent", + "payload_bytes_received", + "payload_bytes_sent", + "cpu_usage"}; + + for (const Metric& metric : metrics) { + if (metric.time_series.samples.empty() && IsEmpty(metric.stats)) { + // If there were no data collected for the metric it is expected that 0 + // will be exported, so add 0 to the samples. + PrintResult(metric.name, /*modifier=*/"", metric.test_case, + ToPrintResultValue(0, metric.unit), + ToPrintResultUnit(metric.unit), /*important=*/false, + ToPrintResultImproveDirection(metric.improvement_direction)); + continue; + } + + if (metric.time_series.samples.empty()) { + PrintResultMeanAndError( + metric.name, /*modifier=*/"", metric.test_case, + ToPrintResultValue(*metric.stats.mean, metric.unit), + ToPrintResultValue(*metric.stats.stddev, metric.unit), + ToPrintResultUnit(metric.unit), + /*important=*/false, + ToPrintResultImproveDirection(metric.improvement_direction)); + continue; + } + + if (metric.time_series.samples.size() == 1lu && + (per_call_metrics.count(metric.name) > 0 || + NameEndsWithConnected(metric.name))) { + // Increase backwards compatibility for 1 value use case. + PrintResult( + metric.name, /*modifier=*/"", metric.test_case, + ToPrintResultValue(metric.time_series.samples[0].value, metric.unit), + ToPrintResultUnit(metric.unit), /*important=*/false, + ToPrintResultImproveDirection(metric.improvement_direction)); + continue; + } + + SamplesStatsCounter counter; + for (size_t i = 0; i < metric.time_series.samples.size(); ++i) { + counter.AddSample(SamplesStatsCounter::StatsSample{ + .value = ToPrintResultValue(metric.time_series.samples[i].value, + metric.unit), + .time = metric.time_series.samples[i].timestamp, + .metadata = metric.time_series.samples[i].sample_metadata}); + } + + PrintResult(metric.name, /*modifier=*/"", metric.test_case, counter, + ToPrintResultUnit(metric.unit), + /*important=*/false, + ToPrintResultImproveDirection(metric.improvement_direction)); + } + return true; +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/print_result_proxy_metrics_exporter.h b/third_party/libwebrtc/api/test/metrics/print_result_proxy_metrics_exporter.h new file mode 100644 index 0000000000..bad0594972 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/print_result_proxy_metrics_exporter.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 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 API_TEST_METRICS_PRINT_RESULT_PROXY_METRICS_EXPORTER_H_ +#define API_TEST_METRICS_PRINT_RESULT_PROXY_METRICS_EXPORTER_H_ + +#include "api/array_view.h" +#include "api/test/metrics/metric.h" +#include "api/test/metrics/metrics_exporter.h" + +namespace webrtc { +namespace test { + +// Proxies all exported metrics to the `webrtc::test::PrintResult` API. +class PrintResultProxyMetricsExporter : public MetricsExporter { + public: + ~PrintResultProxyMetricsExporter() override = default; + + bool Export(rtc::ArrayView<const Metric> metrics) override; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_METRICS_PRINT_RESULT_PROXY_METRICS_EXPORTER_H_ diff --git a/third_party/libwebrtc/api/test/metrics/print_result_proxy_metrics_exporter_test.cc b/third_party/libwebrtc/api/test/metrics/print_result_proxy_metrics_exporter_test.cc new file mode 100644 index 0000000000..768c794b40 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/print_result_proxy_metrics_exporter_test.cc @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/print_result_proxy_metrics_exporter.h" + +#include <map> +#include <string> +#include <vector> + +#include "api/test/metrics/metric.h" +#include "api/units/timestamp.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { +namespace { + +using ::testing::TestWithParam; + +std::map<std::string, std::string> DefaultMetadata() { + return std::map<std::string, std::string>{{"key", "value"}}; +} + +Metric::TimeSeries::Sample Sample(double value) { + return Metric::TimeSeries::Sample{.timestamp = Timestamp::Seconds(1), + .value = value, + .sample_metadata = DefaultMetadata()}; +} + +TEST(PrintResultProxyMetricsExporterTest, + ExportMetricsWithTimeSeriesFormatCorrect) { + Metric metric1{ + .name = "test_metric1", + .unit = Unit::kMilliseconds, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case_name1", + .metric_metadata = DefaultMetadata(), + .time_series = + Metric::TimeSeries{.samples = std::vector{Sample(10), Sample(20)}}, + .stats = + Metric::Stats{.mean = 15.0, .stddev = 5.0, .min = 10.0, .max = 20.0}}; + Metric metric2{ + .name = "test_metric2", + .unit = Unit::kKilobitsPerSecond, + .improvement_direction = ImprovementDirection::kSmallerIsBetter, + .test_case = "test_case_name2", + .metric_metadata = DefaultMetadata(), + .time_series = + Metric::TimeSeries{.samples = std::vector{Sample(20), Sample(40)}}, + .stats = Metric::Stats{ + .mean = 30.0, .stddev = 10.0, .min = 20.0, .max = 40.0}}; + + testing::internal::CaptureStdout(); + PrintResultProxyMetricsExporter exporter; + + std::string expected = + "RESULT test_metric1: test_case_name1= {15,5} " + "msBestFitFormat_biggerIsBetter\n" + "RESULT test_metric2: test_case_name2= {3750,1250} " + "bytesPerSecond_smallerIsBetter\n"; + + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric1, metric2})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(PrintResultProxyMetricsExporterTest, + ExportMetricsTimeSeriesOfSingleValueBackwardCompatibleFormat) { + // This should be printed as {mean, stddev} despite only being a single data + // point. + Metric metric1{ + .name = "available_send_bandwidth", + .unit = Unit::kKilobitsPerSecond, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case/alice", + .metric_metadata = DefaultMetadata(), + .time_series = Metric::TimeSeries{.samples = std::vector{Sample(1000)}}, + .stats = Metric::Stats{ + .mean = 1000.0, .stddev = 0.0, .min = 1000.0, .max = 1000.0}}; + // This is a per-call metric that shouldn't have a stddev estimate. + Metric metric2{ + .name = "min_psnr_dB", + .unit = Unit::kUnitless, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case/alice-video", + .metric_metadata = DefaultMetadata(), + .time_series = Metric::TimeSeries{.samples = std::vector{Sample(10)}}, + .stats = + Metric::Stats{.mean = 10.0, .stddev = 0.0, .min = 10.0, .max = 10.0}}; + // This is a per-call metric that shouldn't have a stddev estimate. + Metric metric3{ + .name = "alice_connected", + .unit = Unit::kUnitless, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case", + .metric_metadata = DefaultMetadata(), + .time_series = Metric::TimeSeries{.samples = std::vector{Sample(1)}}, + .stats = + Metric::Stats{.mean = 1.0, .stddev = 0.0, .min = 1.0, .max = 1.0}}; + + testing::internal::CaptureStdout(); + PrintResultProxyMetricsExporter exporter; + + std::string expected = + "RESULT available_send_bandwidth: test_case/alice= {125000,0} " + "bytesPerSecond_biggerIsBetter\n" + "RESULT min_psnr_dB: test_case/alice-video= 10 " + "unitless_biggerIsBetter\n" + "RESULT alice_connected: test_case= 1 " + "unitless_biggerIsBetter\n"; + + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric1, metric2, metric3})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(PrintResultProxyMetricsExporterTest, + ExportMetricsWithStatsOnlyFormatCorrect) { + Metric metric1{.name = "test_metric1", + .unit = Unit::kMilliseconds, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case_name1", + .metric_metadata = DefaultMetadata(), + .time_series = Metric::TimeSeries{.samples = {}}, + .stats = Metric::Stats{ + .mean = 15.0, .stddev = 5.0, .min = 10.0, .max = 20.0}}; + Metric metric2{ + .name = "test_metric2", + .unit = Unit::kKilobitsPerSecond, + .improvement_direction = ImprovementDirection::kSmallerIsBetter, + .test_case = "test_case_name2", + .metric_metadata = DefaultMetadata(), + .time_series = Metric::TimeSeries{.samples = {}}, + .stats = Metric::Stats{ + .mean = 30.0, .stddev = 10.0, .min = 20.0, .max = 40.0}}; + + testing::internal::CaptureStdout(); + PrintResultProxyMetricsExporter exporter; + + std::string expected = + "RESULT test_metric1: test_case_name1= {15,5} " + "msBestFitFormat_biggerIsBetter\n" + "RESULT test_metric2: test_case_name2= {3750,1250} " + "bytesPerSecond_smallerIsBetter\n"; + + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric1, metric2})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(PrintResultProxyMetricsExporterTest, ExportEmptyMetricOnlyFormatCorrect) { + Metric metric{.name = "test_metric", + .unit = Unit::kMilliseconds, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case_name", + .metric_metadata = DefaultMetadata(), + .time_series = Metric::TimeSeries{.samples = {}}, + .stats = Metric::Stats{}}; + + testing::internal::CaptureStdout(); + PrintResultProxyMetricsExporter exporter; + + std::string expected = + "RESULT test_metric: test_case_name= 0 " + "msBestFitFormat_biggerIsBetter\n"; + + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +} // namespace +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/proto/metric.proto b/third_party/libwebrtc/api/test/metrics/proto/metric.proto new file mode 100644 index 0000000000..cdd312589d --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/proto/metric.proto @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022 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. + */ + +syntax = "proto3"; + +package webrtc.test_metrics; + +// Root message of the proto file. Contains collection of all the metrics. +message MetricsSet { + repeated Metric metrics = 1; +} + +enum Unit { + // Default value that has to be defined. + UNDEFINED_UNIT = 0; + // General unitless value. Can be used either for dimensionless quantities + // (ex ratio) or for units not presented in this enum and too specific to add + // to this enum. + UNITLESS = 1; + MILLISECONDS = 2; + PERCENT = 3; + BYTES = 4; + KILOBITS_PER_SECOND = 5; + HERTZ = 6; + COUNT = 7; +} + +enum ImprovementDirection { + // Default value that has to be defined. + UNDEFINED_IMPROVEMENT_DIRECTION = 0; + BIGGER_IS_BETTER = 1; + NEITHER_IS_BETTER = 2; + SMALLER_IS_BETTER = 3; +} + +// Single performance metric with all related metadata. +message Metric { + // Metric name, for example PSNR, SSIM, decode_time, etc. + string name = 1; + Unit unit = 2; + ImprovementDirection improvement_direction = 3; + // If the metric is generated by a test, this field can be used to specify + // this information. + string test_case = 4; + // Metadata associated with the whole metric. + map<string, string> metric_metadata = 5; + + message TimeSeries { + message Sample { + // Timestamp in microseconds associated with a sample. For example, + // the timestamp when the sample was collected. + int64 timestamp_us = 1; + double value = 2; + // Metadata associated with this particular sample. + map<string, string> sample_metadata = 3; + } + // All samples collected for this metric. It can be empty if the Metric + // object only contains `stats`. + repeated Sample samples = 1; + } + // Contains all samples of the metric collected during test execution. + // It can be empty if the user only stores precomputed statistics into + // `stats`. + TimeSeries time_series = 6; + + // Contains metric's precomputed statistics based on the `time_series` or if + // `time_series` is omitted (has 0 samples) contains precomputed statistics + // provided by the metric's calculator. + message Stats { + // Sample mean of the metric + // (https://en.wikipedia.org/wiki/Sample_mean_and_covariance). + optional double mean = 1; + // Standard deviation (https://en.wikipedia.org/wiki/Standard_deviation). + // Is undefined if `time_series` contains only a single sample. + optional double stddev = 2; + optional double min = 3; + optional double max = 4; + } + Stats stats = 7; +} diff --git a/third_party/libwebrtc/api/test/metrics/stdout_metrics_exporter.cc b/third_party/libwebrtc/api/test/metrics/stdout_metrics_exporter.cc new file mode 100644 index 0000000000..22243e73e8 --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/stdout_metrics_exporter.cc @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/stdout_metrics_exporter.h" + +#include <stdio.h> + +#include <cmath> +#include <string> + +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/test/metrics/metric.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { +namespace test { +namespace { + +// Returns positive integral part of the number. +int64_t IntegralPart(double value) { + return std::lround(std::floor(std::abs(value))); +} + +void AppendWithPrecision(double value, + int digits_after_comma, + rtc::StringBuilder& out) { + int64_t multiplier = std::lround(std::pow(10, digits_after_comma)); + int64_t integral_part = IntegralPart(value); + double decimal_part = std::abs(value) - integral_part; + + // If decimal part has leading zeros then when it will be multiplied on + // `multiplier`, leading zeros will be lost. To preserve them we add "1" + // so then leading digit will be greater than 0 and won't be removed. + // + // During conversion to the string leading digit has to be stripped. + // + // Also due to rounding it may happen that leading digit may be incremented, + // like with `digits_after_comma` 3 number 1.9995 will be rounded to 2. In + // such case this increment has to be propagated to the `integral_part`. + int64_t decimal_holder = std::lround((1 + decimal_part) * multiplier); + if (decimal_holder >= 2 * multiplier) { + // Rounding incremented added leading digit, so we need to transfer 1 to + // integral part. + integral_part++; + decimal_holder -= multiplier; + } + // Remove trailing zeros. + while (decimal_holder % 10 == 0) { + decimal_holder /= 10; + } + + // Print serialized number to output. + if (value < 0) { + out << "-"; + } + out << integral_part; + if (decimal_holder != 1) { + out << "." << std::to_string(decimal_holder).substr(1, digits_after_comma); + } +} + +} // namespace + +StdoutMetricsExporter::StdoutMetricsExporter() : output_(stdout) {} + +bool StdoutMetricsExporter::Export(rtc::ArrayView<const Metric> metrics) { + for (const Metric& metric : metrics) { + PrintMetric(metric); + } + return true; +} + +void StdoutMetricsExporter::PrintMetric(const Metric& metric) { + rtc::StringBuilder value_stream; + value_stream << metric.test_case << " / " << metric.name << "= {mean="; + if (metric.stats.mean.has_value()) { + AppendWithPrecision(*metric.stats.mean, 8, value_stream); + } else { + value_stream << "-"; + } + value_stream << ", stddev="; + if (metric.stats.stddev.has_value()) { + AppendWithPrecision(*metric.stats.stddev, 8, value_stream); + } else { + value_stream << "-"; + } + value_stream << "} " << ToString(metric.unit) << " (" + << ToString(metric.improvement_direction) << ")"; + + fprintf(output_, "RESULT: %s\n", value_stream.str().c_str()); +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/metrics/stdout_metrics_exporter.h b/third_party/libwebrtc/api/test/metrics/stdout_metrics_exporter.h new file mode 100644 index 0000000000..2c572cb2ea --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/stdout_metrics_exporter.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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 API_TEST_METRICS_STDOUT_METRICS_EXPORTER_H_ +#define API_TEST_METRICS_STDOUT_METRICS_EXPORTER_H_ + +#include "api/array_view.h" +#include "api/test/metrics/metric.h" +#include "api/test/metrics/metrics_exporter.h" + +namespace webrtc { +namespace test { + +// Exports all collected metrics to stdout. +class StdoutMetricsExporter : public MetricsExporter { + public: + StdoutMetricsExporter(); + ~StdoutMetricsExporter() override = default; + + StdoutMetricsExporter(const StdoutMetricsExporter&) = delete; + StdoutMetricsExporter& operator=(const StdoutMetricsExporter&) = delete; + + bool Export(rtc::ArrayView<const Metric> metrics) override; + + private: + void PrintMetric(const Metric& metric); + + FILE* const output_; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_METRICS_STDOUT_METRICS_EXPORTER_H_ diff --git a/third_party/libwebrtc/api/test/metrics/stdout_metrics_exporter_test.cc b/third_party/libwebrtc/api/test/metrics/stdout_metrics_exporter_test.cc new file mode 100644 index 0000000000..91c06fac5b --- /dev/null +++ b/third_party/libwebrtc/api/test/metrics/stdout_metrics_exporter_test.cc @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2022 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 "api/test/metrics/stdout_metrics_exporter.h" + +#include <map> +#include <string> +#include <vector> + +#include "api/test/metrics/metric.h" +#include "api/units/timestamp.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { +namespace { + +using ::testing::TestWithParam; + +std::map<std::string, std::string> DefaultMetadata() { + return std::map<std::string, std::string>{{"key", "value"}}; +} + +Metric::TimeSeries::Sample Sample(double value) { + return Metric::TimeSeries::Sample{.timestamp = Timestamp::Seconds(1), + .value = value, + .sample_metadata = DefaultMetadata()}; +} + +Metric PsnrForTestFoo(double mean, double stddev) { + return Metric{.name = "psnr", + .unit = Unit::kUnitless, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "foo", + .time_series = Metric::TimeSeries{}, + .stats = Metric::Stats{.mean = mean, .stddev = stddev}}; +} + +TEST(StdoutMetricsExporterTest, ExportMetricFormatCorrect) { + Metric metric1{ + .name = "test_metric1", + .unit = Unit::kMilliseconds, + .improvement_direction = ImprovementDirection::kBiggerIsBetter, + .test_case = "test_case_name1", + .metric_metadata = DefaultMetadata(), + .time_series = + Metric::TimeSeries{.samples = std::vector{Sample(10), Sample(20)}}, + .stats = + Metric::Stats{.mean = 15.0, .stddev = 5.0, .min = 10.0, .max = 20.0}}; + Metric metric2{ + .name = "test_metric2", + .unit = Unit::kKilobitsPerSecond, + .improvement_direction = ImprovementDirection::kSmallerIsBetter, + .test_case = "test_case_name2", + .metric_metadata = DefaultMetadata(), + .time_series = + Metric::TimeSeries{.samples = std::vector{Sample(20), Sample(40)}}, + .stats = Metric::Stats{ + .mean = 30.0, .stddev = 10.0, .min = 20.0, .max = 40.0}}; + + testing::internal::CaptureStdout(); + StdoutMetricsExporter exporter; + + std::string expected = + "RESULT: test_case_name1 / test_metric1= " + "{mean=15, stddev=5} Milliseconds (BiggerIsBetter)\n" + "RESULT: test_case_name2 / test_metric2= " + "{mean=30, stddev=10} KilobitsPerSecond (SmallerIsBetter)\n"; + + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric1, metric2})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(StdoutMetricsExporterNumberFormatTest, PositiveNumberMaxPrecision) { + testing::internal::CaptureStdout(); + StdoutMetricsExporter exporter; + + Metric metric = PsnrForTestFoo(15.00000001, 0.00000001); + std::string expected = + "RESULT: foo / psnr= " + "{mean=15.00000001, stddev=0.00000001} Unitless (BiggerIsBetter)\n"; + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(StdoutMetricsExporterNumberFormatTest, + PositiveNumberTrailingZeroNotAdded) { + testing::internal::CaptureStdout(); + StdoutMetricsExporter exporter; + + Metric metric = PsnrForTestFoo(15.12345, 0.12); + std::string expected = + "RESULT: foo / psnr= " + "{mean=15.12345, stddev=0.12} Unitless (BiggerIsBetter)\n"; + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(StdoutMetricsExporterNumberFormatTest, + PositiveNumberTrailingZeroAreRemoved) { + testing::internal::CaptureStdout(); + StdoutMetricsExporter exporter; + + Metric metric = PsnrForTestFoo(15.123450000, 0.120000000); + std::string expected = + "RESULT: foo / psnr= " + "{mean=15.12345, stddev=0.12} Unitless (BiggerIsBetter)\n"; + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(StdoutMetricsExporterNumberFormatTest, + PositiveNumberRoundsUpOnPrecisionCorrectly) { + testing::internal::CaptureStdout(); + StdoutMetricsExporter exporter; + + Metric metric = PsnrForTestFoo(15.000000009, 0.999999999); + std::string expected = + "RESULT: foo / psnr= " + "{mean=15.00000001, stddev=1} Unitless (BiggerIsBetter)\n"; + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(StdoutMetricsExporterNumberFormatTest, + PositiveNumberRoundsDownOnPrecisionCorrectly) { + testing::internal::CaptureStdout(); + StdoutMetricsExporter exporter; + + Metric metric = PsnrForTestFoo(15.0000000049, 0.9999999949); + std::string expected = + "RESULT: foo / psnr= " + "{mean=15, stddev=0.99999999} Unitless (BiggerIsBetter)\n"; + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(StdoutMetricsExporterNumberFormatTest, NegativeNumberMaxPrecision) { + testing::internal::CaptureStdout(); + StdoutMetricsExporter exporter; + + Metric metric = PsnrForTestFoo(-15.00000001, -0.00000001); + std::string expected = + "RESULT: foo / psnr= " + "{mean=-15.00000001, stddev=-0.00000001} Unitless (BiggerIsBetter)\n"; + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(StdoutMetricsExporterNumberFormatTest, + NegativeNumberTrailingZeroNotAdded) { + testing::internal::CaptureStdout(); + StdoutMetricsExporter exporter; + + Metric metric = PsnrForTestFoo(-15.12345, -0.12); + std::string expected = + "RESULT: foo / psnr= " + "{mean=-15.12345, stddev=-0.12} Unitless (BiggerIsBetter)\n"; + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(StdoutMetricsExporterNumberFormatTest, + NegativeNumberTrailingZeroAreRemoved) { + testing::internal::CaptureStdout(); + StdoutMetricsExporter exporter; + + Metric metric = PsnrForTestFoo(-15.123450000, -0.120000000); + std::string expected = + "RESULT: foo / psnr= " + "{mean=-15.12345, stddev=-0.12} Unitless (BiggerIsBetter)\n"; + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(StdoutMetricsExporterNumberFormatTest, + NegativeNumberRoundsUpOnPrecisionCorrectly) { + testing::internal::CaptureStdout(); + StdoutMetricsExporter exporter; + + Metric metric = PsnrForTestFoo(-15.000000009, -0.999999999); + std::string expected = + "RESULT: foo / psnr= " + "{mean=-15.00000001, stddev=-1} Unitless (BiggerIsBetter)\n"; + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +TEST(StdoutMetricsExporterNumberFormatTest, + NegativeNumberRoundsDownOnPrecisionCorrectly) { + testing::internal::CaptureStdout(); + StdoutMetricsExporter exporter; + + Metric metric = PsnrForTestFoo(-15.0000000049, -0.9999999949); + std::string expected = + "RESULT: foo / psnr= " + "{mean=-15, stddev=-0.99999999} Unitless (BiggerIsBetter)\n"; + EXPECT_TRUE(exporter.Export(std::vector<Metric>{metric})); + EXPECT_EQ(expected, testing::internal::GetCapturedStdout()); +} + +} // namespace +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/mock_async_dns_resolver.h b/third_party/libwebrtc/api/test/mock_async_dns_resolver.h new file mode 100644 index 0000000000..81132c96a5 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_async_dns_resolver.h @@ -0,0 +1,62 @@ +/* + * Copyright 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 API_TEST_MOCK_ASYNC_DNS_RESOLVER_H_ +#define API_TEST_MOCK_ASYNC_DNS_RESOLVER_H_ + +#include <functional> +#include <memory> + +#include "api/async_dns_resolver.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockAsyncDnsResolverResult : public AsyncDnsResolverResult { + public: + MOCK_METHOD(bool, + GetResolvedAddress, + (int, rtc::SocketAddress*), + (const, override)); + MOCK_METHOD(int, GetError, (), (const, override)); +}; + +class MockAsyncDnsResolver : public AsyncDnsResolverInterface { + public: + MOCK_METHOD(void, + Start, + (const rtc::SocketAddress&, std::function<void()>), + (override)); + MOCK_METHOD(void, + Start, + (const rtc::SocketAddress&, int family, std::function<void()>), + (override)); + MOCK_METHOD(AsyncDnsResolverResult&, result, (), (const, override)); +}; + +class MockAsyncDnsResolverFactory : public AsyncDnsResolverFactoryInterface { + public: + MOCK_METHOD(std::unique_ptr<webrtc::AsyncDnsResolverInterface>, + CreateAndResolve, + (const rtc::SocketAddress&, std::function<void()>), + (override)); + MOCK_METHOD(std::unique_ptr<webrtc::AsyncDnsResolverInterface>, + CreateAndResolve, + (const rtc::SocketAddress&, int, std::function<void()>), + (override)); + MOCK_METHOD(std::unique_ptr<webrtc::AsyncDnsResolverInterface>, + Create, + (), + (override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_ASYNC_DNS_RESOLVER_H_ diff --git a/third_party/libwebrtc/api/test/mock_audio_mixer.h b/third_party/libwebrtc/api/test/mock_audio_mixer.h new file mode 100644 index 0000000000..88dc108ca3 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_audio_mixer.h @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#ifndef API_TEST_MOCK_AUDIO_MIXER_H_ +#define API_TEST_MOCK_AUDIO_MIXER_H_ + +#include "api/audio/audio_mixer.h" +#include "test/gmock.h" + +namespace webrtc { +namespace test { + +class MockAudioMixer : public AudioMixer { + public: + MOCK_METHOD(bool, AddSource, (Source*), (override)); + MOCK_METHOD(void, RemoveSource, (Source*), (override)); + MOCK_METHOD(void, Mix, (size_t number_of_channels, AudioFrame*), (override)); +}; +} // namespace test +} // namespace webrtc + +#endif // API_TEST_MOCK_AUDIO_MIXER_H_ diff --git a/third_party/libwebrtc/api/test/mock_audio_sink.h b/third_party/libwebrtc/api/test/mock_audio_sink.h new file mode 100644 index 0000000000..88f38a3c57 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_audio_sink.h @@ -0,0 +1,44 @@ +/* + * Copyright 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 API_TEST_MOCK_AUDIO_SINK_H_ +#define API_TEST_MOCK_AUDIO_SINK_H_ + +#include "absl/types/optional.h" +#include "api/media_stream_interface.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockAudioSink : public webrtc::AudioTrackSinkInterface { + public: + MOCK_METHOD(void, + OnData, + (const void* audio_data, + int bits_per_sample, + int sample_rate, + size_t number_of_channels, + size_t number_of_frames), + (override)); + + MOCK_METHOD(void, + OnData, + (const void* audio_data, + int bits_per_sample, + int sample_rate, + size_t number_of_channels, + size_t number_of_frames, + absl::optional<int64_t> absolute_capture_timestamp_ms), + (override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_AUDIO_SINK_H_ diff --git a/third_party/libwebrtc/api/test/mock_data_channel.h b/third_party/libwebrtc/api/test/mock_data_channel.h new file mode 100644 index 0000000000..38730eaa51 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_data_channel.h @@ -0,0 +1,61 @@ +/* + * Copyright 2020 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 API_TEST_MOCK_DATA_CHANNEL_H_ +#define API_TEST_MOCK_DATA_CHANNEL_H_ + +#include <string> + +#include "api/data_channel_interface.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockDataChannelInterface + : public rtc::RefCountedObject<webrtc::DataChannelInterface> { + public: + static rtc::scoped_refptr<MockDataChannelInterface> Create() { + return rtc::scoped_refptr<MockDataChannelInterface>( + new MockDataChannelInterface()); + } + + MOCK_METHOD(void, + RegisterObserver, + (DataChannelObserver * observer), + (override)); + MOCK_METHOD(void, UnregisterObserver, (), (override)); + MOCK_METHOD(std::string, label, (), (const, override)); + MOCK_METHOD(bool, reliable, (), (const, override)); + MOCK_METHOD(bool, ordered, (), (const, override)); + MOCK_METHOD(uint16_t, maxRetransmitTime, (), (const, override)); + MOCK_METHOD(uint16_t, maxRetransmits, (), (const, override)); + MOCK_METHOD(absl::optional<int>, maxRetransmitsOpt, (), (const, override)); + MOCK_METHOD(absl::optional<int>, maxPacketLifeTime, (), (const, override)); + MOCK_METHOD(std::string, protocol, (), (const, override)); + MOCK_METHOD(bool, negotiated, (), (const, override)); + MOCK_METHOD(int, id, (), (const, override)); + MOCK_METHOD(Priority, priority, (), (const, override)); + MOCK_METHOD(DataState, state, (), (const, override)); + MOCK_METHOD(RTCError, error, (), (const, override)); + MOCK_METHOD(uint32_t, messages_sent, (), (const, override)); + MOCK_METHOD(uint64_t, bytes_sent, (), (const, override)); + MOCK_METHOD(uint32_t, messages_received, (), (const, override)); + MOCK_METHOD(uint64_t, bytes_received, (), (const, override)); + MOCK_METHOD(uint64_t, buffered_amount, (), (const, override)); + MOCK_METHOD(void, Close, (), (override)); + MOCK_METHOD(bool, Send, (const DataBuffer& buffer), (override)); + + protected: + MockDataChannelInterface() = default; +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_DATA_CHANNEL_H_ diff --git a/third_party/libwebrtc/api/test/mock_dtmf_sender.h b/third_party/libwebrtc/api/test/mock_dtmf_sender.h new file mode 100644 index 0000000000..9029195025 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_dtmf_sender.h @@ -0,0 +1,56 @@ +/* + * Copyright 2022 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 API_TEST_MOCK_DTMF_SENDER_H_ +#define API_TEST_MOCK_DTMF_SENDER_H_ + +#include <string> + +#include "api/dtmf_sender_interface.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockDtmfSenderObserver : public DtmfSenderObserverInterface { + public: + MOCK_METHOD(void, + OnToneChange, + (const std::string&, const std::string&), + (override)); + MOCK_METHOD(void, OnToneChange, (const std::string&), (override)); +}; + +static_assert(!std::is_abstract_v<MockDtmfSenderObserver>, ""); + +class MockDtmfSender : public DtmfSenderInterface { + public: + static rtc::scoped_refptr<MockDtmfSender> Create() { + return rtc::make_ref_counted<MockDtmfSender>(); + } + + MOCK_METHOD(void, + RegisterObserver, + (DtmfSenderObserverInterface * observer), + (override)); + MOCK_METHOD(void, UnregisterObserver, (), (override)); + MOCK_METHOD(bool, CanInsertDtmf, (), (override)); + MOCK_METHOD(std::string, tones, (), (const override)); + MOCK_METHOD(int, duration, (), (const override)); + MOCK_METHOD(int, inter_tone_gap, (), (const override)); + + protected: + MockDtmfSender() = default; +}; + +static_assert(!std::is_abstract_v<rtc::RefCountedObject<MockDtmfSender>>, ""); + +} // namespace webrtc + +#endif // API_TEST_MOCK_DTMF_SENDER_H_ diff --git a/third_party/libwebrtc/api/test/mock_encoder_selector.h b/third_party/libwebrtc/api/test/mock_encoder_selector.h new file mode 100644 index 0000000000..2e018d57ba --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_encoder_selector.h @@ -0,0 +1,42 @@ +/* + * Copyright 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. + */ + +#ifndef API_TEST_MOCK_ENCODER_SELECTOR_H_ +#define API_TEST_MOCK_ENCODER_SELECTOR_H_ + +#include "api/video_codecs/video_encoder_factory.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockEncoderSelector + : public VideoEncoderFactory::EncoderSelectorInterface { + public: + MOCK_METHOD(void, + OnCurrentEncoder, + (const SdpVideoFormat& format), + (override)); + + MOCK_METHOD(absl::optional<SdpVideoFormat>, + OnAvailableBitrate, + (const DataRate& rate), + (override)); + + MOCK_METHOD(absl::optional<SdpVideoFormat>, + OnResolutionChange, + (const RenderResolution& resolution), + (override)); + + MOCK_METHOD(absl::optional<SdpVideoFormat>, OnEncoderBroken, (), (override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_ENCODER_SELECTOR_H_ diff --git a/third_party/libwebrtc/api/test/mock_fec_controller_override.h b/third_party/libwebrtc/api/test/mock_fec_controller_override.h new file mode 100644 index 0000000000..8f3accbc03 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_fec_controller_override.h @@ -0,0 +1,26 @@ +/* + * Copyright 2019 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 API_TEST_MOCK_FEC_CONTROLLER_OVERRIDE_H_ +#define API_TEST_MOCK_FEC_CONTROLLER_OVERRIDE_H_ + +#include "api/fec_controller_override.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockFecControllerOverride : public FecControllerOverride { + public: + MOCK_METHOD(void, SetFecAllowed, (bool fec_allowed), (override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_FEC_CONTROLLER_OVERRIDE_H_ diff --git a/third_party/libwebrtc/api/test/mock_frame_decryptor.h b/third_party/libwebrtc/api/test/mock_frame_decryptor.h new file mode 100644 index 0000000000..9604b96cc2 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_frame_decryptor.h @@ -0,0 +1,40 @@ +/* + * Copyright 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. + */ + +#ifndef API_TEST_MOCK_FRAME_DECRYPTOR_H_ +#define API_TEST_MOCK_FRAME_DECRYPTOR_H_ + +#include <vector> + +#include "api/crypto/frame_decryptor_interface.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockFrameDecryptor : public FrameDecryptorInterface { + public: + MOCK_METHOD(Result, + Decrypt, + (cricket::MediaType, + const std::vector<uint32_t>&, + rtc::ArrayView<const uint8_t>, + rtc::ArrayView<const uint8_t>, + rtc::ArrayView<uint8_t>), + (override)); + + MOCK_METHOD(size_t, + GetMaxPlaintextByteSize, + (cricket::MediaType, size_t encrypted_frame_size), + (override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_FRAME_DECRYPTOR_H_ diff --git a/third_party/libwebrtc/api/test/mock_frame_encryptor.h b/third_party/libwebrtc/api/test/mock_frame_encryptor.h new file mode 100644 index 0000000000..e47321f801 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_frame_encryptor.h @@ -0,0 +1,39 @@ +/* + * Copyright 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. + */ + +#ifndef API_TEST_MOCK_FRAME_ENCRYPTOR_H_ +#define API_TEST_MOCK_FRAME_ENCRYPTOR_H_ + +#include "api/crypto/frame_encryptor_interface.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockFrameEncryptor : public FrameEncryptorInterface { + public: + MOCK_METHOD(int, + Encrypt, + (cricket::MediaType, + uint32_t, + rtc::ArrayView<const uint8_t>, + rtc::ArrayView<const uint8_t>, + rtc::ArrayView<uint8_t>, + size_t*), + (override)); + + MOCK_METHOD(size_t, + GetMaxCiphertextByteSize, + (cricket::MediaType media_type, size_t frame_size), + (override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_FRAME_ENCRYPTOR_H_ diff --git a/third_party/libwebrtc/api/test/mock_media_stream_interface.h b/third_party/libwebrtc/api/test/mock_media_stream_interface.h new file mode 100644 index 0000000000..dfdbab35e9 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_media_stream_interface.h @@ -0,0 +1,134 @@ +/* + * Copyright 2020 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 API_TEST_MOCK_MEDIA_STREAM_INTERFACE_H_ +#define API_TEST_MOCK_MEDIA_STREAM_INTERFACE_H_ + +#include <string> + +#include "api/media_stream_interface.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockAudioSource : public rtc::RefCountedObject<AudioSourceInterface> { + public: + static rtc::scoped_refptr<MockAudioSource> Create() { + return rtc::scoped_refptr<MockAudioSource>(new MockAudioSource()); + } + + MOCK_METHOD(void, + RegisterObserver, + (ObserverInterface * observer), + (override)); + MOCK_METHOD(void, + UnregisterObserver, + (ObserverInterface * observer), + (override)); + MOCK_METHOD(SourceState, state, (), (const, override)); + MOCK_METHOD(bool, remote, (), (const, override)); + MOCK_METHOD(void, SetVolume, (double volume), (override)); + MOCK_METHOD(void, + RegisterAudioObserver, + (AudioObserver * observer), + (override)); + MOCK_METHOD(void, + UnregisterAudioObserver, + (AudioObserver * observer), + (override)); + MOCK_METHOD(void, AddSink, (AudioTrackSinkInterface * sink), (override)); + MOCK_METHOD(void, RemoveSink, (AudioTrackSinkInterface * sink), (override)); + MOCK_METHOD(const cricket::AudioOptions, options, (), (const, override)); + + private: + MockAudioSource() = default; +}; + +class MockAudioTrack : public rtc::RefCountedObject<AudioTrackInterface> { + public: + static rtc::scoped_refptr<MockAudioTrack> Create() { + return rtc::scoped_refptr<MockAudioTrack>(new MockAudioTrack()); + } + + MOCK_METHOD(void, + RegisterObserver, + (ObserverInterface * observer), + (override)); + MOCK_METHOD(void, + UnregisterObserver, + (ObserverInterface * observer), + (override)); + MOCK_METHOD(std::string, kind, (), (const, override)); + MOCK_METHOD(std::string, id, (), (const, override)); + MOCK_METHOD(bool, enabled, (), (const, override)); + MOCK_METHOD(bool, set_enabled, (bool enable), (override)); + MOCK_METHOD(TrackState, state, (), (const, override)); + MOCK_METHOD(AudioSourceInterface*, GetSource, (), (const, override)); + MOCK_METHOD(void, AddSink, (AudioTrackSinkInterface * sink), (override)); + MOCK_METHOD(void, RemoveSink, (AudioTrackSinkInterface * sink), (override)); + MOCK_METHOD(bool, GetSignalLevel, (int* level), (override)); + MOCK_METHOD(rtc::scoped_refptr<AudioProcessorInterface>, + GetAudioProcessor, + (), + (override)); + + private: + MockAudioTrack() = default; +}; + +class MockMediaStream : public MediaStreamInterface { + public: + MOCK_METHOD(std::string, id, (), (const override)); + MOCK_METHOD(AudioTrackVector, GetAudioTracks, (), (override)); + MOCK_METHOD(VideoTrackVector, GetVideoTracks, (), (override)); + MOCK_METHOD(rtc::scoped_refptr<AudioTrackInterface>, + FindAudioTrack, + (const std::string& track_id), + (override)); + MOCK_METHOD(rtc::scoped_refptr<VideoTrackInterface>, + FindVideoTrack, + (const std::string& track_id), + (override)); + MOCK_METHOD(bool, + AddTrack, + (rtc::scoped_refptr<AudioTrackInterface> track), + (override)); + MOCK_METHOD(bool, + AddTrack, + (rtc::scoped_refptr<VideoTrackInterface> track), + (override)); + MOCK_METHOD(bool, + RemoveTrack, + (rtc::scoped_refptr<AudioTrackInterface> track), + (override)); + MOCK_METHOD(bool, + RemoveTrack, + (rtc::scoped_refptr<VideoTrackInterface> track), + (override)); + // Old AddTrack/RemoveTrack methods - slated for removal + MOCK_METHOD(bool, AddTrack, (AudioTrackInterface * track), (override)); + MOCK_METHOD(bool, AddTrack, (VideoTrackInterface * track), (override)); + MOCK_METHOD(bool, RemoveTrack, (AudioTrackInterface * track), (override)); + MOCK_METHOD(bool, RemoveTrack, (VideoTrackInterface * track), (override)); + MOCK_METHOD(void, + RegisterObserver, + (ObserverInterface * observer), + (override)); + MOCK_METHOD(void, + UnregisterObserver, + (ObserverInterface * observer), + (override)); +}; + +static_assert(!std::is_abstract_v<rtc::RefCountedObject<MockMediaStream>>, ""); + +} // namespace webrtc + +#endif // API_TEST_MOCK_MEDIA_STREAM_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/test/mock_packet_socket_factory.h b/third_party/libwebrtc/api/test/mock_packet_socket_factory.h new file mode 100644 index 0000000000..7e59556385 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_packet_socket_factory.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 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 API_TEST_MOCK_PACKET_SOCKET_FACTORY_H_ +#define API_TEST_MOCK_PACKET_SOCKET_FACTORY_H_ + +#include <memory> +#include <string> + +#include "api/packet_socket_factory.h" +#include "test/gmock.h" + +namespace rtc { +class MockPacketSocketFactory : public PacketSocketFactory { + public: + MOCK_METHOD(AsyncPacketSocket*, + CreateUdpSocket, + (const SocketAddress&, uint16_t, uint16_t), + (override)); + MOCK_METHOD(AsyncListenSocket*, + CreateServerTcpSocket, + (const SocketAddress&, uint16_t, uint16_t, int opts), + (override)); + MOCK_METHOD(AsyncPacketSocket*, + CreateClientTcpSocket, + (const SocketAddress& local_address, + const SocketAddress&, + const ProxyInfo&, + const std::string&, + const PacketSocketTcpOptions&), + (override)); + MOCK_METHOD(std::unique_ptr<webrtc::AsyncDnsResolverInterface>, + CreateAsyncDnsResolver, + (), + (override)); +}; + +static_assert(!std::is_abstract_v<MockPacketSocketFactory>, ""); + +} // namespace rtc + +#endif // API_TEST_MOCK_PACKET_SOCKET_FACTORY_H_ diff --git a/third_party/libwebrtc/api/test/mock_peer_connection_factory_interface.h b/third_party/libwebrtc/api/test/mock_peer_connection_factory_interface.h new file mode 100644 index 0000000000..ae1fbfbbb7 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_peer_connection_factory_interface.h @@ -0,0 +1,81 @@ +/* + * Copyright 2020 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 API_TEST_MOCK_PEER_CONNECTION_FACTORY_INTERFACE_H_ +#define API_TEST_MOCK_PEER_CONNECTION_FACTORY_INTERFACE_H_ + +#include <memory> +#include <string> + +#include "api/peer_connection_interface.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockPeerConnectionFactoryInterface + : public rtc::RefCountedObject<webrtc::PeerConnectionFactoryInterface> { + public: + static rtc::scoped_refptr<MockPeerConnectionFactoryInterface> Create() { + return rtc::scoped_refptr<MockPeerConnectionFactoryInterface>( + new MockPeerConnectionFactoryInterface()); + } + + MOCK_METHOD(void, SetOptions, (const Options&), (override)); + MOCK_METHOD(rtc::scoped_refptr<PeerConnectionInterface>, + CreatePeerConnection, + (const PeerConnectionInterface::RTCConfiguration&, + PeerConnectionDependencies), + (override)); + MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<PeerConnectionInterface>>, + CreatePeerConnectionOrError, + (const PeerConnectionInterface::RTCConfiguration&, + PeerConnectionDependencies), + (override)); + MOCK_METHOD(rtc::scoped_refptr<PeerConnectionInterface>, + CreatePeerConnection, + (const PeerConnectionInterface::RTCConfiguration&, + std::unique_ptr<cricket::PortAllocator>, + std::unique_ptr<rtc::RTCCertificateGeneratorInterface>, + PeerConnectionObserver*), + (override)); + MOCK_METHOD(RtpCapabilities, + GetRtpSenderCapabilities, + (cricket::MediaType), + (const, override)); + MOCK_METHOD(RtpCapabilities, + GetRtpReceiverCapabilities, + (cricket::MediaType), + (const, override)); + MOCK_METHOD(rtc::scoped_refptr<MediaStreamInterface>, + CreateLocalMediaStream, + (const std::string&), + (override)); + MOCK_METHOD(rtc::scoped_refptr<AudioSourceInterface>, + CreateAudioSource, + (const cricket::AudioOptions&), + (override)); + MOCK_METHOD(rtc::scoped_refptr<VideoTrackInterface>, + CreateVideoTrack, + (const std::string&, VideoTrackSourceInterface*), + (override)); + MOCK_METHOD(rtc::scoped_refptr<AudioTrackInterface>, + CreateAudioTrack, + (const std::string&, AudioSourceInterface*), + (override)); + MOCK_METHOD(bool, StartAecDump, (FILE*, int64_t), (override)); + MOCK_METHOD(void, StopAecDump, (), (override)); + + protected: + MockPeerConnectionFactoryInterface() = default; +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_PEER_CONNECTION_FACTORY_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/test/mock_peerconnectioninterface.h b/third_party/libwebrtc/api/test/mock_peerconnectioninterface.h new file mode 100644 index 0000000000..ccc6ce46b1 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_peerconnectioninterface.h @@ -0,0 +1,213 @@ +/* + * Copyright 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. + */ + +#ifndef API_TEST_MOCK_PEERCONNECTIONINTERFACE_H_ +#define API_TEST_MOCK_PEERCONNECTIONINTERFACE_H_ + +#include <memory> +#include <string> +#include <type_traits> +#include <utility> +#include <vector> + +#include "api/peer_connection_interface.h" +#include "api/scoped_refptr.h" +#include "api/sctp_transport_interface.h" +#include "rtc_base/ref_counted_object.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockPeerConnectionInterface : public webrtc::PeerConnectionInterface { + public: + static rtc::scoped_refptr<MockPeerConnectionInterface> Create() { + return rtc::make_ref_counted<MockPeerConnectionInterface>(); + } + + // PeerConnectionInterface + MOCK_METHOD(rtc::scoped_refptr<StreamCollectionInterface>, + local_streams, + (), + (override)); + MOCK_METHOD(rtc::scoped_refptr<StreamCollectionInterface>, + remote_streams, + (), + (override)); + MOCK_METHOD(bool, AddStream, (MediaStreamInterface*), (override)); + MOCK_METHOD(void, RemoveStream, (MediaStreamInterface*), (override)); + MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>, + AddTrack, + (rtc::scoped_refptr<MediaStreamTrackInterface>, + const std::vector<std::string>&), + (override)); + MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>, + AddTrack, + (rtc::scoped_refptr<MediaStreamTrackInterface>, + const std::vector<std::string>&, + const std::vector<RtpEncodingParameters>&), + (override)); + MOCK_METHOD(RTCError, + RemoveTrackOrError, + (rtc::scoped_refptr<RtpSenderInterface>), + (override)); + MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>, + AddTransceiver, + (rtc::scoped_refptr<MediaStreamTrackInterface>), + (override)); + MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>, + AddTransceiver, + (rtc::scoped_refptr<MediaStreamTrackInterface>, + const RtpTransceiverInit&), + (override)); + MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>, + AddTransceiver, + (cricket::MediaType), + (override)); + MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>, + AddTransceiver, + (cricket::MediaType, const RtpTransceiverInit&), + (override)); + MOCK_METHOD(rtc::scoped_refptr<RtpSenderInterface>, + CreateSender, + (const std::string&, const std::string&), + (override)); + MOCK_METHOD(std::vector<rtc::scoped_refptr<RtpSenderInterface>>, + GetSenders, + (), + (const, override)); + MOCK_METHOD(std::vector<rtc::scoped_refptr<RtpReceiverInterface>>, + GetReceivers, + (), + (const, override)); + MOCK_METHOD(std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>, + GetTransceivers, + (), + (const, override)); + MOCK_METHOD(bool, + GetStats, + (StatsObserver*, MediaStreamTrackInterface*, StatsOutputLevel), + (override)); + MOCK_METHOD(void, GetStats, (RTCStatsCollectorCallback*), (override)); + MOCK_METHOD(void, + GetStats, + (rtc::scoped_refptr<RtpSenderInterface>, + rtc::scoped_refptr<RTCStatsCollectorCallback>), + (override)); + MOCK_METHOD(void, + GetStats, + (rtc::scoped_refptr<RtpReceiverInterface>, + rtc::scoped_refptr<RTCStatsCollectorCallback>), + (override)); + MOCK_METHOD(void, ClearStatsCache, (), (override)); + MOCK_METHOD(rtc::scoped_refptr<SctpTransportInterface>, + GetSctpTransport, + (), + (const, override)); + MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<DataChannelInterface>>, + CreateDataChannelOrError, + (const std::string&, const DataChannelInit*), + (override)); + MOCK_METHOD(const SessionDescriptionInterface*, + local_description, + (), + (const, override)); + MOCK_METHOD(const SessionDescriptionInterface*, + remote_description, + (), + (const, override)); + MOCK_METHOD(const SessionDescriptionInterface*, + current_local_description, + (), + (const, override)); + MOCK_METHOD(const SessionDescriptionInterface*, + current_remote_description, + (), + (const, override)); + MOCK_METHOD(const SessionDescriptionInterface*, + pending_local_description, + (), + (const, override)); + MOCK_METHOD(const SessionDescriptionInterface*, + pending_remote_description, + (), + (const, override)); + MOCK_METHOD(void, RestartIce, (), (override)); + MOCK_METHOD(void, + CreateOffer, + (CreateSessionDescriptionObserver*, const RTCOfferAnswerOptions&), + (override)); + MOCK_METHOD(void, + CreateAnswer, + (CreateSessionDescriptionObserver*, const RTCOfferAnswerOptions&), + (override)); + MOCK_METHOD(void, + SetLocalDescription, + (SetSessionDescriptionObserver*, SessionDescriptionInterface*), + (override)); + MOCK_METHOD(void, + SetRemoteDescription, + (SetSessionDescriptionObserver*, SessionDescriptionInterface*), + (override)); + MOCK_METHOD(void, + SetRemoteDescription, + (std::unique_ptr<SessionDescriptionInterface>, + rtc::scoped_refptr<SetRemoteDescriptionObserverInterface>), + (override)); + MOCK_METHOD(PeerConnectionInterface::RTCConfiguration, + GetConfiguration, + (), + (override)); + MOCK_METHOD(RTCError, + SetConfiguration, + (const PeerConnectionInterface::RTCConfiguration&), + (override)); + MOCK_METHOD(bool, + AddIceCandidate, + (const IceCandidateInterface*), + (override)); + MOCK_METHOD(bool, + RemoveIceCandidates, + (const std::vector<cricket::Candidate>&), + (override)); + MOCK_METHOD(RTCError, SetBitrate, (const BitrateSettings&), (override)); + MOCK_METHOD(void, SetAudioPlayout, (bool), (override)); + MOCK_METHOD(void, SetAudioRecording, (bool), (override)); + MOCK_METHOD(rtc::scoped_refptr<DtlsTransportInterface>, + LookupDtlsTransportByMid, + (const std::string&), + (override)); + MOCK_METHOD(SignalingState, signaling_state, (), (override)); + MOCK_METHOD(IceConnectionState, ice_connection_state, (), (override)); + MOCK_METHOD(IceConnectionState, + standardized_ice_connection_state, + (), + (override)); + MOCK_METHOD(PeerConnectionState, peer_connection_state, (), (override)); + MOCK_METHOD(IceGatheringState, ice_gathering_state, (), (override)); + MOCK_METHOD(absl::optional<bool>, can_trickle_ice_candidates, (), (override)); + MOCK_METHOD(bool, + StartRtcEventLog, + (std::unique_ptr<RtcEventLogOutput>, int64_t), + (override)); + MOCK_METHOD(bool, + StartRtcEventLog, + (std::unique_ptr<RtcEventLogOutput>), + (override)); + MOCK_METHOD(void, StopRtcEventLog, (), (override)); + MOCK_METHOD(void, Close, (), (override)); +}; + +static_assert( + !std::is_abstract_v<rtc::RefCountedObject<MockPeerConnectionInterface>>, + ""); + +} // namespace webrtc + +#endif // API_TEST_MOCK_PEERCONNECTIONINTERFACE_H_ diff --git a/third_party/libwebrtc/api/test/mock_rtp_transceiver.h b/third_party/libwebrtc/api/test/mock_rtp_transceiver.h new file mode 100644 index 0000000000..1d21bce5eb --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_rtp_transceiver.h @@ -0,0 +1,87 @@ +/* + * Copyright 2020 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 API_TEST_MOCK_RTP_TRANSCEIVER_H_ +#define API_TEST_MOCK_RTP_TRANSCEIVER_H_ + +#include <string> +#include <vector> + +#include "api/rtp_transceiver_interface.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockRtpTransceiver : public RtpTransceiverInterface { + public: + MockRtpTransceiver() = default; + + static rtc::scoped_refptr<MockRtpTransceiver> Create() { + return rtc::make_ref_counted<MockRtpTransceiver>(); + } + + MOCK_METHOD(cricket::MediaType, media_type, (), (const, override)); + MOCK_METHOD(absl::optional<std::string>, mid, (), (const, override)); + MOCK_METHOD(rtc::scoped_refptr<RtpSenderInterface>, + sender, + (), + (const, override)); + MOCK_METHOD(rtc::scoped_refptr<RtpReceiverInterface>, + receiver, + (), + (const, override)); + MOCK_METHOD(bool, stopped, (), (const, override)); + MOCK_METHOD(bool, stopping, (), (const, override)); + MOCK_METHOD(RtpTransceiverDirection, direction, (), (const, override)); + MOCK_METHOD(void, + SetDirection, + (RtpTransceiverDirection new_direction), + (override)); + MOCK_METHOD(RTCError, + SetDirectionWithError, + (RtpTransceiverDirection new_direction), + (override)); + MOCK_METHOD(absl::optional<RtpTransceiverDirection>, + current_direction, + (), + (const, override)); + MOCK_METHOD(absl::optional<RtpTransceiverDirection>, + fired_direction, + (), + (const, override)); + MOCK_METHOD(RTCError, StopStandard, (), (override)); + MOCK_METHOD(void, StopInternal, (), (override)); + MOCK_METHOD(void, Stop, (), (override)); + MOCK_METHOD(RTCError, + SetCodecPreferences, + (rtc::ArrayView<RtpCodecCapability> codecs), + (override)); + MOCK_METHOD(std::vector<RtpCodecCapability>, + codec_preferences, + (), + (const, override)); + MOCK_METHOD(std::vector<RtpHeaderExtensionCapability>, + HeaderExtensionsToOffer, + (), + (const, override)); + MOCK_METHOD(std::vector<RtpHeaderExtensionCapability>, + HeaderExtensionsNegotiated, + (), + (const, override)); + MOCK_METHOD(webrtc::RTCError, + SetOfferedRtpHeaderExtensions, + (rtc::ArrayView<const RtpHeaderExtensionCapability> + header_extensions_to_offer), + (override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_RTP_TRANSCEIVER_H_ diff --git a/third_party/libwebrtc/api/test/mock_rtpreceiver.h b/third_party/libwebrtc/api/test/mock_rtpreceiver.h new file mode 100644 index 0000000000..63318dc32d --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_rtpreceiver.h @@ -0,0 +1,58 @@ +/* + * Copyright 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. + */ + +#ifndef API_TEST_MOCK_RTPRECEIVER_H_ +#define API_TEST_MOCK_RTPRECEIVER_H_ + +#include <string> +#include <vector> + +#include "api/crypto/frame_decryptor_interface.h" +#include "api/rtp_receiver_interface.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockRtpReceiver : public rtc::RefCountedObject<RtpReceiverInterface> { + public: + MOCK_METHOD(rtc::scoped_refptr<MediaStreamTrackInterface>, + track, + (), + (const, override)); + MOCK_METHOD(std::vector<rtc::scoped_refptr<MediaStreamInterface>>, + streams, + (), + (const, override)); + MOCK_METHOD(cricket::MediaType, media_type, (), (const, override)); + MOCK_METHOD(std::string, id, (), (const, override)); + MOCK_METHOD(RtpParameters, GetParameters, (), (const, override)); + MOCK_METHOD(bool, + SetParameters, + (const webrtc::RtpParameters& parameters), + (override)); + MOCK_METHOD(void, SetObserver, (RtpReceiverObserverInterface*), (override)); + MOCK_METHOD(void, + SetJitterBufferMinimumDelay, + (absl::optional<double>), + (override)); + MOCK_METHOD(std::vector<RtpSource>, GetSources, (), (const, override)); + MOCK_METHOD(void, + SetFrameDecryptor, + (rtc::scoped_refptr<webrtc::FrameDecryptorInterface>), + (override)); + MOCK_METHOD(rtc::scoped_refptr<webrtc::FrameDecryptorInterface>, + GetFrameDecryptor, + (), + (const, override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_RTPRECEIVER_H_ diff --git a/third_party/libwebrtc/api/test/mock_rtpsender.h b/third_party/libwebrtc/api/test/mock_rtpsender.h new file mode 100644 index 0000000000..22113678b9 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_rtpsender.h @@ -0,0 +1,78 @@ +/* + * Copyright 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. + */ + +#ifndef API_TEST_MOCK_RTPSENDER_H_ +#define API_TEST_MOCK_RTPSENDER_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "api/rtp_sender_interface.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockRtpSender : public RtpSenderInterface { + public: + static rtc::scoped_refptr<MockRtpSender> Create() { + return rtc::make_ref_counted<MockRtpSender>(); + } + + MOCK_METHOD(bool, SetTrack, (MediaStreamTrackInterface*), (override)); + MOCK_METHOD(rtc::scoped_refptr<MediaStreamTrackInterface>, + track, + (), + (const, override)); + MOCK_METHOD(rtc::scoped_refptr<DtlsTransportInterface>, + dtls_transport, + (), + (const override)); + MOCK_METHOD(uint32_t, ssrc, (), (const, override)); + MOCK_METHOD(cricket::MediaType, media_type, (), (const, override)); + MOCK_METHOD(std::string, id, (), (const, override)); + MOCK_METHOD(std::vector<std::string>, stream_ids, (), (const, override)); + MOCK_METHOD(void, SetStreams, (const std::vector<std::string>&), (override)); + MOCK_METHOD(std::vector<RtpEncodingParameters>, + init_send_encodings, + (), + (const, override)); + MOCK_METHOD(RtpParameters, GetParameters, (), (const, override)); + MOCK_METHOD(RTCError, SetParameters, (const RtpParameters&), (override)); + MOCK_METHOD(void, + SetParametersAsync, + (const RtpParameters&, SetParametersCallback), + (override)); + MOCK_METHOD(rtc::scoped_refptr<DtmfSenderInterface>, + GetDtmfSender, + (), + (const, override)); + MOCK_METHOD(void, + SetFrameEncryptor, + (rtc::scoped_refptr<FrameEncryptorInterface>), + (override)); + MOCK_METHOD(rtc::scoped_refptr<FrameEncryptorInterface>, + GetFrameEncryptor, + (), + (const, override)); + MOCK_METHOD(void, + SetEncoderToPacketizerFrameTransformer, + (rtc::scoped_refptr<FrameTransformerInterface>), + (override)); + MOCK_METHOD(void, + SetEncoderSelector, + (std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface>), + (override)); +}; + +static_assert(!std::is_abstract_v<rtc::RefCountedObject<MockRtpSender>>, ""); +} // namespace webrtc + +#endif // API_TEST_MOCK_RTPSENDER_H_ diff --git a/third_party/libwebrtc/api/test/mock_session_description_interface.h b/third_party/libwebrtc/api/test/mock_session_description_interface.h new file mode 100644 index 0000000000..f0346ceb11 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_session_description_interface.h @@ -0,0 +1,56 @@ +/* + * Copyright 2022 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 API_TEST_MOCK_SESSION_DESCRIPTION_INTERFACE_H_ +#define API_TEST_MOCK_SESSION_DESCRIPTION_INTERFACE_H_ + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "api/jsep.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockSessionDescriptionInterface : public SessionDescriptionInterface { + public: + MOCK_METHOD(std::unique_ptr<SessionDescriptionInterface>, + Clone, + (), + (const, override)); + MOCK_METHOD(cricket::SessionDescription*, description, (), (override)); + MOCK_METHOD(const cricket::SessionDescription*, + description, + (), + (const, override)); + MOCK_METHOD(std::string, session_id, (), (const, override)); + MOCK_METHOD(std::string, session_version, (), (const, override)); + MOCK_METHOD(SdpType, GetType, (), (const, override)); + MOCK_METHOD(std::string, type, (), (const, override)); + MOCK_METHOD(bool, AddCandidate, (const IceCandidateInterface*), (override)); + MOCK_METHOD(size_t, + RemoveCandidates, + (const std::vector<cricket::Candidate>&), + (override)); + MOCK_METHOD(size_t, number_of_mediasections, (), (const, override)); + MOCK_METHOD(const IceCandidateCollection*, + candidates, + (size_t), + (const, override)); + MOCK_METHOD(bool, ToString, (std::string*), (const, override)); +}; + +static_assert(!std::is_abstract_v<MockSessionDescriptionInterface>); + +} // namespace webrtc + +#endif // API_TEST_MOCK_SESSION_DESCRIPTION_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/test/mock_transformable_video_frame.h b/third_party/libwebrtc/api/test/mock_transformable_video_frame.h new file mode 100644 index 0000000000..18b3de534e --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_transformable_video_frame.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 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 API_TEST_MOCK_TRANSFORMABLE_VIDEO_FRAME_H_ +#define API_TEST_MOCK_TRANSFORMABLE_VIDEO_FRAME_H_ + +#include <vector> + +#include "api/frame_transformer_interface.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockTransformableVideoFrame + : public webrtc::TransformableVideoFrameInterface { + public: + MOCK_METHOD(rtc::ArrayView<const uint8_t>, GetData, (), (const, override)); + MOCK_METHOD(void, SetData, (rtc::ArrayView<const uint8_t> data), (override)); + MOCK_METHOD(uint32_t, GetTimestamp, (), (const, override)); + MOCK_METHOD(uint32_t, GetSsrc, (), (const, override)); + MOCK_METHOD(bool, IsKeyFrame, (), (const, override)); + MOCK_METHOD(std::vector<uint8_t>, GetAdditionalData, (), (const, override)); + MOCK_METHOD(const webrtc::VideoFrameMetadata&, + GetMetadata, + (), + (const, override)); + MOCK_METHOD(void, + SetMetadata, + (const webrtc::VideoFrameMetadata&), + (override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_TRANSFORMABLE_VIDEO_FRAME_H_ diff --git a/third_party/libwebrtc/api/test/mock_video_bitrate_allocator.h b/third_party/libwebrtc/api/test/mock_video_bitrate_allocator.h new file mode 100644 index 0000000000..76cf49e955 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_video_bitrate_allocator.h @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#ifndef API_TEST_MOCK_VIDEO_BITRATE_ALLOCATOR_H_ +#define API_TEST_MOCK_VIDEO_BITRATE_ALLOCATOR_H_ + +#include "api/video/video_bitrate_allocator.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockVideoBitrateAllocator : public webrtc::VideoBitrateAllocator { + MOCK_METHOD(VideoBitrateAllocation, + Allocate, + (VideoBitrateAllocationParameters parameters), + (override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_VIDEO_BITRATE_ALLOCATOR_H_ diff --git a/third_party/libwebrtc/api/test/mock_video_bitrate_allocator_factory.h b/third_party/libwebrtc/api/test/mock_video_bitrate_allocator_factory.h new file mode 100644 index 0000000000..16af191970 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_video_bitrate_allocator_factory.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef API_TEST_MOCK_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_ +#define API_TEST_MOCK_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_ + +#include <memory> + +#include "api/video/video_bitrate_allocator_factory.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockVideoBitrateAllocatorFactory + : public webrtc::VideoBitrateAllocatorFactory { + public: + ~MockVideoBitrateAllocatorFactory() override { Die(); } + MOCK_METHOD(std::unique_ptr<VideoBitrateAllocator>, + CreateVideoBitrateAllocator, + (const VideoCodec&), + (override)); + MOCK_METHOD(void, Die, ()); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_ diff --git a/third_party/libwebrtc/api/test/mock_video_decoder.h b/third_party/libwebrtc/api/test/mock_video_decoder.h new file mode 100644 index 0000000000..34f732ca4d --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_video_decoder.h @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#ifndef API_TEST_MOCK_VIDEO_DECODER_H_ +#define API_TEST_MOCK_VIDEO_DECODER_H_ + +#include <utility> + +#include "api/video_codecs/video_decoder.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockDecodedImageCallback : public DecodedImageCallback { + public: + MOCK_METHOD(int32_t, + Decoded, + (VideoFrame & decoded_image), // NOLINT + (override)); + MOCK_METHOD(int32_t, + Decoded, + (VideoFrame & decoded_image, // NOLINT + int64_t decode_time_ms), + (override)); + MOCK_METHOD(void, + Decoded, + (VideoFrame & decoded_image, // NOLINT + absl::optional<int32_t> decode_time_ms, + absl::optional<uint8_t> qp), + (override)); +}; + +class MockVideoDecoder : public VideoDecoder { + public: + MockVideoDecoder() { + // Make `Configure` succeed by default, so that individual tests that + // verify other methods wouldn't need to stub `Configure`. + ON_CALL(*this, Configure).WillByDefault(testing::Return(true)); + } + + ~MockVideoDecoder() override { Destruct(); } + + MOCK_METHOD(bool, Configure, (const Settings& settings), (override)); + MOCK_METHOD(int32_t, + Decode, + (const EncodedImage& input_image, + bool missing_frames, + int64_t render_time_ms), + (override)); + MOCK_METHOD(int32_t, + RegisterDecodeCompleteCallback, + (DecodedImageCallback * callback), + (override)); + MOCK_METHOD(int32_t, Release, (), (override)); + + // Special utility method that allows a test to monitor/verify when + // destruction of the decoder instance occurs. + MOCK_METHOD(void, Destruct, (), ()); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_VIDEO_DECODER_H_ diff --git a/third_party/libwebrtc/api/test/mock_video_decoder_factory.h b/third_party/libwebrtc/api/test/mock_video_decoder_factory.h new file mode 100644 index 0000000000..6150d9f8b5 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_video_decoder_factory.h @@ -0,0 +1,40 @@ +/* + * 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. + */ + +#ifndef API_TEST_MOCK_VIDEO_DECODER_FACTORY_H_ +#define API_TEST_MOCK_VIDEO_DECODER_FACTORY_H_ + +#include <memory> +#include <vector> + +#include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_decoder.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockVideoDecoderFactory : public webrtc::VideoDecoderFactory { + public: + ~MockVideoDecoderFactory() override { Die(); } + + MOCK_METHOD(std::vector<webrtc::SdpVideoFormat>, + GetSupportedFormats, + (), + (const, override)); + MOCK_METHOD(std::unique_ptr<webrtc::VideoDecoder>, + CreateVideoDecoder, + (const webrtc::SdpVideoFormat&), + (override)); + MOCK_METHOD(void, Die, ()); +}; +} // namespace webrtc + +#endif // API_TEST_MOCK_VIDEO_DECODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/test/mock_video_encoder.h b/third_party/libwebrtc/api/test/mock_video_encoder.h new file mode 100644 index 0000000000..11e0f64b3f --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_video_encoder.h @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#ifndef API_TEST_MOCK_VIDEO_ENCODER_H_ +#define API_TEST_MOCK_VIDEO_ENCODER_H_ + +#include <vector> + +#include "api/video_codecs/video_encoder.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockEncodedImageCallback : public EncodedImageCallback { + public: + MOCK_METHOD(Result, + OnEncodedImage, + (const EncodedImage&, const CodecSpecificInfo*), + (override)); + MOCK_METHOD(void, OnDroppedFrame, (DropReason reason), (override)); +}; + +class MockVideoEncoder : public VideoEncoder { + public: + MOCK_METHOD(void, + SetFecControllerOverride, + (FecControllerOverride*), + (override)); + MOCK_METHOD(int32_t, + InitEncode, + (const VideoCodec*, int32_t numberOfCores, size_t maxPayloadSize), + (override)); + MOCK_METHOD(int32_t, + InitEncode, + (const VideoCodec*, const VideoEncoder::Settings& settings), + (override)); + + MOCK_METHOD(int32_t, + Encode, + (const VideoFrame& inputImage, + const std::vector<VideoFrameType>*), + (override)); + MOCK_METHOD(int32_t, + RegisterEncodeCompleteCallback, + (EncodedImageCallback*), + (override)); + MOCK_METHOD(int32_t, Release, (), (override)); + MOCK_METHOD(void, + SetRates, + (const RateControlParameters& parameters), + (override)); + MOCK_METHOD(void, + OnPacketLossRateUpdate, + (float packet_loss_rate), + (override)); + MOCK_METHOD(void, OnRttUpdate, (int64_t rtt_ms), (override)); + MOCK_METHOD(void, + OnLossNotification, + (const LossNotification& loss_notification), + (override)); + MOCK_METHOD(EncoderInfo, GetEncoderInfo, (), (const, override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_VIDEO_ENCODER_H_ diff --git a/third_party/libwebrtc/api/test/mock_video_encoder_factory.h b/third_party/libwebrtc/api/test/mock_video_encoder_factory.h new file mode 100644 index 0000000000..02ee7aa15e --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_video_encoder_factory.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#ifndef API_TEST_MOCK_VIDEO_ENCODER_FACTORY_H_ +#define API_TEST_MOCK_VIDEO_ENCODER_FACTORY_H_ + +#include <memory> +#include <vector> + +#include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_encoder.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockVideoEncoderFactory : public webrtc::VideoEncoderFactory { + public: + ~MockVideoEncoderFactory() override { Die(); } + + MOCK_METHOD(std::vector<SdpVideoFormat>, + GetSupportedFormats, + (), + (const, override)); + MOCK_METHOD(std::unique_ptr<VideoEncoder>, + CreateVideoEncoder, + (const SdpVideoFormat&), + (override)); + + MOCK_METHOD(void, Die, ()); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_VIDEO_ENCODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/test/mock_video_track.h b/third_party/libwebrtc/api/test/mock_video_track.h new file mode 100644 index 0000000000..1212a32527 --- /dev/null +++ b/third_party/libwebrtc/api/test/mock_video_track.h @@ -0,0 +1,69 @@ +/* + * Copyright 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 API_TEST_MOCK_VIDEO_TRACK_H_ +#define API_TEST_MOCK_VIDEO_TRACK_H_ + +#include <string> + +#include "api/media_stream_interface.h" +#include "api/scoped_refptr.h" +#include "rtc_base/ref_counted_object.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockVideoTrack + : public rtc::RefCountedObject<webrtc::VideoTrackInterface> { + public: + static rtc::scoped_refptr<MockVideoTrack> Create() { + return rtc::scoped_refptr<MockVideoTrack>(new MockVideoTrack()); + } + + // NotifierInterface + MOCK_METHOD(void, + RegisterObserver, + (ObserverInterface * observer), + (override)); + MOCK_METHOD(void, + UnregisterObserver, + (ObserverInterface * observer), + (override)); + + // MediaStreamTrackInterface + MOCK_METHOD(std::string, kind, (), (const, override)); + MOCK_METHOD(std::string, id, (), (const, override)); + MOCK_METHOD(bool, enabled, (), (const, override)); + MOCK_METHOD(bool, set_enabled, (bool enable), (override)); + MOCK_METHOD(TrackState, state, (), (const, override)); + + // VideoSourceInterface + MOCK_METHOD(void, + AddOrUpdateSink, + (rtc::VideoSinkInterface<VideoFrame> * sink, + const rtc::VideoSinkWants& wants), + (override)); + // RemoveSink must guarantee that at the time the method returns, + // there is no current and no future calls to VideoSinkInterface::OnFrame. + MOCK_METHOD(void, + RemoveSink, + (rtc::VideoSinkInterface<VideoFrame> * sink), + (override)); + + // VideoTrackInterface + MOCK_METHOD(VideoTrackSourceInterface*, GetSource, (), (const, override)); + + MOCK_METHOD(ContentHint, content_hint, (), (const, override)); + MOCK_METHOD(void, set_content_hint, (ContentHint hint), (override)); +}; + +} // namespace webrtc + +#endif // API_TEST_MOCK_VIDEO_TRACK_H_ diff --git a/third_party/libwebrtc/api/test/neteq_simulator.cc b/third_party/libwebrtc/api/test/neteq_simulator.cc new file mode 100644 index 0000000000..980db96d32 --- /dev/null +++ b/third_party/libwebrtc/api/test/neteq_simulator.cc @@ -0,0 +1,26 @@ +/* + * 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 "api/test/neteq_simulator.h" + +namespace webrtc { +namespace test { + +NetEqSimulator::SimulationStepResult::SimulationStepResult() = default; +NetEqSimulator::SimulationStepResult::SimulationStepResult( + const NetEqSimulator::SimulationStepResult& other) = default; +NetEqSimulator::SimulationStepResult::~SimulationStepResult() = default; + +NetEqSimulator::NetEqState::NetEqState() = default; +NetEqSimulator::NetEqState::NetEqState(const NetEqState& other) = default; +NetEqSimulator::NetEqState::~NetEqState() = default; + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/neteq_simulator.h b/third_party/libwebrtc/api/test/neteq_simulator.h new file mode 100644 index 0000000000..88c7ffa681 --- /dev/null +++ b/third_party/libwebrtc/api/test/neteq_simulator.h @@ -0,0 +1,82 @@ +/* + * 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. + */ + +#ifndef API_TEST_NETEQ_SIMULATOR_H_ +#define API_TEST_NETEQ_SIMULATOR_H_ + +#include <stdint.h> + +#include <map> +#include <vector> + +namespace webrtc { +namespace test { + +class NetEqSimulator { + public: + virtual ~NetEqSimulator() = default; + + enum class Action { kNormal, kExpand, kAccelerate, kPreemptiveExpand }; + + // The results of one simulation step. + struct SimulationStepResult { + SimulationStepResult(); + SimulationStepResult(const SimulationStepResult& other); + ~SimulationStepResult(); + + bool is_simulation_finished = false; + // The amount of audio produced (in ms) with the actions in this time step. + std::map<Action, int> action_times_ms; + // The amount of wall clock time (in ms) that elapsed since the previous + // event. This is not necessarily equal to the sum of the values in + // action_times_ms. + int64_t simulation_step_ms = 0; + }; + + struct NetEqState { + NetEqState(); + NetEqState(const NetEqState& other); + ~NetEqState(); + // The sum of the packet buffer and sync buffer delay. + int current_delay_ms = 0; + // An indicator that packet loss occurred since the last GetAudio event. + bool packet_loss_occurred = false; + // An indicator that the packet buffer has been flushed since the last + // GetAudio event. + bool packet_buffer_flushed = false; + // Indicates if the next needed packet is available in the buffer. + bool next_packet_available = false; + // The inter-arrival times in ms of the packets that have arrived since the + // last GetAudio event. + std::vector<int> packet_iat_ms; + // The current packet size in ms. + int packet_size_ms = 0; + }; + + // Runs the simulation until the end. Returns the duration of the produced + // audio in ms. + virtual int64_t Run() = 0; + // Runs the simulation until we hit the next GetAudio event. If the simulation + // is finished, is_simulation_finished will be set to true in the returned + // SimulationStepResult. + virtual SimulationStepResult RunToNextGetAudio() = 0; + + // Set the next action to be taken by NetEq. This will override any action + // that NetEq would normally decide to take. + virtual void SetNextAction(Action next_operation) = 0; + + // Get the current state of NetEq. + virtual NetEqState GetNetEqState() = 0; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_NETEQ_SIMULATOR_H_ diff --git a/third_party/libwebrtc/api/test/neteq_simulator_factory.cc b/third_party/libwebrtc/api/test/neteq_simulator_factory.cc new file mode 100644 index 0000000000..82b27e546d --- /dev/null +++ b/third_party/libwebrtc/api/test/neteq_simulator_factory.cc @@ -0,0 +1,71 @@ +/* + * 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 "api/test/neteq_simulator_factory.h" + +#include <memory> +#include <string> +#include <vector> + +#include "absl/flags/flag.h" +#include "absl/flags/parse.h" +#include "modules/audio_coding/neteq/tools/neteq_test_factory.h" +#include "rtc_base/checks.h" + +namespace webrtc { +namespace test { +namespace { +NetEqTestFactory::Config convertConfig( + const NetEqSimulatorFactory::Config& simulation_config, + absl::string_view replacement_audio_filename) { + NetEqTestFactory::Config config; + config.replacement_audio_file = std::string(replacement_audio_filename); + config.max_nr_packets_in_buffer = simulation_config.max_nr_packets_in_buffer; + config.initial_dummy_packets = simulation_config.initial_dummy_packets; + config.skip_get_audio_events = simulation_config.skip_get_audio_events; + config.field_trial_string = simulation_config.field_trial_string; + config.output_audio_filename = simulation_config.output_audio_filename; + config.pythonplot = simulation_config.python_plot_filename.has_value(); + config.plot_scripts_basename = simulation_config.python_plot_filename; + config.textlog = simulation_config.text_log_filename.has_value(); + config.textlog_filename = simulation_config.text_log_filename; + return config; +} +} // namespace + +NetEqSimulatorFactory::NetEqSimulatorFactory() + : factory_(std::make_unique<NetEqTestFactory>()) {} + +NetEqSimulatorFactory::~NetEqSimulatorFactory() = default; + +std::unique_ptr<NetEqSimulator> NetEqSimulatorFactory::CreateSimulatorFromFile( + absl::string_view event_log_filename, + absl::string_view replacement_audio_filename, + Config simulation_config) { + NetEqTestFactory::Config config = + convertConfig(simulation_config, replacement_audio_filename); + return factory_->InitializeTestFromFile( + std::string(event_log_filename), simulation_config.neteq_factory, config); +} + +std::unique_ptr<NetEqSimulator> +NetEqSimulatorFactory::CreateSimulatorFromString( + absl::string_view event_log_file_contents, + absl::string_view replacement_audio_filename, + Config simulation_config) { + NetEqTestFactory::Config config = + convertConfig(simulation_config, replacement_audio_filename); + return factory_->InitializeTestFromString( + std::string(event_log_file_contents), simulation_config.neteq_factory, + config); +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/neteq_simulator_factory.h b/third_party/libwebrtc/api/test/neteq_simulator_factory.h new file mode 100644 index 0000000000..2a716e665e --- /dev/null +++ b/third_party/libwebrtc/api/test/neteq_simulator_factory.h @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#ifndef API_TEST_NETEQ_SIMULATOR_FACTORY_H_ +#define API_TEST_NETEQ_SIMULATOR_FACTORY_H_ + +#include <memory> +#include <string> + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/neteq/neteq_factory.h" +#include "api/test/neteq_simulator.h" + +namespace webrtc { +namespace test { + +class NetEqTestFactory; + +class NetEqSimulatorFactory { + public: + NetEqSimulatorFactory(); + ~NetEqSimulatorFactory(); + struct Config { + // The maximum allowed number of packets in the jitter buffer. + int max_nr_packets_in_buffer = 0; + // The number of audio packets to insert at the start of the simulation. + // Since the simulation is done with a replacement audio file, these + // artificial packets will take a small piece of that replacement audio. + int initial_dummy_packets = 0; + // The number of simulation steps to skip at the start of the simulation. + // This removes incoming packets and GetAudio events from the start of the + // simulation, until the requested number of GetAudio events has been + // removed. + int skip_get_audio_events = 0; + // A WebRTC field trial string to be used during the simulation. + std::string field_trial_string; + // A filename for the generated output audio file. + absl::optional<std::string> output_audio_filename; + // A filename for the python plot. + absl::optional<std::string> python_plot_filename; + // A filename for the text log. + absl::optional<std::string> text_log_filename; + // A custom NetEqFactory can be used. + NetEqFactory* neteq_factory = nullptr; + }; + std::unique_ptr<NetEqSimulator> CreateSimulatorFromFile( + absl::string_view event_log_filename, + absl::string_view replacement_audio_filename, + Config simulation_config); + // The same as above, but pass the file contents as a string. + std::unique_ptr<NetEqSimulator> CreateSimulatorFromString( + absl::string_view event_log_file_contents, + absl::string_view replacement_audio_file, + Config simulation_config); + + private: + std::unique_ptr<NetEqTestFactory> factory_; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_NETEQ_SIMULATOR_FACTORY_H_ diff --git a/third_party/libwebrtc/api/test/network_emulation/BUILD.gn b/third_party/libwebrtc/api/test/network_emulation/BUILD.gn new file mode 100644 index 0000000000..d009d39a21 --- /dev/null +++ b/third_party/libwebrtc/api/test/network_emulation/BUILD.gn @@ -0,0 +1,52 @@ +# Copyright (c) 2019 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") + +rtc_library("network_emulation") { + visibility = [ "*" ] + + sources = [ + "cross_traffic.h", + "network_emulation_interfaces.cc", + "network_emulation_interfaces.h", + ] + + deps = [ + "../..:array_view", + "../../../rtc_base:checks", + "../../../rtc_base:copy_on_write_buffer", + "../../../rtc_base:ip_address", + "../../../rtc_base:net_helper", + "../../../rtc_base:socket_address", + "../../numerics", + "../../task_queue", + "../../units:data_rate", + "../../units:data_size", + "../../units:time_delta", + "../../units:timestamp", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("create_cross_traffic") { + visibility = [ "*" ] + testonly = true + + sources = [ + "create_cross_traffic.cc", + "create_cross_traffic.h", + ] + + deps = [ + ":network_emulation", + "../..:network_emulation_manager_api", + "../../../rtc_base/task_utils:repeating_task", + "../../../test/network:emulated_network", + ] +} diff --git a/third_party/libwebrtc/api/test/network_emulation/DEPS b/third_party/libwebrtc/api/test/network_emulation/DEPS new file mode 100644 index 0000000000..0cf128849d --- /dev/null +++ b/third_party/libwebrtc/api/test/network_emulation/DEPS @@ -0,0 +1,7 @@ +specific_include_rules = { + ".*": [ + "+rtc_base/socket_address.h", + "+rtc_base/ip_address.h", + "+rtc_base/copy_on_write_buffer.h", + ], +} diff --git a/third_party/libwebrtc/api/test/network_emulation/create_cross_traffic.cc b/third_party/libwebrtc/api/test/network_emulation/create_cross_traffic.cc new file mode 100644 index 0000000000..36a535cec6 --- /dev/null +++ b/third_party/libwebrtc/api/test/network_emulation/create_cross_traffic.cc @@ -0,0 +1,39 @@ +/* + * 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 "api/test/network_emulation/create_cross_traffic.h" + +#include <memory> + +#include "rtc_base/task_utils/repeating_task.h" +#include "test/network/cross_traffic.h" + +namespace webrtc { + +std::unique_ptr<CrossTrafficGenerator> CreateRandomWalkCrossTraffic( + CrossTrafficRoute* traffic_route, + RandomWalkConfig config) { + return std::make_unique<test::RandomWalkCrossTraffic>(config, traffic_route); +} + +std::unique_ptr<CrossTrafficGenerator> CreatePulsedPeaksCrossTraffic( + CrossTrafficRoute* traffic_route, + PulsedPeaksConfig config) { + return std::make_unique<test::PulsedPeaksCrossTraffic>(config, traffic_route); +} + +std::unique_ptr<CrossTrafficGenerator> CreateFakeTcpCrossTraffic( + EmulatedRoute* send_route, + EmulatedRoute* ret_route, + FakeTcpConfig config) { + return std::make_unique<test::FakeTcpCrossTraffic>(config, send_route, + ret_route); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/network_emulation/create_cross_traffic.h b/third_party/libwebrtc/api/test/network_emulation/create_cross_traffic.h new file mode 100644 index 0000000000..42fc855392 --- /dev/null +++ b/third_party/libwebrtc/api/test/network_emulation/create_cross_traffic.h @@ -0,0 +1,37 @@ +/* + * 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 API_TEST_NETWORK_EMULATION_CREATE_CROSS_TRAFFIC_H_ +#define API_TEST_NETWORK_EMULATION_CREATE_CROSS_TRAFFIC_H_ + +#include <memory> + +#include "api/test/network_emulation/cross_traffic.h" +#include "api/test/network_emulation_manager.h" + +namespace webrtc { + +// This API is still in development and can be changed without prior notice. + +std::unique_ptr<CrossTrafficGenerator> CreateRandomWalkCrossTraffic( + CrossTrafficRoute* traffic_route, + RandomWalkConfig config); + +std::unique_ptr<CrossTrafficGenerator> CreatePulsedPeaksCrossTraffic( + CrossTrafficRoute* traffic_route, + PulsedPeaksConfig config); + +std::unique_ptr<CrossTrafficGenerator> CreateFakeTcpCrossTraffic( + EmulatedRoute* send_route, + EmulatedRoute* ret_route, + FakeTcpConfig config); + +} // namespace webrtc + +#endif // API_TEST_NETWORK_EMULATION_CREATE_CROSS_TRAFFIC_H_ diff --git a/third_party/libwebrtc/api/test/network_emulation/cross_traffic.h b/third_party/libwebrtc/api/test/network_emulation/cross_traffic.h new file mode 100644 index 0000000000..737a93c2fd --- /dev/null +++ b/third_party/libwebrtc/api/test/network_emulation/cross_traffic.h @@ -0,0 +1,85 @@ +/* + * 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 API_TEST_NETWORK_EMULATION_CROSS_TRAFFIC_H_ +#define API_TEST_NETWORK_EMULATION_CROSS_TRAFFIC_H_ + +#include "api/task_queue/task_queue_base.h" +#include "api/test/network_emulation/network_emulation_interfaces.h" +#include "api/units/data_rate.h" +#include "api/units/data_size.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" + +namespace webrtc { + +// This API is still in development and can be changed without prior notice. + +// Represents the endpoint for cross traffic that is going through the network. +// It can be used to emulate unexpected network load. +class CrossTrafficRoute { + public: + virtual ~CrossTrafficRoute() = default; + + // Triggers sending of dummy packets with size `packet_size` bytes. + virtual void TriggerPacketBurst(size_t num_packets, size_t packet_size) = 0; + // Sends a packet over the nodes. The content of the packet is unspecified; + // only the size metter for the emulation purposes. + virtual void SendPacket(size_t packet_size) = 0; + // Sends a packet over the nodes and runs `action` when it has been delivered. + virtual void NetworkDelayedAction(size_t packet_size, + std::function<void()> action) = 0; +}; + +// Describes a way of generating cross traffic on some route. Used by +// NetworkEmulationManager to produce cross traffic during some period of time. +class CrossTrafficGenerator { + public: + virtual ~CrossTrafficGenerator() = default; + + // Time between Process calls. + virtual TimeDelta GetProcessInterval() const = 0; + + // Called periodically by NetworkEmulationManager. Generates traffic on the + // route. + virtual void Process(Timestamp at_time) = 0; +}; + +// Config of a cross traffic generator. Generated traffic rises and falls +// randomly. +struct RandomWalkConfig { + int random_seed = 1; + DataRate peak_rate = DataRate::KilobitsPerSec(100); + DataSize min_packet_size = DataSize::Bytes(200); + TimeDelta min_packet_interval = TimeDelta::Millis(1); + TimeDelta update_interval = TimeDelta::Millis(200); + double variance = 0.6; + double bias = -0.1; +}; + +// Config of a cross traffic generator. Generated traffic has form of periodic +// peaks alternating with periods of silence. +struct PulsedPeaksConfig { + DataRate peak_rate = DataRate::KilobitsPerSec(100); + DataSize min_packet_size = DataSize::Bytes(200); + TimeDelta min_packet_interval = TimeDelta::Millis(1); + TimeDelta send_duration = TimeDelta::Millis(100); + TimeDelta hold_duration = TimeDelta::Millis(2000); +}; + +struct FakeTcpConfig { + DataSize packet_size = DataSize::Bytes(1200); + DataSize send_limit = DataSize::PlusInfinity(); + TimeDelta process_interval = TimeDelta::Millis(200); + TimeDelta packet_timeout = TimeDelta::Seconds(1); +}; + +} // namespace webrtc + +#endif // API_TEST_NETWORK_EMULATION_CROSS_TRAFFIC_H_ diff --git a/third_party/libwebrtc/api/test/network_emulation/network_emulation_interfaces.cc b/third_party/libwebrtc/api/test/network_emulation/network_emulation_interfaces.cc new file mode 100644 index 0000000000..0f3a7f8ffd --- /dev/null +++ b/third_party/libwebrtc/api/test/network_emulation/network_emulation_interfaces.cc @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019 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 "api/test/network_emulation/network_emulation_interfaces.h" + +#include "rtc_base/net_helper.h" + +namespace webrtc { + +EmulatedIpPacket::EmulatedIpPacket(const rtc::SocketAddress& from, + const rtc::SocketAddress& to, + rtc::CopyOnWriteBuffer data, + Timestamp arrival_time, + uint16_t application_overhead) + : from(from), + to(to), + data(data), + headers_size(to.ipaddr().overhead() + application_overhead + + cricket::kUdpHeaderSize), + arrival_time(arrival_time) { + RTC_DCHECK(to.family() == AF_INET || to.family() == AF_INET6); +} + +DataRate EmulatedNetworkOutgoingStats::AverageSendRate() const { + RTC_DCHECK_GE(packets_sent, 2); + RTC_DCHECK(first_packet_sent_time.IsFinite()); + RTC_DCHECK(last_packet_sent_time.IsFinite()); + return (bytes_sent - first_sent_packet_size) / + (last_packet_sent_time - first_packet_sent_time); +} + +DataRate EmulatedNetworkIncomingStats::AverageReceiveRate() const { + RTC_DCHECK_GE(packets_received, 2); + RTC_DCHECK(first_packet_received_time.IsFinite()); + RTC_DCHECK(last_packet_received_time.IsFinite()); + return (bytes_received - first_received_packet_size) / + (last_packet_received_time - first_packet_received_time); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/network_emulation/network_emulation_interfaces.h b/third_party/libwebrtc/api/test/network_emulation/network_emulation_interfaces.h new file mode 100644 index 0000000000..7cab07b75d --- /dev/null +++ b/third_party/libwebrtc/api/test/network_emulation/network_emulation_interfaces.h @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2019 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 API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_ +#define API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_ + +#include <map> +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/numerics/samples_stats_counter.h" +#include "api/units/data_rate.h" +#include "api/units/data_size.h" +#include "api/units/timestamp.h" +#include "rtc_base/copy_on_write_buffer.h" +#include "rtc_base/ip_address.h" +#include "rtc_base/socket_address.h" + +namespace webrtc { + +struct EmulatedIpPacket { + public: + EmulatedIpPacket(const rtc::SocketAddress& from, + const rtc::SocketAddress& to, + rtc::CopyOnWriteBuffer data, + Timestamp arrival_time, + uint16_t application_overhead = 0); + ~EmulatedIpPacket() = default; + // This object is not copyable or assignable. + EmulatedIpPacket(const EmulatedIpPacket&) = delete; + EmulatedIpPacket& operator=(const EmulatedIpPacket&) = delete; + // This object is only moveable. + EmulatedIpPacket(EmulatedIpPacket&&) = default; + EmulatedIpPacket& operator=(EmulatedIpPacket&&) = default; + + size_t size() const { return data.size(); } + const uint8_t* cdata() const { return data.cdata(); } + + size_t ip_packet_size() const { return size() + headers_size; } + rtc::SocketAddress from; + rtc::SocketAddress to; + // Holds the UDP payload. + rtc::CopyOnWriteBuffer data; + uint16_t headers_size; + Timestamp arrival_time; +}; + +// Interface for handling IP packets from an emulated network. This is used with +// EmulatedEndpoint to receive packets on a specific port. +class EmulatedNetworkReceiverInterface { + public: + virtual ~EmulatedNetworkReceiverInterface() = default; + + virtual void OnPacketReceived(EmulatedIpPacket packet) = 0; +}; + +struct EmulatedNetworkOutgoingStats { + int64_t packets_sent = 0; + + DataSize bytes_sent = DataSize::Zero(); + + // Sizes of all sent packets. + // Collected iff EmulatedNetworkStatsGatheringMode::kDebug is enabled. + SamplesStatsCounter sent_packets_size; + + DataSize first_sent_packet_size = DataSize::Zero(); + + // Time of the first packet sent or infinite value if no packets were sent. + Timestamp first_packet_sent_time = Timestamp::PlusInfinity(); + + // Time of the last packet sent or infinite value if no packets were sent. + Timestamp last_packet_sent_time = Timestamp::MinusInfinity(); + + // Returns average send rate. Requires that at least 2 packets were sent. + DataRate AverageSendRate() const; +}; + +struct EmulatedNetworkIncomingStats { + // Total amount of packets received with or without destination. + int64_t packets_received = 0; + + // Total amount of bytes in received packets. + DataSize bytes_received = DataSize::Zero(); + + // Sizes of all received packets. + // Collected iff EmulatedNetworkStatsGatheringMode::kDebug is enabled. + SamplesStatsCounter received_packets_size; + + // Total amount of packets that were received, but no destination was found. + int64_t packets_discarded_no_receiver = 0; + + // Total amount of bytes in discarded packets. + DataSize bytes_discarded_no_receiver = DataSize::Zero(); + + // Sizes of all packets that were received, but no destination was found. + // Collected iff EmulatedNetworkStatsGatheringMode::kDebug is enabled. + SamplesStatsCounter packets_discarded_no_receiver_size; + + DataSize first_received_packet_size = DataSize::Zero(); + + // Time of the first packet received or infinite value if no packets were + // received. + Timestamp first_packet_received_time = Timestamp::PlusInfinity(); + + // Time of the last packet received or infinite value if no packets were + // received. + Timestamp last_packet_received_time = Timestamp::MinusInfinity(); + + DataRate AverageReceiveRate() const; +}; + +struct EmulatedNetworkStats { + int64_t PacketsSent() const { return overall_outgoing_stats.packets_sent; } + + DataSize BytesSent() const { return overall_outgoing_stats.bytes_sent; } + + // Returns the timestamped sizes of all sent packets. + // Returned reference is valid until the next call to a non-const method. + // Collected iff EmulatedNetworkStatsGatheringMode::kDebug is enabled. + const SamplesStatsCounter& SentPacketsSizeCounter() const { + return overall_outgoing_stats.sent_packets_size; + } + + DataSize FirstSentPacketSize() const { + return overall_outgoing_stats.first_sent_packet_size; + } + + // Returns time of the first packet sent or infinite value if no packets were + // sent. + Timestamp FirstPacketSentTime() const { + return overall_outgoing_stats.first_packet_sent_time; + } + + // Returns time of the last packet sent or infinite value if no packets were + // sent. + Timestamp LastPacketSentTime() const { + return overall_outgoing_stats.last_packet_sent_time; + } + + DataRate AverageSendRate() const { + return overall_outgoing_stats.AverageSendRate(); + } + + // Total amount of packets received regardless of the destination address. + int64_t PacketsReceived() const { + return overall_incoming_stats.packets_received; + } + + // Total amount of bytes in received packets. + DataSize BytesReceived() const { + return overall_incoming_stats.bytes_received; + } + + // Returns the timestamped sizes of all received packets. + // Returned reference is valid until the next call to a non-const method. + // Collected iff EmulatedNetworkStatsGatheringMode::kDebug is enabled. + const SamplesStatsCounter& ReceivedPacketsSizeCounter() const { + return overall_incoming_stats.received_packets_size; + } + + // Total amount of packets that were received, but no destination was found. + int64_t PacketsDiscardedNoReceiver() const { + return overall_incoming_stats.packets_discarded_no_receiver; + } + + // Total amount of bytes in dropped packets. + DataSize BytesDiscardedNoReceiver() const { + return overall_incoming_stats.bytes_discarded_no_receiver; + } + + // Returns counter with timestamped sizes of all packets that were received, + // but no destination was found. + // Returned reference is valid until the next call to a non-const method. + // Collected iff EmulatedNetworkStatsGatheringMode::kDebug is enabled. + const SamplesStatsCounter& PacketsDiscardedNoReceiverSizeCounter() const { + return overall_incoming_stats.packets_discarded_no_receiver_size; + } + + DataSize FirstReceivedPacketSize() const { + return overall_incoming_stats.first_received_packet_size; + } + + // Returns time of the first packet received or infinite value if no packets + // were received. + Timestamp FirstPacketReceivedTime() const { + return overall_incoming_stats.first_packet_received_time; + } + + // Returns time of the last packet received or infinite value if no packets + // were received. + Timestamp LastPacketReceivedTime() const { + return overall_incoming_stats.last_packet_received_time; + } + + DataRate AverageReceiveRate() const { + return overall_incoming_stats.AverageReceiveRate(); + } + + // List of IP addresses that were used to send data considered in this stats + // object. + std::vector<rtc::IPAddress> local_addresses; + + // Overall outgoing stats for all IP addresses which were requested. + EmulatedNetworkOutgoingStats overall_outgoing_stats; + + // Overall incoming stats for all IP addresses from which data was received + // on requested interfaces. + EmulatedNetworkIncomingStats overall_incoming_stats; + + std::map<rtc::IPAddress, EmulatedNetworkOutgoingStats> + outgoing_stats_per_destination; + std::map<rtc::IPAddress, EmulatedNetworkIncomingStats> + incoming_stats_per_source; + + // Duration between packet was received on network interface and was + // dispatched to the network in microseconds. + // Collected iff EmulatedNetworkStatsGatheringMode::kDebug is enabled. + SamplesStatsCounter sent_packets_queue_wait_time_us; +}; + +struct EmulatedNetworkNodeStats { + // Amount of time each packet spent in the emulated network node for which + // stats were collected. + // + // Collected iff EmulatedNetworkStatsGatheringMode::kDebug is enabled. + SamplesStatsCounter packet_transport_time; + + // For each packet contains its size divided on the amount of time which it + // spent in the emulated network node for which stats were collected. + // + // Collected iff EmulatedNetworkStatsGatheringMode::kDebug is enabled. + SamplesStatsCounter size_to_packet_transport_time; +}; + +// EmulatedEndpoint is an abstraction for network interface on device. Instances +// of this are created by NetworkEmulationManager::CreateEndpoint and +// thread safe. +class EmulatedEndpoint : public EmulatedNetworkReceiverInterface { + public: + // Send packet into network. + // `from` will be used to set source address for the packet in destination + // socket. + // `to` will be used for routing verification and picking right socket by port + // on destination endpoint. + virtual void SendPacket(const rtc::SocketAddress& from, + const rtc::SocketAddress& to, + rtc::CopyOnWriteBuffer packet_data, + uint16_t application_overhead = 0) = 0; + + // Binds receiver to this endpoint to send and receive data. + // `desired_port` is a port that should be used. If it is equal to 0, + // endpoint will pick the first available port starting from + // `kFirstEphemeralPort`. + // + // Returns the port, that should be used (it will be equals to desired, if + // `desired_port` != 0 and is free or will be the one, selected by endpoint) + // or absl::nullopt if desired_port in used. Also fails if there are no more + // free ports to bind to. + // + // The Bind- and Unbind-methods must not be called from within a bound + // receiver's OnPacketReceived method. + virtual absl::optional<uint16_t> BindReceiver( + uint16_t desired_port, + EmulatedNetworkReceiverInterface* receiver) = 0; + // Unbinds receiver from the specified port. Do nothing if no receiver was + // bound before. After this method returns, no more packets can be delivered + // to the receiver, and it is safe to destroy it. + virtual void UnbindReceiver(uint16_t port) = 0; + // Binds receiver that will accept all packets which arrived on any port + // for which there are no bound receiver. + virtual void BindDefaultReceiver( + EmulatedNetworkReceiverInterface* receiver) = 0; + // Unbinds default receiver. Do nothing if no default receiver was bound + // before. + virtual void UnbindDefaultReceiver() = 0; + virtual rtc::IPAddress GetPeerLocalAddress() const = 0; + + private: + // Ensure that there can be no other subclass than EmulatedEndpointImpl. This + // means that it's always safe to downcast EmulatedEndpoint instances to + // EmulatedEndpointImpl. + friend class EmulatedEndpointImpl; + EmulatedEndpoint() = default; +}; + +// Simulates a TCP connection, this roughly implements the Reno algorithm. In +// difference from TCP this only support sending messages with a fixed length, +// no streaming. This is useful to simulate signaling and cross traffic using +// message based protocols such as HTTP. It differs from UDP messages in that +// they are guranteed to be delivered eventually, even on lossy networks. +class TcpMessageRoute { + public: + // Sends a TCP message of the given `size` over the route, `on_received` is + // called when the message has been delivered. Note that the connection + // parameters are reset iff there's no currently pending message on the route. + virtual void SendMessage(size_t size, std::function<void()> on_received) = 0; + + protected: + ~TcpMessageRoute() = default; +}; +} // namespace webrtc + +#endif // API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_ diff --git a/third_party/libwebrtc/api/test/network_emulation_manager.cc b/third_party/libwebrtc/api/test/network_emulation_manager.cc new file mode 100644 index 0000000000..236e2f0e17 --- /dev/null +++ b/third_party/libwebrtc/api/test/network_emulation_manager.cc @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2019 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 "api/test/network_emulation_manager.h" + +#include <utility> + +#include "call/simulated_network.h" +#include "rtc_base/checks.h" + +namespace webrtc { + +bool AbslParseFlag(absl::string_view text, TimeMode* mode, std::string* error) { + if (text == "realtime") { + *mode = TimeMode::kRealTime; + return true; + } + if (text == "simulated") { + *mode = TimeMode::kSimulated; + return true; + } + *error = + "Unknown value for TimeMode enum. Options are 'realtime' or 'simulated'"; + return false; +} + +std::string AbslUnparseFlag(TimeMode mode) { + switch (mode) { + case TimeMode::kRealTime: + return "realtime"; + case TimeMode::kSimulated: + return "simulated"; + } + RTC_CHECK_NOTREACHED(); + return "unknown"; +} + +NetworkEmulationManager::SimulatedNetworkNode::Builder& +NetworkEmulationManager::SimulatedNetworkNode::Builder::config( + BuiltInNetworkBehaviorConfig config) { + config_ = config; + return *this; +} + +NetworkEmulationManager::SimulatedNetworkNode::Builder& +NetworkEmulationManager::SimulatedNetworkNode::Builder::delay_ms( + int queue_delay_ms) { + config_.queue_delay_ms = queue_delay_ms; + return *this; +} + +NetworkEmulationManager::SimulatedNetworkNode::Builder& +NetworkEmulationManager::SimulatedNetworkNode::Builder::capacity_kbps( + int link_capacity_kbps) { + config_.link_capacity_kbps = link_capacity_kbps; + return *this; +} + +NetworkEmulationManager::SimulatedNetworkNode::Builder& +NetworkEmulationManager::SimulatedNetworkNode::Builder::capacity_Mbps( + int link_capacity_Mbps) { + config_.link_capacity_kbps = link_capacity_Mbps * 1000; + return *this; +} + +NetworkEmulationManager::SimulatedNetworkNode::Builder& +NetworkEmulationManager::SimulatedNetworkNode::Builder::loss(double loss_rate) { + config_.loss_percent = std::round(loss_rate * 100); + return *this; +} + +NetworkEmulationManager::SimulatedNetworkNode::Builder& +NetworkEmulationManager::SimulatedNetworkNode::Builder::packet_queue_length( + int max_queue_length_in_packets) { + config_.queue_length_packets = max_queue_length_in_packets; + return *this; +} + +NetworkEmulationManager::SimulatedNetworkNode +NetworkEmulationManager::SimulatedNetworkNode::Builder::Build( + uint64_t random_seed) const { + RTC_CHECK(net_); + return Build(net_, random_seed); +} + +NetworkEmulationManager::SimulatedNetworkNode +NetworkEmulationManager::SimulatedNetworkNode::Builder::Build( + NetworkEmulationManager* net, + uint64_t random_seed) const { + RTC_CHECK(net); + RTC_CHECK(net_ == nullptr || net_ == net); + SimulatedNetworkNode res; + auto behavior = std::make_unique<SimulatedNetwork>(config_, random_seed); + res.simulation = behavior.get(); + res.node = net->CreateEmulatedNode(std::move(behavior)); + return res; +} + +std::pair<EmulatedNetworkManagerInterface*, EmulatedNetworkManagerInterface*> +NetworkEmulationManager::CreateEndpointPairWithTwoWayRoutes( + const BuiltInNetworkBehaviorConfig& config) { + auto* alice_node = CreateEmulatedNode(config); + auto* bob_node = CreateEmulatedNode(config); + + auto* alice_endpoint = CreateEndpoint(EmulatedEndpointConfig()); + auto* bob_endpoint = CreateEndpoint(EmulatedEndpointConfig()); + + CreateRoute(alice_endpoint, {alice_node}, bob_endpoint); + CreateRoute(bob_endpoint, {bob_node}, alice_endpoint); + + return { + CreateEmulatedNetworkManagerInterface({alice_endpoint}), + CreateEmulatedNetworkManagerInterface({bob_endpoint}), + }; +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/network_emulation_manager.h b/third_party/libwebrtc/api/test/network_emulation_manager.h new file mode 100644 index 0000000000..bc9279d306 --- /dev/null +++ b/third_party/libwebrtc/api/test/network_emulation_manager.h @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2019 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 API_TEST_NETWORK_EMULATION_MANAGER_H_ +#define API_TEST_NETWORK_EMULATION_MANAGER_H_ + +#include <functional> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "api/array_view.h" +#include "api/packet_socket_factory.h" +#include "api/test/network_emulation/cross_traffic.h" +#include "api/test/network_emulation/network_emulation_interfaces.h" +#include "api/test/peer_network_dependencies.h" +#include "api/test/simulated_network.h" +#include "api/test/time_controller.h" +#include "api/units/timestamp.h" +#include "rtc_base/network.h" +#include "rtc_base/network_constants.h" +#include "rtc_base/thread.h" + +namespace webrtc { + +// This API is still in development and can be changed without prior notice. + +// These classes are forward declared here, because they used as handles, to +// make it possible for client code to operate with these abstractions and build +// required network configuration. With forward declaration here implementation +// is more readable, than with interfaces approach and cause user needn't any +// API methods on these abstractions it is acceptable here. + +// EmulatedNetworkNode is an abstraction for some network in the real world, +// like 3G network between peers, or Wi-Fi for one peer and LTE for another. +// Multiple networks can be joined into chain emulating a network path from +// one peer to another. +class EmulatedNetworkNode; + +// EmulatedRoute is handle for single route from one network interface on one +// peer device to another network interface on another peer device. +class EmulatedRoute; + +enum class EmulatedNetworkStatsGatheringMode { + // Gather main network stats counters. See more details on which particular + // metrics are collected in the `EmulatedNetworkStats` and + // `EmulatedNetworkNodeStats` documentation. + kDefault, + // kDefault + also gather per packet statistics. In this mode more memory + // will be used. + kDebug +}; + +struct EmulatedEndpointConfig { + enum class IpAddressFamily { kIpv4, kIpv6 }; + + // If specified will be used to name endpoint for logging purposes. + absl::optional<std::string> name = absl::nullopt; + IpAddressFamily generated_ip_family = IpAddressFamily::kIpv4; + // If specified will be used as IP address for endpoint node. Must be unique + // among all created nodes. + absl::optional<rtc::IPAddress> ip; + // Should endpoint be enabled or not, when it will be created. + // Enabled endpoints will be available for webrtc to send packets. + bool start_as_enabled = true; + // Network type which will be used to represent endpoint to WebRTC. + rtc::AdapterType type = rtc::AdapterType::ADAPTER_TYPE_UNKNOWN; + // Allow endpoint to send packets specifying source IP address different to + // the current endpoint IP address. If false endpoint will crash if attempt + // to send such packet will be done. + bool allow_send_packet_with_different_source_ip = false; + // Allow endpoint to receive packet with destination IP address different to + // the current endpoint IP address. If false endpoint will crash if such + // packet will arrive. + bool allow_receive_packets_with_different_dest_ip = false; +}; + +struct EmulatedTURNServerConfig { + EmulatedEndpointConfig client_config; + EmulatedEndpointConfig peer_config; +}; + +// EmulatedTURNServer is an abstraction for a TURN server. +class EmulatedTURNServerInterface { + public: + struct IceServerConfig { + std::string username; + std::string password; + std::string url; + }; + + virtual ~EmulatedTURNServerInterface() {} + + // Get an IceServer configuration suitable to add to a PeerConnection. + virtual IceServerConfig GetIceServerConfig() const = 0; + + // Get non-null client endpoint, an endpoint that accepts TURN allocations. + // This shall typically be connected to one or more webrtc endpoint. + virtual EmulatedEndpoint* GetClientEndpoint() const = 0; + + // Returns socket address, which client should use to connect to TURN server + // and do TURN allocation. + virtual rtc::SocketAddress GetClientEndpointAddress() const = 0; + + // Get non-null peer endpoint, that is "connected to the internet". + // This shall typically be connected to another TURN server. + virtual EmulatedEndpoint* GetPeerEndpoint() const = 0; +}; + +// Provide interface to obtain all required objects to inject network emulation +// layer into PeerConnection. Also contains information about network interfaces +// accessible by PeerConnection. +class EmulatedNetworkManagerInterface { + public: + virtual ~EmulatedNetworkManagerInterface() = default; + + // Returns non-null pointer to thread that have to be used as network thread + // for WebRTC to properly setup network emulation. Returned thread is owned + // by EmulatedNetworkManagerInterface implementation. + virtual rtc::Thread* network_thread() = 0; + // Returns non-null pointer to network manager that have to be injected into + // WebRTC to properly setup network emulation. Returned manager is owned by + // EmulatedNetworkManagerInterface implementation. + virtual rtc::NetworkManager* network_manager() = 0; + // Returns non-null pointer to packet socket factory that have to be injected + // into WebRTC to properly setup network emulation. Returned factory is owned + // by EmulatedNetworkManagerInterface implementation. + virtual rtc::PacketSocketFactory* packet_socket_factory() = 0; + webrtc::webrtc_pc_e2e::PeerNetworkDependencies network_dependencies() { + return {network_thread(), network_manager(), packet_socket_factory()}; + } + // Returns list of endpoints that are associated with this instance. Pointers + // are guaranteed to be non-null and are owned by NetworkEmulationManager. + virtual std::vector<EmulatedEndpoint*> endpoints() const = 0; + + // Passes summarized network stats for endpoints for this manager into + // specified `stats_callback`. Callback will be executed on network emulation + // internal task queue. + virtual void GetStats( + std::function<void(EmulatedNetworkStats)> stats_callback) const = 0; +}; + +enum class TimeMode { kRealTime, kSimulated }; + +// Called implicitly when parsing an ABSL_FLAG of type TimeMode. +// from the command line flag value `text`. +// Returns `true` and sets `*mode` on success; +// returns `false` and sets `*error` on failure. +bool AbslParseFlag(absl::string_view text, TimeMode* mode, std::string* error); + +// AbslUnparseFlag returns a textual flag value corresponding to the TimeMode +// `mode`. +std::string AbslUnparseFlag(TimeMode mode); + +// Provides an API for creating and configuring emulated network layer. +// All objects returned by this API are owned by NetworkEmulationManager itself +// and will be deleted when manager will be deleted. +class NetworkEmulationManager { + public: + // Helper struct to simplify creation of simulated network behaviors. Contains + // non-owning pointers as the underlying instances are owned by the manager. + struct SimulatedNetworkNode { + SimulatedNetworkInterface* simulation; + EmulatedNetworkNode* node; + + class Builder { + public: + explicit Builder(NetworkEmulationManager* net) : net_(net) {} + Builder() : net_(nullptr) {} + Builder(const Builder&) = default; + // Sets the config state, note that this will replace any previously set + // values. + Builder& config(BuiltInNetworkBehaviorConfig config); + Builder& delay_ms(int queue_delay_ms); + Builder& capacity_kbps(int link_capacity_kbps); + Builder& capacity_Mbps(int link_capacity_Mbps); + Builder& loss(double loss_rate); + Builder& packet_queue_length(int max_queue_length_in_packets); + SimulatedNetworkNode Build(uint64_t random_seed = 1) const; + SimulatedNetworkNode Build(NetworkEmulationManager* net, + uint64_t random_seed = 1) const; + + private: + NetworkEmulationManager* const net_; + BuiltInNetworkBehaviorConfig config_; + }; + }; + virtual ~NetworkEmulationManager() = default; + + virtual TimeController* time_controller() = 0; + // Returns a mode in which underlying time controller operates. + virtual TimeMode time_mode() const = 0; + + // Creates an emulated network node, which represents ideal network with + // unlimited capacity, no delay and no packet loss. + EmulatedNetworkNode* CreateUnconstrainedEmulatedNode() { + return CreateEmulatedNode(BuiltInNetworkBehaviorConfig()); + } + // Creates an emulated network node, which represents single network in + // the emulated network layer. Uses default implementation on network behavior + // which can be configured with `config`. `random_seed` can be provided to + // alter randomization behavior. + virtual EmulatedNetworkNode* CreateEmulatedNode( + BuiltInNetworkBehaviorConfig config, + uint64_t random_seed = 1) = 0; + // Creates an emulated network node, which represents single network in + // the emulated network layer. `network_behavior` determines how created node + // will forward incoming packets to the next receiver. + virtual EmulatedNetworkNode* CreateEmulatedNode( + std::unique_ptr<NetworkBehaviorInterface> network_behavior) = 0; + + virtual SimulatedNetworkNode::Builder NodeBuilder() = 0; + + // Creates an emulated endpoint, which represents single network interface on + // the peer's device. + virtual EmulatedEndpoint* CreateEndpoint(EmulatedEndpointConfig config) = 0; + // Enable emulated endpoint to make it available for webrtc. + // Caller mustn't enable currently enabled endpoint. + virtual void EnableEndpoint(EmulatedEndpoint* endpoint) = 0; + // Disable emulated endpoint to make it unavailable for webrtc. + // Caller mustn't disable currently disabled endpoint. + virtual void DisableEndpoint(EmulatedEndpoint* endpoint) = 0; + + // Creates a route between endpoints going through specified network nodes. + // This route is single direction only and describe how traffic that was + // sent by network interface `from` have to be delivered to the network + // interface `to`. Return object can be used to remove created route. The + // route must contains at least one network node inside it. + // + // Assume that E{0-9} are endpoints and N{0-9} are network nodes, then + // creation of the route have to follow these rules: + // 1. A route consists of a source endpoint, an ordered list of one or + // more network nodes, and a destination endpoint. + // 2. If (E1, ..., E2) is a route, then E1 != E2. + // In other words, the source and the destination may not be the same. + // 3. Given two simultaneously existing routes (E1, ..., E2) and + // (E3, ..., E4), either E1 != E3 or E2 != E4. + // In other words, there may be at most one route from any given source + // endpoint to any given destination endpoint. + // 4. Given two simultaneously existing routes (E1, ..., N1, ..., E2) + // and (E3, ..., N2, ..., E4), either N1 != N2 or E2 != E4. + // In other words, a network node may not belong to two routes that lead + // to the same destination endpoint. + virtual EmulatedRoute* CreateRoute( + EmulatedEndpoint* from, + const std::vector<EmulatedNetworkNode*>& via_nodes, + EmulatedEndpoint* to) = 0; + + // Creates a route over the given `via_nodes` creating the required endpoints + // in the process. The returned EmulatedRoute pointer can be used in other + // calls as a transport route for message or cross traffic. + virtual EmulatedRoute* CreateRoute( + const std::vector<EmulatedNetworkNode*>& via_nodes) = 0; + + // Creates a default route between endpoints going through specified network + // nodes. Default route is used for packet when there is no known route for + // packet's destination IP. + // + // This route is single direction only and describe how traffic that was + // sent by network interface `from` have to be delivered in case if routing + // was unspecified. Return object can be used to remove created route. The + // route must contains at least one network node inside it. + // + // Assume that E{0-9} are endpoints and N{0-9} are network nodes, then + // creation of the route have to follow these rules: + // 1. A route consists of a source endpoint, an ordered list of one or + // more network nodes, and a destination endpoint. + // 2. If (E1, ..., E2) is a route, then E1 != E2. + // In other words, the source and the destination may not be the same. + // 3. Given two simultaneously existing routes (E1, ..., E2) and + // (E3, ..., E4), either E1 != E3 or E2 != E4. + // In other words, there may be at most one route from any given source + // endpoint to any given destination endpoint. + // 4. Given two simultaneously existing routes (E1, ..., N1, ..., E2) + // and (E3, ..., N2, ..., E4), either N1 != N2 or E2 != E4. + // In other words, a network node may not belong to two routes that lead + // to the same destination endpoint. + // 5. Any node N can belong to only one default route. + virtual EmulatedRoute* CreateDefaultRoute( + EmulatedEndpoint* from, + const std::vector<EmulatedNetworkNode*>& via_nodes, + EmulatedEndpoint* to) = 0; + + // Removes route previously created by CreateRoute(...). + // Caller mustn't call this function with route, that have been already + // removed earlier. Removing a route that is currently in use will lead to + // packets being dropped. + virtual void ClearRoute(EmulatedRoute* route) = 0; + + // Creates a simulated TCP connection using `send_route` for traffic and + // `ret_route` for feedback. This can be used to emulate HTTP cross traffic + // and to implement realistic reliable signaling over lossy networks. + // TODO(srte): Handle clearing of the routes involved. + virtual TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route, + EmulatedRoute* ret_route) = 0; + + // Creates a route over the given `via_nodes`. Returns an object that can be + // used to emulate network load with cross traffic over the created route. + virtual CrossTrafficRoute* CreateCrossTrafficRoute( + const std::vector<EmulatedNetworkNode*>& via_nodes) = 0; + + // Starts generating cross traffic using given `generator`. Takes ownership + // over the generator. + virtual CrossTrafficGenerator* StartCrossTraffic( + std::unique_ptr<CrossTrafficGenerator> generator) = 0; + + // Stops generating cross traffic that was started using given `generator`. + // The `generator` shouldn't be used after and the reference may be invalid. + virtual void StopCrossTraffic(CrossTrafficGenerator* generator) = 0; + + // Creates EmulatedNetworkManagerInterface which can be used then to inject + // network emulation layer into PeerConnection. `endpoints` - are available + // network interfaces for PeerConnection. If endpoint is enabled, it will be + // immediately available for PeerConnection, otherwise user will be able to + // enable endpoint later to make it available for PeerConnection. + virtual EmulatedNetworkManagerInterface* + CreateEmulatedNetworkManagerInterface( + const std::vector<EmulatedEndpoint*>& endpoints) = 0; + + // Passes combined network stats for all specified `endpoints` into specified + // `stats_callback`. Callback will be executed on network emulation + // internal task queue. + virtual void GetStats( + rtc::ArrayView<EmulatedEndpoint* const> endpoints, + std::function<void(EmulatedNetworkStats)> stats_callback) = 0; + + // Passes combined network stats for all specified `nodes` into specified + // `stats_callback`. Callback will be executed on network emulation + // internal task queue. + virtual void GetStats( + rtc::ArrayView<EmulatedNetworkNode* const> nodes, + std::function<void(EmulatedNetworkNodeStats)> stats_callback) = 0; + + // Create a EmulatedTURNServer. + // The TURN server has 2 endpoints that need to be connected with routes, + // - GetClientEndpoint() - the endpoint that accepts TURN allocations. + // - GetPeerEndpoint() - the endpoint that is "connected to the internet". + virtual EmulatedTURNServerInterface* CreateTURNServer( + EmulatedTURNServerConfig config) = 0; + + // Create a pair of EmulatedNetworkManagerInterfaces connected to each other. + std::pair<EmulatedNetworkManagerInterface*, EmulatedNetworkManagerInterface*> + CreateEndpointPairWithTwoWayRoutes( + const BuiltInNetworkBehaviorConfig& config); +}; + +} // namespace webrtc + +#endif // API_TEST_NETWORK_EMULATION_MANAGER_H_ diff --git a/third_party/libwebrtc/api/test/pclf/BUILD.gn b/third_party/libwebrtc/api/test/pclf/BUILD.gn new file mode 100644 index 0000000000..0526478e8b --- /dev/null +++ b/third_party/libwebrtc/api/test/pclf/BUILD.gn @@ -0,0 +1,114 @@ +# Copyright (c) 2022 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") + +rtc_source_set("media_configuration") { + visibility = [ "*" ] + testonly = true + sources = [ + "media_configuration.cc", + "media_configuration.h", + ] + + deps = [ + "../..:array_view", + "../..:audio_options_api", + "../..:audio_quality_analyzer_api", + "../..:callfactory_api", + "../..:fec_controller_api", + "../..:frame_generator_api", + "../..:function_view", + "../..:libjingle_peerconnection_api", + "../..:media_stream_interface", + "../..:packet_socket_factory", + "../..:peer_network_dependencies", + "../..:rtp_parameters", + "../..:simulated_network_api", + "../..:stats_observer_interface", + "../..:track_id_stream_info_map", + "../..:video_quality_analyzer_api", + "../../../modules/audio_processing:api", + "../../../rtc_base:checks", + "../../../rtc_base:network", + "../../../rtc_base:rtc_certificate_generator", + "../../../rtc_base:ssl", + "../../../rtc_base:stringutils", + "../../../rtc_base:threading", + "../../../test:fileutils", + "../../../test:video_test_support", + "../../../test/pc/e2e/analyzer/video:video_dumping", + "../../audio:audio_mixer_api", + "../../rtc_event_log", + "../../task_queue", + "../../transport:network_control", + "../../units:time_delta", + "../../video_codecs:video_codecs_api", + "../video:video_frame_writer", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("media_quality_test_params") { + visibility = [ "*" ] + testonly = true + sources = [ "media_quality_test_params.h" ] + + deps = [ + ":media_configuration", + "../../../api:callfactory_api", + "../../../api:fec_controller_api", + "../../../api:field_trials_view", + "../../../api:libjingle_peerconnection_api", + "../../../api:packet_socket_factory", + "../../../api/audio:audio_mixer_api", + "../../../api/rtc_event_log", + "../../../api/task_queue", + "../../../api/transport:network_control", + "../../../api/video_codecs:video_codecs_api", + "../../../modules/audio_processing:api", + "../../../p2p:rtc_p2p", + "../../../rtc_base:network", + "../../../rtc_base:rtc_certificate_generator", + "../../../rtc_base:ssl", + "../../../rtc_base:threading", + ] +} + +rtc_library("peer_configurer") { + visibility = [ "*" ] + testonly = true + sources = [ + "peer_configurer.cc", + "peer_configurer.h", + ] + deps = [ + ":media_configuration", + ":media_quality_test_params", + "../../../api:callfactory_api", + "../../../api:create_peer_connection_quality_test_frame_generator", + "../../../api:fec_controller_api", + "../../../api:packet_socket_factory", + "../../../api:peer_network_dependencies", + "../../../api/audio:audio_mixer_api", + "../../../api/rtc_event_log", + "../../../api/task_queue", + "../../../api/transport:network_control", + "../../../api/video_codecs:video_codecs_api", + "../../../modules/audio_processing:api", + "../../../rtc_base:network", + "../../../rtc_base:rtc_certificate_generator", + "../../../rtc_base:ssl", + "../../../rtc_base:threading", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} diff --git a/third_party/libwebrtc/api/test/pclf/DEPS b/third_party/libwebrtc/api/test/pclf/DEPS new file mode 100644 index 0000000000..60cc0aeeb3 --- /dev/null +++ b/third_party/libwebrtc/api/test/pclf/DEPS @@ -0,0 +1,13 @@ +specific_include_rules = { + ".*": [ + "+modules/audio_processing/include/audio_processing.h", + "+rtc_base/checks.h", + "+rtc_base/network.h", + "+rtc_base/rtc_certificate_generator.h", + "+rtc_base/ssl_certificate.h", + "+rtc_base/thread.h", + ], + "media_quality_test_params\.h": [ + "+p2p/base/port_allocator.h", + ], +} diff --git a/third_party/libwebrtc/api/test/pclf/media_configuration.cc b/third_party/libwebrtc/api/test/pclf/media_configuration.cc new file mode 100644 index 0000000000..56b9e52e01 --- /dev/null +++ b/third_party/libwebrtc/api/test/pclf/media_configuration.cc @@ -0,0 +1,314 @@ +/* + * Copyright 2022 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 "api/test/pclf/media_configuration.h" + +#include <string> +#include <utility> + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/test/video/video_frame_writer.h" +#include "rtc_base/checks.h" +#include "rtc_base/strings/string_builder.h" +#include "test/pc/e2e/analyzer/video/video_dumping.h" +#include "test/testsupport/file_utils.h" +#include "test/testsupport/video_frame_writer.h" + +namespace webrtc { +namespace webrtc_pc_e2e { +namespace { + +std::string SpecToString(VideoResolution::Spec spec) { + switch (spec) { + case VideoResolution::Spec::kNone: + return "None"; + case VideoResolution::Spec::kMaxFromSender: + return "MaxFromSender"; + } +} + +void AppendResolution(const VideoResolution& resolution, + rtc::StringBuilder& builder) { + builder << "_" << resolution.width() << "x" << resolution.height() << "_" + << resolution.fps(); +} + +} // namespace + +ScreenShareConfig::ScreenShareConfig(TimeDelta slide_change_interval) + : slide_change_interval(slide_change_interval) { + RTC_CHECK_GT(slide_change_interval.ms(), 0); +} +VideoSimulcastConfig::VideoSimulcastConfig(int simulcast_streams_count) + : simulcast_streams_count(simulcast_streams_count) { + RTC_CHECK_GT(simulcast_streams_count, 1); +} +EmulatedSFUConfig::EmulatedSFUConfig(int target_layer_index) + : target_layer_index(target_layer_index) { + RTC_CHECK_GE(target_layer_index, 0); +} + +EmulatedSFUConfig::EmulatedSFUConfig(absl::optional<int> target_layer_index, + absl::optional<int> target_temporal_index) + : target_layer_index(target_layer_index), + target_temporal_index(target_temporal_index) { + RTC_CHECK_GE(target_temporal_index.value_or(0), 0); + if (target_temporal_index) + RTC_CHECK_GE(*target_temporal_index, 0); +} + +VideoResolution::VideoResolution(size_t width, size_t height, int32_t fps) + : width_(width), height_(height), fps_(fps), spec_(Spec::kNone) {} +VideoResolution::VideoResolution(Spec spec) + : width_(0), height_(0), fps_(0), spec_(spec) {} + +bool VideoResolution::operator==(const VideoResolution& other) const { + if (spec_ != Spec::kNone && spec_ == other.spec_) { + // If there is some particular spec set, then it doesn't matter what + // values we have in other fields. + return true; + } + return width_ == other.width_ && height_ == other.height_ && + fps_ == other.fps_ && spec_ == other.spec_; +} +bool VideoResolution::operator!=(const VideoResolution& other) const { + return !(*this == other); +} + +bool VideoResolution::IsRegular() const { + return spec_ == Spec::kNone; +} +std::string VideoResolution::ToString() const { + rtc::StringBuilder out; + out << "{ width=" << width_ << ", height=" << height_ << ", fps=" << fps_ + << ", spec=" << SpecToString(spec_) << " }"; + return out.Release(); +} + +VideoDumpOptions::VideoDumpOptions( + absl::string_view output_directory, + int sampling_modulo, + bool export_frame_ids, + std::function<std::unique_ptr<test::VideoFrameWriter>( + absl::string_view file_name_prefix, + const VideoResolution& resolution)> video_frame_writer_factory) + : output_directory_(output_directory), + sampling_modulo_(sampling_modulo), + export_frame_ids_(export_frame_ids), + video_frame_writer_factory_(video_frame_writer_factory) { + RTC_CHECK_GT(sampling_modulo, 0); +} + +VideoDumpOptions::VideoDumpOptions(absl::string_view output_directory, + bool export_frame_ids) + : VideoDumpOptions(output_directory, + kDefaultSamplingModulo, + export_frame_ids) {} + +std::unique_ptr<test::VideoFrameWriter> +VideoDumpOptions::CreateInputDumpVideoFrameWriter( + absl::string_view stream_label, + const VideoResolution& resolution) const { + std::unique_ptr<test::VideoFrameWriter> writer = video_frame_writer_factory_( + GetInputDumpFileName(stream_label, resolution), resolution); + absl::optional<std::string> frame_ids_file = + GetInputFrameIdsDumpFileName(stream_label, resolution); + if (frame_ids_file.has_value()) { + writer = CreateVideoFrameWithIdsWriter(std::move(writer), *frame_ids_file); + } + return writer; +} + +std::unique_ptr<test::VideoFrameWriter> +VideoDumpOptions::CreateOutputDumpVideoFrameWriter( + absl::string_view stream_label, + absl::string_view receiver, + const VideoResolution& resolution) const { + std::unique_ptr<test::VideoFrameWriter> writer = video_frame_writer_factory_( + GetOutputDumpFileName(stream_label, receiver, resolution), resolution); + absl::optional<std::string> frame_ids_file = + GetOutputFrameIdsDumpFileName(stream_label, receiver, resolution); + if (frame_ids_file.has_value()) { + writer = CreateVideoFrameWithIdsWriter(std::move(writer), *frame_ids_file); + } + return writer; +} + +std::unique_ptr<test::VideoFrameWriter> +VideoDumpOptions::Y4mVideoFrameWriterFactory( + absl::string_view file_name_prefix, + const VideoResolution& resolution) { + return std::make_unique<test::Y4mVideoFrameWriterImpl>( + std::string(file_name_prefix) + ".y4m", resolution.width(), + resolution.height(), resolution.fps()); +} + +std::string VideoDumpOptions::GetInputDumpFileName( + absl::string_view stream_label, + const VideoResolution& resolution) const { + rtc::StringBuilder file_name; + file_name << stream_label; + AppendResolution(resolution, file_name); + return test::JoinFilename(output_directory_, file_name.Release()); +} + +absl::optional<std::string> VideoDumpOptions::GetInputFrameIdsDumpFileName( + absl::string_view stream_label, + const VideoResolution& resolution) const { + if (!export_frame_ids_) { + return absl::nullopt; + } + return GetInputDumpFileName(stream_label, resolution) + ".frame_ids.txt"; +} + +std::string VideoDumpOptions::GetOutputDumpFileName( + absl::string_view stream_label, + absl::string_view receiver, + const VideoResolution& resolution) const { + rtc::StringBuilder file_name; + file_name << stream_label << "_" << receiver; + AppendResolution(resolution, file_name); + return test::JoinFilename(output_directory_, file_name.Release()); +} + +absl::optional<std::string> VideoDumpOptions::GetOutputFrameIdsDumpFileName( + absl::string_view stream_label, + absl::string_view receiver, + const VideoResolution& resolution) const { + if (!export_frame_ids_) { + return absl::nullopt; + } + return GetOutputDumpFileName(stream_label, receiver, resolution) + + ".frame_ids.txt"; +} + +std::string VideoDumpOptions::ToString() const { + rtc::StringBuilder out; + out << "{ output_directory_=" << output_directory_ + << ", sampling_modulo_=" << sampling_modulo_ + << ", export_frame_ids_=" << export_frame_ids_ << " }"; + return out.Release(); +} + +VideoConfig::VideoConfig(const VideoResolution& resolution) + : width(resolution.width()), + height(resolution.height()), + fps(resolution.fps()) { + RTC_CHECK(resolution.IsRegular()); +} +VideoConfig::VideoConfig(size_t width, size_t height, int32_t fps) + : width(width), height(height), fps(fps) {} +VideoConfig::VideoConfig(std::string stream_label, + size_t width, + size_t height, + int32_t fps) + : width(width), + height(height), + fps(fps), + stream_label(std::move(stream_label)) {} + +AudioConfig::AudioConfig(std::string stream_label) + : stream_label(std::move(stream_label)) {} + +VideoCodecConfig::VideoCodecConfig(std::string name) + : name(std::move(name)), required_params() {} +VideoCodecConfig::VideoCodecConfig( + std::string name, + std::map<std::string, std::string> required_params) + : name(std::move(name)), required_params(std::move(required_params)) {} + +absl::optional<VideoResolution> VideoSubscription::GetMaxResolution( + rtc::ArrayView<const VideoConfig> video_configs) { + std::vector<VideoResolution> resolutions; + for (const auto& video_config : video_configs) { + resolutions.push_back(video_config.GetResolution()); + } + return GetMaxResolution(resolutions); +} + +absl::optional<VideoResolution> VideoSubscription::GetMaxResolution( + rtc::ArrayView<const VideoResolution> resolutions) { + if (resolutions.empty()) { + return absl::nullopt; + } + + VideoResolution max_resolution; + for (const VideoResolution& resolution : resolutions) { + if (max_resolution.width() < resolution.width()) { + max_resolution.set_width(resolution.width()); + } + if (max_resolution.height() < resolution.height()) { + max_resolution.set_height(resolution.height()); + } + if (max_resolution.fps() < resolution.fps()) { + max_resolution.set_fps(resolution.fps()); + } + } + return max_resolution; +} + +bool VideoSubscription::operator==(const VideoSubscription& other) const { + return default_resolution_ == other.default_resolution_ && + peers_resolution_ == other.peers_resolution_; +} +bool VideoSubscription::operator!=(const VideoSubscription& other) const { + return !(*this == other); +} + +VideoSubscription& VideoSubscription::SubscribeToPeer( + absl::string_view peer_name, + VideoResolution resolution) { + peers_resolution_[std::string(peer_name)] = resolution; + return *this; +} + +VideoSubscription& VideoSubscription::SubscribeToAllPeers( + VideoResolution resolution) { + default_resolution_ = resolution; + return *this; +} + +absl::optional<VideoResolution> VideoSubscription::GetResolutionForPeer( + absl::string_view peer_name) const { + auto it = peers_resolution_.find(std::string(peer_name)); + if (it == peers_resolution_.end()) { + return default_resolution_; + } + return it->second; +} + +std::vector<std::string> VideoSubscription::GetSubscribedPeers() const { + std::vector<std::string> subscribed_streams; + subscribed_streams.reserve(peers_resolution_.size()); + for (const auto& entry : peers_resolution_) { + subscribed_streams.push_back(entry.first); + } + return subscribed_streams; +} + +std::string VideoSubscription::ToString() const { + rtc::StringBuilder out; + out << "{ default_resolution_=["; + if (default_resolution_.has_value()) { + out << default_resolution_->ToString(); + } else { + out << "undefined"; + } + out << "], {"; + for (const auto& [peer_name, resolution] : peers_resolution_) { + out << "[" << peer_name << ": " << resolution.ToString() << "], "; + } + out << "} }"; + return out.Release(); +} +} // namespace webrtc_pc_e2e +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/pclf/media_configuration.h b/third_party/libwebrtc/api/test/pclf/media_configuration.h new file mode 100644 index 0000000000..8e841a265b --- /dev/null +++ b/third_party/libwebrtc/api/test/pclf/media_configuration.h @@ -0,0 +1,484 @@ +/* + * Copyright (c) 2022 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 API_TEST_PCLF_MEDIA_CONFIGURATION_H_ +#define API_TEST_PCLF_MEDIA_CONFIGURATION_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <functional> +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "absl/memory/memory.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/async_resolver_factory.h" +#include "api/audio/audio_mixer.h" +#include "api/audio_options.h" +#include "api/call/call_factory_interface.h" +#include "api/fec_controller.h" +#include "api/function_view.h" +#include "api/media_stream_interface.h" +#include "api/peer_connection_interface.h" +#include "api/rtc_event_log/rtc_event_log_factory_interface.h" +#include "api/rtp_parameters.h" +#include "api/task_queue/task_queue_factory.h" +#include "api/test/audio_quality_analyzer_interface.h" +#include "api/test/frame_generator_interface.h" +#include "api/test/peer_network_dependencies.h" +#include "api/test/simulated_network.h" +#include "api/test/stats_observer_interface.h" +#include "api/test/track_id_stream_info_map.h" +#include "api/test/video/video_frame_writer.h" +#include "api/test/video_quality_analyzer_interface.h" +#include "api/transport/network_control.h" +#include "api/units/time_delta.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "modules/audio_processing/include/audio_processing.h" +#include "rtc_base/checks.h" +#include "rtc_base/network.h" +#include "rtc_base/rtc_certificate_generator.h" +#include "rtc_base/ssl_certificate.h" +#include "rtc_base/thread.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +constexpr size_t kDefaultSlidesWidth = 1850; +constexpr size_t kDefaultSlidesHeight = 1110; + +// The index of required capturing device in OS provided list of video +// devices. On Linux and Windows the list will be obtained via +// webrtc::VideoCaptureModule::DeviceInfo, on Mac OS via +// [RTCCameraVideoCapturer captureDevices]. +enum class CapturingDeviceIndex : size_t {}; + +// Contains parameters for screen share scrolling. +// +// If scrolling is enabled, then it will be done by putting sliding window +// on source video and moving this window from top left corner to the +// bottom right corner of the picture. +// +// In such case source dimensions must be greater or equal to the sliding +// window dimensions. So `source_width` and `source_height` are the dimensions +// of the source frame, while `VideoConfig::width` and `VideoConfig::height` +// are the dimensions of the sliding window. +// +// Because `source_width` and `source_height` are dimensions of the source +// frame, they have to be width and height of videos from +// `ScreenShareConfig::slides_yuv_file_names`. +// +// Because scrolling have to be done on single slide it also requires, that +// `duration` must be less or equal to +// `ScreenShareConfig::slide_change_interval`. +struct ScrollingParams { + // Duration of scrolling. + TimeDelta duration; + // Width of source slides video. + size_t source_width = kDefaultSlidesWidth; + // Height of source slides video. + size_t source_height = kDefaultSlidesHeight; +}; + +// Contains screen share video stream properties. +struct ScreenShareConfig { + explicit ScreenShareConfig(TimeDelta slide_change_interval); + + // Shows how long one slide should be presented on the screen during + // slide generation. + TimeDelta slide_change_interval; + // If true, slides will be generated programmatically. No scrolling params + // will be applied in such case. + bool generate_slides = false; + // If present scrolling will be applied. Please read extra requirement on + // `slides_yuv_file_names` for scrolling. + absl::optional<ScrollingParams> scrolling_params; + // Contains list of yuv files with slides. + // + // If empty, default set of slides will be used. In such case + // `VideoConfig::width` must be equal to `kDefaultSlidesWidth` and + // `VideoConfig::height` must be equal to `kDefaultSlidesHeight` or if + // `scrolling_params` are specified, then `ScrollingParams::source_width` + // must be equal to `kDefaultSlidesWidth` and + // `ScrollingParams::source_height` must be equal to `kDefaultSlidesHeight`. + std::vector<std::string> slides_yuv_file_names; +}; + +// Config for Vp8 simulcast or non-standard Vp9 SVC testing. +// +// To configure standard SVC setting, use `scalability_mode` in the +// `encoding_params` array. +// This configures Vp9 SVC by requesting simulcast layers, the request is +// internally converted to a request for SVC layers. +// +// SVC support is limited: +// During SVC testing there is no SFU, so framework will try to emulate SFU +// behavior in regular p2p call. Because of it there are such limitations: +// * if `target_spatial_index` is not equal to the highest spatial layer +// then no packet/frame drops are allowed. +// +// If there will be any drops, that will affect requested layer, then +// WebRTC SVC implementation will continue decoding only the highest +// available layer and won't restore lower layers, so analyzer won't +// receive required data which will cause wrong results or test failures. +struct VideoSimulcastConfig { + explicit VideoSimulcastConfig(int simulcast_streams_count); + + // Specified amount of simulcast streams/SVC layers, depending on which + // encoder is used. + int simulcast_streams_count; +}; + +// Configuration for the emulated Selective Forward Unit (SFU) +// +// The framework can optionally filter out frames that are decoded +// using an emulated SFU. +// When using simulcast or SVC, it's not always desirable to receive +// all frames. In a real world call, a SFU will only forward a subset +// of the frames. +// The emulated SFU is not able to change its configuration dynamically, +// if adaptation happens during the call, layers may be dropped and the +// analyzer won't receive the required data which will cause wrong results or +// test failures. +struct EmulatedSFUConfig { + EmulatedSFUConfig() = default; + explicit EmulatedSFUConfig(int target_layer_index); + EmulatedSFUConfig(absl::optional<int> target_layer_index, + absl::optional<int> target_temporal_index); + + // Specifies simulcast or spatial index of the video stream to analyze. + // There are 2 cases: + // 1. simulcast encoding is used: + // in such case `target_layer_index` will specify the index of + // simulcast stream, that should be analyzed. Other streams will be + // dropped. + // 2. SVC encoding is used: + // in such case `target_layer_index` will specify the top interesting + // spatial layer and all layers below, including target one will be + // processed. All layers above target one will be dropped. + // If not specified then all streams will be received and analyzed. + // When set, it instructs the framework to create an emulated Selective + // Forwarding Unit (SFU) that will propagate only the requested layers. + absl::optional<int> target_layer_index; + // Specifies the index of the maximum temporal unit to keep. + // If not specified then all temporal layers will be received and analyzed. + // When set, it instructs the framework to create an emulated Selective + // Forwarding Unit (SFU) that will propagate only up to the requested layer. + absl::optional<int> target_temporal_index; +}; + +class VideoResolution { + public: + // Determines special resolutions, which can't be expressed in terms of + // width, height and fps. + enum class Spec { + // No extra spec set. It describes a regular resolution described by + // width, height and fps. + kNone, + // Describes resolution which contains max value among all sender's + // video streams in each dimension (width, height, fps). + kMaxFromSender + }; + + VideoResolution(size_t width, size_t height, int32_t fps); + explicit VideoResolution(Spec spec = Spec::kNone); + + bool operator==(const VideoResolution& other) const; + bool operator!=(const VideoResolution& other) const; + + size_t width() const { return width_; } + void set_width(size_t width) { width_ = width; } + size_t height() const { return height_; } + void set_height(size_t height) { height_ = height; } + int32_t fps() const { return fps_; } + void set_fps(int32_t fps) { fps_ = fps; } + + // Returns if it is a regular resolution or not. The resolution is regular + // if it's spec is `Spec::kNone`. + bool IsRegular() const; + + std::string ToString() const; + + private: + size_t width_ = 0; + size_t height_ = 0; + int32_t fps_ = 0; + Spec spec_ = Spec::kNone; +}; + +class VideoDumpOptions { + public: + static constexpr int kDefaultSamplingModulo = 1; + + // output_directory - the output directory where stream will be dumped. The + // output files' names will be constructed as + // <stream_name>_<receiver_name>_<resolution>.<extension> for output dumps + // and <stream_name>_<resolution>.<extension> for input dumps. + // By default <extension> is "y4m". Resolution is in the format + // <width>x<height>_<fps>. + // sampling_modulo - the module for the video frames to be dumped. Modulo + // equals X means every Xth frame will be written to the dump file. The + // value must be greater than 0. (Default: 1) + // export_frame_ids - specifies if frame ids should be exported together + // with content of the stream. If true, an output file with the same name as + // video dump and suffix ".frame_ids.txt" will be created. It will contain + // the frame ids in the same order as original frames in the output + // file with stream content. File will contain one frame id per line. + // (Default: false) + // `video_frame_writer_factory` - factory function to create a video frame + // writer for input and output video files. (Default: Y4M video writer + // factory). + explicit VideoDumpOptions( + absl::string_view output_directory, + int sampling_modulo = kDefaultSamplingModulo, + bool export_frame_ids = false, + std::function<std::unique_ptr<test::VideoFrameWriter>( + absl::string_view file_name_prefix, + const VideoResolution& resolution)> video_frame_writer_factory = + Y4mVideoFrameWriterFactory); + VideoDumpOptions(absl::string_view output_directory, bool export_frame_ids); + + VideoDumpOptions(const VideoDumpOptions&) = default; + VideoDumpOptions& operator=(const VideoDumpOptions&) = default; + VideoDumpOptions(VideoDumpOptions&&) = default; + VideoDumpOptions& operator=(VideoDumpOptions&&) = default; + + std::string output_directory() const { return output_directory_; } + int sampling_modulo() const { return sampling_modulo_; } + bool export_frame_ids() const { return export_frame_ids_; } + + std::unique_ptr<test::VideoFrameWriter> CreateInputDumpVideoFrameWriter( + absl::string_view stream_label, + const VideoResolution& resolution) const; + + std::unique_ptr<test::VideoFrameWriter> CreateOutputDumpVideoFrameWriter( + absl::string_view stream_label, + absl::string_view receiver, + const VideoResolution& resolution) const; + + std::string ToString() const; + + private: + static std::unique_ptr<test::VideoFrameWriter> Y4mVideoFrameWriterFactory( + absl::string_view file_name_prefix, + const VideoResolution& resolution); + std::string GetInputDumpFileName(absl::string_view stream_label, + const VideoResolution& resolution) const; + // Returns file name for input frame ids dump if `export_frame_ids()` is + // true, absl::nullopt otherwise. + absl::optional<std::string> GetInputFrameIdsDumpFileName( + absl::string_view stream_label, + const VideoResolution& resolution) const; + std::string GetOutputDumpFileName(absl::string_view stream_label, + absl::string_view receiver, + const VideoResolution& resolution) const; + // Returns file name for output frame ids dump if `export_frame_ids()` is + // true, absl::nullopt otherwise. + absl::optional<std::string> GetOutputFrameIdsDumpFileName( + absl::string_view stream_label, + absl::string_view receiver, + const VideoResolution& resolution) const; + + std::string output_directory_; + int sampling_modulo_ = 1; + bool export_frame_ids_ = false; + std::function<std::unique_ptr<test::VideoFrameWriter>( + absl::string_view file_name_prefix, + const VideoResolution& resolution)> + video_frame_writer_factory_; +}; + +// Contains properties of single video stream. +struct VideoConfig { + explicit VideoConfig(const VideoResolution& resolution); + VideoConfig(size_t width, size_t height, int32_t fps); + VideoConfig(std::string stream_label, + size_t width, + size_t height, + int32_t fps); + + // Video stream width. + size_t width; + // Video stream height. + size_t height; + int32_t fps; + VideoResolution GetResolution() const { + return VideoResolution(width, height, fps); + } + + // Have to be unique among all specified configs for all peers in the call. + // Will be auto generated if omitted. + absl::optional<std::string> stream_label; + // Will be set for current video track. If equals to kText or kDetailed - + // screencast in on. + absl::optional<VideoTrackInterface::ContentHint> content_hint; + // If presented video will be transfered in simulcast/SVC mode depending on + // which encoder is used. + // + // Simulcast is supported only from 1st added peer. For VP8 simulcast only + // without RTX is supported so it will be automatically disabled for all + // simulcast tracks. For VP9 simulcast enables VP9 SVC mode and support RTX, + // but only on non-lossy networks. See more in documentation to + // VideoSimulcastConfig. + absl::optional<VideoSimulcastConfig> simulcast_config; + // Configuration for the emulated Selective Forward Unit (SFU). + absl::optional<EmulatedSFUConfig> emulated_sfu_config; + // Encoding parameters for both singlecast and per simulcast layer. + // If singlecast is used, if not empty, a single value can be provided. + // If simulcast is used, if not empty, `encoding_params` size have to be + // equal to `simulcast_config.simulcast_streams_count`. Will be used to set + // transceiver send encoding params for each layer. + // RtpEncodingParameters::rid may be changed by fixture implementation to + // ensure signaling correctness. + std::vector<RtpEncodingParameters> encoding_params; + // Count of temporal layers for video stream. This value will be set into + // each RtpEncodingParameters of RtpParameters of corresponding + // RtpSenderInterface for this video stream. + absl::optional<int> temporal_layers_count; + // If specified defines how input should be dumped. It is actually one of + // the test's output file, which contains copy of what was captured during + // the test for this video stream on sender side. It is useful when + // generator is used as input. + absl::optional<VideoDumpOptions> input_dump_options; + // If specified defines how output should be dumped on the receiver side for + // this stream. The produced files contain what was rendered for this video + // stream on receiver side per each receiver. + absl::optional<VideoDumpOptions> output_dump_options; + // If set to true uses fixed frame rate while dumping output video to the + // file. Requested `VideoSubscription::fps()` will be used as frame rate. + bool output_dump_use_fixed_framerate = false; + // If true will display input and output video on the user's screen. + bool show_on_screen = false; + // If specified, determines a sync group to which this video stream belongs. + // According to bugs.webrtc.org/4762 WebRTC supports synchronization only + // for pair of single audio and single video stream. + absl::optional<std::string> sync_group; + // If specified, it will be set into RtpParameters of corresponding + // RtpSenderInterface for this video stream. + // Note that this setting takes precedence over `content_hint`. + absl::optional<DegradationPreference> degradation_preference; +}; + +// Contains properties for audio in the call. +struct AudioConfig { + enum Mode { + kGenerated, + kFile, + }; + + AudioConfig() = default; + explicit AudioConfig(std::string stream_label); + + // Have to be unique among all specified configs for all peers in the call. + // Will be auto generated if omitted. + absl::optional<std::string> stream_label; + Mode mode = kGenerated; + // Have to be specified only if mode = kFile + absl::optional<std::string> input_file_name; + // If specified the input stream will be also copied to specified file. + absl::optional<std::string> input_dump_file_name; + // If specified the output stream will be copied to specified file. + absl::optional<std::string> output_dump_file_name; + + // Audio options to use. + cricket::AudioOptions audio_options; + // Sampling frequency of input audio data (from file or generated). + int sampling_frequency_in_hz = 48000; + // If specified, determines a sync group to which this audio stream belongs. + // According to bugs.webrtc.org/4762 WebRTC supports synchronization only + // for pair of single audio and single video stream. + absl::optional<std::string> sync_group; +}; + +struct VideoCodecConfig { + explicit VideoCodecConfig(std::string name); + VideoCodecConfig(std::string name, + std::map<std::string, std::string> required_params); + // Next two fields are used to specify concrete video codec, that should be + // used in the test. Video code will be negotiated in SDP during offer/ + // answer exchange. + // Video codec name. You can find valid names in + // media/base/media_constants.h + std::string name; + // Map of parameters, that have to be specified on SDP codec. Each parameter + // is described by key and value. Codec parameters will match the specified + // map if and only if for each key from `required_params` there will be + // a parameter with name equal to this key and parameter value will be equal + // to the value from `required_params` for this key. + // If empty then only name will be used to match the codec. + std::map<std::string, std::string> required_params; +}; + +// Subscription to the remote video streams. It declares which remote stream +// peer should receive and in which resolution (width x height x fps). +class VideoSubscription { + public: + // Returns the resolution constructed as maximum from all resolution + // dimensions: width, height and fps. + static absl::optional<VideoResolution> GetMaxResolution( + rtc::ArrayView<const VideoConfig> video_configs); + static absl::optional<VideoResolution> GetMaxResolution( + rtc::ArrayView<const VideoResolution> resolutions); + + bool operator==(const VideoSubscription& other) const; + bool operator!=(const VideoSubscription& other) const; + + // Subscribes receiver to all streams sent by the specified peer with + // specified resolution. It will override any resolution that was used in + // `SubscribeToAll` independently from methods call order. + VideoSubscription& SubscribeToPeer( + absl::string_view peer_name, + VideoResolution resolution = + VideoResolution(VideoResolution::Spec::kMaxFromSender)); + + // Subscribes receiver to the all sent streams with specified resolution. + // If any stream was subscribed to with `SubscribeTo` method that will + // override resolution passed to this function independently from methods + // call order. + VideoSubscription& SubscribeToAllPeers( + VideoResolution resolution = + VideoResolution(VideoResolution::Spec::kMaxFromSender)); + + // Returns resolution for specific sender. If no specific resolution was + // set for this sender, then will return resolution used for all streams. + // If subscription doesn't subscribe to all streams, `absl::nullopt` will be + // returned. + absl::optional<VideoResolution> GetResolutionForPeer( + absl::string_view peer_name) const; + + // Returns a maybe empty list of senders for which peer explicitly + // subscribed to with specific resolution. + std::vector<std::string> GetSubscribedPeers() const; + + std::string ToString() const; + + private: + absl::optional<VideoResolution> default_resolution_ = absl::nullopt; + std::map<std::string, VideoResolution> peers_resolution_; +}; + +// Contains configuration for echo emulator. +struct EchoEmulationConfig { + // Delay which represents the echo path delay, i.e. how soon rendered signal + // should reach capturer. + TimeDelta echo_delay = TimeDelta::Millis(50); +}; + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // API_TEST_PCLF_MEDIA_CONFIGURATION_H_ diff --git a/third_party/libwebrtc/api/test/pclf/media_quality_test_params.h b/third_party/libwebrtc/api/test/pclf/media_quality_test_params.h new file mode 100644 index 0000000000..3377d31f68 --- /dev/null +++ b/third_party/libwebrtc/api/test/pclf/media_quality_test_params.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2022 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 API_TEST_PCLF_MEDIA_QUALITY_TEST_PARAMS_H_ +#define API_TEST_PCLF_MEDIA_QUALITY_TEST_PARAMS_H_ + +#include <cstddef> +#include <memory> +#include <string> +#include <vector> + +#include "api/async_resolver_factory.h" +#include "api/audio/audio_mixer.h" +#include "api/call/call_factory_interface.h" +#include "api/fec_controller.h" +#include "api/field_trials_view.h" +#include "api/rtc_event_log/rtc_event_log_factory_interface.h" +#include "api/task_queue/task_queue_factory.h" +#include "api/test/pclf/media_configuration.h" +#include "api/transport/network_control.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "modules/audio_processing/include/audio_processing.h" +#include "p2p/base/port_allocator.h" +#include "rtc_base/network.h" +#include "rtc_base/rtc_certificate_generator.h" +#include "rtc_base/ssl_certificate.h" +#include "rtc_base/thread.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +// Contains most part from PeerConnectionFactoryDependencies. Also all fields +// are optional and defaults will be provided by fixture implementation if +// any will be omitted. +// +// Separate class was introduced to clarify which components can be +// overridden. For example worker and signaling threads will be provided by +// fixture implementation. The same is applicable to the media engine. So user +// can override only some parts of media engine like video encoder/decoder +// factories. +struct PeerConnectionFactoryComponents { + std::unique_ptr<TaskQueueFactory> task_queue_factory; + std::unique_ptr<CallFactoryInterface> call_factory; + std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory; + std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory; + std::unique_ptr<NetworkControllerFactoryInterface> network_controller_factory; + std::unique_ptr<NetEqFactory> neteq_factory; + + // Will be passed to MediaEngineInterface, that will be used in + // PeerConnectionFactory. + std::unique_ptr<VideoEncoderFactory> video_encoder_factory; + std::unique_ptr<VideoDecoderFactory> video_decoder_factory; + + std::unique_ptr<FieldTrialsView> trials; + + rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing; + rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer; +}; + +// Contains most parts from PeerConnectionDependencies. Also all fields are +// optional and defaults will be provided by fixture implementation if any +// will be omitted. +// +// Separate class was introduced to clarify which components can be +// overridden. For example observer, which is required to +// PeerConnectionDependencies, will be provided by fixture implementation, +// so client can't inject its own. Also only network manager can be overridden +// inside port allocator. +struct PeerConnectionComponents { + PeerConnectionComponents(rtc::NetworkManager* network_manager, + rtc::PacketSocketFactory* packet_socket_factory) + : network_manager(network_manager), + packet_socket_factory(packet_socket_factory) { + RTC_CHECK(network_manager); + } + + rtc::NetworkManager* const network_manager; + rtc::PacketSocketFactory* const packet_socket_factory; + std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory; + std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator; + std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier; + std::unique_ptr<IceTransportFactory> ice_transport_factory; +}; + +// Contains all components, that can be overridden in peer connection. Also +// has a network thread, that will be used to communicate with another peers. +struct InjectableComponents { + InjectableComponents(rtc::Thread* network_thread, + rtc::NetworkManager* network_manager, + rtc::PacketSocketFactory* packet_socket_factory) + : network_thread(network_thread), + worker_thread(nullptr), + pcf_dependencies(std::make_unique<PeerConnectionFactoryComponents>()), + pc_dependencies( + std::make_unique<PeerConnectionComponents>(network_manager, + packet_socket_factory)) { + RTC_CHECK(network_thread); + } + + rtc::Thread* const network_thread; + rtc::Thread* worker_thread; + + std::unique_ptr<PeerConnectionFactoryComponents> pcf_dependencies; + std::unique_ptr<PeerConnectionComponents> pc_dependencies; +}; + +// Contains information about call media streams (up to 1 audio stream and +// unlimited amount of video streams) and rtc configuration, that will be used +// to set up peer connection. +struct Params { + // Peer name. If empty - default one will be set by the fixture. + absl::optional<std::string> name; + // If `audio_config` is set audio stream will be configured + absl::optional<AudioConfig> audio_config; + // Flags to set on `cricket::PortAllocator`. These flags will be added + // to the default ones that are presented on the port allocator. + uint32_t port_allocator_extra_flags = cricket::kDefaultPortAllocatorFlags; + // If `rtc_event_log_path` is set, an RTCEventLog will be saved in that + // location and it will be available for further analysis. + absl::optional<std::string> rtc_event_log_path; + // If `aec_dump_path` is set, an AEC dump will be saved in that location and + // it will be available for further analysis. + absl::optional<std::string> aec_dump_path; + + bool use_ulp_fec = false; + bool use_flex_fec = false; + // Specifies how much video encoder target bitrate should be different than + // target bitrate, provided by WebRTC stack. Must be greater then 0. Can be + // used to emulate overshooting of video encoders. This multiplier will + // be applied for all video encoder on both sides for all layers. Bitrate + // estimated by WebRTC stack will be multiplied by this multiplier and then + // provided into VideoEncoder::SetRates(...). + double video_encoder_bitrate_multiplier = 1.0; + + PeerConnectionInterface::RTCConfiguration rtc_configuration; + PeerConnectionInterface::RTCOfferAnswerOptions rtc_offer_answer_options; + BitrateSettings bitrate_settings; + std::vector<VideoCodecConfig> video_codecs; + + // A list of RTP header extensions which will be enforced on all video streams + // added to this peer. + std::vector<std::string> extra_video_rtp_header_extensions; + // A list of RTP header extensions which will be enforced on all audio streams + // added to this peer. + std::vector<std::string> extra_audio_rtp_header_extensions; +}; + +// Contains parameters that maybe changed by test writer during the test call. +struct ConfigurableParams { + // If `video_configs` is empty - no video should be added to the test call. + std::vector<VideoConfig> video_configs; + + VideoSubscription video_subscription = + VideoSubscription().SubscribeToAllPeers(); +}; + +// Contains parameters, that describe how long framework should run quality +// test. +struct RunParams { + explicit RunParams(TimeDelta run_duration) : run_duration(run_duration) {} + + // Specifies how long the test should be run. This time shows how long + // the media should flow after connection was established and before + // it will be shut downed. + TimeDelta run_duration; + + // If set to true peers will be able to use Flex FEC, otherwise they won't + // be able to negotiate it even if it's enabled on per peer level. + bool enable_flex_fec_support = false; + // If true will set conference mode in SDP media section for all video + // tracks for all peers. + bool use_conference_mode = false; + // If specified echo emulation will be done, by mixing the render audio into + // the capture signal. In such case input signal will be reduced by half to + // avoid saturation or compression in the echo path simulation. + absl::optional<EchoEmulationConfig> echo_emulation_config; +}; + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // API_TEST_PCLF_MEDIA_QUALITY_TEST_PARAMS_H_ diff --git a/third_party/libwebrtc/api/test/pclf/peer_configurer.cc b/third_party/libwebrtc/api/test/pclf/peer_configurer.cc new file mode 100644 index 0000000000..2203a4c4f0 --- /dev/null +++ b/third_party/libwebrtc/api/test/pclf/peer_configurer.cc @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2022 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 "api/test/pclf/peer_configurer.h" + +#include <set> + +#include "absl/strings/string_view.h" +#include "api/test/pclf/media_configuration.h" +#include "api/test/pclf/media_quality_test_params.h" +#include "api/test/peer_network_dependencies.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +PeerConfigurer::PeerConfigurer( + const PeerNetworkDependencies& network_dependencies) + : components_(std::make_unique<InjectableComponents>( + network_dependencies.network_thread, + network_dependencies.network_manager, + network_dependencies.packet_socket_factory)), + params_(std::make_unique<Params>()), + configurable_params_(std::make_unique<ConfigurableParams>()) {} + +PeerConfigurer* PeerConfigurer::SetName(absl::string_view name) { + params_->name = std::string(name); + return this; +} + +PeerConfigurer* PeerConfigurer::SetTaskQueueFactory( + std::unique_ptr<TaskQueueFactory> task_queue_factory) { + components_->pcf_dependencies->task_queue_factory = + std::move(task_queue_factory); + return this; +} +PeerConfigurer* PeerConfigurer::SetCallFactory( + std::unique_ptr<CallFactoryInterface> call_factory) { + components_->pcf_dependencies->call_factory = std::move(call_factory); + return this; +} +PeerConfigurer* PeerConfigurer::SetEventLogFactory( + std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory) { + components_->pcf_dependencies->event_log_factory = + std::move(event_log_factory); + return this; +} +PeerConfigurer* PeerConfigurer::SetFecControllerFactory( + std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory) { + components_->pcf_dependencies->fec_controller_factory = + std::move(fec_controller_factory); + return this; +} +PeerConfigurer* PeerConfigurer::SetNetworkControllerFactory( + std::unique_ptr<NetworkControllerFactoryInterface> + network_controller_factory) { + components_->pcf_dependencies->network_controller_factory = + std::move(network_controller_factory); + return this; +} +PeerConfigurer* PeerConfigurer::SetVideoEncoderFactory( + std::unique_ptr<VideoEncoderFactory> video_encoder_factory) { + components_->pcf_dependencies->video_encoder_factory = + std::move(video_encoder_factory); + return this; +} +PeerConfigurer* PeerConfigurer::SetVideoDecoderFactory( + std::unique_ptr<VideoDecoderFactory> video_decoder_factory) { + components_->pcf_dependencies->video_decoder_factory = + std::move(video_decoder_factory); + return this; +} + +PeerConfigurer* PeerConfigurer::SetAsyncResolverFactory( + std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory) { + components_->pc_dependencies->async_resolver_factory = + std::move(async_resolver_factory); + return this; +} +PeerConfigurer* PeerConfigurer::SetRTCCertificateGenerator( + std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator) { + components_->pc_dependencies->cert_generator = std::move(cert_generator); + return this; +} +PeerConfigurer* PeerConfigurer::SetSSLCertificateVerifier( + std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier) { + components_->pc_dependencies->tls_cert_verifier = + std::move(tls_cert_verifier); + return this; +} + +PeerConfigurer* PeerConfigurer::AddVideoConfig(VideoConfig config) { + video_sources_.push_back( + CreateSquareFrameGenerator(config, /*type=*/absl::nullopt)); + configurable_params_->video_configs.push_back(std::move(config)); + return this; +} +PeerConfigurer* PeerConfigurer::AddVideoConfig( + VideoConfig config, + std::unique_ptr<test::FrameGeneratorInterface> generator) { + configurable_params_->video_configs.push_back(std::move(config)); + video_sources_.push_back(std::move(generator)); + return this; +} +PeerConfigurer* PeerConfigurer::AddVideoConfig(VideoConfig config, + CapturingDeviceIndex index) { + configurable_params_->video_configs.push_back(std::move(config)); + video_sources_.push_back(index); + return this; +} +PeerConfigurer* PeerConfigurer::SetVideoSubscription( + VideoSubscription subscription) { + configurable_params_->video_subscription = std::move(subscription); + return this; +} +PeerConfigurer* PeerConfigurer::SetVideoCodecs( + std::vector<VideoCodecConfig> video_codecs) { + params_->video_codecs = std::move(video_codecs); + return this; +} +PeerConfigurer* PeerConfigurer::SetExtraVideoRtpHeaderExtensions( + std::vector<std::string> extensions) { + params_->extra_video_rtp_header_extensions = std::move(extensions); + return this; +} +PeerConfigurer* PeerConfigurer::SetAudioConfig(AudioConfig config) { + params_->audio_config = std::move(config); + return this; +} +PeerConfigurer* PeerConfigurer::SetExtraAudioRtpHeaderExtensions( + std::vector<std::string> extensions) { + params_->extra_audio_rtp_header_extensions = std::move(extensions); + return this; +} +PeerConfigurer* PeerConfigurer::SetUseUlpFEC(bool value) { + params_->use_ulp_fec = value; + return this; +} +PeerConfigurer* PeerConfigurer::SetUseFlexFEC(bool value) { + params_->use_flex_fec = value; + return this; +} +PeerConfigurer* PeerConfigurer::SetVideoEncoderBitrateMultiplier( + double multiplier) { + params_->video_encoder_bitrate_multiplier = multiplier; + return this; +} +PeerConfigurer* PeerConfigurer::SetNetEqFactory( + std::unique_ptr<NetEqFactory> neteq_factory) { + components_->pcf_dependencies->neteq_factory = std::move(neteq_factory); + return this; +} +PeerConfigurer* PeerConfigurer::SetAudioProcessing( + rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing) { + components_->pcf_dependencies->audio_processing = audio_processing; + return this; +} +PeerConfigurer* PeerConfigurer::SetAudioMixer( + rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) { + components_->pcf_dependencies->audio_mixer = audio_mixer; + return this; +} + +PeerConfigurer* PeerConfigurer::SetUseNetworkThreadAsWorkerThread() { + components_->worker_thread = components_->network_thread; + return this; +} + +PeerConfigurer* PeerConfigurer::SetRtcEventLogPath(std::string path) { + params_->rtc_event_log_path = std::move(path); + return this; +} +PeerConfigurer* PeerConfigurer::SetAecDumpPath(std::string path) { + params_->aec_dump_path = std::move(path); + return this; +} +PeerConfigurer* PeerConfigurer::SetRTCConfiguration( + PeerConnectionInterface::RTCConfiguration configuration) { + params_->rtc_configuration = std::move(configuration); + return this; +} +PeerConfigurer* PeerConfigurer::SetRTCOfferAnswerOptions( + PeerConnectionInterface::RTCOfferAnswerOptions options) { + params_->rtc_offer_answer_options = std::move(options); + return this; +} +PeerConfigurer* PeerConfigurer::SetBitrateSettings( + BitrateSettings bitrate_settings) { + params_->bitrate_settings = bitrate_settings; + return this; +} + +PeerConfigurer* PeerConfigurer::SetIceTransportFactory( + std::unique_ptr<IceTransportFactory> factory) { + components_->pc_dependencies->ice_transport_factory = std::move(factory); + return this; +} + +PeerConfigurer* PeerConfigurer::SetPortAllocatorExtraFlags( + uint32_t extra_flags) { + params_->port_allocator_extra_flags = extra_flags; + return this; +} +std::unique_ptr<InjectableComponents> PeerConfigurer::ReleaseComponents() { + RTC_CHECK(components_); + auto components = std::move(components_); + components_ = nullptr; + return components; +} + +// Returns Params and transfer ownership to the caller. +// Can be called once. +std::unique_ptr<Params> PeerConfigurer::ReleaseParams() { + RTC_CHECK(params_); + auto params = std::move(params_); + params_ = nullptr; + return params; +} + +// Returns ConfigurableParams and transfer ownership to the caller. +// Can be called once. +std::unique_ptr<ConfigurableParams> +PeerConfigurer::ReleaseConfigurableParams() { + RTC_CHECK(configurable_params_); + auto configurable_params = std::move(configurable_params_); + configurable_params_ = nullptr; + return configurable_params; +} + +// Returns video sources and transfer frame generators ownership to the +// caller. Can be called once. +std::vector<PeerConfigurer::VideoSource> PeerConfigurer::ReleaseVideoSources() { + auto video_sources = std::move(video_sources_); + video_sources_.clear(); + return video_sources; +} + +} // namespace webrtc_pc_e2e +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/pclf/peer_configurer.h b/third_party/libwebrtc/api/test/pclf/peer_configurer.h new file mode 100644 index 0000000000..996dc5cd89 --- /dev/null +++ b/third_party/libwebrtc/api/test/pclf/peer_configurer.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2022 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 API_TEST_PCLF_PEER_CONFIGURER_H_ +#define API_TEST_PCLF_PEER_CONFIGURER_H_ + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "absl/strings/string_view.h" +#include "api/async_resolver_factory.h" +#include "api/audio/audio_mixer.h" +#include "api/call/call_factory_interface.h" +#include "api/fec_controller.h" +#include "api/rtc_event_log/rtc_event_log_factory_interface.h" +#include "api/task_queue/task_queue_factory.h" +#include "api/test/create_peer_connection_quality_test_frame_generator.h" +#include "api/test/pclf/media_configuration.h" +#include "api/test/pclf/media_quality_test_params.h" +#include "api/test/peer_network_dependencies.h" +#include "api/transport/network_control.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "modules/audio_processing/include/audio_processing.h" +#include "rtc_base/network.h" +#include "rtc_base/rtc_certificate_generator.h" +#include "rtc_base/ssl_certificate.h" +#include "rtc_base/thread.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +// This class is used to fully configure one peer inside a call. +class PeerConfigurer { + public: + using VideoSource = + absl::variant<std::unique_ptr<test::FrameGeneratorInterface>, + CapturingDeviceIndex>; + + explicit PeerConfigurer(const PeerNetworkDependencies& network_dependencies); + + // Sets peer name that will be used to report metrics related to this peer. + // If not set, some default name will be assigned. All names have to be + // unique. + PeerConfigurer* SetName(absl::string_view name); + + // The parameters of the following 9 methods will be passed to the + // PeerConnectionFactoryInterface implementation that will be created for + // this peer. + PeerConfigurer* SetTaskQueueFactory( + std::unique_ptr<TaskQueueFactory> task_queue_factory); + PeerConfigurer* SetCallFactory( + std::unique_ptr<CallFactoryInterface> call_factory); + PeerConfigurer* SetEventLogFactory( + std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory); + PeerConfigurer* SetFecControllerFactory( + std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory); + PeerConfigurer* SetNetworkControllerFactory( + std::unique_ptr<NetworkControllerFactoryInterface> + network_controller_factory); + PeerConfigurer* SetVideoEncoderFactory( + std::unique_ptr<VideoEncoderFactory> video_encoder_factory); + PeerConfigurer* SetVideoDecoderFactory( + std::unique_ptr<VideoDecoderFactory> video_decoder_factory); + // Set a custom NetEqFactory to be used in the call. + PeerConfigurer* SetNetEqFactory(std::unique_ptr<NetEqFactory> neteq_factory); + PeerConfigurer* SetAudioProcessing( + rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing); + PeerConfigurer* SetAudioMixer( + rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer); + + // Forces the Peerconnection to use the network thread as the worker thread. + // Ie, worker thread and the network thread is the same thread. + PeerConfigurer* SetUseNetworkThreadAsWorkerThread(); + + // The parameters of the following 4 methods will be passed to the + // PeerConnectionInterface implementation that will be created for this + // peer. + PeerConfigurer* SetAsyncResolverFactory( + std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory); + PeerConfigurer* SetRTCCertificateGenerator( + std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator); + PeerConfigurer* SetSSLCertificateVerifier( + std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier); + PeerConfigurer* SetIceTransportFactory( + std::unique_ptr<IceTransportFactory> factory); + // Flags to set on `cricket::PortAllocator`. These flags will be added + // to the default ones that are presented on the port allocator. + // For possible values check p2p/base/port_allocator.h. + PeerConfigurer* SetPortAllocatorExtraFlags(uint32_t extra_flags); + + // Add new video stream to the call that will be sent from this peer. + // Default implementation of video frames generator will be used. + PeerConfigurer* AddVideoConfig(VideoConfig config); + // Add new video stream to the call that will be sent from this peer with + // provided own implementation of video frames generator. + PeerConfigurer* AddVideoConfig( + VideoConfig config, + std::unique_ptr<test::FrameGeneratorInterface> generator); + // Add new video stream to the call that will be sent from this peer. + // Capturing device with specified index will be used to get input video. + PeerConfigurer* AddVideoConfig(VideoConfig config, + CapturingDeviceIndex capturing_device_index); + // Sets video subscription for the peer. By default subscription will + // include all streams with `VideoSubscription::kSameAsSendStream` + // resolution. To this behavior use this method. + PeerConfigurer* SetVideoSubscription(VideoSubscription subscription); + // Sets the list of video codecs used by the peer during the test. These + // codecs will be negotiated in SDP during offer/answer exchange. The order + // of these codecs during negotiation will be the same as in `video_codecs`. + // Codecs have to be available in codecs list provided by peer connection to + // be negotiated. If some of specified codecs won't be found, the test will + // crash. + PeerConfigurer* SetVideoCodecs(std::vector<VideoCodecConfig> video_codecs); + // Sets a list of RTP header extensions which will be enforced on all video + // streams added to this peer. + PeerConfigurer* SetExtraVideoRtpHeaderExtensions( + std::vector<std::string> extensions); + // Sets the audio stream for the call from this peer. If this method won't + // be invoked, this peer will send no audio. + PeerConfigurer* SetAudioConfig(AudioConfig config); + // Sets a list of RTP header extensions which will be enforced on all audio + // streams added to this peer. + PeerConfigurer* SetExtraAudioRtpHeaderExtensions( + std::vector<std::string> extensions); + + // Set if ULP FEC should be used or not. False by default. + PeerConfigurer* SetUseUlpFEC(bool value); + // Set if Flex FEC should be used or not. False by default. + // Client also must enable `enable_flex_fec_support` in the `RunParams` to + // be able to use this feature. + PeerConfigurer* SetUseFlexFEC(bool value); + // Specifies how much video encoder target bitrate should be different than + // target bitrate, provided by WebRTC stack. Must be greater than 0. Can be + // used to emulate overshooting of video encoders. This multiplier will + // be applied for all video encoder on both sides for all layers. Bitrate + // estimated by WebRTC stack will be multiplied by this multiplier and then + // provided into VideoEncoder::SetRates(...). 1.0 by default. + PeerConfigurer* SetVideoEncoderBitrateMultiplier(double multiplier); + + // If is set, an RTCEventLog will be saved in that location and it will be + // available for further analysis. + PeerConfigurer* SetRtcEventLogPath(std::string path); + // If is set, an AEC dump will be saved in that location and it will be + // available for further analysis. + PeerConfigurer* SetAecDumpPath(std::string path); + PeerConfigurer* SetRTCConfiguration( + PeerConnectionInterface::RTCConfiguration configuration); + PeerConfigurer* SetRTCOfferAnswerOptions( + PeerConnectionInterface::RTCOfferAnswerOptions options); + // Set bitrate parameters on PeerConnection. This constraints will be + // applied to all summed RTP streams for this peer. + PeerConfigurer* SetBitrateSettings(BitrateSettings bitrate_settings); + + // Returns InjectableComponents and transfer ownership to the caller. + // Can be called once. + std::unique_ptr<InjectableComponents> ReleaseComponents(); + + // Returns Params and transfer ownership to the caller. + // Can be called once. + std::unique_ptr<Params> ReleaseParams(); + + // Returns ConfigurableParams and transfer ownership to the caller. + // Can be called once. + std::unique_ptr<ConfigurableParams> ReleaseConfigurableParams(); + + // Returns video sources and transfer frame generators ownership to the + // caller. Can be called once. + std::vector<VideoSource> ReleaseVideoSources(); + + InjectableComponents* components() { return components_.get(); } + Params* params() { return params_.get(); } + ConfigurableParams* configurable_params() { + return configurable_params_.get(); + } + const Params& params() const { return *params_; } + const ConfigurableParams& configurable_params() const { + return *configurable_params_; + } + std::vector<VideoSource>* video_sources() { return &video_sources_; } + + private: + std::unique_ptr<InjectableComponents> components_; + std::unique_ptr<Params> params_; + std::unique_ptr<ConfigurableParams> configurable_params_; + std::vector<VideoSource> video_sources_; +}; + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // API_TEST_PCLF_PEER_CONFIGURER_H_ diff --git a/third_party/libwebrtc/api/test/peer_network_dependencies.h b/third_party/libwebrtc/api/test/peer_network_dependencies.h new file mode 100644 index 0000000000..6f85ad0a4d --- /dev/null +++ b/third_party/libwebrtc/api/test/peer_network_dependencies.h @@ -0,0 +1,32 @@ +/* + * 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 API_TEST_PEER_NETWORK_DEPENDENCIES_H_ +#define API_TEST_PEER_NETWORK_DEPENDENCIES_H_ + +#include "api/packet_socket_factory.h" +#include "rtc_base/network.h" +#include "rtc_base/thread.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +// The network dependencies needed when adding a peer to tests using +// PeerConnectionE2EQualityTestFixture. +struct PeerNetworkDependencies { + rtc::Thread* network_thread; + rtc::NetworkManager* network_manager; + rtc::PacketSocketFactory* packet_socket_factory; +}; + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // API_TEST_PEER_NETWORK_DEPENDENCIES_H_ diff --git a/third_party/libwebrtc/api/test/peerconnection_quality_test_fixture.h b/third_party/libwebrtc/api/test/peerconnection_quality_test_fixture.h new file mode 100644 index 0000000000..74470cdf86 --- /dev/null +++ b/third_party/libwebrtc/api/test/peerconnection_quality_test_fixture.h @@ -0,0 +1,142 @@ +/* + * 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. + */ +#ifndef API_TEST_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_ +#define API_TEST_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <functional> +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "absl/base/macros.h" +#include "absl/memory/memory.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/async_resolver_factory.h" +#include "api/audio/audio_mixer.h" +#include "api/call/call_factory_interface.h" +#include "api/fec_controller.h" +#include "api/function_view.h" +#include "api/media_stream_interface.h" +#include "api/peer_connection_interface.h" +#include "api/rtc_event_log/rtc_event_log_factory_interface.h" +#include "api/rtp_parameters.h" +#include "api/task_queue/task_queue_factory.h" +#include "api/test/audio_quality_analyzer_interface.h" +#include "api/test/frame_generator_interface.h" +#include "api/test/pclf/media_configuration.h" +#include "api/test/pclf/media_quality_test_params.h" +#include "api/test/pclf/peer_configurer.h" +#include "api/test/peer_network_dependencies.h" +#include "api/test/simulated_network.h" +#include "api/test/stats_observer_interface.h" +#include "api/test/track_id_stream_info_map.h" +#include "api/test/video/video_frame_writer.h" +#include "api/test/video_quality_analyzer_interface.h" +#include "api/transport/network_control.h" +#include "api/units/time_delta.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "media/base/media_constants.h" +#include "modules/audio_processing/include/audio_processing.h" +#include "rtc_base/checks.h" +#include "rtc_base/network.h" +#include "rtc_base/rtc_certificate_generator.h" +#include "rtc_base/ssl_certificate.h" +#include "rtc_base/thread.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +// API is in development. Can be changed/removed without notice. +class PeerConnectionE2EQualityTestFixture { + public: + // Represent an entity that will report quality metrics after test. + class QualityMetricsReporter : public StatsObserverInterface { + public: + virtual ~QualityMetricsReporter() = default; + + // Invoked by framework after peer connection factory and peer connection + // itself will be created but before offer/answer exchange will be started. + // `test_case_name` is name of test case, that should be used to report all + // metrics. + // `reporter_helper` is a pointer to a class that will allow track_id to + // stream_id matching. The caller is responsible for ensuring the + // TrackIdStreamInfoMap will be valid from Start() to + // StopAndReportResults(). + virtual void Start(absl::string_view test_case_name, + const TrackIdStreamInfoMap* reporter_helper) = 0; + + // Invoked by framework after call is ended and peer connection factory and + // peer connection are destroyed. + virtual void StopAndReportResults() = 0; + }; + + // Represents single participant in call and can be used to perform different + // in-call actions. Might be extended in future. + class PeerHandle { + public: + virtual ~PeerHandle() = default; + }; + + virtual ~PeerConnectionE2EQualityTestFixture() = default; + + // Add activity that will be executed on the best effort at least after + // `target_time_since_start` after call will be set up (after offer/answer + // exchange, ICE gathering will be done and ICE candidates will passed to + // remote side). `func` param is amount of time spent from the call set up. + virtual void ExecuteAt(TimeDelta target_time_since_start, + std::function<void(TimeDelta)> func) = 0; + // Add activity that will be executed every `interval` with first execution + // on the best effort at least after `initial_delay_since_start` after call + // will be set up (after all participants will be connected). `func` param is + // amount of time spent from the call set up. + virtual void ExecuteEvery(TimeDelta initial_delay_since_start, + TimeDelta interval, + std::function<void(TimeDelta)> func) = 0; + + // Add stats reporter entity to observe the test. + virtual void AddQualityMetricsReporter( + std::unique_ptr<QualityMetricsReporter> quality_metrics_reporter) = 0; + + // Add a new peer to the call and return an object through which caller + // can configure peer's behavior. + // `network_dependencies` are used to provide networking for peer's peer + // connection. Members must be non-null. + // `configurer` function will be used to configure peer in the call. + virtual PeerHandle* AddPeer(std::unique_ptr<PeerConfigurer> configurer) = 0; + + // Runs the media quality test, which includes setting up the call with + // configured participants, running it according to provided `run_params` and + // terminating it properly at the end. During call duration media quality + // metrics are gathered, which are then reported to stdout and (if configured) + // to the json/protobuf output file through the WebRTC perf test results + // reporting system. + virtual void Run(RunParams run_params) = 0; + + // Returns real test duration - the time of test execution measured during + // test. Client must call this method only after test is finished (after + // Run(...) method returned). Test execution time is time from end of call + // setup (offer/answer, ICE candidates exchange done and ICE connected) to + // start of call tear down (PeerConnection closed). + virtual TimeDelta GetRealTestDuration() const = 0; +}; + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // API_TEST_PEERCONNECTION_QUALITY_TEST_FIXTURE_H_ diff --git a/third_party/libwebrtc/api/test/peerconnection_quality_test_fixture_unittest.cc b/third_party/libwebrtc/api/test/peerconnection_quality_test_fixture_unittest.cc new file mode 100644 index 0000000000..26ae8cf98f --- /dev/null +++ b/third_party/libwebrtc/api/test/peerconnection_quality_test_fixture_unittest.cc @@ -0,0 +1,142 @@ +/* + * Copyright 2022 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 "api/test/peerconnection_quality_test_fixture.h" + +#include <vector> + +#include "absl/types/optional.h" +#include "api/test/pclf/media_configuration.h" +#include "api/test/video/video_frame_writer.h" +#include "rtc_base/gunit.h" +#include "test/gmock.h" +#include "test/testsupport/file_utils.h" + +namespace webrtc { +namespace webrtc_pc_e2e { +namespace { + +using ::testing::Eq; + +TEST(PclfVideoSubscriptionTest, + MaxFromSenderSpecEqualIndependentOfOtherFields) { + VideoResolution r1(VideoResolution::Spec::kMaxFromSender); + r1.set_width(1); + r1.set_height(2); + r1.set_fps(3); + VideoResolution r2(VideoResolution::Spec::kMaxFromSender); + r1.set_width(4); + r1.set_height(5); + r1.set_fps(6); + EXPECT_EQ(r1, r2); +} + +TEST(PclfVideoSubscriptionTest, WhenSpecIsNotSetFieldsAreCompared) { + VideoResolution test_resolution(/*width=*/1, /*height=*/2, + /*fps=*/3); + VideoResolution equal_resolution(/*width=*/1, /*height=*/2, + /*fps=*/3); + VideoResolution different_width(/*width=*/10, /*height=*/2, + /*fps=*/3); + VideoResolution different_height(/*width=*/1, /*height=*/20, + /*fps=*/3); + VideoResolution different_fps(/*width=*/1, /*height=*/20, + /*fps=*/30); + + EXPECT_EQ(test_resolution, equal_resolution); + EXPECT_NE(test_resolution, different_width); + EXPECT_NE(test_resolution, different_height); + EXPECT_NE(test_resolution, different_fps); +} + +TEST(PclfVideoSubscriptionTest, GetMaxResolutionForEmptyReturnsNullopt) { + absl::optional<VideoResolution> resolution = + VideoSubscription::GetMaxResolution(std::vector<VideoConfig>{}); + ASSERT_FALSE(resolution.has_value()); +} + +TEST(PclfVideoSubscriptionTest, GetMaxResolutionSelectMaxForEachDimention) { + VideoConfig max_width(/*width=*/1000, /*height=*/1, /*fps=*/1); + VideoConfig max_height(/*width=*/1, /*height=*/100, /*fps=*/1); + VideoConfig max_fps(/*width=*/1, /*height=*/1, /*fps=*/10); + + absl::optional<VideoResolution> resolution = + VideoSubscription::GetMaxResolution( + std::vector<VideoConfig>{max_width, max_height, max_fps}); + ASSERT_TRUE(resolution.has_value()); + EXPECT_EQ(resolution->width(), static_cast<size_t>(1000)); + EXPECT_EQ(resolution->height(), static_cast<size_t>(100)); + EXPECT_EQ(resolution->fps(), 10); +} + +struct TestVideoFrameWriter : public test::VideoFrameWriter { + public: + TestVideoFrameWriter(absl::string_view file_name_prefix, + const VideoResolution& resolution) + : file_name_prefix(file_name_prefix), resolution(resolution) {} + + bool WriteFrame(const VideoFrame& frame) override { return true; } + + void Close() override {} + + std::string file_name_prefix; + VideoResolution resolution; +}; + +TEST(VideoDumpOptionsTest, InputVideoWriterHasCorrectFileName) { + VideoResolution resolution(/*width=*/1280, /*height=*/720, /*fps=*/30); + + TestVideoFrameWriter* writer = nullptr; + VideoDumpOptions options("foo", /*sampling_modulo=*/1, + /*export_frame_ids=*/false, + /*video_frame_writer_factory=*/ + [&](absl::string_view file_name_prefix, + const VideoResolution& resolution) { + auto out = std::make_unique<TestVideoFrameWriter>( + file_name_prefix, resolution); + writer = out.get(); + return out; + }); + std::unique_ptr<test::VideoFrameWriter> created_writer = + options.CreateInputDumpVideoFrameWriter("alice-video", resolution); + + ASSERT_TRUE(writer != nullptr); + ASSERT_THAT(writer->file_name_prefix, + Eq(test::JoinFilename("foo", "alice-video_1280x720_30"))); + ASSERT_THAT(writer->resolution, Eq(resolution)); +} + +TEST(VideoDumpOptionsTest, OutputVideoWriterHasCorrectFileName) { + VideoResolution resolution(/*width=*/1280, /*height=*/720, /*fps=*/30); + + TestVideoFrameWriter* writer = nullptr; + VideoDumpOptions options("foo", /*sampling_modulo=*/1, + /*export_frame_ids=*/false, + /*video_frame_writer_factory=*/ + [&](absl::string_view file_name_prefix, + const VideoResolution& resolution) { + auto out = std::make_unique<TestVideoFrameWriter>( + file_name_prefix, resolution); + writer = out.get(); + return out; + }); + std::unique_ptr<test::VideoFrameWriter> created_writer = + options.CreateOutputDumpVideoFrameWriter("alice-video", "bob", + resolution); + + ASSERT_TRUE(writer != nullptr); + ASSERT_THAT(writer->file_name_prefix, + Eq(test::JoinFilename("foo", "alice-video_bob_1280x720_30"))); + ASSERT_THAT(writer->resolution, Eq(resolution)); +} + +} // namespace +} // namespace webrtc_pc_e2e +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/simulated_network.h b/third_party/libwebrtc/api/test/simulated_network.h new file mode 100644 index 0000000000..04c5517c8d --- /dev/null +++ b/third_party/libwebrtc/api/test/simulated_network.h @@ -0,0 +1,139 @@ +/* + * 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. + */ + +#ifndef API_TEST_SIMULATED_NETWORK_H_ +#define API_TEST_SIMULATED_NETWORK_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <deque> +#include <queue> +#include <vector> + +#include "absl/types/optional.h" +#include "rtc_base/random.h" +#include "rtc_base/thread_annotations.h" + +namespace webrtc { + +struct PacketInFlightInfo { + PacketInFlightInfo(size_t size, int64_t send_time_us, uint64_t packet_id) + : size(size), send_time_us(send_time_us), packet_id(packet_id) {} + + size_t size; + int64_t send_time_us; + // Unique identifier for the packet in relation to other packets in flight. + uint64_t packet_id; +}; + +struct PacketDeliveryInfo { + static constexpr int kNotReceived = -1; + PacketDeliveryInfo(PacketInFlightInfo source, int64_t receive_time_us) + : receive_time_us(receive_time_us), packet_id(source.packet_id) {} + + bool operator==(const PacketDeliveryInfo& other) const { + return receive_time_us == other.receive_time_us && + packet_id == other.packet_id; + } + + int64_t receive_time_us; + uint64_t packet_id; +}; + +// BuiltInNetworkBehaviorConfig is a built-in network behavior configuration +// for built-in network behavior that will be used by WebRTC if no custom +// NetworkBehaviorInterface is provided. +struct BuiltInNetworkBehaviorConfig { + // Queue length in number of packets. + size_t queue_length_packets = 0; + // Delay in addition to capacity induced delay. + int queue_delay_ms = 0; + // Standard deviation of the extra delay. + int delay_standard_deviation_ms = 0; + // Link capacity in kbps. + int link_capacity_kbps = 0; + // Random packet loss. + int loss_percent = 0; + // If packets are allowed to be reordered. + bool allow_reordering = false; + // The average length of a burst of lost packets. + int avg_burst_loss_length = -1; + // Additional bytes to add to packet size. + int packet_overhead = 0; +}; + +// Interface that represents a Network behaviour. +// +// It is clients of this interface responsibility to enqueue and dequeue +// packets (based on the estimated delivery time expressed by +// NextDeliveryTimeUs). +// +// To enqueue packets, call EnqueuePacket: +// EXPECT_TRUE(network.EnqueuePacket( +// PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/1))); +// +// To know when to call DequeueDeliverablePackets to pull packets out of the +// network, call NextDeliveryTimeUs and schedule a task to invoke +// DequeueDeliverablePackets (if not already scheduled). +// +// DequeueDeliverablePackets will return a vector of delivered packets, but this +// vector can be empty in case of extra delay. In such case, make sure to invoke +// NextDeliveryTimeUs and schedule a task to call DequeueDeliverablePackets for +// the next estimated delivery of packets. +// +// std::vector<PacketDeliveryInfo> delivered_packets = +// network.DequeueDeliverablePackets(/*receive_time_us=*/1000000); +class NetworkBehaviorInterface { + public: + // Enqueues a packet in the network and returns true if the action was + // successful, false otherwise (for example, because the network capacity has + // been saturated). If the return value is false, the packet should be + // considered as dropped and it will not be returned by future calls + // to DequeueDeliverablePackets. + // Packets enqueued will exit the network when DequeueDeliverablePackets is + // called and enough time has passed (see NextDeliveryTimeUs). + virtual bool EnqueuePacket(PacketInFlightInfo packet_info) = 0; + // Retrieves all packets that should be delivered by the given receive time. + // Not all the packets in the returned std::vector are actually delivered. + // In order to know the state of each packet it is necessary to check the + // `receive_time_us` field of each packet. If that is set to + // PacketDeliveryInfo::kNotReceived then the packet is considered lost in the + // network. + virtual std::vector<PacketDeliveryInfo> DequeueDeliverablePackets( + int64_t receive_time_us) = 0; + // Returns time in microseconds when caller should call + // DequeueDeliverablePackets to get the next set of delivered packets. It is + // possible that no packet will be delivered by that time (e.g. in case of + // random extra delay), in such case this method should be called again to get + // the updated estimated delivery time. + virtual absl::optional<int64_t> NextDeliveryTimeUs() const = 0; + virtual ~NetworkBehaviorInterface() = default; +}; + +// Class simulating a network link. This is a simple and naive solution just +// faking capacity and adding an extra transport delay in addition to the +// capacity introduced delay. +class SimulatedNetworkInterface : public NetworkBehaviorInterface { + public: + // Sets a new configuration. + virtual void SetConfig(const BuiltInNetworkBehaviorConfig& config) = 0; + virtual void UpdateConfig( + std::function<void(BuiltInNetworkBehaviorConfig*)> config_modifier) = 0; + // Pauses the network until `until_us`. This affects both delivery (calling + // DequeueDeliverablePackets before `until_us` results in an empty std::vector + // of packets) and capacity (the network is paused, so packets are not + // flowing and they will restart flowing at `until_us`). + virtual void PauseTransmissionUntil(int64_t until_us) = 0; +}; + +} // namespace webrtc + +#endif // API_TEST_SIMULATED_NETWORK_H_ diff --git a/third_party/libwebrtc/api/test/simulcast_test_fixture.h b/third_party/libwebrtc/api/test/simulcast_test_fixture.h new file mode 100644 index 0000000000..c7130d2909 --- /dev/null +++ b/third_party/libwebrtc/api/test/simulcast_test_fixture.h @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#ifndef API_TEST_SIMULCAST_TEST_FIXTURE_H_ +#define API_TEST_SIMULCAST_TEST_FIXTURE_H_ + +namespace webrtc { +namespace test { + +class SimulcastTestFixture { + public: + virtual ~SimulcastTestFixture() = default; + + virtual void TestKeyFrameRequestsOnAllStreams() = 0; + virtual void TestKeyFrameRequestsOnSpecificStreams() = 0; + virtual void TestPaddingAllStreams() = 0; + virtual void TestPaddingTwoStreams() = 0; + virtual void TestPaddingTwoStreamsOneMaxedOut() = 0; + virtual void TestPaddingOneStream() = 0; + virtual void TestPaddingOneStreamTwoMaxedOut() = 0; + virtual void TestSendAllStreams() = 0; + virtual void TestDisablingStreams() = 0; + virtual void TestActiveStreams() = 0; + virtual void TestSwitchingToOneStream() = 0; + virtual void TestSwitchingToOneOddStream() = 0; + virtual void TestSwitchingToOneSmallStream() = 0; + virtual void TestSpatioTemporalLayers333PatternEncoder() = 0; + virtual void TestSpatioTemporalLayers321PatternEncoder() = 0; + virtual void TestStrideEncodeDecode() = 0; + virtual void TestDecodeWidthHeightSet() = 0; + virtual void + TestEncoderInfoForDefaultTemporalLayerProfileHasFpsAllocation() = 0; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_SIMULCAST_TEST_FIXTURE_H_ diff --git a/third_party/libwebrtc/api/test/stats_observer_interface.h b/third_party/libwebrtc/api/test/stats_observer_interface.h new file mode 100644 index 0000000000..58d8f52d77 --- /dev/null +++ b/third_party/libwebrtc/api/test/stats_observer_interface.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019 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 API_TEST_STATS_OBSERVER_INTERFACE_H_ +#define API_TEST_STATS_OBSERVER_INTERFACE_H_ + +#include "absl/strings/string_view.h" +#include "api/stats/rtc_stats_report.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +// API is in development and can be changed without notice. +class StatsObserverInterface { + public: + virtual ~StatsObserverInterface() = default; + + // Method called when stats reports are available for the PeerConnection + // identified by `pc_label`. + virtual void OnStatsReports( + absl::string_view pc_label, + const rtc::scoped_refptr<const RTCStatsReport>& report) = 0; +}; + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // API_TEST_STATS_OBSERVER_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/test/test_dependency_factory.cc b/third_party/libwebrtc/api/test/test_dependency_factory.cc new file mode 100644 index 0000000000..41ad70cc3f --- /dev/null +++ b/third_party/libwebrtc/api/test/test_dependency_factory.cc @@ -0,0 +1,54 @@ +/* + * 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 "api/test/test_dependency_factory.h" + +#include <memory> +#include <utility> + +#include "rtc_base/checks.h" +#include "rtc_base/platform_thread_types.h" + +namespace webrtc { + +namespace { +// This checks everything in this file gets called on the same thread. It's +// static because it needs to look at the static methods too. +bool IsValidTestDependencyFactoryThread() { + const rtc::PlatformThreadRef main_thread = rtc::CurrentThreadRef(); + return rtc::IsThreadRefEqual(main_thread, rtc::CurrentThreadRef()); +} +} // namespace + +std::unique_ptr<TestDependencyFactory> TestDependencyFactory::instance_ = + nullptr; + +const TestDependencyFactory& TestDependencyFactory::GetInstance() { + RTC_DCHECK(IsValidTestDependencyFactoryThread()); + if (instance_ == nullptr) { + instance_ = std::make_unique<TestDependencyFactory>(); + } + return *instance_; +} + +void TestDependencyFactory::SetInstance( + std::unique_ptr<TestDependencyFactory> instance) { + RTC_DCHECK(IsValidTestDependencyFactoryThread()); + RTC_CHECK(instance_ == nullptr); + instance_ = std::move(instance); +} + +std::unique_ptr<VideoQualityTestFixtureInterface::InjectionComponents> +TestDependencyFactory::CreateComponents() const { + RTC_DCHECK(IsValidTestDependencyFactoryThread()); + return nullptr; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/test_dependency_factory.h b/third_party/libwebrtc/api/test/test_dependency_factory.h new file mode 100644 index 0000000000..29f00b8070 --- /dev/null +++ b/third_party/libwebrtc/api/test/test_dependency_factory.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#ifndef API_TEST_TEST_DEPENDENCY_FACTORY_H_ +#define API_TEST_TEST_DEPENDENCY_FACTORY_H_ + +#include <memory> + +#include "api/test/video_quality_test_fixture.h" + +namespace webrtc { + +// Override this class if to inject custom components into WebRTC tests. +// Not all WebRTC tests get their components from here, so you need to make +// sure the tests you want actually use this class. +// +// This class is not thread safe and you need to make call calls from the same +// (test main) thread. +class TestDependencyFactory { + public: + virtual ~TestDependencyFactory() = default; + + // The singleton MUST be stateless since tests execute in any order. It must + // be set before tests start executing. + static const TestDependencyFactory& GetInstance(); + static void SetInstance(std::unique_ptr<TestDependencyFactory> instance); + + // Returns the component a test should use. Returning nullptr means that the + // test is free to use whatever defaults it wants. The injection components + // themselves can be mutable, but we need to make new ones for every test that + // executes so state doesn't spread between tests. + virtual std::unique_ptr<VideoQualityTestFixtureInterface::InjectionComponents> + CreateComponents() const; + + private: + static std::unique_ptr<TestDependencyFactory> instance_; +}; + +} // namespace webrtc + +#endif // API_TEST_TEST_DEPENDENCY_FACTORY_H_ diff --git a/third_party/libwebrtc/api/test/time_controller.cc b/third_party/libwebrtc/api/test/time_controller.cc new file mode 100644 index 0000000000..364dbc235d --- /dev/null +++ b/third_party/libwebrtc/api/test/time_controller.cc @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020 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 "api/test/time_controller.h" + +namespace webrtc { +std::unique_ptr<TaskQueueFactory> TimeController::CreateTaskQueueFactory() { + class FactoryWrapper final : public TaskQueueFactory { + public: + explicit FactoryWrapper(TaskQueueFactory* inner_factory) + : inner_(inner_factory) {} + std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue( + absl::string_view name, + Priority priority) const override { + return inner_->CreateTaskQueue(name, priority); + } + + private: + TaskQueueFactory* const inner_; + }; + return std::make_unique<FactoryWrapper>(GetTaskQueueFactory()); +} +bool TimeController::Wait(const std::function<bool()>& condition, + TimeDelta max_duration) { + // Step size is chosen to be short enough to not significantly affect latency + // in real time tests while being long enough to avoid adding too much load to + // the system. + const auto kStep = TimeDelta::Millis(5); + for (auto elapsed = TimeDelta::Zero(); elapsed < max_duration; + elapsed += kStep) { + if (condition()) + return true; + AdvanceTime(kStep); + } + return condition(); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/time_controller.h b/third_party/libwebrtc/api/test/time_controller.h new file mode 100644 index 0000000000..121f65cea9 --- /dev/null +++ b/third_party/libwebrtc/api/test/time_controller.h @@ -0,0 +1,89 @@ +/* + * Copyright 2019 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 API_TEST_TIME_CONTROLLER_H_ +#define API_TEST_TIME_CONTROLLER_H_ + +#include <functional> +#include <memory> +#include <string> + +#include "api/task_queue/task_queue_factory.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "rtc_base/synchronization/yield_policy.h" +#include "rtc_base/thread.h" +#include "system_wrappers/include/clock.h" + +namespace webrtc { +// Interface for controlling time progress. This allows us to execute test code +// in either real time or simulated time by using different implementation of +// this interface. +class TimeController { + public: + virtual ~TimeController() = default; + // Provides a clock instance that follows implementation defined time + // progress. + virtual Clock* GetClock() = 0; + // The returned factory will created task queues that runs in implementation + // defined time domain. + virtual TaskQueueFactory* GetTaskQueueFactory() = 0; + // Simple helper to create an owned factory that can be used as a parameter + // for PeerConnectionFactory. Note that this might depend on the underlying + // time controller and therfore must be destroyed before the time controller + // is destroyed. + std::unique_ptr<TaskQueueFactory> CreateTaskQueueFactory(); + + // Creates an rtc::Thread instance. If `socket_server` is nullptr, a default + // noop socket server is created. + // Returned thread is not null and started. + virtual std::unique_ptr<rtc::Thread> CreateThread( + const std::string& name, + std::unique_ptr<rtc::SocketServer> socket_server = nullptr) = 0; + + // Creates an rtc::Thread instance that ensure that it's set as the current + // thread. + virtual rtc::Thread* GetMainThread() = 0; + // Allow task queues and process threads created by this instance to execute + // for the given `duration`. + virtual void AdvanceTime(TimeDelta duration) = 0; + + // Waits until condition() == true, polling condition() in small time + // intervals. + // Returns true if condition() was evaluated to true before `max_duration` + // elapsed and false otherwise. + bool Wait(const std::function<bool()>& condition, + TimeDelta max_duration = TimeDelta::Seconds(5)); +}; + +// Interface for telling time, scheduling an event to fire at a particular time, +// and waiting for time to pass. +class ControlledAlarmClock { + public: + virtual ~ControlledAlarmClock() = default; + + // Gets a clock that tells the alarm clock's notion of time. + virtual Clock* GetClock() = 0; + + // Schedules the alarm to fire at `deadline`. + // An alarm clock only supports one deadline. Calls to `ScheduleAlarmAt` with + // an earlier deadline will reset the alarm to fire earlier.Calls to + // `ScheduleAlarmAt` with a later deadline are ignored. Returns true if the + // deadline changed, false otherwise. + virtual bool ScheduleAlarmAt(Timestamp deadline) = 0; + + // Sets the callback that should be run when the alarm fires. + virtual void SetCallback(std::function<void()> callback) = 0; + + // Waits for `duration` to pass, according to the alarm clock. + virtual void Sleep(TimeDelta duration) = 0; +}; + +} // namespace webrtc +#endif // API_TEST_TIME_CONTROLLER_H_ diff --git a/third_party/libwebrtc/api/test/track_id_stream_info_map.h b/third_party/libwebrtc/api/test/track_id_stream_info_map.h new file mode 100644 index 0000000000..b016de57a9 --- /dev/null +++ b/third_party/libwebrtc/api/test/track_id_stream_info_map.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 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 API_TEST_TRACK_ID_STREAM_INFO_MAP_H_ +#define API_TEST_TRACK_ID_STREAM_INFO_MAP_H_ + +#include <string> + +#include "absl/strings/string_view.h" + +namespace webrtc { +namespace webrtc_pc_e2e { + +// Instances of `TrackIdStreamInfoMap` provide bookkeeping capabilities that +// are useful to associate stats reports track_ids to the remote stream info. +class TrackIdStreamInfoMap { + public: + struct StreamInfo { + std::string receiver_peer; + std::string stream_label; + std::string sync_group; + }; + + virtual ~TrackIdStreamInfoMap() = default; + + // These methods must be called on the same thread where + // StatsObserverInterface::OnStatsReports is invoked. + + // Precondition: `track_id` must be already mapped to stream info. + virtual StreamInfo GetStreamInfoFromTrackId( + absl::string_view track_id) const = 0; +}; + +} // namespace webrtc_pc_e2e +} // namespace webrtc + +#endif // API_TEST_TRACK_ID_STREAM_INFO_MAP_H_ diff --git a/third_party/libwebrtc/api/test/video/BUILD.gn b/third_party/libwebrtc/api/test/video/BUILD.gn new file mode 100644 index 0000000000..d24ffa5fa6 --- /dev/null +++ b/third_party/libwebrtc/api/test/video/BUILD.gn @@ -0,0 +1,31 @@ +# 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. + +import("../../../webrtc.gni") + +rtc_library("function_video_factory") { + visibility = [ "*" ] + testonly = true + public = [ + "function_video_decoder_factory.h", + "function_video_encoder_factory.h", + ] + + deps = [ + "../../../rtc_base:checks", + "../../video_codecs:video_codecs_api", + ] +} + +rtc_library("video_frame_writer") { + visibility = [ "*" ] + testonly = true + public = [ "video_frame_writer.h" ] + + deps = [ "../../video:video_frame" ] +} diff --git a/third_party/libwebrtc/api/test/video/function_video_decoder_factory.h b/third_party/libwebrtc/api/test/video/function_video_decoder_factory.h new file mode 100644 index 0000000000..2145c71bff --- /dev/null +++ b/third_party/libwebrtc/api/test/video/function_video_decoder_factory.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#ifndef API_TEST_VIDEO_FUNCTION_VIDEO_DECODER_FACTORY_H_ +#define API_TEST_VIDEO_FUNCTION_VIDEO_DECODER_FACTORY_H_ + +#include <functional> +#include <memory> +#include <utility> +#include <vector> + +#include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_decoder.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "rtc_base/checks.h" + +namespace webrtc { +namespace test { + +// A decoder factory producing decoders by calling a supplied create function. +class FunctionVideoDecoderFactory final : public VideoDecoderFactory { + public: + explicit FunctionVideoDecoderFactory( + std::function<std::unique_ptr<VideoDecoder>()> create) + : create_([create = std::move(create)](const SdpVideoFormat&) { + return create(); + }) {} + explicit FunctionVideoDecoderFactory( + std::function<std::unique_ptr<VideoDecoder>(const SdpVideoFormat&)> + create) + : create_(std::move(create)) {} + FunctionVideoDecoderFactory( + std::function<std::unique_ptr<VideoDecoder>()> create, + std::vector<SdpVideoFormat> sdp_video_formats) + : create_([create = std::move(create)](const SdpVideoFormat&) { + return create(); + }), + sdp_video_formats_(std::move(sdp_video_formats)) {} + + std::vector<SdpVideoFormat> GetSupportedFormats() const override { + return sdp_video_formats_; + } + + std::unique_ptr<VideoDecoder> CreateVideoDecoder( + const SdpVideoFormat& format) override { + return create_(format); + } + + private: + const std::function<std::unique_ptr<VideoDecoder>(const SdpVideoFormat&)> + create_; + const std::vector<SdpVideoFormat> sdp_video_formats_; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_VIDEO_FUNCTION_VIDEO_DECODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/test/video/function_video_encoder_factory.h b/third_party/libwebrtc/api/test/video/function_video_encoder_factory.h new file mode 100644 index 0000000000..98ece2bc94 --- /dev/null +++ b/third_party/libwebrtc/api/test/video/function_video_encoder_factory.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#ifndef API_TEST_VIDEO_FUNCTION_VIDEO_ENCODER_FACTORY_H_ +#define API_TEST_VIDEO_FUNCTION_VIDEO_ENCODER_FACTORY_H_ + +#include <functional> +#include <memory> +#include <utility> +#include <vector> + +#include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_encoder.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "rtc_base/checks.h" + +namespace webrtc { +namespace test { + +// An encoder factory producing encoders by calling a supplied create +// function. +class FunctionVideoEncoderFactory final : public VideoEncoderFactory { + public: + explicit FunctionVideoEncoderFactory( + std::function<std::unique_ptr<VideoEncoder>()> create) + : create_([create = std::move(create)](const SdpVideoFormat&) { + return create(); + }) {} + explicit FunctionVideoEncoderFactory( + std::function<std::unique_ptr<VideoEncoder>(const SdpVideoFormat&)> + create) + : create_(std::move(create)) {} + + // Unused by tests. + std::vector<SdpVideoFormat> GetSupportedFormats() const override { + RTC_DCHECK_NOTREACHED(); + return {}; + } + + std::unique_ptr<VideoEncoder> CreateVideoEncoder( + const SdpVideoFormat& format) override { + return create_(format); + } + + private: + const std::function<std::unique_ptr<VideoEncoder>(const SdpVideoFormat&)> + create_; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_VIDEO_FUNCTION_VIDEO_ENCODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/test/video/video_frame_writer.h b/third_party/libwebrtc/api/test/video/video_frame_writer.h new file mode 100644 index 0000000000..ac72534890 --- /dev/null +++ b/third_party/libwebrtc/api/test/video/video_frame_writer.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 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 API_TEST_VIDEO_VIDEO_FRAME_WRITER_H_ +#define API_TEST_VIDEO_VIDEO_FRAME_WRITER_H_ + +#include "api/video/video_frame.h" + +namespace webrtc { +namespace test { + +class VideoFrameWriter { + public: + virtual ~VideoFrameWriter() = default; + + // Writes `VideoFrame` and returns true if operation was successful, false + // otherwise. + // + // Calling `WriteFrame` after `Close` is not allowed. + virtual bool WriteFrame(const VideoFrame& frame) = 0; + + // Closes writer and cleans up all resources. No invocations to `WriteFrame` + // are allowed after `Close` was invoked. + virtual void Close() = 0; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_VIDEO_VIDEO_FRAME_WRITER_H_ diff --git a/third_party/libwebrtc/api/test/video_codec_tester.h b/third_party/libwebrtc/api/test/video_codec_tester.h new file mode 100644 index 0000000000..0eaaa1b895 --- /dev/null +++ b/third_party/libwebrtc/api/test/video_codec_tester.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2022 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 API_TEST_VIDEO_CODEC_TESTER_H_ +#define API_TEST_VIDEO_CODEC_TESTER_H_ + +#include <memory> + +#include "absl/functional/any_invocable.h" +#include "api/test/videocodec_test_stats.h" +#include "api/video/encoded_image.h" +#include "api/video/resolution.h" +#include "api/video/video_frame.h" + +namespace webrtc { +namespace test { + +// Interface for a video codec tester. The interface provides minimalistic set +// of data structures that enables implementation of decode-only, encode-only +// and encode-decode tests. +class VideoCodecTester { + public: + // Pacing settings for codec input. + struct PacingSettings { + enum PacingMode { + // Pacing is not used. Frames are sent to codec back-to-back. + kNoPacing, + // Pace with the rate equal to the target video frame rate. Pacing time is + // derived from RTP timestamp. + kRealTime, + // Pace with the explicitly provided rate. + kConstantRate, + }; + PacingMode mode = PacingMode::kNoPacing; + // Pacing rate for `kConstantRate` mode. + Frequency constant_rate = Frequency::Zero(); + }; + + struct DecoderSettings { + PacingSettings pacing; + }; + + struct EncoderSettings { + PacingSettings pacing; + }; + + virtual ~VideoCodecTester() = default; + + // Interface for a raw video frames source. + class RawVideoSource { + public: + virtual ~RawVideoSource() = default; + + // Returns next frame. If no more frames to pull, returns `absl::nullopt`. + // For analysis and pacing purposes, frame must have RTP timestamp set. The + // timestamp must represent the target video frame rate and be unique. + virtual absl::optional<VideoFrame> PullFrame() = 0; + + // Returns early pulled frame with RTP timestamp equal to `timestamp_rtp`. + virtual VideoFrame GetFrame(uint32_t timestamp_rtp, + Resolution resolution) = 0; + }; + + // Interface for a coded video frames source. + class CodedVideoSource { + public: + virtual ~CodedVideoSource() = default; + + // Returns next frame. If no more frames to pull, returns `absl::nullopt`. + // For analysis and pacing purposes, frame must have RTP timestamp set. The + // timestamp must represent the target video frame rate and be unique. + virtual absl::optional<EncodedImage> PullFrame() = 0; + }; + + // Interface for a video encoder. + class Encoder { + public: + using EncodeCallback = + absl::AnyInvocable<void(const EncodedImage& encoded_frame)>; + + virtual ~Encoder() = default; + + virtual void Encode(const VideoFrame& frame, EncodeCallback callback) = 0; + }; + + // Interface for a video decoder. + class Decoder { + public: + using DecodeCallback = + absl::AnyInvocable<void(const VideoFrame& decoded_frame)>; + + virtual ~Decoder() = default; + + virtual void Decode(const EncodedImage& frame, DecodeCallback callback) = 0; + }; + + // Pulls coded video frames from `video_source` and passes them to `decoder`. + // Returns `VideoCodecTestStats` object that contains collected per-frame + // metrics. + virtual std::unique_ptr<VideoCodecTestStats> RunDecodeTest( + std::unique_ptr<CodedVideoSource> video_source, + std::unique_ptr<Decoder> decoder, + const DecoderSettings& decoder_settings) = 0; + + // Pulls raw video frames from `video_source` and passes them to `encoder`. + // Returns `VideoCodecTestStats` object that contains collected per-frame + // metrics. + virtual std::unique_ptr<VideoCodecTestStats> RunEncodeTest( + std::unique_ptr<RawVideoSource> video_source, + std::unique_ptr<Encoder> encoder, + const EncoderSettings& encoder_settings) = 0; + + // Pulls raw video frames from `video_source`, passes them to `encoder` and + // then passes encoded frames to `decoder`. Returns `VideoCodecTestStats` + // object that contains collected per-frame metrics. + virtual std::unique_ptr<VideoCodecTestStats> RunEncodeDecodeTest( + std::unique_ptr<RawVideoSource> video_source, + std::unique_ptr<Encoder> encoder, + std::unique_ptr<Decoder> decoder, + const EncoderSettings& encoder_settings, + const DecoderSettings& decoder_settings) = 0; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_VIDEO_CODEC_TESTER_H_ diff --git a/third_party/libwebrtc/api/test/video_quality_analyzer_interface.h b/third_party/libwebrtc/api/test/video_quality_analyzer_interface.h new file mode 100644 index 0000000000..d35be8ca1a --- /dev/null +++ b/third_party/libwebrtc/api/test/video_quality_analyzer_interface.h @@ -0,0 +1,165 @@ +/* + * 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. + */ + +#ifndef API_TEST_VIDEO_QUALITY_ANALYZER_INTERFACE_H_ +#define API_TEST_VIDEO_QUALITY_ANALYZER_INTERFACE_H_ + +#include <memory> +#include <string> + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/test/stats_observer_interface.h" +#include "api/video/encoded_image.h" +#include "api/video/video_frame.h" +#include "api/video_codecs/video_encoder.h" + +namespace webrtc { + +// API is in development and can be changed without notice. + +// Base interface for video quality analyzer for peer connection level end-2-end +// tests. Interface has only one abstract method, which have to return frame id. +// Other methods have empty implementation by default, so user can override only +// required parts. +// +// VideoQualityAnalyzerInterface will be injected into WebRTC pipeline on both +// sides of the call. Here is video data flow in WebRTC pipeline +// +// Alice: +// ___________ ________ _________ +// | | | | | | +// | Frame |-(A)→| WebRTC |-(B)→| Video |-(C)┐ +// | Generator | | Stack | | Decoder | | +// ¯¯¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯ | +// __↓________ +// | Transport | +// | & | +// | Network | +// ¯¯|¯¯¯¯¯¯¯¯ +// Bob: | +// _______ ________ _________ | +// | | | | | | | +// | Video |←(F)-| WebRTC |←(E)-| Video |←(D)----┘ +// | Sink | | Stack | | Decoder | +// ¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯ +// The analyzer will be injected in all points from A to F. +class VideoQualityAnalyzerInterface + : public webrtc_pc_e2e::StatsObserverInterface { + public: + // Contains extra statistic provided by video encoder. + struct EncoderStats { + std::string encoder_name = "unknown"; + // TODO(hbos) https://crbug.com/webrtc/9547, + // https://crbug.com/webrtc/11443: improve stats API to make available + // there. + uint32_t target_encode_bitrate = 0; + // Encoder quantizer value. + int qp = -1; + }; + // Contains extra statistic provided by video decoder. + struct DecoderStats { + std::string decoder_name = "unknown"; + // Decode time provided by decoder itself. If decoder doesn’t produce such + // information can be omitted. + absl::optional<int32_t> decode_time_ms = absl::nullopt; + }; + + ~VideoQualityAnalyzerInterface() override = default; + + // Will be called by framework before test. + // `test_case_name` is name of test case, that should be used to report all + // video metrics. + // `threads_count` is number of threads that analyzer can use for heavy + // calculations. Analyzer can perform simple calculations on the calling + // thread in each method, but should remember, that it is the same thread, + // that is used in video pipeline. + virtual void Start(std::string test_case_name, + rtc::ArrayView<const std::string> peer_names, + int max_threads_count) {} + + // Will be called when frame was generated from the input stream. + // `peer_name` is name of the peer on which side frame was captured. + // Returns frame id, that will be set by framework to the frame. + virtual uint16_t OnFrameCaptured(absl::string_view peer_name, + const std::string& stream_label, + const VideoFrame& frame) = 0; + // Will be called before calling the encoder. + // `peer_name` is name of the peer on which side frame came to encoder. + virtual void OnFramePreEncode(absl::string_view peer_name, + const VideoFrame& frame) {} + // Will be called for each EncodedImage received from encoder. Single + // VideoFrame can produce multiple EncodedImages. Each encoded image will + // have id from VideoFrame. + // `peer_name` is name of the peer on which side frame was encoded. + virtual void OnFrameEncoded(absl::string_view peer_name, + uint16_t frame_id, + const EncodedImage& encoded_image, + const EncoderStats& stats, + bool discarded) {} + // Will be called for each frame dropped by encoder. + // `peer_name` is name of the peer on which side frame drop was detected. + virtual void OnFrameDropped(absl::string_view peer_name, + EncodedImageCallback::DropReason reason) {} + // Will be called before calling the decoder. + // `peer_name` is name of the peer on which side frame was received. + virtual void OnFramePreDecode(absl::string_view peer_name, + uint16_t frame_id, + const EncodedImage& encoded_image) {} + // Will be called after decoding the frame. + // `peer_name` is name of the peer on which side frame was decoded. + virtual void OnFrameDecoded(absl::string_view peer_name, + const VideoFrame& frame, + const DecoderStats& stats) {} + // Will be called when frame will be obtained from PeerConnection stack. + // `peer_name` is name of the peer on which side frame was rendered. + virtual void OnFrameRendered(absl::string_view peer_name, + const VideoFrame& frame) {} + // Will be called if encoder return not WEBRTC_VIDEO_CODEC_OK. + // All available codes are listed in + // modules/video_coding/include/video_error_codes.h + // `peer_name` is name of the peer on which side error acquired. + virtual void OnEncoderError(absl::string_view peer_name, + const VideoFrame& frame, + int32_t error_code) {} + // Will be called if decoder return not WEBRTC_VIDEO_CODEC_OK. + // All available codes are listed in + // modules/video_coding/include/video_error_codes.h + // `peer_name` is name of the peer on which side error acquired. + virtual void OnDecoderError(absl::string_view peer_name, + uint16_t frame_id, + int32_t error_code, + const DecoderStats& stats) {} + // Will be called every time new stats reports are available for the + // Peer Connection identified by `pc_label`. + void OnStatsReports( + absl::string_view pc_label, + const rtc::scoped_refptr<const RTCStatsReport>& report) override {} + + // Will be called before test adds new participant in the middle of a call. + virtual void RegisterParticipantInCall(absl::string_view peer_name) {} + // Will be called after test removed existing participant in the middle of the + // call. + virtual void UnregisterParticipantInCall(absl::string_view peer_name) {} + + // Tells analyzer that analysis complete and it should calculate final + // statistics. + virtual void Stop() {} + + // Returns the last stream where this frame was captured. It means that if + // frame ids space wraps around, then stream label for frame id may change. + // It will crash, if the specified `frame_id` wasn't captured. + virtual std::string GetStreamLabel(uint16_t frame_id) = 0; +}; + +} // namespace webrtc + +#endif // API_TEST_VIDEO_QUALITY_ANALYZER_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/test/video_quality_test_fixture.h b/third_party/libwebrtc/api/test/video_quality_test_fixture.h new file mode 100644 index 0000000000..b45faef286 --- /dev/null +++ b/third_party/libwebrtc/api/test/video_quality_test_fixture.h @@ -0,0 +1,143 @@ +/* + * 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. + */ + +#ifndef API_TEST_VIDEO_QUALITY_TEST_FIXTURE_H_ +#define API_TEST_VIDEO_QUALITY_TEST_FIXTURE_H_ + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "api/fec_controller.h" +#include "api/media_types.h" +#include "api/network_state_predictor.h" +#include "api/test/simulated_network.h" +#include "api/transport/bitrate_settings.h" +#include "api/transport/network_control.h" +#include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "video/config/video_encoder_config.h" + +namespace webrtc { + +class VideoQualityTestFixtureInterface { + public: + // Parameters are grouped into smaller structs to make it easier to set + // the desired elements and skip unused. + struct Params { + struct CallConfig { + bool send_side_bwe = false; + bool generic_descriptor = false; + bool dependency_descriptor = false; + BitrateConstraints call_bitrate_config; + int num_thumbnails = 0; + // Indicates if secondary_(video|ss|screenshare) structures are used. + bool dual_video = false; + } call; + struct Video { + bool enabled = false; + size_t width = 640; + size_t height = 480; + int32_t fps = 30; + int min_bitrate_bps = 50; + int target_bitrate_bps = 800; + int max_bitrate_bps = 800; + bool suspend_below_min_bitrate = false; + std::string codec = "VP8"; + int num_temporal_layers = 1; + int selected_tl = -1; + int min_transmit_bps = 0; + bool ulpfec = false; + bool flexfec = false; + bool automatic_scaling = false; + std::string clip_path; // "Generator" to generate frames instead. + size_t capture_device_index = 0; + SdpVideoFormat::Parameters sdp_params; + double encoder_overshoot_factor = 0.0; + } video[2]; + struct Audio { + bool enabled = false; + bool sync_video = false; + bool dtx = false; + bool use_real_adm = false; + absl::optional<std::string> ana_config; + } audio; + struct Screenshare { + bool enabled = false; + bool generate_slides = false; + int32_t slide_change_interval = 10; + int32_t scroll_duration = 0; + std::vector<std::string> slides; + } screenshare[2]; + struct Analyzer { + std::string test_label; + double avg_psnr_threshold = 0.0; // (*) + double avg_ssim_threshold = 0.0; // (*) + int test_durations_secs = 0; + std::string graph_data_output_filename; + std::string graph_title; + } analyzer; + // Config for default simulation implementation. Must be nullopt if + // `sender_network` and `receiver_network` in InjectionComponents are + // non-null. May be nullopt even if `sender_network` and `receiver_network` + // are null; in that case, a default config will be used. + absl::optional<BuiltInNetworkBehaviorConfig> config; + struct SS { // Spatial scalability. + std::vector<VideoStream> streams; // If empty, one stream is assumed. + size_t selected_stream = 0; + int num_spatial_layers = 0; + int selected_sl = -1; + InterLayerPredMode inter_layer_pred = InterLayerPredMode::kOn; + // If empty, bitrates are generated in VP9Impl automatically. + std::vector<SpatialLayer> spatial_layers; + // If set, default parameters will be used instead of `streams`. + bool infer_streams = false; + } ss[2]; + struct Logging { + std::string rtc_event_log_name; + std::string rtp_dump_name; + std::string encoded_frame_base_path; + } logging; + }; + + // Contains objects, that will be injected on different layers of test + // framework to override the behavior of system parts. + struct InjectionComponents { + InjectionComponents(); + ~InjectionComponents(); + + // Simulations of sender and receiver networks. They must either both be + // null (in which case `config` from Params is used), or both be non-null + // (in which case `config` from Params must be nullopt). + std::unique_ptr<NetworkBehaviorInterface> sender_network; + std::unique_ptr<NetworkBehaviorInterface> receiver_network; + + std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory; + std::unique_ptr<VideoEncoderFactory> video_encoder_factory; + std::unique_ptr<VideoDecoderFactory> video_decoder_factory; + std::unique_ptr<NetworkStatePredictorFactoryInterface> + network_state_predictor_factory; + std::unique_ptr<NetworkControllerFactoryInterface> + network_controller_factory; + }; + + virtual ~VideoQualityTestFixtureInterface() = default; + + virtual void RunWithAnalyzer(const Params& params) = 0; + virtual void RunWithRenderers(const Params& params) = 0; + + virtual const std::map<uint8_t, webrtc::MediaType>& payload_type_map() = 0; +}; + +} // namespace webrtc + +#endif // API_TEST_VIDEO_QUALITY_TEST_FIXTURE_H_ diff --git a/third_party/libwebrtc/api/test/videocodec_test_fixture.h b/third_party/libwebrtc/api/test/videocodec_test_fixture.h new file mode 100644 index 0000000000..dbf20993e2 --- /dev/null +++ b/third_party/libwebrtc/api/test/videocodec_test_fixture.h @@ -0,0 +1,177 @@ +/* + * 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. + */ + +#ifndef API_TEST_VIDEOCODEC_TEST_FIXTURE_H_ +#define API_TEST_VIDEOCODEC_TEST_FIXTURE_H_ + +#include <string> +#include <vector> + +#include "api/test/videocodec_test_stats.h" +#include "api/video_codecs/h264_profile_level_id.h" +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "modules/video_coding/include/video_codec_interface.h" + +namespace webrtc { +namespace test { + +// Rates for the encoder and the frame number when to apply profile. +struct RateProfile { + size_t target_kbps; + double input_fps; + size_t frame_num; +}; + +struct RateControlThresholds { + double max_avg_bitrate_mismatch_percent; + double max_time_to_reach_target_bitrate_sec; + // TODO(ssilkin): Use absolute threshold for framerate. + double max_avg_framerate_mismatch_percent; + double max_avg_buffer_level_sec; + double max_max_key_frame_delay_sec; + double max_max_delta_frame_delay_sec; + size_t max_num_spatial_resizes; + size_t max_num_key_frames; +}; + +struct QualityThresholds { + double min_avg_psnr; + double min_min_psnr; + double min_avg_ssim; + double min_min_ssim; +}; + +struct BitstreamThresholds { + size_t max_max_nalu_size_bytes; +}; + +// NOTE: This class is still under development and may change without notice. +class VideoCodecTestFixture { + public: + class EncodedFrameChecker { + public: + virtual ~EncodedFrameChecker() = default; + virtual void CheckEncodedFrame(VideoCodecType codec, + const EncodedImage& encoded_frame) const = 0; + }; + + struct Config { + Config(); + void SetCodecSettings(std::string codec_name, + size_t num_simulcast_streams, + size_t num_spatial_layers, + size_t num_temporal_layers, + bool denoising_on, + bool frame_dropper_on, + bool spatial_resize_on, + size_t width, + size_t height); + + size_t NumberOfCores() const; + size_t NumberOfTemporalLayers() const; + size_t NumberOfSpatialLayers() const; + size_t NumberOfSimulcastStreams() const; + + std::string ToString() const; + std::string CodecName() const; + + // Name of this config, to be used for accounting by the test runner. + std::string test_name; + + // Plain name of YUV file to process without file extension. + std::string filename; + // Dimensions of test clip. Falls back to (codec_settings.width/height) if + // not set. + absl::optional<int> clip_width; + absl::optional<int> clip_height; + // Framerate of input clip. Defaults to 30fps if not set. + absl::optional<int> clip_fps; + + // The resolution at which psnr/ssim comparisons should be made. Frames + // will be scaled to this size if different. + absl::optional<int> reference_width; + absl::optional<int> reference_height; + + // File to process. This must be a video file in the YUV format. + std::string filepath; + + // Number of frames to process. + size_t num_frames = 0; + + // Bitstream constraints. + size_t max_payload_size_bytes = 1440; + + // Should we decode the encoded frames? + bool decode = true; + + // Force the encoder and decoder to use a single core for processing. + bool use_single_core = false; + + // Should cpu usage be measured? + // If set to true, the encoding will run in real-time. + bool measure_cpu = false; + + // Simulate frames arriving in real-time by adding delays between frames. + bool encode_in_real_time = false; + + // Codec settings to use. + VideoCodec codec_settings; + + // Name of the codec being tested. + std::string codec_name; + + // Encoder and decoder format and parameters. If provided, format is used to + // instantiate the codec. If not provided, the test creates and uses the + // default `SdpVideoFormat` based on `codec_name`. + // Encoder and decoder name (`SdpVideoFormat::name`) should be the same as + // `codec_name`. + absl::optional<SdpVideoFormat> encoder_format; + absl::optional<SdpVideoFormat> decoder_format; + + // H.264 specific settings. + struct H264CodecSettings { + H264Profile profile = H264Profile::kProfileConstrainedBaseline; + H264PacketizationMode packetization_mode = + H264PacketizationMode::NonInterleaved; + } h264_codec_settings; + + // Custom checker that will be called for each frame. + const EncodedFrameChecker* encoded_frame_checker = nullptr; + + // Print out frame level stats. + bool print_frame_level_stats = false; + + // Path to a directory where encoded or/and decoded video should be saved. + std::string output_path; + + // Should video be saved persistently to disk for post-run visualization? + struct VisualizationParams { + bool save_encoded_ivf = false; + bool save_decoded_y4m = false; + } visualization_params; + + // Enables quality analysis for dropped frames. + bool analyze_quality_of_dropped_frames = false; + }; + + virtual ~VideoCodecTestFixture() = default; + + virtual void RunTest(const std::vector<RateProfile>& rate_profiles, + const std::vector<RateControlThresholds>* rc_thresholds, + const std::vector<QualityThresholds>* quality_thresholds, + const BitstreamThresholds* bs_thresholds) = 0; + virtual VideoCodecTestStats& GetStats() = 0; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_VIDEOCODEC_TEST_FIXTURE_H_ diff --git a/third_party/libwebrtc/api/test/videocodec_test_stats.cc b/third_party/libwebrtc/api/test/videocodec_test_stats.cc new file mode 100644 index 0000000000..f082b1e935 --- /dev/null +++ b/third_party/libwebrtc/api/test/videocodec_test_stats.cc @@ -0,0 +1,121 @@ +/* + * 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 "api/test/videocodec_test_stats.h" + +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { +namespace test { + +VideoCodecTestStats::FrameStatistics::FrameStatistics(size_t frame_number, + size_t rtp_timestamp, + size_t spatial_idx) + : frame_number(frame_number), + rtp_timestamp(rtp_timestamp), + spatial_idx(spatial_idx) {} + +std::string VideoCodecTestStats::FrameStatistics::ToString() const { + rtc::StringBuilder ss; + for (const auto& entry : ToMap()) { + if (ss.size() > 0) { + ss << " "; + } + ss << entry.first << " " << entry.second; + } + return ss.Release(); +} + +std::map<std::string, std::string> VideoCodecTestStats::FrameStatistics::ToMap() + const { + std::map<std::string, std::string> map; + map["frame_number"] = std::to_string(frame_number); + map["decoded_width"] = std::to_string(decoded_width); + map["decoded_height"] = std::to_string(decoded_height); + map["spatial_idx"] = std::to_string(spatial_idx); + map["temporal_idx"] = std::to_string(temporal_idx); + map["inter_layer_predicted"] = std::to_string(inter_layer_predicted); + map["non_ref_for_inter_layer_pred"] = + std::to_string(non_ref_for_inter_layer_pred); + map["frame_type"] = std::to_string(static_cast<int>(frame_type)); + map["length_bytes"] = std::to_string(length_bytes); + map["qp"] = std::to_string(qp); + map["psnr"] = std::to_string(psnr); + map["psnr_y"] = std::to_string(psnr_y); + map["psnr_u"] = std::to_string(psnr_u); + map["psnr_v"] = std::to_string(psnr_v); + map["ssim"] = std::to_string(ssim); + map["encode_time_us"] = std::to_string(encode_time_us); + map["decode_time_us"] = std::to_string(decode_time_us); + map["rtp_timestamp"] = std::to_string(rtp_timestamp); + map["target_bitrate_kbps"] = std::to_string(target_bitrate_kbps); + map["target_framerate_fps"] = std::to_string(target_framerate_fps); + return map; +} + +std::string VideoCodecTestStats::VideoStatistics::ToString( + std::string prefix) const { + rtc::StringBuilder ss; + for (const auto& entry : ToMap()) { + if (ss.size() > 0) { + ss << "\n"; + } + ss << prefix << entry.first << ": " << entry.second; + } + return ss.Release(); +} + +std::map<std::string, std::string> VideoCodecTestStats::VideoStatistics::ToMap() + const { + std::map<std::string, std::string> map; + map["target_bitrate_kbps"] = std::to_string(target_bitrate_kbps); + map["input_framerate_fps"] = std::to_string(input_framerate_fps); + map["spatial_idx"] = std::to_string(spatial_idx); + map["temporal_idx"] = std::to_string(temporal_idx); + map["width"] = std::to_string(width); + map["height"] = std::to_string(height); + map["length_bytes"] = std::to_string(length_bytes); + map["bitrate_kbps"] = std::to_string(bitrate_kbps); + map["framerate_fps"] = std::to_string(framerate_fps); + map["enc_speed_fps"] = std::to_string(enc_speed_fps); + map["dec_speed_fps"] = std::to_string(dec_speed_fps); + map["avg_encode_latency_sec"] = std::to_string(avg_encode_latency_sec); + map["max_encode_latency_sec"] = std::to_string(max_encode_latency_sec); + map["avg_decode_latency_sec"] = std::to_string(avg_decode_latency_sec); + map["max_decode_latency_sec"] = std::to_string(max_decode_latency_sec); + map["avg_delay_sec"] = std::to_string(avg_delay_sec); + map["max_key_frame_delay_sec"] = std::to_string(max_key_frame_delay_sec); + map["max_delta_frame_delay_sec"] = std::to_string(max_delta_frame_delay_sec); + map["time_to_reach_target_bitrate_sec"] = + std::to_string(time_to_reach_target_bitrate_sec); + map["avg_bitrate_mismatch_pct"] = std::to_string(avg_bitrate_mismatch_pct); + map["avg_framerate_mismatch_pct"] = + std::to_string(avg_framerate_mismatch_pct); + map["avg_key_frame_size_bytes"] = std::to_string(avg_key_frame_size_bytes); + map["avg_delta_frame_size_bytes"] = + std::to_string(avg_delta_frame_size_bytes); + map["avg_qp"] = std::to_string(avg_qp); + map["avg_psnr"] = std::to_string(avg_psnr); + map["min_psnr"] = std::to_string(min_psnr); + map["avg_ssim"] = std::to_string(avg_ssim); + map["min_ssim"] = std::to_string(min_ssim); + map["num_input_frames"] = std::to_string(num_input_frames); + map["num_encoded_frames"] = std::to_string(num_encoded_frames); + map["num_decoded_frames"] = std::to_string(num_decoded_frames); + map["num_dropped_frames"] = + std::to_string(num_input_frames - num_encoded_frames); + map["num_key_frames"] = std::to_string(num_key_frames); + map["num_spatial_resizes"] = std::to_string(num_spatial_resizes); + map["max_nalu_size_bytes"] = std::to_string(max_nalu_size_bytes); + return map; +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/videocodec_test_stats.h b/third_party/libwebrtc/api/test/videocodec_test_stats.h new file mode 100644 index 0000000000..12c60638db --- /dev/null +++ b/third_party/libwebrtc/api/test/videocodec_test_stats.h @@ -0,0 +1,156 @@ +/* + * 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. + */ + +#ifndef API_TEST_VIDEOCODEC_TEST_STATS_H_ +#define API_TEST_VIDEOCODEC_TEST_STATS_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <map> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/units/data_rate.h" +#include "api/units/frequency.h" +#include "api/video/video_frame_type.h" + +namespace webrtc { +namespace test { + +// Statistics for a sequence of processed frames. This class is not thread safe. +class VideoCodecTestStats { + public: + // Statistics for one processed frame. + struct FrameStatistics { + FrameStatistics(size_t frame_number, + size_t rtp_timestamp, + size_t spatial_idx); + + std::string ToString() const; + + // Returns name -> value text map of frame statistics. + std::map<std::string, std::string> ToMap() const; + + size_t frame_number = 0; + size_t rtp_timestamp = 0; + + // Encoding. + int64_t encode_start_ns = 0; + int encode_return_code = 0; + bool encoding_successful = false; + size_t encode_time_us = 0; + size_t target_bitrate_kbps = 0; + double target_framerate_fps = 0.0; + size_t length_bytes = 0; + VideoFrameType frame_type = VideoFrameType::kVideoFrameDelta; + + // Layering. + size_t spatial_idx = 0; + size_t temporal_idx = 0; + bool inter_layer_predicted = false; + bool non_ref_for_inter_layer_pred = true; + + // H264 specific. + size_t max_nalu_size_bytes = 0; + + // Decoding. + int64_t decode_start_ns = 0; + int decode_return_code = 0; + bool decoding_successful = false; + size_t decode_time_us = 0; + size_t decoded_width = 0; + size_t decoded_height = 0; + + // Quantization. + int qp = -1; + + // Quality. + bool quality_analysis_successful = false; + float psnr_y = 0.0f; + float psnr_u = 0.0f; + float psnr_v = 0.0f; + float psnr = 0.0f; // 10 * log10(255^2 / (mse_y + mse_u + mse_v)). + float ssim = 0.0f; // 0.8 * ssim_y + 0.1 * (ssim_u + ssim_v). + }; + + struct VideoStatistics { + std::string ToString(std::string prefix) const; + + // Returns name -> value text map of video statistics. + std::map<std::string, std::string> ToMap() const; + + size_t target_bitrate_kbps = 0; + float input_framerate_fps = 0.0f; + + size_t spatial_idx = 0; + size_t temporal_idx = 0; + + size_t width = 0; + size_t height = 0; + + size_t length_bytes = 0; + size_t bitrate_kbps = 0; + float framerate_fps = 0; + + float enc_speed_fps = 0.0f; + float dec_speed_fps = 0.0f; + + float avg_encode_latency_sec = 0.0f; + float max_encode_latency_sec = 0.0f; + float avg_decode_latency_sec = 0.0f; + float max_decode_latency_sec = 0.0f; + + float avg_delay_sec = 0.0f; + float max_key_frame_delay_sec = 0.0f; + float max_delta_frame_delay_sec = 0.0f; + float time_to_reach_target_bitrate_sec = 0.0f; + float avg_bitrate_mismatch_pct = 0.0f; + float avg_framerate_mismatch_pct = 0.0f; + + float avg_key_frame_size_bytes = 0.0f; + float avg_delta_frame_size_bytes = 0.0f; + float avg_qp = 0.0f; + + float avg_psnr_y = 0.0f; + float avg_psnr_u = 0.0f; + float avg_psnr_v = 0.0f; + float avg_psnr = 0.0f; + float min_psnr = 0.0f; + float avg_ssim = 0.0f; + float min_ssim = 0.0f; + + size_t num_input_frames = 0; + size_t num_encoded_frames = 0; + size_t num_decoded_frames = 0; + size_t num_key_frames = 0; + size_t num_spatial_resizes = 0; + size_t max_nalu_size_bytes = 0; + }; + + virtual ~VideoCodecTestStats() = default; + + virtual std::vector<FrameStatistics> GetFrameStatistics() const = 0; + + virtual std::vector<VideoStatistics> SliceAndCalcLayerVideoStatistic( + size_t first_frame_num, + size_t last_frame_num) = 0; + + virtual VideoStatistics CalcVideoStatistic(size_t first_frame, + size_t last_frame, + DataRate target_bitrate, + Frequency target_framerate) = 0; +}; + +} // namespace test +} // namespace webrtc + +#endif // API_TEST_VIDEOCODEC_TEST_STATS_H_ diff --git a/third_party/libwebrtc/api/transport/BUILD.gn b/third_party/libwebrtc/api/transport/BUILD.gn new file mode 100644 index 0000000000..e0b31122b2 --- /dev/null +++ b/third_party/libwebrtc/api/transport/BUILD.gn @@ -0,0 +1,167 @@ +# 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. + +import("../../webrtc.gni") + +rtc_library("bitrate_settings") { + visibility = [ "*" ] + sources = [ + "bitrate_settings.cc", + "bitrate_settings.h", + ] + deps = [ "../../rtc_base/system:rtc_export" ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_source_set("enums") { + visibility = [ "*" ] + sources = [ "enums.h" ] +} + +rtc_library("network_control") { + visibility = [ "*" ] + sources = [ + "network_control.h", + "network_types.cc", + "network_types.h", + ] + + deps = [ + "../../api:field_trials_view", + "../rtc_event_log", + "../units:data_rate", + "../units:data_size", + "../units:time_delta", + "../units:timestamp", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("field_trial_based_config") { + visibility = [ "*" ] + sources = [ + "field_trial_based_config.cc", + "field_trial_based_config.h", + ] + deps = [ + "../../api:field_trials_registry", + "../../system_wrappers:field_trial", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} + +rtc_source_set("datagram_transport_interface") { + visibility = [ "*" ] + sources = [ "data_channel_transport_interface.h" ] + deps = [ + "..:array_view", + "..:rtc_error", + "../../rtc_base:copy_on_write_buffer", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("goog_cc") { + visibility = [ "*" ] + sources = [ + "goog_cc_factory.cc", + "goog_cc_factory.h", + ] + deps = [ + ":network_control", + "..:network_state_predictor_api", + "../../api:field_trials_view", + "../../modules/congestion_controller/goog_cc", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/base:core_headers" ] +} + +rtc_source_set("sctp_transport_factory_interface") { + visibility = [ "*" ] + sources = [ "sctp_transport_factory_interface.h" ] +} + +rtc_source_set("stun_types") { +if (!build_with_mozilla) { + visibility = [ "*" ] + sources = [ + "stun.cc", + "stun.h", + ] + + deps = [ + "../../api:array_view", + "../../rtc_base:byte_buffer", + "../../rtc_base:byte_order", + "../../rtc_base:checks", + "../../rtc_base:crc32", + "../../rtc_base:ip_address", + "../../rtc_base:logging", + "../../rtc_base:socket_address", + "../../rtc_base:ssl", + "../../system_wrappers:metrics", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} +} + +if (rtc_include_tests) { + rtc_source_set("test_feedback_generator_interface") { + testonly = true + sources = [ "test/feedback_generator_interface.h" ] + deps = [ + ":network_control", + "..:simulated_network_api", + ] + } + rtc_library("test_feedback_generator") { + testonly = true + sources = [ + "test/create_feedback_generator.cc", + "test/create_feedback_generator.h", + ] + visibility = [ "*" ] + deps = [ + ":network_control", + ":test_feedback_generator_interface", + "../../test/network:feedback_generator", + ] + } +} + +if (rtc_include_tests) { + rtc_source_set("stun_unittest") { + visibility = [ "*" ] + testonly = true + sources = [ "stun_unittest.cc" ] + deps = [ + ":stun_types", + "../../rtc_base:byte_buffer", + "../../rtc_base:byte_order", + "../../rtc_base:macromagic", + "../../rtc_base:socket_address", + "../../system_wrappers:metrics", + "../../test:test_support", + "//testing/gtest", + ] + } +} + +if (rtc_include_tests) { + rtc_source_set("mock_network_control") { + testonly = true + sources = [ "test/mock_network_control.h" ] + deps = [ + ":network_control", + "../../test:test_support", + ] + } +} diff --git a/third_party/libwebrtc/api/transport/DEPS b/third_party/libwebrtc/api/transport/DEPS new file mode 100644 index 0000000000..53a68e0e85 --- /dev/null +++ b/third_party/libwebrtc/api/transport/DEPS @@ -0,0 +1,7 @@ +specific_include_rules = { + "stun\.h": [ + "+rtc_base/byte_buffer.h", + "+rtc_base/ip_address.h", + "+rtc_base/socket_address.h", + ], +} diff --git a/third_party/libwebrtc/api/transport/OWNERS b/third_party/libwebrtc/api/transport/OWNERS new file mode 100644 index 0000000000..5991f6fc56 --- /dev/null +++ b/third_party/libwebrtc/api/transport/OWNERS @@ -0,0 +1,2 @@ +srte@webrtc.org +terelius@webrtc.org diff --git a/third_party/libwebrtc/api/transport/bitrate_settings.cc b/third_party/libwebrtc/api/transport/bitrate_settings.cc new file mode 100644 index 0000000000..c72bd82791 --- /dev/null +++ b/third_party/libwebrtc/api/transport/bitrate_settings.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 "api/transport/bitrate_settings.h" + +namespace webrtc { + +BitrateSettings::BitrateSettings() = default; +BitrateSettings::~BitrateSettings() = default; +BitrateSettings::BitrateSettings(const BitrateSettings&) = default; + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/transport/bitrate_settings.h b/third_party/libwebrtc/api/transport/bitrate_settings.h new file mode 100644 index 0000000000..562309a46c --- /dev/null +++ b/third_party/libwebrtc/api/transport/bitrate_settings.h @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#ifndef API_TRANSPORT_BITRATE_SETTINGS_H_ +#define API_TRANSPORT_BITRATE_SETTINGS_H_ + +#include <algorithm> + +#include "absl/types/optional.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Configuration of send bitrate. The `start_bitrate_bps` value is +// used for multiple purposes, both as a prior in the bandwidth +// estimator, and for initial configuration of the encoder. We may +// want to create separate apis for those, and use a smaller struct +// with only the min and max constraints. +struct RTC_EXPORT BitrateSettings { + BitrateSettings(); + ~BitrateSettings(); + BitrateSettings(const BitrateSettings&); + // 0 <= min <= start <= max should hold for set parameters. + absl::optional<int> min_bitrate_bps; + absl::optional<int> start_bitrate_bps; + absl::optional<int> max_bitrate_bps; +}; + +// TODO(srte): BitrateConstraints and BitrateSettings should be merged. +// Both represent the same kind data, but are using different default +// initializer and representation of unset values. +struct BitrateConstraints { + int min_bitrate_bps = 0; + int start_bitrate_bps = kDefaultStartBitrateBps; + int max_bitrate_bps = -1; + + private: + static constexpr int kDefaultStartBitrateBps = 300000; +}; + +} // namespace webrtc + +#endif // API_TRANSPORT_BITRATE_SETTINGS_H_ diff --git a/third_party/libwebrtc/api/transport/bitrate_settings_gn/moz.build b/third_party/libwebrtc/api/transport/bitrate_settings_gn/moz.build new file mode 100644 index 0000000000..fba5b45a5d --- /dev/null +++ b/third_party/libwebrtc/api/transport/bitrate_settings_gn/moz.build @@ -0,0 +1,217 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/transport/bitrate_settings.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("bitrate_settings_gn") diff --git a/third_party/libwebrtc/api/transport/data_channel_transport_interface.h b/third_party/libwebrtc/api/transport/data_channel_transport_interface.h new file mode 100644 index 0000000000..cdae6fee19 --- /dev/null +++ b/third_party/libwebrtc/api/transport/data_channel_transport_interface.h @@ -0,0 +1,125 @@ +/* Copyright 2019 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 is an experimental interface and is subject to change without notice. + +#ifndef API_TRANSPORT_DATA_CHANNEL_TRANSPORT_INTERFACE_H_ +#define API_TRANSPORT_DATA_CHANNEL_TRANSPORT_INTERFACE_H_ + +#include "absl/types/optional.h" +#include "api/rtc_error.h" +#include "rtc_base/copy_on_write_buffer.h" + +namespace webrtc { + +// Supported types of application data messages. +enum class DataMessageType { + // Application data buffer with the binary bit unset. + kText, + + // Application data buffer with the binary bit set. + kBinary, + + // Transport-agnostic control messages, such as open or open-ack messages. + kControl, +}; + +// Parameters for sending data. The parameters may change from message to +// message, even within a single channel. For example, control messages may be +// sent reliably and in-order, even if the data channel is configured for +// unreliable delivery. +struct SendDataParams { + DataMessageType type = DataMessageType::kText; + + // Whether to deliver the message in order with respect to other ordered + // messages with the same channel_id. + bool ordered = false; + + // If set, the maximum number of times this message may be + // retransmitted by the transport before it is dropped. + // Setting this value to zero disables retransmission. + // Valid values are in the range [0-UINT16_MAX]. + // `max_rtx_count` and `max_rtx_ms` may not be set simultaneously. + absl::optional<int> max_rtx_count; + + // If set, the maximum number of milliseconds for which the transport + // may retransmit this message before it is dropped. + // Setting this value to zero disables retransmission. + // Valid values are in the range [0-UINT16_MAX]. + // `max_rtx_count` and `max_rtx_ms` may not be set simultaneously. + absl::optional<int> max_rtx_ms; +}; + +// Sink for callbacks related to a data channel. +class DataChannelSink { + public: + virtual ~DataChannelSink() = default; + + // Callback issued when data is received by the transport. + virtual void OnDataReceived(int channel_id, + DataMessageType type, + const rtc::CopyOnWriteBuffer& buffer) = 0; + + // Callback issued when a remote data channel begins the closing procedure. + // Messages sent after the closing procedure begins will not be transmitted. + virtual void OnChannelClosing(int channel_id) = 0; + + // Callback issued when a (remote or local) data channel completes the closing + // procedure. Closing channels become closed after all pending data has been + // transmitted. + virtual void OnChannelClosed(int channel_id) = 0; + + // Callback issued when the data channel becomes ready to send. + // This callback will be issued immediately when the data channel sink is + // registered if the transport is ready at that time. This callback may be + // invoked again following send errors (eg. due to the transport being + // temporarily blocked or unavailable). + virtual void OnReadyToSend() = 0; + + // Callback issued when the data channel becomes unusable (closed). + // TODO(https://crbug.com/webrtc/10360): Make pure virtual when all + // consumers updated. + virtual void OnTransportClosed(RTCError error) {} +}; + +// Transport for data channels. +class DataChannelTransportInterface { + public: + virtual ~DataChannelTransportInterface() = default; + + // Opens a data `channel_id` for sending. May return an error if the + // specified `channel_id` is unusable. Must be called before `SendData`. + virtual RTCError OpenChannel(int channel_id) = 0; + + // Sends a data buffer to the remote endpoint using the given send parameters. + // `buffer` may not be larger than 256 KiB. Returns an error if the send + // fails. + virtual RTCError SendData(int channel_id, + const SendDataParams& params, + const rtc::CopyOnWriteBuffer& buffer) = 0; + + // Closes `channel_id` gracefully. Returns an error if `channel_id` is not + // open. Data sent after the closing procedure begins will not be + // transmitted. The channel becomes closed after pending data is transmitted. + virtual RTCError CloseChannel(int channel_id) = 0; + + // Sets a sink for data messages and channel state callbacks. Before media + // transport is destroyed, the sink must be unregistered by setting it to + // nullptr. + virtual void SetDataSink(DataChannelSink* sink) = 0; + + // Returns whether this data channel transport is ready to send. + // Note: the default implementation always returns false (as it assumes no one + // has implemented the interface). This default implementation is temporary. + virtual bool IsReadyToSend() const = 0; +}; + +} // namespace webrtc + +#endif // API_TRANSPORT_DATA_CHANNEL_TRANSPORT_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/transport/datagram_transport_interface_gn/moz.build b/third_party/libwebrtc/api/transport/datagram_transport_interface_gn/moz.build new file mode 100644 index 0000000000..ac59bcbcde --- /dev/null +++ b/third_party/libwebrtc/api/transport/datagram_transport_interface_gn/moz.build @@ -0,0 +1,209 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("datagram_transport_interface_gn") diff --git a/third_party/libwebrtc/api/transport/enums.h b/third_party/libwebrtc/api/transport/enums.h new file mode 100644 index 0000000000..3bc8fd1529 --- /dev/null +++ b/third_party/libwebrtc/api/transport/enums.h @@ -0,0 +1,49 @@ +/* + * Copyright 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. + */ + +#ifndef API_TRANSPORT_ENUMS_H_ +#define API_TRANSPORT_ENUMS_H_ + +namespace webrtc { + +// See https://w3c.github.io/webrtc-pc/#rtcicetransportstate +// Note that kFailed is currently not a terminal state, and a transport might +// incorrectly be marked as failed while gathering candidates, see +// bugs.webrtc.org/8833 +enum class IceTransportState { + kNew, + kChecking, + kConnected, + kCompleted, + kFailed, + kDisconnected, + kClosed, +}; + +enum PortPrunePolicy { + NO_PRUNE, // Do not prune. + PRUNE_BASED_ON_PRIORITY, // Prune lower-priority ports on the same network. + KEEP_FIRST_READY // Keep the first ready port and prune the rest + // on the same network. +}; + +enum class VpnPreference { + kDefault, // No VPN preference. + kOnlyUseVpn, // only use VPN connections. + kNeverUseVpn, // never use VPN connections + kPreferVpn, // use a VPN connection if possible, + // i.e VPN connections sorts first. + kAvoidVpn, // only use VPN if there is no other connections, + // i.e VPN connections sorts last. +}; + +} // namespace webrtc + +#endif // API_TRANSPORT_ENUMS_H_ diff --git a/third_party/libwebrtc/api/transport/field_trial_based_config.cc b/third_party/libwebrtc/api/transport/field_trial_based_config.cc new file mode 100644 index 0000000000..0cef30f054 --- /dev/null +++ b/third_party/libwebrtc/api/transport/field_trial_based_config.cc @@ -0,0 +1,18 @@ +/* + * Copyright 2019 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 "api/transport/field_trial_based_config.h" + +#include "system_wrappers/include/field_trial.h" + +namespace webrtc { +std::string FieldTrialBasedConfig::GetValue(absl::string_view key) const { + return webrtc::field_trial::FindFullName(std::string(key)); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/transport/field_trial_based_config.h b/third_party/libwebrtc/api/transport/field_trial_based_config.h new file mode 100644 index 0000000000..d47140e579 --- /dev/null +++ b/third_party/libwebrtc/api/transport/field_trial_based_config.h @@ -0,0 +1,26 @@ +/* + * Copyright 2019 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 API_TRANSPORT_FIELD_TRIAL_BASED_CONFIG_H_ +#define API_TRANSPORT_FIELD_TRIAL_BASED_CONFIG_H_ + +#include <string> + +#include "absl/strings/string_view.h" +#include "api/field_trials_registry.h" + +namespace webrtc { +// Implementation using the field trial API fo the key value lookup. +class FieldTrialBasedConfig : public FieldTrialsRegistry { + private: + std::string GetValue(absl::string_view key) const override; +}; +} // namespace webrtc + +#endif // API_TRANSPORT_FIELD_TRIAL_BASED_CONFIG_H_ diff --git a/third_party/libwebrtc/api/transport/field_trial_based_config_gn/moz.build b/third_party/libwebrtc/api/transport/field_trial_based_config_gn/moz.build new file mode 100644 index 0000000000..1ef79b4d20 --- /dev/null +++ b/third_party/libwebrtc/api/transport/field_trial_based_config_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/transport/field_trial_based_config.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("field_trial_based_config_gn") diff --git a/third_party/libwebrtc/api/transport/goog_cc_factory.cc b/third_party/libwebrtc/api/transport/goog_cc_factory.cc new file mode 100644 index 0000000000..fd1189901f --- /dev/null +++ b/third_party/libwebrtc/api/transport/goog_cc_factory.cc @@ -0,0 +1,65 @@ +/* + * 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 "api/transport/goog_cc_factory.h" + +#include <memory> +#include <utility> + +#include "modules/congestion_controller/goog_cc/goog_cc_network_control.h" + +namespace webrtc { +GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory( + RtcEventLog* event_log) + : event_log_(event_log) {} + +GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory( + NetworkStatePredictorFactoryInterface* network_state_predictor_factory) { + factory_config_.network_state_predictor_factory = + network_state_predictor_factory; +} + +GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory( + GoogCcFactoryConfig config) + : factory_config_(std::move(config)) {} + +std::unique_ptr<NetworkControllerInterface> +GoogCcNetworkControllerFactory::Create(NetworkControllerConfig config) { + if (event_log_) + config.event_log = event_log_; + GoogCcConfig goog_cc_config; + goog_cc_config.feedback_only = factory_config_.feedback_only; + if (factory_config_.network_state_estimator_factory) { + RTC_DCHECK(config.key_value_config); + goog_cc_config.network_state_estimator = + factory_config_.network_state_estimator_factory->Create( + config.key_value_config); + } + if (factory_config_.network_state_predictor_factory) { + goog_cc_config.network_state_predictor = + factory_config_.network_state_predictor_factory + ->CreateNetworkStatePredictor(); + } + return std::make_unique<GoogCcNetworkController>(config, + std::move(goog_cc_config)); +} + +TimeDelta GoogCcNetworkControllerFactory::GetProcessInterval() const { + const int64_t kUpdateIntervalMs = 25; + return TimeDelta::Millis(kUpdateIntervalMs); +} + +GoogCcFeedbackNetworkControllerFactory::GoogCcFeedbackNetworkControllerFactory( + RtcEventLog* event_log) + : GoogCcNetworkControllerFactory(event_log) { + factory_config_.feedback_only = true; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/transport/goog_cc_factory.h b/third_party/libwebrtc/api/transport/goog_cc_factory.h new file mode 100644 index 0000000000..e12755d745 --- /dev/null +++ b/third_party/libwebrtc/api/transport/goog_cc_factory.h @@ -0,0 +1,61 @@ +/* + * 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. + */ + +#ifndef API_TRANSPORT_GOOG_CC_FACTORY_H_ +#define API_TRANSPORT_GOOG_CC_FACTORY_H_ +#include <memory> + +#include "absl/base/attributes.h" +#include "api/network_state_predictor.h" +#include "api/transport/network_control.h" + +namespace webrtc { +class RtcEventLog; + +struct GoogCcFactoryConfig { + std::unique_ptr<NetworkStateEstimatorFactory> + network_state_estimator_factory = nullptr; + NetworkStatePredictorFactoryInterface* network_state_predictor_factory = + nullptr; + bool feedback_only = false; +}; + +class GoogCcNetworkControllerFactory + : public NetworkControllerFactoryInterface { + public: + GoogCcNetworkControllerFactory() = default; + ABSL_DEPRECATED("") + explicit GoogCcNetworkControllerFactory(RtcEventLog* event_log); + explicit GoogCcNetworkControllerFactory( + NetworkStatePredictorFactoryInterface* network_state_predictor_factory); + + explicit GoogCcNetworkControllerFactory(GoogCcFactoryConfig config); + std::unique_ptr<NetworkControllerInterface> Create( + NetworkControllerConfig config) override; + TimeDelta GetProcessInterval() const override; + + protected: + RtcEventLog* const event_log_ = nullptr; + GoogCcFactoryConfig factory_config_; +}; + +// Deprecated, use GoogCcFactoryConfig to enable feedback only mode instead. +// Factory to create packet feedback only GoogCC, this can be used for +// connections providing packet receive time feedback but no other reports. +class ABSL_DEPRECATED("use GoogCcFactoryConfig instead") + GoogCcFeedbackNetworkControllerFactory + : public GoogCcNetworkControllerFactory { + public: + explicit GoogCcFeedbackNetworkControllerFactory(RtcEventLog* event_log); +}; + +} // namespace webrtc + +#endif // API_TRANSPORT_GOOG_CC_FACTORY_H_ diff --git a/third_party/libwebrtc/api/transport/goog_cc_gn/moz.build b/third_party/libwebrtc/api/transport/goog_cc_gn/moz.build new file mode 100644 index 0000000000..95cbec37f0 --- /dev/null +++ b/third_party/libwebrtc/api/transport/goog_cc_gn/moz.build @@ -0,0 +1,232 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/transport/goog_cc_factory.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("goog_cc_gn") diff --git a/third_party/libwebrtc/api/transport/network_control.h b/third_party/libwebrtc/api/transport/network_control.h new file mode 100644 index 0000000000..862322443d --- /dev/null +++ b/third_party/libwebrtc/api/transport/network_control.h @@ -0,0 +1,140 @@ +/* + * 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. + */ + +#ifndef API_TRANSPORT_NETWORK_CONTROL_H_ +#define API_TRANSPORT_NETWORK_CONTROL_H_ +#include <stdint.h> + +#include <memory> + +#include "absl/base/attributes.h" +#include "api/field_trials_view.h" +#include "api/rtc_event_log/rtc_event_log.h" +#include "api/transport/network_types.h" + +namespace webrtc { + +class TargetTransferRateObserver { + public: + virtual ~TargetTransferRateObserver() = default; + // Called to indicate target transfer rate as well as giving information about + // the current estimate of network parameters. + virtual void OnTargetTransferRate(TargetTransferRate) = 0; + // Called to provide updates to the expected target rate in case it changes + // before the first call to OnTargetTransferRate. + virtual void OnStartRateUpdate(DataRate) {} +}; + +// Configuration sent to factory create function. The parameters here are +// optional to use for a network controller implementation. +struct NetworkControllerConfig { + // The initial constraints to start with, these can be changed at any later + // time by calls to OnTargetRateConstraints. Note that the starting rate + // has to be set initially to provide a starting state for the network + // controller, even though the field is marked as optional. + TargetRateConstraints constraints; + // Initial stream specific configuration, these are changed at any later time + // by calls to OnStreamsConfig. + StreamsConfig stream_based_config; + + // Optional override of configuration of WebRTC internals. Using nullptr here + // indicates that the field trial API will be used. + const FieldTrialsView* key_value_config = nullptr; + // Optional override of event log. + RtcEventLog* event_log = nullptr; +}; + +// NetworkControllerInterface is implemented by network controllers. A network +// controller is a class that uses information about network state and traffic +// to estimate network parameters such as round trip time and bandwidth. Network +// controllers does not guarantee thread safety, the interface must be used in a +// non-concurrent fashion. +class NetworkControllerInterface { + public: + virtual ~NetworkControllerInterface() = default; + + // Called when network availabilty changes. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnNetworkAvailability( + NetworkAvailability) = 0; + // Called when the receiving or sending endpoint changes address. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnNetworkRouteChange( + NetworkRouteChange) = 0; + // Called periodically with a periodicy as specified by + // NetworkControllerFactoryInterface::GetProcessInterval. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnProcessInterval( + ProcessInterval) = 0; + // Called when remotely calculated bitrate is received. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnRemoteBitrateReport( + RemoteBitrateReport) = 0; + // Called round trip time has been calculated by protocol specific mechanisms. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnRoundTripTimeUpdate( + RoundTripTimeUpdate) = 0; + // Called when a packet is sent on the network. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnSentPacket( + SentPacket) = 0; + // Called when a packet is received from the remote client. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnReceivedPacket( + ReceivedPacket) = 0; + // Called when the stream specific configuration has been updated. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnStreamsConfig( + StreamsConfig) = 0; + // Called when target transfer rate constraints has been changed. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnTargetRateConstraints( + TargetRateConstraints) = 0; + // Called when a protocol specific calculation of packet loss has been made. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnTransportLossReport( + TransportLossReport) = 0; + // Called with per packet feedback regarding receive time. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnTransportPacketsFeedback( + TransportPacketsFeedback) = 0; + // Called with network state estimate updates. + ABSL_MUST_USE_RESULT virtual NetworkControlUpdate OnNetworkStateEstimate( + NetworkStateEstimate) = 0; +}; + +// NetworkControllerFactoryInterface is an interface for creating a network +// controller. +class NetworkControllerFactoryInterface { + public: + virtual ~NetworkControllerFactoryInterface() = default; + + // Used to create a new network controller, requires an observer to be + // provided to handle callbacks. + virtual std::unique_ptr<NetworkControllerInterface> Create( + NetworkControllerConfig config) = 0; + // Returns the interval by which the network controller expects + // OnProcessInterval calls. + virtual TimeDelta GetProcessInterval() const = 0; +}; + +// Under development, subject to change without notice. +class NetworkStateEstimator { + public: + // Gets the current best estimate according to the estimator. + virtual absl::optional<NetworkStateEstimate> GetCurrentEstimate() = 0; + // Called with per packet feedback regarding receive time. + // Used when the NetworkStateEstimator runs in the sending endpoint. + virtual void OnTransportPacketsFeedback(const TransportPacketsFeedback&) = 0; + // Called with per packet feedback regarding receive time. + // Used when the NetworkStateEstimator runs in the receiving endpoint. + virtual void OnReceivedPacket(const PacketResult&) {} + // Called when the receiving or sending endpoint changes address. + virtual void OnRouteChange(const NetworkRouteChange&) = 0; + virtual ~NetworkStateEstimator() = default; +}; +class NetworkStateEstimatorFactory { + public: + virtual std::unique_ptr<NetworkStateEstimator> Create( + const FieldTrialsView* key_value_config) = 0; + virtual ~NetworkStateEstimatorFactory() = default; +}; +} // namespace webrtc + +#endif // API_TRANSPORT_NETWORK_CONTROL_H_ diff --git a/third_party/libwebrtc/api/transport/network_control_gn/moz.build b/third_party/libwebrtc/api/transport/network_control_gn/moz.build new file mode 100644 index 0000000000..181843597f --- /dev/null +++ b/third_party/libwebrtc/api/transport/network_control_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/transport/network_types.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("network_control_gn") diff --git a/third_party/libwebrtc/api/transport/network_types.cc b/third_party/libwebrtc/api/transport/network_types.cc new file mode 100644 index 0000000000..d6495ce490 --- /dev/null +++ b/third_party/libwebrtc/api/transport/network_types.cc @@ -0,0 +1,106 @@ +/* + * 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 "api/transport/network_types.h" + +#include <algorithm> + +namespace webrtc { +StreamsConfig::StreamsConfig() = default; +StreamsConfig::StreamsConfig(const StreamsConfig&) = default; +StreamsConfig::~StreamsConfig() = default; + +TargetRateConstraints::TargetRateConstraints() = default; +TargetRateConstraints::TargetRateConstraints(const TargetRateConstraints&) = + default; +TargetRateConstraints::~TargetRateConstraints() = default; + +NetworkRouteChange::NetworkRouteChange() = default; +NetworkRouteChange::NetworkRouteChange(const NetworkRouteChange&) = default; +NetworkRouteChange::~NetworkRouteChange() = default; + +PacketResult::PacketResult() = default; +PacketResult::PacketResult(const PacketResult& other) = default; +PacketResult::~PacketResult() = default; + +bool PacketResult::ReceiveTimeOrder::operator()(const PacketResult& lhs, + const PacketResult& rhs) { + if (lhs.receive_time != rhs.receive_time) + return lhs.receive_time < rhs.receive_time; + if (lhs.sent_packet.send_time != rhs.sent_packet.send_time) + return lhs.sent_packet.send_time < rhs.sent_packet.send_time; + return lhs.sent_packet.sequence_number < rhs.sent_packet.sequence_number; +} + +TransportPacketsFeedback::TransportPacketsFeedback() = default; +TransportPacketsFeedback::TransportPacketsFeedback( + const TransportPacketsFeedback& other) = default; +TransportPacketsFeedback::~TransportPacketsFeedback() = default; + +std::vector<PacketResult> TransportPacketsFeedback::ReceivedWithSendInfo() + const { + std::vector<PacketResult> res; + for (const PacketResult& fb : packet_feedbacks) { + if (fb.IsReceived()) { + res.push_back(fb); + } + } + return res; +} + +std::vector<PacketResult> TransportPacketsFeedback::LostWithSendInfo() const { + std::vector<PacketResult> res; + for (const PacketResult& fb : packet_feedbacks) { + if (!fb.IsReceived()) { + res.push_back(fb); + } + } + return res; +} + +std::vector<PacketResult> TransportPacketsFeedback::PacketsWithFeedback() + const { + return packet_feedbacks; +} + +std::vector<PacketResult> TransportPacketsFeedback::SortedByReceiveTime() + const { + std::vector<PacketResult> res; + for (const PacketResult& fb : packet_feedbacks) { + if (fb.IsReceived()) { + res.push_back(fb); + } + } + std::sort(res.begin(), res.end(), PacketResult::ReceiveTimeOrder()); + return res; +} + +NetworkControlUpdate::NetworkControlUpdate() = default; +NetworkControlUpdate::NetworkControlUpdate(const NetworkControlUpdate&) = + default; +NetworkControlUpdate::~NetworkControlUpdate() = default; + +PacedPacketInfo::PacedPacketInfo() = default; + +PacedPacketInfo::PacedPacketInfo(int probe_cluster_id, + int probe_cluster_min_probes, + int probe_cluster_min_bytes) + : probe_cluster_id(probe_cluster_id), + probe_cluster_min_probes(probe_cluster_min_probes), + probe_cluster_min_bytes(probe_cluster_min_bytes) {} + +bool PacedPacketInfo::operator==(const PacedPacketInfo& rhs) const { + return send_bitrate_bps == rhs.send_bitrate_bps && + probe_cluster_id == rhs.probe_cluster_id && + probe_cluster_min_probes == rhs.probe_cluster_min_probes && + probe_cluster_min_bytes == rhs.probe_cluster_min_bytes; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/transport/network_types.h b/third_party/libwebrtc/api/transport/network_types.h new file mode 100644 index 0000000000..29a7cf7705 --- /dev/null +++ b/third_party/libwebrtc/api/transport/network_types.h @@ -0,0 +1,278 @@ +/* + * 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. + */ + +#ifndef API_TRANSPORT_NETWORK_TYPES_H_ +#define API_TRANSPORT_NETWORK_TYPES_H_ +#include <stdint.h> + +#include <vector> + +#include "absl/types/optional.h" +#include "api/units/data_rate.h" +#include "api/units/data_size.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" + +namespace webrtc { + +// Configuration + +// Represents constraints and rates related to the currently enabled streams. +// This is used as input to the congestion controller via the StreamsConfig +// struct. +struct BitrateAllocationLimits { + // The total minimum send bitrate required by all sending streams. + DataRate min_allocatable_rate = DataRate::Zero(); + // The total maximum allocatable bitrate for all currently available streams. + DataRate max_allocatable_rate = DataRate::Zero(); + // The max bitrate to use for padding. The sum of the per-stream max padding + // rate. + DataRate max_padding_rate = DataRate::Zero(); +}; + +// Use StreamsConfig for information about streams that is required for specific +// adjustments to the algorithms in network controllers. Especially useful +// for experiments. +struct StreamsConfig { + StreamsConfig(); + StreamsConfig(const StreamsConfig&); + ~StreamsConfig(); + Timestamp at_time = Timestamp::PlusInfinity(); + absl::optional<bool> requests_alr_probing; + absl::optional<double> pacing_factor; + + // TODO(srte): Use BitrateAllocationLimits here. + absl::optional<DataRate> min_total_allocated_bitrate; + absl::optional<DataRate> max_padding_rate; + absl::optional<DataRate> max_total_allocated_bitrate; +}; + +struct TargetRateConstraints { + TargetRateConstraints(); + TargetRateConstraints(const TargetRateConstraints&); + ~TargetRateConstraints(); + Timestamp at_time = Timestamp::PlusInfinity(); + absl::optional<DataRate> min_data_rate; + absl::optional<DataRate> max_data_rate; + // The initial bandwidth estimate to base target rate on. This should be used + // as the basis for initial OnTargetTransferRate and OnPacerConfig callbacks. + absl::optional<DataRate> starting_rate; +}; + +// Send side information + +struct NetworkAvailability { + Timestamp at_time = Timestamp::PlusInfinity(); + bool network_available = false; +}; + +struct NetworkRouteChange { + NetworkRouteChange(); + NetworkRouteChange(const NetworkRouteChange&); + ~NetworkRouteChange(); + Timestamp at_time = Timestamp::PlusInfinity(); + // The TargetRateConstraints are set here so they can be changed synchronously + // when network route changes. + TargetRateConstraints constraints; +}; + +struct PacedPacketInfo { + PacedPacketInfo(); + PacedPacketInfo(int probe_cluster_id, + int probe_cluster_min_probes, + int probe_cluster_min_bytes); + + bool operator==(const PacedPacketInfo& rhs) const; + + // TODO(srte): Move probing info to a separate, optional struct. + static constexpr int kNotAProbe = -1; + int send_bitrate_bps = -1; + int probe_cluster_id = kNotAProbe; + int probe_cluster_min_probes = -1; + int probe_cluster_min_bytes = -1; + int probe_cluster_bytes_sent = 0; +}; + +struct SentPacket { + Timestamp send_time = Timestamp::PlusInfinity(); + // Size of packet with overhead up to IP layer. + DataSize size = DataSize::Zero(); + // Size of preceeding packets that are not part of feedback. + DataSize prior_unacked_data = DataSize::Zero(); + // Probe cluster id and parameters including bitrate, number of packets and + // number of bytes. + PacedPacketInfo pacing_info; + // True if the packet is an audio packet, false for video, padding, RTX etc. + bool audio = false; + // Transport independent sequence number, any tracked packet should have a + // sequence number that is unique over the whole call and increasing by 1 for + // each packet. + int64_t sequence_number; + // Tracked data in flight when the packet was sent, excluding unacked data. + DataSize data_in_flight = DataSize::Zero(); +}; + +struct ReceivedPacket { + Timestamp send_time = Timestamp::MinusInfinity(); + Timestamp receive_time = Timestamp::PlusInfinity(); + DataSize size = DataSize::Zero(); +}; + +// Transport level feedback + +struct RemoteBitrateReport { + Timestamp receive_time = Timestamp::PlusInfinity(); + DataRate bandwidth = DataRate::Infinity(); +}; + +struct RoundTripTimeUpdate { + Timestamp receive_time = Timestamp::PlusInfinity(); + TimeDelta round_trip_time = TimeDelta::PlusInfinity(); + bool smoothed = false; +}; + +struct TransportLossReport { + Timestamp receive_time = Timestamp::PlusInfinity(); + Timestamp start_time = Timestamp::PlusInfinity(); + Timestamp end_time = Timestamp::PlusInfinity(); + uint64_t packets_lost_delta = 0; + uint64_t packets_received_delta = 0; +}; + +// Packet level feedback + +struct PacketResult { + class ReceiveTimeOrder { + public: + bool operator()(const PacketResult& lhs, const PacketResult& rhs); + }; + + PacketResult(); + PacketResult(const PacketResult&); + ~PacketResult(); + + inline bool IsReceived() const { return !receive_time.IsPlusInfinity(); } + + SentPacket sent_packet; + Timestamp receive_time = Timestamp::PlusInfinity(); +}; + +struct TransportPacketsFeedback { + TransportPacketsFeedback(); + TransportPacketsFeedback(const TransportPacketsFeedback& other); + ~TransportPacketsFeedback(); + + Timestamp feedback_time = Timestamp::PlusInfinity(); + Timestamp first_unacked_send_time = Timestamp::PlusInfinity(); + DataSize data_in_flight = DataSize::Zero(); + DataSize prior_in_flight = DataSize::Zero(); + std::vector<PacketResult> packet_feedbacks; + + // Arrival times for messages without send time information. + std::vector<Timestamp> sendless_arrival_times; + + std::vector<PacketResult> ReceivedWithSendInfo() const; + std::vector<PacketResult> LostWithSendInfo() const; + std::vector<PacketResult> PacketsWithFeedback() const; + std::vector<PacketResult> SortedByReceiveTime() const; +}; + +// Network estimation + +struct NetworkEstimate { + Timestamp at_time = Timestamp::PlusInfinity(); + // Deprecated, use TargetTransferRate::target_rate instead. + DataRate bandwidth = DataRate::Infinity(); + TimeDelta round_trip_time = TimeDelta::PlusInfinity(); + TimeDelta bwe_period = TimeDelta::PlusInfinity(); + + float loss_rate_ratio = 0; +}; + +// Network control + +struct PacerConfig { + Timestamp at_time = Timestamp::PlusInfinity(); + // Pacer should send at most data_window data over time_window duration. + DataSize data_window = DataSize::Infinity(); + TimeDelta time_window = TimeDelta::PlusInfinity(); + // Pacer should send at least pad_window data over time_window duration. + DataSize pad_window = DataSize::Zero(); + DataRate data_rate() const { return data_window / time_window; } + DataRate pad_rate() const { return pad_window / time_window; } +}; + +struct ProbeClusterConfig { + Timestamp at_time = Timestamp::PlusInfinity(); + DataRate target_data_rate = DataRate::Zero(); + TimeDelta target_duration = TimeDelta::Zero(); + int32_t target_probe_count = 0; + int32_t id = 0; +}; + +struct TargetTransferRate { + Timestamp at_time = Timestamp::PlusInfinity(); + // The estimate on which the target rate is based on. + NetworkEstimate network_estimate; + DataRate target_rate = DataRate::Zero(); + DataRate stable_target_rate = DataRate::Zero(); + double cwnd_reduce_ratio = 0; +}; + +// Contains updates of network controller comand state. Using optionals to +// indicate whether a member has been updated. The array of probe clusters +// should be used to send out probes if not empty. +struct NetworkControlUpdate { + NetworkControlUpdate(); + NetworkControlUpdate(const NetworkControlUpdate&); + ~NetworkControlUpdate(); + absl::optional<DataSize> congestion_window; + absl::optional<PacerConfig> pacer_config; + std::vector<ProbeClusterConfig> probe_cluster_configs; + absl::optional<TargetTransferRate> target_rate; +}; + +// Process control +struct ProcessInterval { + Timestamp at_time = Timestamp::PlusInfinity(); + absl::optional<DataSize> pacer_queue; +}; + +// Under development, subject to change without notice. +struct NetworkStateEstimate { + double confidence = NAN; + // The time the estimate was received/calculated. + Timestamp update_time = Timestamp::MinusInfinity(); + Timestamp last_receive_time = Timestamp::MinusInfinity(); + Timestamp last_send_time = Timestamp::MinusInfinity(); + + // Total estimated link capacity. + DataRate link_capacity = DataRate::MinusInfinity(); + // Used as a safe measure of available capacity. + DataRate link_capacity_lower = DataRate::MinusInfinity(); + // Used as limit for increasing bitrate. + DataRate link_capacity_upper = DataRate::MinusInfinity(); + + TimeDelta pre_link_buffer_delay = TimeDelta::MinusInfinity(); + TimeDelta post_link_buffer_delay = TimeDelta::MinusInfinity(); + TimeDelta propagation_delay = TimeDelta::MinusInfinity(); + + // Only for debugging + TimeDelta time_delta = TimeDelta::MinusInfinity(); + Timestamp last_feed_time = Timestamp::MinusInfinity(); + double cross_delay_rate = NAN; + double spike_delay_rate = NAN; + DataRate link_capacity_std_dev = DataRate::MinusInfinity(); + DataRate link_capacity_min = DataRate::MinusInfinity(); + double cross_traffic_ratio = NAN; +}; +} // namespace webrtc + +#endif // API_TRANSPORT_NETWORK_TYPES_H_ diff --git a/third_party/libwebrtc/api/transport/rtp/BUILD.gn b/third_party/libwebrtc/api/transport/rtp/BUILD.gn new file mode 100644 index 0000000000..205bbcc988 --- /dev/null +++ b/third_party/libwebrtc/api/transport/rtp/BUILD.gn @@ -0,0 +1,37 @@ +# Copyright (c) 2019 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") + +rtc_source_set("rtp_source") { + visibility = [ "*" ] + sources = [ "rtp_source.h" ] + deps = [ + "../../../api:rtp_headers", + "../../../api/units:time_delta", + "../../../rtc_base:checks", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_source_set("dependency_descriptor") { + visibility = [ "*" ] + sources = [ + "dependency_descriptor.cc", + "dependency_descriptor.h", + ] + deps = [ + "../../../rtc_base:checks", + "../../video:render_resolution", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/container:inlined_vector", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} diff --git a/third_party/libwebrtc/api/transport/rtp/dependency_descriptor.cc b/third_party/libwebrtc/api/transport/rtp/dependency_descriptor.cc new file mode 100644 index 0000000000..e784853cd6 --- /dev/null +++ b/third_party/libwebrtc/api/transport/rtp/dependency_descriptor.cc @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020 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 "api/transport/rtp/dependency_descriptor.h" + +#include "absl/container/inlined_vector.h" +#include "absl/strings/string_view.h" +#include "rtc_base/checks.h" + +namespace webrtc { + +constexpr int DependencyDescriptor::kMaxSpatialIds; +constexpr int DependencyDescriptor::kMaxTemporalIds; +constexpr int DependencyDescriptor::kMaxTemplates; +constexpr int DependencyDescriptor::kMaxDecodeTargets; + +namespace webrtc_impl { + +absl::InlinedVector<DecodeTargetIndication, 10> StringToDecodeTargetIndications( + absl::string_view symbols) { + absl::InlinedVector<DecodeTargetIndication, 10> dtis; + dtis.reserve(symbols.size()); + for (char symbol : symbols) { + DecodeTargetIndication indication; + switch (symbol) { + case '-': + indication = DecodeTargetIndication::kNotPresent; + break; + case 'D': + indication = DecodeTargetIndication::kDiscardable; + break; + case 'R': + indication = DecodeTargetIndication::kRequired; + break; + case 'S': + indication = DecodeTargetIndication::kSwitch; + break; + default: + RTC_DCHECK_NOTREACHED(); + } + dtis.push_back(indication); + } + return dtis; +} + +} // namespace webrtc_impl +} // namespace webrtc diff --git a/third_party/libwebrtc/api/transport/rtp/dependency_descriptor.h b/third_party/libwebrtc/api/transport/rtp/dependency_descriptor.h new file mode 100644 index 0000000000..0db600918e --- /dev/null +++ b/third_party/libwebrtc/api/transport/rtp/dependency_descriptor.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2020 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 API_TRANSPORT_RTP_DEPENDENCY_DESCRIPTOR_H_ +#define API_TRANSPORT_RTP_DEPENDENCY_DESCRIPTOR_H_ + +#include <stdint.h> + +#include <initializer_list> +#include <memory> +#include <vector> + +#include "absl/container/inlined_vector.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/video/render_resolution.h" + +namespace webrtc { +// Structures to build and parse dependency descriptor as described in +// https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension + +// Relationship of a frame to a Decode target. +enum class DecodeTargetIndication { + kNotPresent = 0, // DecodeTargetInfo symbol '-' + kDiscardable = 1, // DecodeTargetInfo symbol 'D' + kSwitch = 2, // DecodeTargetInfo symbol 'S' + kRequired = 3 // DecodeTargetInfo symbol 'R' +}; + +struct FrameDependencyTemplate { + // Setters are named briefly to chain them when building the template. + FrameDependencyTemplate& S(int spatial_layer); + FrameDependencyTemplate& T(int temporal_layer); + FrameDependencyTemplate& Dtis(absl::string_view dtis); + FrameDependencyTemplate& FrameDiffs(std::initializer_list<int> diffs); + FrameDependencyTemplate& ChainDiffs(std::initializer_list<int> diffs); + + friend bool operator==(const FrameDependencyTemplate& lhs, + const FrameDependencyTemplate& rhs) { + return lhs.spatial_id == rhs.spatial_id && + lhs.temporal_id == rhs.temporal_id && + lhs.decode_target_indications == rhs.decode_target_indications && + lhs.frame_diffs == rhs.frame_diffs && + lhs.chain_diffs == rhs.chain_diffs; + } + + int spatial_id = 0; + int temporal_id = 0; + absl::InlinedVector<DecodeTargetIndication, 10> decode_target_indications; + absl::InlinedVector<int, 4> frame_diffs; + absl::InlinedVector<int, 4> chain_diffs; +}; + +struct FrameDependencyStructure { + friend bool operator==(const FrameDependencyStructure& lhs, + const FrameDependencyStructure& rhs) { + return lhs.num_decode_targets == rhs.num_decode_targets && + lhs.num_chains == rhs.num_chains && + lhs.decode_target_protected_by_chain == + rhs.decode_target_protected_by_chain && + lhs.resolutions == rhs.resolutions && lhs.templates == rhs.templates; + } + + int structure_id = 0; + int num_decode_targets = 0; + int num_chains = 0; + // If chains are used (num_chains > 0), maps decode target index into index of + // the chain protecting that target. + absl::InlinedVector<int, 10> decode_target_protected_by_chain; + absl::InlinedVector<RenderResolution, 4> resolutions; + std::vector<FrameDependencyTemplate> templates; +}; + +struct DependencyDescriptor { + static constexpr int kMaxSpatialIds = 4; + static constexpr int kMaxTemporalIds = 8; + static constexpr int kMaxDecodeTargets = 32; + static constexpr int kMaxTemplates = 64; + + bool first_packet_in_frame = true; + bool last_packet_in_frame = true; + int frame_number = 0; + FrameDependencyTemplate frame_dependencies; + absl::optional<RenderResolution> resolution; + absl::optional<uint32_t> active_decode_targets_bitmask; + std::unique_ptr<FrameDependencyStructure> attached_structure; +}; + +// Below are implementation details. +namespace webrtc_impl { +absl::InlinedVector<DecodeTargetIndication, 10> StringToDecodeTargetIndications( + absl::string_view indication_symbols); +} // namespace webrtc_impl + +inline FrameDependencyTemplate& FrameDependencyTemplate::S(int spatial_layer) { + this->spatial_id = spatial_layer; + return *this; +} +inline FrameDependencyTemplate& FrameDependencyTemplate::T(int temporal_layer) { + this->temporal_id = temporal_layer; + return *this; +} +inline FrameDependencyTemplate& FrameDependencyTemplate::Dtis( + absl::string_view dtis) { + this->decode_target_indications = + webrtc_impl::StringToDecodeTargetIndications(dtis); + return *this; +} +inline FrameDependencyTemplate& FrameDependencyTemplate::FrameDiffs( + std::initializer_list<int> diffs) { + this->frame_diffs.assign(diffs.begin(), diffs.end()); + return *this; +} +inline FrameDependencyTemplate& FrameDependencyTemplate::ChainDiffs( + std::initializer_list<int> diffs) { + this->chain_diffs.assign(diffs.begin(), diffs.end()); + return *this; +} + +} // namespace webrtc + +#endif // API_TRANSPORT_RTP_DEPENDENCY_DESCRIPTOR_H_ diff --git a/third_party/libwebrtc/api/transport/rtp/dependency_descriptor_gn/moz.build b/third_party/libwebrtc/api/transport/rtp/dependency_descriptor_gn/moz.build new file mode 100644 index 0000000000..0ee9e1fa1b --- /dev/null +++ b/third_party/libwebrtc/api/transport/rtp/dependency_descriptor_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/transport/rtp/dependency_descriptor.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("dependency_descriptor_gn") diff --git a/third_party/libwebrtc/api/transport/rtp/rtp_source.h b/third_party/libwebrtc/api/transport/rtp/rtp_source.h new file mode 100644 index 0000000000..e51dcd70b6 --- /dev/null +++ b/third_party/libwebrtc/api/transport/rtp/rtp_source.h @@ -0,0 +1,111 @@ +/* + * Copyright 2019 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 API_TRANSPORT_RTP_RTP_SOURCE_H_ +#define API_TRANSPORT_RTP_RTP_SOURCE_H_ + +#include <stdint.h> + +#include "absl/types/optional.h" +#include "api/rtp_headers.h" +#include "api/units/time_delta.h" +#include "rtc_base/checks.h" + +namespace webrtc { + +enum class RtpSourceType { + SSRC, + CSRC, +}; + +class RtpSource { + public: + struct Extensions { + absl::optional<uint8_t> audio_level; + + // Fields from the Absolute Capture Time header extension: + // http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time + absl::optional<AbsoluteCaptureTime> absolute_capture_time; + + // Clock offset between the local clock and the capturer's clock. + // Do not confuse with `AbsoluteCaptureTime::estimated_capture_clock_offset` + // which instead represents the clock offset between a remote sender and the + // capturer. The following holds: + // Capture's NTP Clock = Local NTP Clock + Local-Capture Clock Offset + absl::optional<TimeDelta> local_capture_clock_offset; + }; + + RtpSource() = delete; + + RtpSource(int64_t timestamp_ms, + uint32_t source_id, + RtpSourceType source_type, + uint32_t rtp_timestamp, + const RtpSource::Extensions& extensions) + : timestamp_ms_(timestamp_ms), + source_id_(source_id), + source_type_(source_type), + extensions_(extensions), + rtp_timestamp_(rtp_timestamp) {} + + RtpSource(const RtpSource&) = default; + RtpSource& operator=(const RtpSource&) = default; + ~RtpSource() = default; + + int64_t timestamp_ms() const { return timestamp_ms_; } + void update_timestamp_ms(int64_t timestamp_ms) { + RTC_DCHECK_LE(timestamp_ms_, timestamp_ms); + timestamp_ms_ = timestamp_ms; + } + + // The identifier of the source can be the CSRC or the SSRC. + uint32_t source_id() const { return source_id_; } + + // The source can be either a contributing source or a synchronization source. + RtpSourceType source_type() const { return source_type_; } + + absl::optional<uint8_t> audio_level() const { + return extensions_.audio_level; + } + + void set_audio_level(const absl::optional<uint8_t>& level) { + extensions_.audio_level = level; + } + + uint32_t rtp_timestamp() const { return rtp_timestamp_; } + + absl::optional<AbsoluteCaptureTime> absolute_capture_time() const { + return extensions_.absolute_capture_time; + } + + absl::optional<TimeDelta> local_capture_clock_offset() const { + return extensions_.local_capture_clock_offset; + } + + bool operator==(const RtpSource& o) const { + return timestamp_ms_ == o.timestamp_ms() && source_id_ == o.source_id() && + source_type_ == o.source_type() && + extensions_.audio_level == o.extensions_.audio_level && + extensions_.absolute_capture_time == + o.extensions_.absolute_capture_time && + rtp_timestamp_ == o.rtp_timestamp(); + } + + private: + int64_t timestamp_ms_; + uint32_t source_id_; + RtpSourceType source_type_; + RtpSource::Extensions extensions_; + uint32_t rtp_timestamp_; +}; + +} // namespace webrtc + +#endif // API_TRANSPORT_RTP_RTP_SOURCE_H_ diff --git a/third_party/libwebrtc/api/transport/rtp/rtp_source_gn/moz.build b/third_party/libwebrtc/api/transport/rtp/rtp_source_gn/moz.build new file mode 100644 index 0000000000..b43f4a77ec --- /dev/null +++ b/third_party/libwebrtc/api/transport/rtp/rtp_source_gn/moz.build @@ -0,0 +1,209 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rtp_source_gn") diff --git a/third_party/libwebrtc/api/transport/sctp_transport_factory_interface.h b/third_party/libwebrtc/api/transport/sctp_transport_factory_interface.h new file mode 100644 index 0000000000..4fc8af5bad --- /dev/null +++ b/third_party/libwebrtc/api/transport/sctp_transport_factory_interface.h @@ -0,0 +1,42 @@ +/* + * Copyright 2020 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 API_TRANSPORT_SCTP_TRANSPORT_FACTORY_INTERFACE_H_ +#define API_TRANSPORT_SCTP_TRANSPORT_FACTORY_INTERFACE_H_ + +#include <memory> + +// These classes are not part of the API, and are treated as opaque pointers. +namespace cricket { +class SctpTransportInternal; +} // namespace cricket + +namespace rtc { +class PacketTransportInternal; +} // namespace rtc + +namespace webrtc { + +// Factory class which can be used to allow fake SctpTransports to be injected +// for testing. An application is not intended to implement this interface nor +// 'cricket::SctpTransportInternal' because SctpTransportInternal is not +// guaranteed to remain stable in future WebRTC versions. +class SctpTransportFactoryInterface { + public: + virtual ~SctpTransportFactoryInterface() = default; + + // Create an SCTP transport using `channel` for the underlying transport. + virtual std::unique_ptr<cricket::SctpTransportInternal> CreateSctpTransport( + rtc::PacketTransportInternal* channel) = 0; +}; + +} // namespace webrtc + +#endif // API_TRANSPORT_SCTP_TRANSPORT_FACTORY_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/transport/stun.cc b/third_party/libwebrtc/api/transport/stun.cc new file mode 100644 index 0000000000..1098c6720e --- /dev/null +++ b/third_party/libwebrtc/api/transport/stun.cc @@ -0,0 +1,1515 @@ +/* + * Copyright 2004 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 "api/transport/stun.h" + +#include <string.h> + +#include <algorithm> +#include <cstdint> +#include <iterator> +#include <memory> +#include <utility> + +#include "rtc_base/byte_order.h" +#include "rtc_base/checks.h" +#include "rtc_base/crc32.h" +#include "rtc_base/helpers.h" +#include "rtc_base/logging.h" +#include "rtc_base/message_digest.h" +#include "system_wrappers/include/metrics.h" + +using rtc::ByteBufferReader; +using rtc::ByteBufferWriter; + +namespace cricket { + +namespace { + +const int k127Utf8CharactersLengthInBytes = 508; +const int kMessageIntegrityAttributeLength = 20; +const int kTheoreticalMaximumAttributeLength = 65535; + +uint32_t ReduceTransactionId(absl::string_view transaction_id) { + RTC_DCHECK(transaction_id.length() == cricket::kStunTransactionIdLength || + transaction_id.length() == cricket::kStunLegacyTransactionIdLength) + << transaction_id.length(); + ByteBufferReader reader(transaction_id.data(), transaction_id.size()); + uint32_t result = 0; + uint32_t next; + while (reader.ReadUInt32(&next)) { + result ^= next; + } + return result; +} + +// Check the maximum length of a BYTE_STRING attribute against specifications. +bool LengthValid(int type, int length) { + // "Less than 509 bytes" is intended to indicate a maximum of 127 + // UTF-8 characters, which may take up to 4 bytes per character. + switch (type) { + case STUN_ATTR_USERNAME: + return length <= + k127Utf8CharactersLengthInBytes; // RFC 8489 section 14.3 + case STUN_ATTR_MESSAGE_INTEGRITY: + return length == + kMessageIntegrityAttributeLength; // RFC 8489 section 14.5 + case STUN_ATTR_REALM: + return length <= + k127Utf8CharactersLengthInBytes; // RFC 8489 section 14.9 + case STUN_ATTR_NONCE: + return length <= + k127Utf8CharactersLengthInBytes; // RFC 8489 section 14.10 + case STUN_ATTR_SOFTWARE: + return length <= + k127Utf8CharactersLengthInBytes; // RFC 8489 section 14.14 + case STUN_ATTR_DATA: + // No length restriction in RFC; it's the content of an UDP datagram, + // which in theory can be up to 65.535 bytes. + // TODO(bugs.webrtc.org/12179): Write a test to find the real limit. + return length <= kTheoreticalMaximumAttributeLength; + default: + // Return an arbitrary restriction for all other types. + return length <= kTheoreticalMaximumAttributeLength; + } + RTC_DCHECK_NOTREACHED(); + return true; +} + +} // namespace + +const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[] = "Try Alternate Server"; +const char STUN_ERROR_REASON_BAD_REQUEST[] = "Bad Request"; +const char STUN_ERROR_REASON_UNAUTHORIZED[] = "Unauthorized"; +const char STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE[] = "Unknown Attribute"; +const char STUN_ERROR_REASON_FORBIDDEN[] = "Forbidden"; +const char STUN_ERROR_REASON_ALLOCATION_MISMATCH[] = "Allocation Mismatch"; +const char STUN_ERROR_REASON_STALE_NONCE[] = "Stale Nonce"; +const char STUN_ERROR_REASON_WRONG_CREDENTIALS[] = "Wrong Credentials"; +const char STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL[] = "Unsupported Protocol"; +const char STUN_ERROR_REASON_ROLE_CONFLICT[] = "Role Conflict"; +const char STUN_ERROR_REASON_SERVER_ERROR[] = "Server Error"; + +const char TURN_MAGIC_COOKIE_VALUE[] = {'\x72', '\xC6', '\x4B', '\xC6'}; +const char EMPTY_TRANSACTION_ID[] = "0000000000000000"; +const uint32_t STUN_FINGERPRINT_XOR_VALUE = 0x5354554E; +const int SERVER_NOT_REACHABLE_ERROR = 701; + +// StunMessage + +StunMessage::StunMessage() + : StunMessage(STUN_INVALID_MESSAGE_TYPE, EMPTY_TRANSACTION_ID) {} + +StunMessage::StunMessage(uint16_t type) + : StunMessage(type, GenerateTransactionId()) {} + +StunMessage::StunMessage(uint16_t type, absl::string_view transaction_id) + : type_(type), + transaction_id_(transaction_id), + reduced_transaction_id_(ReduceTransactionId(transaction_id_)) { + RTC_DCHECK(IsValidTransactionId(transaction_id_)); +} + +StunMessage::~StunMessage() = default; + +bool StunMessage::IsLegacy() const { + if (transaction_id_.size() == kStunLegacyTransactionIdLength) + return true; + RTC_DCHECK(transaction_id_.size() == kStunTransactionIdLength); + return false; +} + +static bool DesignatedExpertRange(int attr_type) { + return (attr_type >= 0x4000 && attr_type <= 0x7FFF) || + (attr_type >= 0xC000 && attr_type <= 0xFFFF); +} + +void StunMessage::AddAttribute(std::unique_ptr<StunAttribute> attr) { + // Fail any attributes that aren't valid for this type of message, + // but allow any type for the range that in the RFC is reserved for + // the "designated experts". + if (!DesignatedExpertRange(attr->type())) { + RTC_DCHECK_EQ(attr->value_type(), GetAttributeValueType(attr->type())); + } + + attr->SetOwner(this); + size_t attr_length = attr->length(); + if (attr_length % 4 != 0) { + attr_length += (4 - (attr_length % 4)); + } + length_ += static_cast<uint16_t>(attr_length + 4); + + attrs_.push_back(std::move(attr)); +} + +std::unique_ptr<StunAttribute> StunMessage::RemoveAttribute(int type) { + std::unique_ptr<StunAttribute> attribute; + for (auto it = attrs_.rbegin(); it != attrs_.rend(); ++it) { + if ((*it)->type() == type) { + attribute = std::move(*it); + attrs_.erase(std::next(it).base()); + break; + } + } + if (attribute) { + attribute->SetOwner(nullptr); + size_t attr_length = attribute->length(); + if (attr_length % 4 != 0) { + attr_length += (4 - (attr_length % 4)); + } + length_ -= static_cast<uint16_t>(attr_length + 4); + } + return attribute; +} + +void StunMessage::ClearAttributes() { + for (auto it = attrs_.rbegin(); it != attrs_.rend(); ++it) { + (*it)->SetOwner(nullptr); + } + attrs_.clear(); + length_ = 0; +} + +std::vector<uint16_t> StunMessage::GetNonComprehendedAttributes() const { + std::vector<uint16_t> unknown_attributes; + for (auto& attr : attrs_) { + // "comprehension-required" range is 0x0000-0x7FFF. + if (attr->type() >= 0x0000 && attr->type() <= 0x7FFF && + GetAttributeValueType(attr->type()) == STUN_VALUE_UNKNOWN) { + unknown_attributes.push_back(attr->type()); + } + } + return unknown_attributes; +} + +const StunAddressAttribute* StunMessage::GetAddress(int type) const { + switch (type) { + case STUN_ATTR_MAPPED_ADDRESS: { + // Return XOR-MAPPED-ADDRESS when MAPPED-ADDRESS attribute is + // missing. + const StunAttribute* mapped_address = + GetAttribute(STUN_ATTR_MAPPED_ADDRESS); + if (!mapped_address) + mapped_address = GetAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS); + return reinterpret_cast<const StunAddressAttribute*>(mapped_address); + } + + default: + return static_cast<const StunAddressAttribute*>(GetAttribute(type)); + } +} + +const StunUInt32Attribute* StunMessage::GetUInt32(int type) const { + return static_cast<const StunUInt32Attribute*>(GetAttribute(type)); +} + +const StunUInt64Attribute* StunMessage::GetUInt64(int type) const { + return static_cast<const StunUInt64Attribute*>(GetAttribute(type)); +} + +const StunByteStringAttribute* StunMessage::GetByteString(int type) const { + return static_cast<const StunByteStringAttribute*>(GetAttribute(type)); +} + +const StunUInt16ListAttribute* StunMessage::GetUInt16List(int type) const { + return static_cast<const StunUInt16ListAttribute*>(GetAttribute(type)); +} + +const StunErrorCodeAttribute* StunMessage::GetErrorCode() const { + return static_cast<const StunErrorCodeAttribute*>( + GetAttribute(STUN_ATTR_ERROR_CODE)); +} + +int StunMessage::GetErrorCodeValue() const { + const StunErrorCodeAttribute* error_attribute = GetErrorCode(); + return error_attribute ? error_attribute->code() : STUN_ERROR_GLOBAL_FAILURE; +} + +const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const { + return static_cast<const StunUInt16ListAttribute*>( + GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES)); +} + +StunMessage::IntegrityStatus StunMessage::ValidateMessageIntegrity( + const std::string& password) { + RTC_DCHECK(integrity_ == IntegrityStatus::kNotSet) + << "Usage error: Verification should only be done once"; + password_ = password; + if (GetByteString(STUN_ATTR_MESSAGE_INTEGRITY)) { + if (ValidateMessageIntegrityOfType( + STUN_ATTR_MESSAGE_INTEGRITY, kStunMessageIntegritySize, + buffer_.c_str(), buffer_.size(), password)) { + integrity_ = IntegrityStatus::kIntegrityOk; + } else { + integrity_ = IntegrityStatus::kIntegrityBad; + } + } else if (GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32)) { + if (ValidateMessageIntegrityOfType( + STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32, kStunMessageIntegrity32Size, + buffer_.c_str(), buffer_.size(), password)) { + integrity_ = IntegrityStatus::kIntegrityOk; + } else { + integrity_ = IntegrityStatus::kIntegrityBad; + } + } else { + integrity_ = IntegrityStatus::kNoIntegrity; + } + // Log the result of integrity checking. See crbug.com/1177125 for background. + // Convert args to integer for the benefit of the macros. + int bucket_count = static_cast<int>(IntegrityStatus::kMaxValue) + 1; + int integrity = static_cast<int>(integrity_); + if (IsStunRequestType(type_)) { + RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Request", integrity, + bucket_count); + } else if (IsStunSuccessResponseType(type_)) { + RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Response", integrity, + bucket_count); + } else if (IsStunIndicationType(type_)) { + RTC_HISTOGRAM_ENUMERATION("WebRTC.Stun.Integrity.Indication", integrity, + bucket_count); + } else { + RTC_DCHECK(IsStunErrorResponseType(type_)); + auto* error_attribute = GetErrorCode(); + if (!error_attribute) { + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.NoErrorAttribute", integrity, + bucket_count); + } else { + switch (error_attribute->code()) { + case STUN_ERROR_TRY_ALTERNATE: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.TryAlternate", integrity, + bucket_count); + break; + case STUN_ERROR_BAD_REQUEST: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.BadRequest", integrity, + bucket_count); + break; + case STUN_ERROR_UNAUTHORIZED: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.Unauthorized", integrity, + bucket_count); + break; + case STUN_ERROR_UNKNOWN_ATTRIBUTE: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.UnknownAttribute", integrity, + bucket_count); + break; + case STUN_ERROR_STALE_NONCE: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.StaleNonce", integrity, + bucket_count); + break; + case STUN_ERROR_SERVER_ERROR: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.ServerError", integrity, + bucket_count); + break; + case STUN_ERROR_GLOBAL_FAILURE: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.GlobalFailure", integrity, + bucket_count); + break; + default: + RTC_HISTOGRAM_ENUMERATION( + "WebRTC.Stun.Integrity.ErrorResponse.ErrorOther", integrity, + bucket_count); + break; + } + } + } + return integrity_; +} + +StunMessage::IntegrityStatus StunMessage::RevalidateMessageIntegrity( + const std::string& password) { + RTC_LOG(LS_INFO) << "Message revalidation, old status was " + << static_cast<int>(integrity_); + integrity_ = IntegrityStatus::kNotSet; + return ValidateMessageIntegrity(password); +} + +bool StunMessage::ValidateMessageIntegrityForTesting( + const char* data, + size_t size, + const std::string& password) { + return ValidateMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY, + kStunMessageIntegritySize, data, size, + password); +} + +bool StunMessage::ValidateMessageIntegrity32ForTesting( + const char* data, + size_t size, + const std::string& password) { + return ValidateMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32, + kStunMessageIntegrity32Size, data, size, + password); +} + +// Deprecated +bool StunMessage::ValidateMessageIntegrity(const char* data, + size_t size, + const std::string& password) { + return ValidateMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY, + kStunMessageIntegritySize, data, size, + password); +} + +// Deprecated +bool StunMessage::ValidateMessageIntegrity32(const char* data, + size_t size, + const std::string& password) { + return ValidateMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32, + kStunMessageIntegrity32Size, data, size, + password); +} + +// Verifies a STUN message has a valid MESSAGE-INTEGRITY attribute, using the +// procedure outlined in RFC 5389, section 15.4. +bool StunMessage::ValidateMessageIntegrityOfType(int mi_attr_type, + size_t mi_attr_size, + const char* data, + size_t size, + const std::string& password) { + RTC_DCHECK(mi_attr_size <= kStunMessageIntegritySize); + + // Verifying the size of the message. + if ((size % 4) != 0 || size < kStunHeaderSize) { + return false; + } + + // Getting the message length from the STUN header. + uint16_t msg_length = rtc::GetBE16(&data[2]); + if (size != (msg_length + kStunHeaderSize)) { + return false; + } + + // Finding Message Integrity attribute in stun message. + size_t current_pos = kStunHeaderSize; + bool has_message_integrity_attr = false; + while (current_pos + 4 <= size) { + uint16_t attr_type, attr_length; + // Getting attribute type and length. + attr_type = rtc::GetBE16(&data[current_pos]); + attr_length = rtc::GetBE16(&data[current_pos + sizeof(attr_type)]); + + // If M-I, sanity check it, and break out. + if (attr_type == mi_attr_type) { + if (attr_length != mi_attr_size || + current_pos + sizeof(attr_type) + sizeof(attr_length) + attr_length > + size) { + return false; + } + has_message_integrity_attr = true; + break; + } + + // Otherwise, skip to the next attribute. + current_pos += sizeof(attr_type) + sizeof(attr_length) + attr_length; + if ((attr_length % 4) != 0) { + current_pos += (4 - (attr_length % 4)); + } + } + + if (!has_message_integrity_attr) { + return false; + } + + // Getting length of the message to calculate Message Integrity. + size_t mi_pos = current_pos; + std::unique_ptr<char[]> temp_data(new char[current_pos]); + memcpy(temp_data.get(), data, current_pos); + if (size > mi_pos + kStunAttributeHeaderSize + mi_attr_size) { + // Stun message has other attributes after message integrity. + // Adjust the length parameter in stun message to calculate HMAC. + size_t extra_offset = + size - (mi_pos + kStunAttributeHeaderSize + mi_attr_size); + size_t new_adjusted_len = size - extra_offset - kStunHeaderSize; + + // Writing new length of the STUN message @ Message Length in temp buffer. + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |0 0| STUN Message Type | Message Length | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + rtc::SetBE16(temp_data.get() + 2, static_cast<uint16_t>(new_adjusted_len)); + } + + char hmac[kStunMessageIntegritySize]; + size_t ret = + rtc::ComputeHmac(rtc::DIGEST_SHA_1, password.c_str(), password.size(), + temp_data.get(), mi_pos, hmac, sizeof(hmac)); + RTC_DCHECK(ret == sizeof(hmac)); + if (ret != sizeof(hmac)) { + return false; + } + + // Comparing the calculated HMAC with the one present in the message. + return memcmp(data + current_pos + kStunAttributeHeaderSize, hmac, + mi_attr_size) == 0; +} + +bool StunMessage::AddMessageIntegrity(absl::string_view password) { + return AddMessageIntegrityOfType(STUN_ATTR_MESSAGE_INTEGRITY, + kStunMessageIntegritySize, password); +} + +bool StunMessage::AddMessageIntegrity32(absl::string_view password) { + return AddMessageIntegrityOfType(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32, + kStunMessageIntegrity32Size, password); +} + +bool StunMessage::AddMessageIntegrityOfType(int attr_type, + size_t attr_size, + absl::string_view key) { + // Add the attribute with a dummy value. Since this is a known attribute, it + // can't fail. + RTC_DCHECK(attr_size <= kStunMessageIntegritySize); + auto msg_integrity_attr_ptr = std::make_unique<StunByteStringAttribute>( + attr_type, std::string(attr_size, '0')); + auto* msg_integrity_attr = msg_integrity_attr_ptr.get(); + AddAttribute(std::move(msg_integrity_attr_ptr)); + + // Calculate the HMAC for the message. + ByteBufferWriter buf; + if (!Write(&buf)) + return false; + + int msg_len_for_hmac = static_cast<int>( + buf.Length() - kStunAttributeHeaderSize - msg_integrity_attr->length()); + char hmac[kStunMessageIntegritySize]; + size_t ret = + rtc::ComputeHmac(rtc::DIGEST_SHA_1, key.data(), key.size(), buf.Data(), + msg_len_for_hmac, hmac, sizeof(hmac)); + RTC_DCHECK(ret == sizeof(hmac)); + if (ret != sizeof(hmac)) { + RTC_LOG(LS_ERROR) << "HMAC computation failed. Message-Integrity " + "has dummy value."; + return false; + } + + // Insert correct HMAC into the attribute. + msg_integrity_attr->CopyBytes(hmac, attr_size); + password_ = std::string(key); + integrity_ = IntegrityStatus::kIntegrityOk; + return true; +} + +// Verifies a message is in fact a STUN message, by performing the checks +// outlined in RFC 5389, section 7.3, including the FINGERPRINT check detailed +// in section 15.5. +bool StunMessage::ValidateFingerprint(const char* data, size_t size) { + // Check the message length. + size_t fingerprint_attr_size = + kStunAttributeHeaderSize + StunUInt32Attribute::SIZE; + if (size % 4 != 0 || size < kStunHeaderSize + fingerprint_attr_size) + return false; + + // Skip the rest if the magic cookie isn't present. + const char* magic_cookie = + data + kStunTransactionIdOffset - kStunMagicCookieLength; + if (rtc::GetBE32(magic_cookie) != kStunMagicCookie) + return false; + + // Check the fingerprint type and length. + const char* fingerprint_attr_data = data + size - fingerprint_attr_size; + if (rtc::GetBE16(fingerprint_attr_data) != STUN_ATTR_FINGERPRINT || + rtc::GetBE16(fingerprint_attr_data + sizeof(uint16_t)) != + StunUInt32Attribute::SIZE) + return false; + + // Check the fingerprint value. + uint32_t fingerprint = + rtc::GetBE32(fingerprint_attr_data + kStunAttributeHeaderSize); + return ((fingerprint ^ STUN_FINGERPRINT_XOR_VALUE) == + rtc::ComputeCrc32(data, size - fingerprint_attr_size)); +} + +// static +std::string StunMessage::GenerateTransactionId() { + return rtc::CreateRandomString(kStunTransactionIdLength); +} + +bool StunMessage::IsStunMethod(rtc::ArrayView<int> methods, + const char* data, + size_t size) { + // Check the message length. + if (size % 4 != 0 || size < kStunHeaderSize) + return false; + + // Skip the rest if the magic cookie isn't present. + const char* magic_cookie = + data + kStunTransactionIdOffset - kStunMagicCookieLength; + if (rtc::GetBE32(magic_cookie) != kStunMagicCookie) + return false; + + int method = rtc::GetBE16(data); + for (int m : methods) { + if (m == method) { + return true; + } + } + return false; +} + +bool StunMessage::AddFingerprint() { + // Add the attribute with a dummy value. Since this is a known attribute, + // it can't fail. + auto fingerprint_attr_ptr = + std::make_unique<StunUInt32Attribute>(STUN_ATTR_FINGERPRINT, 0); + auto* fingerprint_attr = fingerprint_attr_ptr.get(); + AddAttribute(std::move(fingerprint_attr_ptr)); + + // Calculate the CRC-32 for the message and insert it. + ByteBufferWriter buf; + if (!Write(&buf)) + return false; + + int msg_len_for_crc32 = static_cast<int>( + buf.Length() - kStunAttributeHeaderSize - fingerprint_attr->length()); + uint32_t c = rtc::ComputeCrc32(buf.Data(), msg_len_for_crc32); + + // Insert the correct CRC-32, XORed with a constant, into the attribute. + fingerprint_attr->SetValue(c ^ STUN_FINGERPRINT_XOR_VALUE); + return true; +} + +bool StunMessage::Read(ByteBufferReader* buf) { + // Keep a copy of the buffer data around for later verification. + buffer_.assign(buf->Data(), buf->Length()); + + if (!buf->ReadUInt16(&type_)) { + return false; + } + + if (type_ & 0x8000) { + // RTP and RTCP set the MSB of first byte, since first two bits are version, + // and version is always 2 (10). If set, this is not a STUN packet. + return false; + } + + if (!buf->ReadUInt16(&length_)) { + return false; + } + + std::string magic_cookie; + if (!buf->ReadString(&magic_cookie, kStunMagicCookieLength)) { + return false; + } + + std::string transaction_id; + if (!buf->ReadString(&transaction_id, kStunTransactionIdLength)) { + return false; + } + + uint32_t magic_cookie_int; + static_assert(sizeof(magic_cookie_int) == kStunMagicCookieLength, + "Integer size mismatch: magic_cookie_int and kStunMagicCookie"); + std::memcpy(&magic_cookie_int, magic_cookie.data(), sizeof(magic_cookie_int)); + if (rtc::NetworkToHost32(magic_cookie_int) != kStunMagicCookie) { + // If magic cookie is invalid it means that the peer implements + // RFC3489 instead of RFC5389. + transaction_id.insert(0, magic_cookie); + } + RTC_DCHECK(IsValidTransactionId(transaction_id)); + transaction_id_ = transaction_id; + reduced_transaction_id_ = ReduceTransactionId(transaction_id_); + + if (length_ != buf->Length()) { + return false; + } + + attrs_.resize(0); + + size_t rest = buf->Length() - length_; + while (buf->Length() > rest) { + uint16_t attr_type, attr_length; + if (!buf->ReadUInt16(&attr_type)) + return false; + if (!buf->ReadUInt16(&attr_length)) + return false; + + std::unique_ptr<StunAttribute> attr( + CreateAttribute(attr_type, attr_length)); + if (!attr) { + // Skip any unknown or malformed attributes. + if ((attr_length % 4) != 0) { + attr_length += (4 - (attr_length % 4)); + } + if (!buf->Consume(attr_length)) { + return false; + } + } else { + if (!attr->Read(buf)) { + return false; + } + attrs_.push_back(std::move(attr)); + } + } + + RTC_DCHECK(buf->Length() == rest); + return true; +} + +bool StunMessage::Write(ByteBufferWriter* buf) const { + buf->WriteUInt16(type_); + buf->WriteUInt16(length_); + if (!IsLegacy()) + buf->WriteUInt32(stun_magic_cookie_); + buf->WriteString(transaction_id_); + + for (const auto& attr : attrs_) { + buf->WriteUInt16(attr->type()); + buf->WriteUInt16(static_cast<uint16_t>(attr->length())); + if (!attr->Write(buf)) { + return false; + } + } + + return true; +} + +StunMessage* StunMessage::CreateNew() const { + return new StunMessage(); +} + +void StunMessage::SetStunMagicCookie(uint32_t val) { + stun_magic_cookie_ = val; +} + +void StunMessage::SetTransactionIdForTesting(absl::string_view transaction_id) { + RTC_DCHECK(IsValidTransactionId(transaction_id)); + transaction_id_ = std::string(transaction_id); + reduced_transaction_id_ = ReduceTransactionId(transaction_id_); +} + +StunAttributeValueType StunMessage::GetAttributeValueType(int type) const { + switch (type) { + case STUN_ATTR_MAPPED_ADDRESS: + return STUN_VALUE_ADDRESS; + case STUN_ATTR_USERNAME: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_MESSAGE_INTEGRITY: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_ERROR_CODE: + return STUN_VALUE_ERROR_CODE; + case STUN_ATTR_UNKNOWN_ATTRIBUTES: + return STUN_VALUE_UINT16_LIST; + case STUN_ATTR_REALM: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_NONCE: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_XOR_MAPPED_ADDRESS: + return STUN_VALUE_XOR_ADDRESS; + case STUN_ATTR_SOFTWARE: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_ALTERNATE_SERVER: + return STUN_VALUE_ADDRESS; + case STUN_ATTR_FINGERPRINT: + return STUN_VALUE_UINT32; + case STUN_ATTR_RETRANSMIT_COUNT: + return STUN_VALUE_UINT32; + case STUN_ATTR_GOOG_LAST_ICE_CHECK_RECEIVED: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_GOOG_MISC_INFO: + return STUN_VALUE_UINT16_LIST; + default: + return STUN_VALUE_UNKNOWN; + } +} + +StunAttribute* StunMessage::CreateAttribute(int type, size_t length) /*const*/ { + StunAttributeValueType value_type = GetAttributeValueType(type); + if (value_type != STUN_VALUE_UNKNOWN) { + return StunAttribute::Create(value_type, type, + static_cast<uint16_t>(length), this); + } else if (DesignatedExpertRange(type)) { + // Read unknown attributes as STUN_VALUE_BYTE_STRING + return StunAttribute::Create(STUN_VALUE_BYTE_STRING, type, + static_cast<uint16_t>(length), this); + } else { + return NULL; + } +} + +const StunAttribute* StunMessage::GetAttribute(int type) const { + for (const auto& attr : attrs_) { + if (attr->type() == type) { + return attr.get(); + } + } + return NULL; +} + +bool StunMessage::IsValidTransactionId(absl::string_view transaction_id) { + return transaction_id.size() == kStunTransactionIdLength || + transaction_id.size() == kStunLegacyTransactionIdLength; +} + +bool StunMessage::EqualAttributes( + const StunMessage* other, + std::function<bool(int type)> attribute_type_mask) const { + RTC_DCHECK(other != nullptr); + rtc::ByteBufferWriter tmp_buffer_ptr1; + rtc::ByteBufferWriter tmp_buffer_ptr2; + for (const auto& attr : attrs_) { + if (attribute_type_mask(attr->type())) { + const StunAttribute* other_attr = other->GetAttribute(attr->type()); + if (other_attr == nullptr) { + return false; + } + tmp_buffer_ptr1.Clear(); + tmp_buffer_ptr2.Clear(); + attr->Write(&tmp_buffer_ptr1); + other_attr->Write(&tmp_buffer_ptr2); + if (tmp_buffer_ptr1.Length() != tmp_buffer_ptr2.Length()) { + return false; + } + if (memcmp(tmp_buffer_ptr1.Data(), tmp_buffer_ptr2.Data(), + tmp_buffer_ptr1.Length()) != 0) { + return false; + } + } + } + + for (const auto& attr : other->attrs_) { + if (attribute_type_mask(attr->type())) { + const StunAttribute* own_attr = GetAttribute(attr->type()); + if (own_attr == nullptr) { + return false; + } + // we have already compared all values... + } + } + return true; +} + +// StunAttribute + +StunAttribute::StunAttribute(uint16_t type, uint16_t length) + : type_(type), length_(length) {} + +void StunAttribute::ConsumePadding(ByteBufferReader* buf) const { + int remainder = length_ % 4; + if (remainder > 0) { + buf->Consume(4 - remainder); + } +} + +void StunAttribute::WritePadding(ByteBufferWriter* buf) const { + int remainder = length_ % 4; + if (remainder > 0) { + char zeroes[4] = {0}; + buf->WriteBytes(zeroes, 4 - remainder); + } +} + +StunAttribute* StunAttribute::Create(StunAttributeValueType value_type, + uint16_t type, + uint16_t length, + StunMessage* owner) { + switch (value_type) { + case STUN_VALUE_ADDRESS: + return new StunAddressAttribute(type, length); + case STUN_VALUE_XOR_ADDRESS: + return new StunXorAddressAttribute(type, length, owner); + case STUN_VALUE_UINT32: + return new StunUInt32Attribute(type); + case STUN_VALUE_UINT64: + return new StunUInt64Attribute(type); + case STUN_VALUE_BYTE_STRING: + return new StunByteStringAttribute(type, length); + case STUN_VALUE_ERROR_CODE: + return new StunErrorCodeAttribute(type, length); + case STUN_VALUE_UINT16_LIST: + return new StunUInt16ListAttribute(type, length); + default: + return NULL; + } +} + +std::unique_ptr<StunAddressAttribute> StunAttribute::CreateAddress( + uint16_t type) { + return std::make_unique<StunAddressAttribute>(type, 0); +} + +std::unique_ptr<StunXorAddressAttribute> StunAttribute::CreateXorAddress( + uint16_t type) { + return std::make_unique<StunXorAddressAttribute>(type, 0, nullptr); +} + +std::unique_ptr<StunUInt64Attribute> StunAttribute::CreateUInt64( + uint16_t type) { + return std::make_unique<StunUInt64Attribute>(type); +} + +std::unique_ptr<StunUInt32Attribute> StunAttribute::CreateUInt32( + uint16_t type) { + return std::make_unique<StunUInt32Attribute>(type); +} + +std::unique_ptr<StunByteStringAttribute> StunAttribute::CreateByteString( + uint16_t type) { + return std::make_unique<StunByteStringAttribute>(type, 0); +} + +std::unique_ptr<StunErrorCodeAttribute> StunAttribute::CreateErrorCode() { + return std::make_unique<StunErrorCodeAttribute>( + STUN_ATTR_ERROR_CODE, StunErrorCodeAttribute::MIN_SIZE); +} + +std::unique_ptr<StunUInt16ListAttribute> +StunAttribute::CreateUInt16ListAttribute(uint16_t type) { + return std::make_unique<StunUInt16ListAttribute>(type, 0); +} + +std::unique_ptr<StunUInt16ListAttribute> +StunAttribute::CreateUnknownAttributes() { + return std::make_unique<StunUInt16ListAttribute>(STUN_ATTR_UNKNOWN_ATTRIBUTES, + 0); +} + +StunAddressAttribute::StunAddressAttribute(uint16_t type, + const rtc::SocketAddress& addr) + : StunAttribute(type, 0) { + SetAddress(addr); +} + +StunAddressAttribute::StunAddressAttribute(uint16_t type, uint16_t length) + : StunAttribute(type, length) {} + +StunAttributeValueType StunAddressAttribute::value_type() const { + return STUN_VALUE_ADDRESS; +} + +bool StunAddressAttribute::Read(ByteBufferReader* buf) { + uint8_t dummy; + if (!buf->ReadUInt8(&dummy)) + return false; + + uint8_t stun_family; + if (!buf->ReadUInt8(&stun_family)) { + return false; + } + uint16_t port; + if (!buf->ReadUInt16(&port)) + return false; + if (stun_family == STUN_ADDRESS_IPV4) { + in_addr v4addr; + if (length() != SIZE_IP4) { + return false; + } + if (!buf->ReadBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr))) { + return false; + } + rtc::IPAddress ipaddr(v4addr); + SetAddress(rtc::SocketAddress(ipaddr, port)); + } else if (stun_family == STUN_ADDRESS_IPV6) { + in6_addr v6addr; + if (length() != SIZE_IP6) { + return false; + } + if (!buf->ReadBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr))) { + return false; + } + rtc::IPAddress ipaddr(v6addr); + SetAddress(rtc::SocketAddress(ipaddr, port)); + } else { + return false; + } + return true; +} + +bool StunAddressAttribute::Write(ByteBufferWriter* buf) const { + StunAddressFamily address_family = family(); + if (address_family == STUN_ADDRESS_UNDEF) { + RTC_LOG(LS_ERROR) << "Error writing address attribute: unknown family."; + return false; + } + buf->WriteUInt8(0); + buf->WriteUInt8(address_family); + buf->WriteUInt16(address_.port()); + switch (address_.family()) { + case AF_INET: { + in_addr v4addr = address_.ipaddr().ipv4_address(); + buf->WriteBytes(reinterpret_cast<char*>(&v4addr), sizeof(v4addr)); + break; + } + case AF_INET6: { + in6_addr v6addr = address_.ipaddr().ipv6_address(); + buf->WriteBytes(reinterpret_cast<char*>(&v6addr), sizeof(v6addr)); + break; + } + } + return true; +} + +StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type, + const rtc::SocketAddress& addr) + : StunAddressAttribute(type, addr), owner_(NULL) {} + +StunXorAddressAttribute::StunXorAddressAttribute(uint16_t type, + uint16_t length, + StunMessage* owner) + : StunAddressAttribute(type, length), owner_(owner) {} + +StunAttributeValueType StunXorAddressAttribute::value_type() const { + return STUN_VALUE_XOR_ADDRESS; +} + +void StunXorAddressAttribute::SetOwner(StunMessage* owner) { + owner_ = owner; +} + +rtc::IPAddress StunXorAddressAttribute::GetXoredIP() const { + if (owner_) { + rtc::IPAddress ip = ipaddr(); + switch (ip.family()) { + case AF_INET: { + in_addr v4addr = ip.ipv4_address(); + v4addr.s_addr = + (v4addr.s_addr ^ rtc::HostToNetwork32(kStunMagicCookie)); + return rtc::IPAddress(v4addr); + } + case AF_INET6: { + in6_addr v6addr = ip.ipv6_address(); + const std::string& transaction_id = owner_->transaction_id(); + if (transaction_id.length() == kStunTransactionIdLength) { + uint32_t transactionid_as_ints[3]; + memcpy(&transactionid_as_ints[0], transaction_id.c_str(), + transaction_id.length()); + uint32_t* ip_as_ints = reinterpret_cast<uint32_t*>(&v6addr.s6_addr); + // Transaction ID is in network byte order, but magic cookie + // is stored in host byte order. + ip_as_ints[0] = + (ip_as_ints[0] ^ rtc::HostToNetwork32(kStunMagicCookie)); + ip_as_ints[1] = (ip_as_ints[1] ^ transactionid_as_ints[0]); + ip_as_ints[2] = (ip_as_ints[2] ^ transactionid_as_ints[1]); + ip_as_ints[3] = (ip_as_ints[3] ^ transactionid_as_ints[2]); + return rtc::IPAddress(v6addr); + } + break; + } + } + } + // Invalid ip family or transaction ID, or missing owner. + // Return an AF_UNSPEC address. + return rtc::IPAddress(); +} + +bool StunXorAddressAttribute::Read(ByteBufferReader* buf) { + if (!StunAddressAttribute::Read(buf)) + return false; + uint16_t xoredport = port() ^ (kStunMagicCookie >> 16); + rtc::IPAddress xored_ip = GetXoredIP(); + SetAddress(rtc::SocketAddress(xored_ip, xoredport)); + return true; +} + +bool StunXorAddressAttribute::Write(ByteBufferWriter* buf) const { + StunAddressFamily address_family = family(); + if (address_family == STUN_ADDRESS_UNDEF) { + RTC_LOG(LS_ERROR) << "Error writing xor-address attribute: unknown family."; + return false; + } + rtc::IPAddress xored_ip = GetXoredIP(); + if (xored_ip.family() == AF_UNSPEC) { + return false; + } + buf->WriteUInt8(0); + buf->WriteUInt8(family()); + buf->WriteUInt16(port() ^ (kStunMagicCookie >> 16)); + switch (xored_ip.family()) { + case AF_INET: { + in_addr v4addr = xored_ip.ipv4_address(); + buf->WriteBytes(reinterpret_cast<const char*>(&v4addr), sizeof(v4addr)); + break; + } + case AF_INET6: { + in6_addr v6addr = xored_ip.ipv6_address(); + buf->WriteBytes(reinterpret_cast<const char*>(&v6addr), sizeof(v6addr)); + break; + } + } + return true; +} + +StunUInt32Attribute::StunUInt32Attribute(uint16_t type, uint32_t value) + : StunAttribute(type, SIZE), bits_(value) {} + +StunUInt32Attribute::StunUInt32Attribute(uint16_t type) + : StunAttribute(type, SIZE), bits_(0) {} + +StunAttributeValueType StunUInt32Attribute::value_type() const { + return STUN_VALUE_UINT32; +} + +bool StunUInt32Attribute::GetBit(size_t index) const { + RTC_DCHECK(index < 32); + return static_cast<bool>((bits_ >> index) & 0x1); +} + +void StunUInt32Attribute::SetBit(size_t index, bool value) { + RTC_DCHECK(index < 32); + bits_ &= ~(1 << index); + bits_ |= value ? (1 << index) : 0; +} + +bool StunUInt32Attribute::Read(ByteBufferReader* buf) { + if (length() != SIZE || !buf->ReadUInt32(&bits_)) + return false; + return true; +} + +bool StunUInt32Attribute::Write(ByteBufferWriter* buf) const { + buf->WriteUInt32(bits_); + return true; +} + +StunUInt64Attribute::StunUInt64Attribute(uint16_t type, uint64_t value) + : StunAttribute(type, SIZE), bits_(value) {} + +StunUInt64Attribute::StunUInt64Attribute(uint16_t type) + : StunAttribute(type, SIZE), bits_(0) {} + +StunAttributeValueType StunUInt64Attribute::value_type() const { + return STUN_VALUE_UINT64; +} + +bool StunUInt64Attribute::Read(ByteBufferReader* buf) { + if (length() != SIZE || !buf->ReadUInt64(&bits_)) + return false; + return true; +} + +bool StunUInt64Attribute::Write(ByteBufferWriter* buf) const { + buf->WriteUInt64(bits_); + return true; +} + +StunByteStringAttribute::StunByteStringAttribute(uint16_t type) + : StunAttribute(type, 0), bytes_(NULL) {} + +StunByteStringAttribute::StunByteStringAttribute(uint16_t type, + absl::string_view str) + : StunAttribute(type, 0), bytes_(NULL) { + CopyBytes(str); +} + +StunByteStringAttribute::StunByteStringAttribute(uint16_t type, + const void* bytes, + size_t length) + : StunAttribute(type, 0), bytes_(NULL) { + CopyBytes(bytes, length); +} + +StunByteStringAttribute::StunByteStringAttribute(uint16_t type, uint16_t length) + : StunAttribute(type, length), bytes_(NULL) {} + +StunByteStringAttribute::~StunByteStringAttribute() { + delete[] bytes_; +} + +StunAttributeValueType StunByteStringAttribute::value_type() const { + return STUN_VALUE_BYTE_STRING; +} + +void StunByteStringAttribute::CopyBytes(absl::string_view bytes) { + char* new_bytes = new char[bytes.size()]; + memcpy(new_bytes, bytes.data(), bytes.size()); + SetBytes(new_bytes, bytes.size()); +} + +void StunByteStringAttribute::CopyBytes(const void* bytes, size_t length) { + char* new_bytes = new char[length]; + memcpy(new_bytes, bytes, length); + SetBytes(new_bytes, length); +} + +uint8_t StunByteStringAttribute::GetByte(size_t index) const { + RTC_DCHECK(bytes_ != NULL); + RTC_DCHECK(index < length()); + return static_cast<uint8_t>(bytes_[index]); +} + +void StunByteStringAttribute::SetByte(size_t index, uint8_t value) { + RTC_DCHECK(bytes_ != NULL); + RTC_DCHECK(index < length()); + bytes_[index] = value; +} + +bool StunByteStringAttribute::Read(ByteBufferReader* buf) { + bytes_ = new char[length()]; + if (!buf->ReadBytes(bytes_, length())) { + return false; + } + + ConsumePadding(buf); + return true; +} + +bool StunByteStringAttribute::Write(ByteBufferWriter* buf) const { + // Check that length is legal according to specs + if (!LengthValid(type(), length())) { + return false; + } + buf->WriteBytes(bytes_, length()); + WritePadding(buf); + return true; +} + +void StunByteStringAttribute::SetBytes(char* bytes, size_t length) { + delete[] bytes_; + bytes_ = bytes; + SetLength(static_cast<uint16_t>(length)); +} + +const uint16_t StunErrorCodeAttribute::MIN_SIZE = 4; + +StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type, + int code, + const std::string& reason) + : StunAttribute(type, 0) { + SetCode(code); + SetReason(reason); +} + +StunErrorCodeAttribute::StunErrorCodeAttribute(uint16_t type, uint16_t length) + : StunAttribute(type, length), class_(0), number_(0) {} + +StunErrorCodeAttribute::~StunErrorCodeAttribute() {} + +StunAttributeValueType StunErrorCodeAttribute::value_type() const { + return STUN_VALUE_ERROR_CODE; +} + +int StunErrorCodeAttribute::code() const { + return class_ * 100 + number_; +} + +void StunErrorCodeAttribute::SetCode(int code) { + class_ = static_cast<uint8_t>(code / 100); + number_ = static_cast<uint8_t>(code % 100); +} + +void StunErrorCodeAttribute::SetReason(const std::string& reason) { + SetLength(MIN_SIZE + static_cast<uint16_t>(reason.size())); + reason_ = reason; +} + +bool StunErrorCodeAttribute::Read(ByteBufferReader* buf) { + uint32_t val; + if (length() < MIN_SIZE || !buf->ReadUInt32(&val)) + return false; + + if ((val >> 11) != 0) + RTC_LOG(LS_ERROR) << "error-code bits not zero"; + + class_ = ((val >> 8) & 0x7); + number_ = (val & 0xff); + + if (!buf->ReadString(&reason_, length() - 4)) + return false; + + ConsumePadding(buf); + return true; +} + +bool StunErrorCodeAttribute::Write(ByteBufferWriter* buf) const { + buf->WriteUInt32(class_ << 8 | number_); + buf->WriteString(reason_); + WritePadding(buf); + return true; +} + +StunUInt16ListAttribute::StunUInt16ListAttribute(uint16_t type, uint16_t length) + : StunAttribute(type, length) { + attr_types_ = new std::vector<uint16_t>(); +} + +StunUInt16ListAttribute::~StunUInt16ListAttribute() { + delete attr_types_; +} + +StunAttributeValueType StunUInt16ListAttribute::value_type() const { + return STUN_VALUE_UINT16_LIST; +} + +size_t StunUInt16ListAttribute::Size() const { + return attr_types_->size(); +} + +uint16_t StunUInt16ListAttribute::GetType(int index) const { + return (*attr_types_)[index]; +} + +void StunUInt16ListAttribute::SetType(int index, uint16_t value) { + (*attr_types_)[index] = value; +} + +void StunUInt16ListAttribute::AddType(uint16_t value) { + attr_types_->push_back(value); + SetLength(static_cast<uint16_t>(attr_types_->size() * 2)); +} + +void StunUInt16ListAttribute::AddTypeAtIndex(uint16_t index, uint16_t value) { + if (attr_types_->size() < static_cast<size_t>(index + 1)) { + attr_types_->resize(index + 1); + } + (*attr_types_)[index] = value; + SetLength(static_cast<uint16_t>(attr_types_->size() * 2)); +} + +bool StunUInt16ListAttribute::Read(ByteBufferReader* buf) { + if (length() % 2) { + return false; + } + + for (size_t i = 0; i < length() / 2; i++) { + uint16_t attr; + if (!buf->ReadUInt16(&attr)) + return false; + attr_types_->push_back(attr); + } + // Padding of these attributes is done in RFC 5389 style. This is + // slightly different from RFC3489, but it shouldn't be important. + // RFC3489 pads out to a 32 bit boundary by duplicating one of the + // entries in the list (not necessarily the last one - it's unspecified). + // RFC5389 pads on the end, and the bytes are always ignored. + ConsumePadding(buf); + return true; +} + +bool StunUInt16ListAttribute::Write(ByteBufferWriter* buf) const { + for (size_t i = 0; i < attr_types_->size(); ++i) { + buf->WriteUInt16((*attr_types_)[i]); + } + WritePadding(buf); + return true; +} + +std::string StunMethodToString(int msg_type) { + switch (msg_type) { + case STUN_BINDING_REQUEST: + return "STUN BINDING request"; + case STUN_BINDING_INDICATION: + return "STUN BINDING indication"; + case STUN_BINDING_RESPONSE: + return "STUN BINDING response"; + case STUN_BINDING_ERROR_RESPONSE: + return "STUN BINDING error response"; + case GOOG_PING_REQUEST: + return "GOOG PING request"; + case GOOG_PING_RESPONSE: + return "GOOG PING response"; + case GOOG_PING_ERROR_RESPONSE: + return "GOOG PING error response"; + case STUN_ALLOCATE_REQUEST: + return "TURN ALLOCATE request"; + case STUN_ALLOCATE_RESPONSE: + return "TURN ALLOCATE response"; + case STUN_ALLOCATE_ERROR_RESPONSE: + return "TURN ALLOCATE error response"; + case TURN_REFRESH_REQUEST: + return "TURN REFRESH request"; + case TURN_REFRESH_RESPONSE: + return "TURN REFRESH response"; + case TURN_REFRESH_ERROR_RESPONSE: + return "TURN REFRESH error response"; + case TURN_SEND_INDICATION: + return "TURN SEND INDICATION"; + case TURN_DATA_INDICATION: + return "TURN DATA INDICATION"; + case TURN_CREATE_PERMISSION_REQUEST: + return "TURN CREATE PERMISSION request"; + case TURN_CREATE_PERMISSION_RESPONSE: + return "TURN CREATE PERMISSION response"; + case TURN_CREATE_PERMISSION_ERROR_RESPONSE: + return "TURN CREATE PERMISSION error response"; + case TURN_CHANNEL_BIND_REQUEST: + return "TURN CHANNEL BIND request"; + case TURN_CHANNEL_BIND_RESPONSE: + return "TURN CHANNEL BIND response"; + case TURN_CHANNEL_BIND_ERROR_RESPONSE: + return "TURN CHANNEL BIND error response"; + default: + return "UNKNOWN<" + std::to_string(msg_type) + ">"; + } +} + +int GetStunSuccessResponseType(int req_type) { + return IsStunRequestType(req_type) ? (req_type | 0x100) : -1; +} + +int GetStunErrorResponseType(int req_type) { + return IsStunRequestType(req_type) ? (req_type | 0x110) : -1; +} + +bool IsStunRequestType(int msg_type) { + return ((msg_type & kStunTypeMask) == 0x000); +} + +bool IsStunIndicationType(int msg_type) { + return ((msg_type & kStunTypeMask) == 0x010); +} + +bool IsStunSuccessResponseType(int msg_type) { + return ((msg_type & kStunTypeMask) == 0x100); +} + +bool IsStunErrorResponseType(int msg_type) { + return ((msg_type & kStunTypeMask) == 0x110); +} + +bool ComputeStunCredentialHash(const std::string& username, + const std::string& realm, + const std::string& password, + std::string* hash) { + // http://tools.ietf.org/html/rfc5389#section-15.4 + // long-term credentials will be calculated using the key and key is + // key = MD5(username ":" realm ":" SASLprep(password)) + std::string input = username; + input += ':'; + input += realm; + input += ':'; + input += password; + + char digest[rtc::MessageDigest::kMaxSize]; + size_t size = rtc::ComputeDigest(rtc::DIGEST_MD5, input.c_str(), input.size(), + digest, sizeof(digest)); + if (size == 0) { + return false; + } + + *hash = std::string(digest, size); + return true; +} + +std::unique_ptr<StunAttribute> CopyStunAttribute( + const StunAttribute& attribute, + rtc::ByteBufferWriter* tmp_buffer_ptr) { + ByteBufferWriter tmpBuffer; + if (tmp_buffer_ptr == nullptr) { + tmp_buffer_ptr = &tmpBuffer; + } + + std::unique_ptr<StunAttribute> copy(StunAttribute::Create( + attribute.value_type(), attribute.type(), + static_cast<uint16_t>(attribute.length()), nullptr)); + + if (!copy) { + return nullptr; + } + tmp_buffer_ptr->Clear(); + if (!attribute.Write(tmp_buffer_ptr)) { + return nullptr; + } + rtc::ByteBufferReader reader(*tmp_buffer_ptr); + if (!copy->Read(&reader)) { + return nullptr; + } + + return copy; +} + +StunAttributeValueType RelayMessage::GetAttributeValueType(int type) const { + switch (type) { + case STUN_ATTR_LIFETIME: + return STUN_VALUE_UINT32; + case STUN_ATTR_MAGIC_COOKIE: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_BANDWIDTH: + return STUN_VALUE_UINT32; + case STUN_ATTR_DESTINATION_ADDRESS: + return STUN_VALUE_ADDRESS; + case STUN_ATTR_SOURCE_ADDRESS2: + return STUN_VALUE_ADDRESS; + case STUN_ATTR_DATA: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_OPTIONS: + return STUN_VALUE_UINT32; + default: + return StunMessage::GetAttributeValueType(type); + } +} + +StunMessage* RelayMessage::CreateNew() const { + return new RelayMessage(); +} + +StunAttributeValueType TurnMessage::GetAttributeValueType(int type) const { + switch (type) { + case STUN_ATTR_CHANNEL_NUMBER: + return STUN_VALUE_UINT32; + case STUN_ATTR_TURN_LIFETIME: + return STUN_VALUE_UINT32; + case STUN_ATTR_XOR_PEER_ADDRESS: + return STUN_VALUE_XOR_ADDRESS; + case STUN_ATTR_DATA: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_XOR_RELAYED_ADDRESS: + return STUN_VALUE_XOR_ADDRESS; + case STUN_ATTR_EVEN_PORT: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_REQUESTED_TRANSPORT: + return STUN_VALUE_UINT32; + case STUN_ATTR_DONT_FRAGMENT: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_RESERVATION_TOKEN: + return STUN_VALUE_BYTE_STRING; + default: + return StunMessage::GetAttributeValueType(type); + } +} + +StunMessage* TurnMessage::CreateNew() const { + return new TurnMessage(); +} + +StunAttributeValueType IceMessage::GetAttributeValueType(int type) const { + switch (type) { + case STUN_ATTR_PRIORITY: + case STUN_ATTR_GOOG_NETWORK_INFO: + case STUN_ATTR_NOMINATION: + return STUN_VALUE_UINT32; + case STUN_ATTR_USE_CANDIDATE: + return STUN_VALUE_BYTE_STRING; + case STUN_ATTR_ICE_CONTROLLED: + return STUN_VALUE_UINT64; + case STUN_ATTR_ICE_CONTROLLING: + return STUN_VALUE_UINT64; + default: + return StunMessage::GetAttributeValueType(type); + } +} + +StunMessage* IceMessage::CreateNew() const { + return new IceMessage(); +} + +std::unique_ptr<StunMessage> StunMessage::Clone() const { + std::unique_ptr<StunMessage> copy(CreateNew()); + if (!copy) { + return nullptr; + } + rtc::ByteBufferWriter buf; + if (!Write(&buf)) { + return nullptr; + } + rtc::ByteBufferReader reader(buf); + if (!copy->Read(&reader)) { + return nullptr; + } + return copy; +} + +} // namespace cricket diff --git a/third_party/libwebrtc/api/transport/stun.h b/third_party/libwebrtc/api/transport/stun.h new file mode 100644 index 0000000000..c2c9ad4b9c --- /dev/null +++ b/third_party/libwebrtc/api/transport/stun.h @@ -0,0 +1,798 @@ +/* + * Copyright 2004 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 API_TRANSPORT_STUN_H_ +#define API_TRANSPORT_STUN_H_ + +// This file contains classes for dealing with the STUN protocol, as specified +// in RFC 5389, and its descendants. + +#include <stddef.h> +#include <stdint.h> + +#include <functional> +#include <memory> +#include <string> +#include <vector> + +#include "absl/strings/string_view.h" +#include "api/array_view.h" +#include "rtc_base/byte_buffer.h" +#include "rtc_base/ip_address.h" +#include "rtc_base/socket_address.h" + +namespace cricket { + +// These are the types of STUN messages defined in RFC 5389. +enum StunMessageType : uint16_t { + STUN_INVALID_MESSAGE_TYPE = 0x0000, + STUN_BINDING_REQUEST = 0x0001, + STUN_BINDING_INDICATION = 0x0011, + STUN_BINDING_RESPONSE = 0x0101, + STUN_BINDING_ERROR_RESPONSE = 0x0111, + + // Method 0x80, GOOG-PING is a variant of STUN BINDING + // that is sent instead of a STUN BINDING if the binding + // was identical to the one before. + GOOG_PING_REQUEST = 0x200, + GOOG_PING_RESPONSE = 0x300, + GOOG_PING_ERROR_RESPONSE = 0x310, +}; + +// These are all known STUN attributes, defined in RFC 5389 and elsewhere. +// Next to each is the name of the class (T is StunTAttribute) that implements +// that type. +// RETRANSMIT_COUNT is the number of outstanding pings without a response at +// the time the packet is generated. +enum StunAttributeType { + STUN_ATTR_MAPPED_ADDRESS = 0x0001, // Address + STUN_ATTR_USERNAME = 0x0006, // ByteString + STUN_ATTR_MESSAGE_INTEGRITY = 0x0008, // ByteString, 20 bytes + STUN_ATTR_ERROR_CODE = 0x0009, // ErrorCode + STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000a, // UInt16List + STUN_ATTR_REALM = 0x0014, // ByteString + STUN_ATTR_NONCE = 0x0015, // ByteString + STUN_ATTR_XOR_MAPPED_ADDRESS = 0x0020, // XorAddress + STUN_ATTR_SOFTWARE = 0x8022, // ByteString + STUN_ATTR_ALTERNATE_SERVER = 0x8023, // Address + STUN_ATTR_FINGERPRINT = 0x8028, // UInt32 + STUN_ATTR_RETRANSMIT_COUNT = 0xFF00 // UInt32 +}; + +// These are the types of the values associated with the attributes above. +// This allows us to perform some basic validation when reading or adding +// attributes. Note that these values are for our own use, and not defined in +// RFC 5389. +enum StunAttributeValueType { + STUN_VALUE_UNKNOWN = 0, + STUN_VALUE_ADDRESS = 1, + STUN_VALUE_XOR_ADDRESS = 2, + STUN_VALUE_UINT32 = 3, + STUN_VALUE_UINT64 = 4, + STUN_VALUE_BYTE_STRING = 5, + STUN_VALUE_ERROR_CODE = 6, + STUN_VALUE_UINT16_LIST = 7 +}; + +// These are the types of STUN addresses defined in RFC 5389. +enum StunAddressFamily { + // NB: UNDEF is not part of the STUN spec. + STUN_ADDRESS_UNDEF = 0, + STUN_ADDRESS_IPV4 = 1, + STUN_ADDRESS_IPV6 = 2 +}; + +// These are the types of STUN error codes defined in RFC 5389. +enum StunErrorCode { + STUN_ERROR_TRY_ALTERNATE = 300, + STUN_ERROR_BAD_REQUEST = 400, + STUN_ERROR_UNAUTHORIZED = 401, + STUN_ERROR_UNKNOWN_ATTRIBUTE = 420, + STUN_ERROR_STALE_NONCE = 438, + STUN_ERROR_SERVER_ERROR = 500, + STUN_ERROR_GLOBAL_FAILURE = 600 +}; + +// Strings for the error codes above. +extern const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[]; +extern const char STUN_ERROR_REASON_BAD_REQUEST[]; +extern const char STUN_ERROR_REASON_UNAUTHORIZED[]; +extern const char STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE[]; +extern const char STUN_ERROR_REASON_STALE_NONCE[]; +extern const char STUN_ERROR_REASON_SERVER_ERROR[]; + +// The mask used to determine whether a STUN message is a request/response etc. +const uint32_t kStunTypeMask = 0x0110; + +// STUN Attribute header length. +const size_t kStunAttributeHeaderSize = 4; + +// Following values correspond to RFC5389. +const size_t kStunHeaderSize = 20; +const size_t kStunTransactionIdOffset = 8; +const size_t kStunTransactionIdLength = 12; +const uint32_t kStunMagicCookie = 0x2112A442; +constexpr size_t kStunMagicCookieLength = sizeof(kStunMagicCookie); + +// Following value corresponds to an earlier version of STUN from +// RFC3489. +const size_t kStunLegacyTransactionIdLength = 16; + +// STUN Message Integrity HMAC length. +const size_t kStunMessageIntegritySize = 20; +// Size of STUN_ATTR_MESSAGE_INTEGRITY_32 +const size_t kStunMessageIntegrity32Size = 4; + +class StunAddressAttribute; +class StunAttribute; +class StunByteStringAttribute; +class StunErrorCodeAttribute; +class StunUInt16ListAttribute; +class StunUInt32Attribute; +class StunUInt64Attribute; +class StunXorAddressAttribute; + +// Records a complete STUN/TURN message. Each message consists of a type and +// any number of attributes. Each attribute is parsed into an instance of an +// appropriate class (see above). The Get* methods will return instances of +// that attribute class. +class StunMessage { + public: + // Constructs a StunMessage with an invalid type and empty, legacy length + // (16 bytes, RFC3489) transaction id. + StunMessage(); + + // Construct a `StunMessage` with a specific type and generate a new + // 12 byte transaction id (RFC5389). + explicit StunMessage(uint16_t type); + + StunMessage(uint16_t type, absl::string_view transaction_id); + + virtual ~StunMessage(); + + // The verification status of the message. This is checked on parsing, + // or set by AddMessageIntegrity. + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class IntegrityStatus { + kNotSet = 0, + kNoIntegrity = 1, // Message-integrity attribute missing + kIntegrityOk = 2, // Message-integrity checked OK + kIntegrityBad = 3, // Message-integrity verification failed + kMaxValue = kIntegrityBad, + }; + + int type() const { return type_; } + size_t length() const { return length_; } + const std::string& transaction_id() const { return transaction_id_; } + uint32_t reduced_transaction_id() const { return reduced_transaction_id_; } + + // Returns true if the message confirms to RFC3489 rather than + // RFC5389. The main difference between the two versions of the STUN + // protocol is the presence of the magic cookie and different length + // of transaction ID. For outgoing packets the version of the protocol + // is determined by the lengths of the transaction ID. + bool IsLegacy() const; + + [[deprecated]] void SetType(int type) { type_ = static_cast<uint16_t>(type); } + [[deprecated]] bool SetTransactionID(absl::string_view transaction_id) { + if (!IsValidTransactionId(transaction_id)) + return false; + SetTransactionIdForTesting(transaction_id); + return true; + } + + // Get a list of all of the attribute types in the "comprehension required" + // range that were not recognized. + std::vector<uint16_t> GetNonComprehendedAttributes() const; + + // Gets the desired attribute value, or NULL if no such attribute type exists. + const StunAddressAttribute* GetAddress(int type) const; + const StunUInt32Attribute* GetUInt32(int type) const; + const StunUInt64Attribute* GetUInt64(int type) const; + const StunByteStringAttribute* GetByteString(int type) const; + const StunUInt16ListAttribute* GetUInt16List(int type) const; + + // Gets these specific attribute values. + const StunErrorCodeAttribute* GetErrorCode() const; + // Returns the code inside the error code attribute, if present, and + // STUN_ERROR_GLOBAL_FAILURE otherwise. + int GetErrorCodeValue() const; + const StunUInt16ListAttribute* GetUnknownAttributes() const; + + // Takes ownership of the specified attribute and adds it to the message. + void AddAttribute(std::unique_ptr<StunAttribute> attr); + + // Remove the last occurrence of an attribute. + std::unique_ptr<StunAttribute> RemoveAttribute(int type); + + // Remote all attributes and releases them. + void ClearAttributes(); + + // Validates that a STUN message has a correct MESSAGE-INTEGRITY value. + // This uses the buffered raw-format message stored by Read(). + IntegrityStatus ValidateMessageIntegrity(const std::string& password); + + // Revalidates the STUN message with (possibly) a new password. + // Indicates that calling logic needs review - probably previous call + // was checking with the wrong password. + IntegrityStatus RevalidateMessageIntegrity(const std::string& password); + + // Returns the current integrity status of the message. + IntegrityStatus integrity() const { return integrity_; } + + // Shortcut for checking if integrity is verified. + bool IntegrityOk() const { + return integrity_ == IntegrityStatus::kIntegrityOk; + } + + // Returns the password attribute used to set or check the integrity. + // Can only be called after adding or checking the integrity. + std::string password() const { + RTC_DCHECK(integrity_ != IntegrityStatus::kNotSet); + return password_; + } + + // Adds a MESSAGE-INTEGRITY attribute that is valid for the current message. + bool AddMessageIntegrity(absl::string_view password); + + // Adds a STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32 attribute that is valid for the + // current message. + bool AddMessageIntegrity32(absl::string_view password); + + // Verify that a buffer has stun magic cookie and one of the specified + // methods. Note that it does not check for the existance of FINGERPRINT. + static bool IsStunMethod(rtc::ArrayView<int> methods, + const char* data, + size_t size); + + // Verifies that a given buffer is STUN by checking for a correct FINGERPRINT. + static bool ValidateFingerprint(const char* data, size_t size); + + // Generates a new 12 byte (RFC5389) transaction id. + static std::string GenerateTransactionId(); + + // Adds a FINGERPRINT attribute that is valid for the current message. + bool AddFingerprint(); + + // Parses the STUN packet in the given buffer and records it here. The + // return value indicates whether this was successful. + bool Read(rtc::ByteBufferReader* buf); + + // Writes this object into a STUN packet. The return value indicates whether + // this was successful. + bool Write(rtc::ByteBufferWriter* buf) const; + + // Creates an empty message. Overridable by derived classes. + virtual StunMessage* CreateNew() const; + + // Modify the stun magic cookie used for this STUN message. + // This is used for testing. + [[deprecated]] void SetStunMagicCookie(uint32_t val); + + // Change the internal transaction id. Used only for testing. + void SetTransactionIdForTesting(absl::string_view transaction_id); + + // Contruct a copy of `this`. + std::unique_ptr<StunMessage> Clone() const; + + // Check if the attributes of this StunMessage equals those of `other` + // for all attributes that `attribute_type_mask` return true + bool EqualAttributes(const StunMessage* other, + std::function<bool(int type)> attribute_type_mask) const; + + // Validates that a STUN message in byte buffer form + // has a correct MESSAGE-INTEGRITY value. + // These functions are not recommended and will be deprecated; use + // ValidateMessageIntegrity(password) on the parsed form instead. + [[deprecated("Use member function")]] static bool ValidateMessageIntegrity( + const char* data, + size_t size, + const std::string& password); + [[deprecated("Use member function")]] static bool ValidateMessageIntegrity32( + const char* data, + size_t size, + const std::string& password); + + // Expose raw-buffer ValidateMessageIntegrity function for testing. + static bool ValidateMessageIntegrityForTesting(const char* data, + size_t size, + const std::string& password); + // Expose raw-buffer ValidateMessageIntegrity function for testing. + static bool ValidateMessageIntegrity32ForTesting(const char* data, + size_t size, + const std::string& password); + + protected: + // Verifies that the given attribute is allowed for this message. + virtual StunAttributeValueType GetAttributeValueType(int type) const; + + std::vector<std::unique_ptr<StunAttribute>> attrs_; + + private: + StunAttribute* CreateAttribute(int type, size_t length) /* const*/; + const StunAttribute* GetAttribute(int type) const; + static bool IsValidTransactionId(absl::string_view transaction_id); + bool AddMessageIntegrityOfType(int mi_attr_type, + size_t mi_attr_size, + absl::string_view key); + static bool ValidateMessageIntegrityOfType(int mi_attr_type, + size_t mi_attr_size, + const char* data, + size_t size, + const std::string& password); + + uint16_t type_ = STUN_INVALID_MESSAGE_TYPE; + uint16_t length_ = 0; + std::string transaction_id_; + uint32_t reduced_transaction_id_ = 0; + uint32_t stun_magic_cookie_ = kStunMagicCookie; + // The original buffer for messages created by Read(). + std::string buffer_; + IntegrityStatus integrity_ = IntegrityStatus::kNotSet; + std::string password_; +}; + +// Base class for all STUN/TURN attributes. +class StunAttribute { + public: + virtual ~StunAttribute() {} + + int type() const { return type_; } + size_t length() const { return length_; } + + // Return the type of this attribute. + virtual StunAttributeValueType value_type() const = 0; + + // Only XorAddressAttribute needs this so far. + virtual void SetOwner(StunMessage* owner) {} + + // Reads the body (not the type or length) for this type of attribute from + // the given buffer. Return value is true if successful. + virtual bool Read(rtc::ByteBufferReader* buf) = 0; + + // Writes the body (not the type or length) to the given buffer. Return + // value is true if successful. + virtual bool Write(rtc::ByteBufferWriter* buf) const = 0; + + // Creates an attribute object with the given type and smallest length. + static StunAttribute* Create(StunAttributeValueType value_type, + uint16_t type, + uint16_t length, + StunMessage* owner); + // TODO(?): Allow these create functions to take parameters, to reduce + // the amount of work callers need to do to initialize attributes. + static std::unique_ptr<StunAddressAttribute> CreateAddress(uint16_t type); + static std::unique_ptr<StunXorAddressAttribute> CreateXorAddress( + uint16_t type); + static std::unique_ptr<StunUInt32Attribute> CreateUInt32(uint16_t type); + static std::unique_ptr<StunUInt64Attribute> CreateUInt64(uint16_t type); + static std::unique_ptr<StunByteStringAttribute> CreateByteString( + uint16_t type); + static std::unique_ptr<StunUInt16ListAttribute> CreateUInt16ListAttribute( + uint16_t type); + static std::unique_ptr<StunErrorCodeAttribute> CreateErrorCode(); + static std::unique_ptr<StunUInt16ListAttribute> CreateUnknownAttributes(); + + protected: + StunAttribute(uint16_t type, uint16_t length); + void SetLength(uint16_t length) { length_ = length; } + void WritePadding(rtc::ByteBufferWriter* buf) const; + void ConsumePadding(rtc::ByteBufferReader* buf) const; + + private: + uint16_t type_; + uint16_t length_; +}; + +// Implements STUN attributes that record an Internet address. +class StunAddressAttribute : public StunAttribute { + public: + static const uint16_t SIZE_UNDEF = 0; + static const uint16_t SIZE_IP4 = 8; + static const uint16_t SIZE_IP6 = 20; + StunAddressAttribute(uint16_t type, const rtc::SocketAddress& addr); + StunAddressAttribute(uint16_t type, uint16_t length); + + StunAttributeValueType value_type() const override; + + StunAddressFamily family() const { + switch (address_.ipaddr().family()) { + case AF_INET: + return STUN_ADDRESS_IPV4; + case AF_INET6: + return STUN_ADDRESS_IPV6; + } + return STUN_ADDRESS_UNDEF; + } + + const rtc::SocketAddress& GetAddress() const { return address_; } + const rtc::IPAddress& ipaddr() const { return address_.ipaddr(); } + uint16_t port() const { return address_.port(); } + + void SetAddress(const rtc::SocketAddress& addr) { + address_ = addr; + EnsureAddressLength(); + } + void SetIP(const rtc::IPAddress& ip) { + address_.SetIP(ip); + EnsureAddressLength(); + } + void SetPort(uint16_t port) { address_.SetPort(port); } + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + void EnsureAddressLength() { + switch (family()) { + case STUN_ADDRESS_IPV4: { + SetLength(SIZE_IP4); + break; + } + case STUN_ADDRESS_IPV6: { + SetLength(SIZE_IP6); + break; + } + default: { + SetLength(SIZE_UNDEF); + break; + } + } + } + rtc::SocketAddress address_; +}; + +// Implements STUN attributes that record an Internet address. When encoded +// in a STUN message, the address contained in this attribute is XORed with the +// transaction ID of the message. +class StunXorAddressAttribute : public StunAddressAttribute { + public: + StunXorAddressAttribute(uint16_t type, const rtc::SocketAddress& addr); + StunXorAddressAttribute(uint16_t type, uint16_t length, StunMessage* owner); + + StunAttributeValueType value_type() const override; + void SetOwner(StunMessage* owner) override; + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + rtc::IPAddress GetXoredIP() const; + StunMessage* owner_; +}; + +// Implements STUN attributes that record a 32-bit integer. +class StunUInt32Attribute : public StunAttribute { + public: + static const uint16_t SIZE = 4; + StunUInt32Attribute(uint16_t type, uint32_t value); + explicit StunUInt32Attribute(uint16_t type); + + StunAttributeValueType value_type() const override; + + uint32_t value() const { return bits_; } + void SetValue(uint32_t bits) { bits_ = bits; } + + bool GetBit(size_t index) const; + void SetBit(size_t index, bool value); + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + uint32_t bits_; +}; + +class StunUInt64Attribute : public StunAttribute { + public: + static const uint16_t SIZE = 8; + StunUInt64Attribute(uint16_t type, uint64_t value); + explicit StunUInt64Attribute(uint16_t type); + + StunAttributeValueType value_type() const override; + + uint64_t value() const { return bits_; } + void SetValue(uint64_t bits) { bits_ = bits; } + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + uint64_t bits_; +}; + +// Implements STUN attributes that record an arbitrary byte string. +class StunByteStringAttribute : public StunAttribute { + public: + explicit StunByteStringAttribute(uint16_t type); + StunByteStringAttribute(uint16_t type, absl::string_view str); + StunByteStringAttribute(uint16_t type, const void* bytes, size_t length); + StunByteStringAttribute(uint16_t type, uint16_t length); + ~StunByteStringAttribute() override; + + StunAttributeValueType value_type() const override; + + const char* bytes() const { return bytes_; } + absl::string_view string_view() const { + return absl::string_view(bytes_, length()); + } + + [[deprecated]] std::string GetString() const { + return std::string(bytes_, length()); + } + + void CopyBytes(const void* bytes, size_t length); + void CopyBytes(absl::string_view bytes); + + uint8_t GetByte(size_t index) const; + void SetByte(size_t index, uint8_t value); + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + void SetBytes(char* bytes, size_t length); + + char* bytes_; +}; + +// Implements STUN attributes that record an error code. +class StunErrorCodeAttribute : public StunAttribute { + public: + static const uint16_t MIN_SIZE; + StunErrorCodeAttribute(uint16_t type, int code, const std::string& reason); + StunErrorCodeAttribute(uint16_t type, uint16_t length); + ~StunErrorCodeAttribute() override; + + StunAttributeValueType value_type() const override; + + // The combined error and class, e.g. 0x400. + int code() const; + void SetCode(int code); + + // The individual error components. + int eclass() const { return class_; } + int number() const { return number_; } + const std::string& reason() const { return reason_; } + void SetClass(uint8_t eclass) { class_ = eclass; } + void SetNumber(uint8_t number) { number_ = number; } + void SetReason(const std::string& reason); + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + uint8_t class_; + uint8_t number_; + std::string reason_; +}; + +// Implements STUN attributes that record a list of attribute names. +class StunUInt16ListAttribute : public StunAttribute { + public: + StunUInt16ListAttribute(uint16_t type, uint16_t length); + ~StunUInt16ListAttribute() override; + + StunAttributeValueType value_type() const override; + + size_t Size() const; + uint16_t GetType(int index) const; + void SetType(int index, uint16_t value); + void AddType(uint16_t value); + void AddTypeAtIndex(uint16_t index, uint16_t value); + + bool Read(rtc::ByteBufferReader* buf) override; + bool Write(rtc::ByteBufferWriter* buf) const override; + + private: + std::vector<uint16_t>* attr_types_; +}; + +// Return a string e.g "STUN BINDING request". +std::string StunMethodToString(int msg_type); + +// Returns the (successful) response type for the given request type. +// Returns -1 if `request_type` is not a valid request type. +int GetStunSuccessResponseType(int request_type); + +// Returns the error response type for the given request type. +// Returns -1 if `request_type` is not a valid request type. +int GetStunErrorResponseType(int request_type); + +// Returns whether a given message is a request type. +bool IsStunRequestType(int msg_type); + +// Returns whether a given message is an indication type. +bool IsStunIndicationType(int msg_type); + +// Returns whether a given response is a success type. +bool IsStunSuccessResponseType(int msg_type); + +// Returns whether a given response is an error type. +bool IsStunErrorResponseType(int msg_type); + +// Computes the STUN long-term credential hash. +bool ComputeStunCredentialHash(const std::string& username, + const std::string& realm, + const std::string& password, + std::string* hash); + +// Make a copy af `attribute` and return a new StunAttribute. +// This is useful if you don't care about what kind of attribute you +// are handling. +// +// The implementation copies by calling Write() followed by Read(). +// +// If `tmp_buffer` is supplied this buffer will be used, otherwise +// a buffer will created in the method. +std::unique_ptr<StunAttribute> CopyStunAttribute( + const StunAttribute& attribute, + rtc::ByteBufferWriter* tmp_buffer_ptr = 0); + +// TODO(?): Move the TURN/ICE stuff below out to separate files. +extern const char TURN_MAGIC_COOKIE_VALUE[4]; + +// "GTURN" STUN methods. +// TODO(?): Rename these methods to GTURN_ to make it clear they aren't +// part of standard STUN/TURN. +enum RelayMessageType { + // For now, using the same defs from TurnMessageType below. + // STUN_ALLOCATE_REQUEST = 0x0003, + // STUN_ALLOCATE_RESPONSE = 0x0103, + // STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, + STUN_SEND_REQUEST = 0x0004, + STUN_SEND_RESPONSE = 0x0104, + STUN_SEND_ERROR_RESPONSE = 0x0114, + STUN_DATA_INDICATION = 0x0115, +}; + +// "GTURN"-specific STUN attributes. +// TODO(?): Rename these attributes to GTURN_ to avoid conflicts. +enum RelayAttributeType { + STUN_ATTR_LIFETIME = 0x000d, // UInt32 + STUN_ATTR_MAGIC_COOKIE = 0x000f, // ByteString, 4 bytes + STUN_ATTR_BANDWIDTH = 0x0010, // UInt32 + STUN_ATTR_DESTINATION_ADDRESS = 0x0011, // Address + STUN_ATTR_SOURCE_ADDRESS2 = 0x0012, // Address + STUN_ATTR_DATA = 0x0013, // ByteString + STUN_ATTR_OPTIONS = 0x8001, // UInt32 +}; + +// A "GTURN" STUN message. +class RelayMessage : public StunMessage { + public: + using StunMessage::StunMessage; + + protected: + StunAttributeValueType GetAttributeValueType(int type) const override; + StunMessage* CreateNew() const override; +}; + +// Defined in TURN RFC 5766. +enum TurnMessageType : uint16_t { + STUN_ALLOCATE_REQUEST = 0x0003, + STUN_ALLOCATE_RESPONSE = 0x0103, + STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, + TURN_REFRESH_REQUEST = 0x0004, + TURN_REFRESH_RESPONSE = 0x0104, + TURN_REFRESH_ERROR_RESPONSE = 0x0114, + TURN_SEND_INDICATION = 0x0016, + TURN_DATA_INDICATION = 0x0017, + TURN_CREATE_PERMISSION_REQUEST = 0x0008, + TURN_CREATE_PERMISSION_RESPONSE = 0x0108, + TURN_CREATE_PERMISSION_ERROR_RESPONSE = 0x0118, + TURN_CHANNEL_BIND_REQUEST = 0x0009, + TURN_CHANNEL_BIND_RESPONSE = 0x0109, + TURN_CHANNEL_BIND_ERROR_RESPONSE = 0x0119, +}; + +enum TurnAttributeType { + STUN_ATTR_CHANNEL_NUMBER = 0x000C, // UInt32 + STUN_ATTR_TURN_LIFETIME = 0x000d, // UInt32 + STUN_ATTR_XOR_PEER_ADDRESS = 0x0012, // XorAddress + // TODO(mallinath) - Uncomment after RelayAttributes are renamed. + // STUN_ATTR_DATA = 0x0013, // ByteString + STUN_ATTR_XOR_RELAYED_ADDRESS = 0x0016, // XorAddress + STUN_ATTR_EVEN_PORT = 0x0018, // ByteString, 1 byte. + STUN_ATTR_REQUESTED_TRANSPORT = 0x0019, // UInt32 + STUN_ATTR_DONT_FRAGMENT = 0x001A, // No content, Length = 0 + STUN_ATTR_RESERVATION_TOKEN = 0x0022, // ByteString, 8 bytes. + // TODO(mallinath) - Rename STUN_ATTR_TURN_LIFETIME to STUN_ATTR_LIFETIME and + // STUN_ATTR_TURN_DATA to STUN_ATTR_DATA. Also rename RelayMessage attributes + // by appending G to attribute name. +}; + +// RFC 5766-defined errors. +enum TurnErrorType { + STUN_ERROR_FORBIDDEN = 403, + STUN_ERROR_ALLOCATION_MISMATCH = 437, + STUN_ERROR_WRONG_CREDENTIALS = 441, + STUN_ERROR_UNSUPPORTED_PROTOCOL = 442 +}; + +extern const int SERVER_NOT_REACHABLE_ERROR; + +extern const char STUN_ERROR_REASON_FORBIDDEN[]; +extern const char STUN_ERROR_REASON_ALLOCATION_MISMATCH[]; +extern const char STUN_ERROR_REASON_WRONG_CREDENTIALS[]; +extern const char STUN_ERROR_REASON_UNSUPPORTED_PROTOCOL[]; +class TurnMessage : public StunMessage { + public: + using StunMessage::StunMessage; + + protected: + StunAttributeValueType GetAttributeValueType(int type) const override; + StunMessage* CreateNew() const override; +}; + +enum IceAttributeType { + // RFC 5245 ICE STUN attributes. + STUN_ATTR_PRIORITY = 0x0024, // UInt32 + STUN_ATTR_USE_CANDIDATE = 0x0025, // No content, Length = 0 + STUN_ATTR_ICE_CONTROLLED = 0x8029, // UInt64 + STUN_ATTR_ICE_CONTROLLING = 0x802A, // UInt64 + // The following attributes are in the comprehension-optional range + // (0xC000-0xFFFF) and are not registered with IANA. These STUN attributes are + // intended for ICE and should NOT be used in generic use cases of STUN + // messages. + // + // Note that the value 0xC001 has already been assigned by IANA to + // ENF-FLOW-DESCRIPTION + // (https://www.iana.org/assignments/stun-parameters/stun-parameters.xml). + STUN_ATTR_NOMINATION = 0xC001, // UInt32 + // UInt32. The higher 16 bits are the network ID. The lower 16 bits are the + // network cost. + STUN_ATTR_GOOG_NETWORK_INFO = 0xC057, + // Experimental: Transaction ID of the last connectivity check received. + STUN_ATTR_GOOG_LAST_ICE_CHECK_RECEIVED = 0xC058, + // Uint16List. Miscellaneous attributes for future extension. + STUN_ATTR_GOOG_MISC_INFO = 0xC059, + // Obsolete. + STUN_ATTR_GOOG_OBSOLETE_1 = 0xC05A, + STUN_ATTR_GOOG_CONNECTION_ID = 0xC05B, // Not yet implemented. + STUN_ATTR_GOOG_DELTA = 0xC05C, // Not yet implemented. + STUN_ATTR_GOOG_DELTA_ACK = 0xC05D, // Not yet implemented. + // MESSAGE-INTEGRITY truncated to 32-bit. + STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32 = 0xC060, +}; + +// When adding new attributes to STUN_ATTR_GOOG_MISC_INFO +// (which is a list of uint16_t), append the indices of these attributes below +// and do NOT change the existing indices. The indices of attributes must be +// consistent with those used in ConnectionRequest::Prepare when forming a STUN +// message for the ICE connectivity check, and they are used when parsing a +// received STUN message. +enum class IceGoogMiscInfoBindingRequestAttributeIndex { + SUPPORT_GOOG_PING_VERSION = 0, +}; + +enum class IceGoogMiscInfoBindingResponseAttributeIndex { + SUPPORT_GOOG_PING_VERSION = 0, +}; + +// RFC 5245-defined errors. +enum IceErrorCode { + STUN_ERROR_ROLE_CONFLICT = 487, +}; +extern const char STUN_ERROR_REASON_ROLE_CONFLICT[]; + +// A RFC 5245 ICE STUN message. +class IceMessage : public StunMessage { + public: + using StunMessage::StunMessage; + + protected: + StunAttributeValueType GetAttributeValueType(int type) const override; + StunMessage* CreateNew() const override; +}; + +} // namespace cricket + +#endif // API_TRANSPORT_STUN_H_ diff --git a/third_party/libwebrtc/api/transport/stun_types_gn/moz.build b/third_party/libwebrtc/api/transport/stun_types_gn/moz.build new file mode 100644 index 0000000000..dd75da361b --- /dev/null +++ b/third_party/libwebrtc/api/transport/stun_types_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("stun_types_gn") diff --git a/third_party/libwebrtc/api/transport/stun_unittest.cc b/third_party/libwebrtc/api/transport/stun_unittest.cc new file mode 100644 index 0000000000..96ad45843b --- /dev/null +++ b/third_party/libwebrtc/api/transport/stun_unittest.cc @@ -0,0 +1,1882 @@ +/* + * Copyright 2004 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 "api/transport/stun.h" + +#include <string.h> + +#include <memory> +#include <string> +#include <utility> + +#include "rtc_base/arraysize.h" +#include "rtc_base/byte_buffer.h" +#include "rtc_base/byte_order.h" +#include "rtc_base/socket_address.h" +#include "system_wrappers/include/metrics.h" +#include "test/gtest.h" + +namespace cricket { + +class StunTest : public ::testing::Test { + protected: + void CheckStunHeader(const StunMessage& msg, + StunMessageType expected_type, + size_t expected_length) { + ASSERT_EQ(expected_type, msg.type()); + ASSERT_EQ(expected_length, msg.length()); + } + + void CheckStunTransactionID(const StunMessage& msg, + const unsigned char* expectedID, + size_t length) { + ASSERT_EQ(length, msg.transaction_id().size()); + ASSERT_EQ(length == kStunTransactionIdLength + 4, msg.IsLegacy()); + ASSERT_EQ(length == kStunTransactionIdLength, !msg.IsLegacy()); + ASSERT_EQ(0, memcmp(msg.transaction_id().c_str(), expectedID, length)); + } + + void CheckStunAddressAttribute(const StunAddressAttribute* addr, + StunAddressFamily expected_family, + int expected_port, + const rtc::IPAddress& expected_address) { + ASSERT_EQ(expected_family, addr->family()); + ASSERT_EQ(expected_port, addr->port()); + + if (addr->family() == STUN_ADDRESS_IPV4) { + in_addr v4_address = expected_address.ipv4_address(); + in_addr stun_address = addr->ipaddr().ipv4_address(); + ASSERT_EQ(0, memcmp(&v4_address, &stun_address, sizeof(stun_address))); + } else if (addr->family() == STUN_ADDRESS_IPV6) { + in6_addr v6_address = expected_address.ipv6_address(); + in6_addr stun_address = addr->ipaddr().ipv6_address(); + ASSERT_EQ(0, memcmp(&v6_address, &stun_address, sizeof(stun_address))); + } else { + ASSERT_TRUE(addr->family() == STUN_ADDRESS_IPV6 || + addr->family() == STUN_ADDRESS_IPV4); + } + } + + size_t ReadStunMessageTestCase(StunMessage* msg, + const unsigned char* testcase, + size_t size) { + const char* input = reinterpret_cast<const char*>(testcase); + rtc::ByteBufferReader buf(input, size); + if (msg->Read(&buf)) { + // Returns the size the stun message should report itself as being + return (size - 20); + } else { + return 0; + } + } +}; + +// Sample STUN packets with various attributes +// Gathered by wiresharking pjproject's pjnath test programs +// pjproject available at www.pjsip.org + +// clang-format off +// clang formatting doesn't respect inline comments. + +static const unsigned char kStunMessageWithIPv6MappedAddress[] = { + 0x00, 0x01, 0x00, 0x18, // message header + 0x21, 0x12, 0xa4, 0x42, // transaction id + 0x29, 0x1f, 0xcd, 0x7c, + 0xba, 0x58, 0xab, 0xd7, + 0xf2, 0x41, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x14, // Address type (mapped), length + 0x00, 0x02, 0xb8, 0x81, // family (IPv6), port + 0x24, 0x01, 0xfa, 0x00, // an IPv6 address + 0x00, 0x04, 0x10, 0x00, + 0xbe, 0x30, 0x5b, 0xff, + 0xfe, 0xe5, 0x00, 0xc3 +}; + +static const unsigned char kStunMessageWithIPv4MappedAddress[] = { + 0x01, 0x01, 0x00, 0x0c, // binding response, length 12 + 0x21, 0x12, 0xa4, 0x42, // magic cookie + 0x29, 0x1f, 0xcd, 0x7c, // transaction ID + 0xba, 0x58, 0xab, 0xd7, + 0xf2, 0x41, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x08, // Mapped, 8 byte length + 0x00, 0x01, 0x9d, 0xfc, // AF_INET, unxor-ed port + 0xac, 0x17, 0x44, 0xe6 // IPv4 address +}; + +// Test XOR-mapped IP addresses: +static const unsigned char kStunMessageWithIPv6XorMappedAddress[] = { + 0x01, 0x01, 0x00, 0x18, // message header (binding response) + 0x21, 0x12, 0xa4, 0x42, // magic cookie (rfc5389) + 0xe3, 0xa9, 0x46, 0xe1, // transaction ID + 0x7c, 0x00, 0xc2, 0x62, + 0x54, 0x08, 0x01, 0x00, + 0x00, 0x20, 0x00, 0x14, // Address Type (XOR), length + 0x00, 0x02, 0xcb, 0x5b, // family, XOR-ed port + 0x05, 0x13, 0x5e, 0x42, // XOR-ed IPv6 address + 0xe3, 0xad, 0x56, 0xe1, + 0xc2, 0x30, 0x99, 0x9d, + 0xaa, 0xed, 0x01, 0xc3 +}; + +static const unsigned char kStunMessageWithIPv4XorMappedAddress[] = { + 0x01, 0x01, 0x00, 0x0c, // message header (binding response) + 0x21, 0x12, 0xa4, 0x42, // magic cookie + 0x29, 0x1f, 0xcd, 0x7c, // transaction ID + 0xba, 0x58, 0xab, 0xd7, + 0xf2, 0x41, 0x01, 0x00, + 0x00, 0x20, 0x00, 0x08, // address type (xor), length + 0x00, 0x01, 0xfc, 0xb5, // family (AF_INET), XOR-ed port + 0x8d, 0x05, 0xe0, 0xa4 // IPv4 address +}; + +// ByteString Attribute (username) +static const unsigned char kStunMessageWithByteStringAttribute[] = { + 0x00, 0x01, 0x00, 0x0c, + 0x21, 0x12, 0xa4, 0x42, + 0xe3, 0xa9, 0x46, 0xe1, + 0x7c, 0x00, 0xc2, 0x62, + 0x54, 0x08, 0x01, 0x00, + 0x00, 0x06, 0x00, 0x08, // username attribute (length 8) + 0x61, 0x62, 0x63, 0x64, // abcdefgh + 0x65, 0x66, 0x67, 0x68 +}; + +// Message with an unknown but comprehensible optional attribute. +// Parsing should succeed despite this unknown attribute. +static const unsigned char kStunMessageWithUnknownAttribute[] = { + 0x00, 0x01, 0x00, 0x14, + 0x21, 0x12, 0xa4, 0x42, + 0xe3, 0xa9, 0x46, 0xe1, + 0x7c, 0x00, 0xc2, 0x62, + 0x54, 0x08, 0x01, 0x00, + 0x00, 0xaa, 0x00, 0x07, // Unknown attribute, length 7 (needs padding!) + 0x61, 0x62, 0x63, 0x64, // abcdefg + padding + 0x65, 0x66, 0x67, 0x00, + 0x00, 0x06, 0x00, 0x03, // Followed by a known attribute we can + 0x61, 0x62, 0x63, 0x00 // check for (username of length 3) +}; + +// ByteString Attribute (username) with padding byte +static const unsigned char kStunMessageWithPaddedByteStringAttribute[] = { + 0x00, 0x01, 0x00, 0x08, + 0x21, 0x12, 0xa4, 0x42, + 0xe3, 0xa9, 0x46, 0xe1, + 0x7c, 0x00, 0xc2, 0x62, + 0x54, 0x08, 0x01, 0x00, + 0x00, 0x06, 0x00, 0x03, // username attribute (length 3) + 0x61, 0x62, 0x63, 0xcc // abc +}; + +// Message with an Unknown Attributes (uint16_t list) attribute. +static const unsigned char kStunMessageWithUInt16ListAttribute[] = { + 0x00, 0x01, 0x00, 0x0c, + 0x21, 0x12, 0xa4, 0x42, + 0xe3, 0xa9, 0x46, 0xe1, + 0x7c, 0x00, 0xc2, 0x62, + 0x54, 0x08, 0x01, 0x00, + 0x00, 0x0a, 0x00, 0x06, // username attribute (length 6) + 0x00, 0x01, 0x10, 0x00, // three attributes plus padding + 0xAB, 0xCU, 0xBE, 0xEF +}; + +// Error response message (unauthorized) +static const unsigned char kStunMessageWithErrorAttribute[] = { + 0x01, 0x11, 0x00, 0x14, + 0x21, 0x12, 0xa4, 0x42, + 0x29, 0x1f, 0xcd, 0x7c, + 0xba, 0x58, 0xab, 0xd7, + 0xf2, 0x41, 0x01, 0x00, + 0x00, 0x09, 0x00, 0x10, + 0x00, 0x00, 0x04, 0x01, + 0x55, 0x6e, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x65, 0x64 +}; + +// Sample messages with an invalid length Field + +// The actual length in bytes of the invalid messages (including STUN header) +static const int kRealLengthOfInvalidLengthTestCases = 32; + +static const unsigned char kStunMessageWithZeroLength[] = { + 0x00, 0x01, 0x00, 0x00, // length of 0 (last 2 bytes) + 0x21, 0x12, 0xA4, 0x42, // magic cookie + '0', '1', '2', '3', // transaction id + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 0x00, 0x20, 0x00, 0x08, // xor mapped address + 0x00, 0x01, 0x21, 0x1F, + 0x21, 0x12, 0xA4, 0x53, +}; + +static const unsigned char kStunMessageWithExcessLength[] = { + 0x00, 0x01, 0x00, 0x55, // length of 85 + 0x21, 0x12, 0xA4, 0x42, // magic cookie + '0', '1', '2', '3', // transaction id + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 0x00, 0x20, 0x00, 0x08, // xor mapped address + 0x00, 0x01, 0x21, 0x1F, + 0x21, 0x12, 0xA4, 0x53, +}; + +static const unsigned char kStunMessageWithSmallLength[] = { + 0x00, 0x01, 0x00, 0x03, // length of 3 + 0x21, 0x12, 0xA4, 0x42, // magic cookie + '0', '1', '2', '3', // transaction id + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 0x00, 0x20, 0x00, 0x08, // xor mapped address + 0x00, 0x01, 0x21, 0x1F, + 0x21, 0x12, 0xA4, 0x53, +}; + +static const unsigned char kStunMessageWithBadHmacAtEnd[] = { + 0x00, 0x01, 0x00, 0x14, // message length exactly 20 + 0x21, 0x12, 0xA4, 0x42, // magic cookie + '0', '1', '2', '3', // transaction ID + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 0x00, 0x08, 0x00, 0x14, // type=STUN_ATTR_MESSAGE_INTEGRITY, length=20 + '0', '0', '0', '0', // We lied, there are only 16 bytes of HMAC. + '0', '0', '0', '0', + '0', '0', '0', '0', + '0', '0', '0', '0', +}; + +// RTCP packet, for testing we correctly ignore non stun packet types. +// V=2, P=false, RC=0, Type=200, Len=6, Sender-SSRC=85, etc +static const unsigned char kRtcpPacket[] = { + 0x80, 0xc8, 0x00, 0x06, 0x00, 0x00, 0x00, 0x55, + 0xce, 0xa5, 0x18, 0x3a, 0x39, 0xcc, 0x7d, 0x09, + 0x23, 0xed, 0x19, 0x07, 0x00, 0x00, 0x01, 0x56, + 0x00, 0x03, 0x73, 0x50, +}; + + +// RFC5769 Test Vectors +// Software name (request): "STUN test client" (without quotes) +// Software name (response): "test vector" (without quotes) +// Username: "evtj:h6vY" (without quotes) +// Password: "VOkJxbRl1RmTxUk/WvJxBt" (without quotes) +static const unsigned char kRfc5769SampleMsgTransactionId[] = { + 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae +}; +static const char kRfc5769SampleMsgClientSoftware[] = "STUN test client"; +static const char kRfc5769SampleMsgServerSoftware[] = "test vector"; +static const char kRfc5769SampleMsgUsername[] = "evtj:h6vY"; +static const char kRfc5769SampleMsgPassword[] = "VOkJxbRl1RmTxUk/WvJxBt"; +static const rtc::SocketAddress kRfc5769SampleMsgMappedAddress( + "192.0.2.1", 32853); +static const rtc::SocketAddress kRfc5769SampleMsgIPv6MappedAddress( + "2001:db8:1234:5678:11:2233:4455:6677", 32853); + +static const unsigned char kRfc5769SampleMsgWithAuthTransactionId[] = { + 0x78, 0xad, 0x34, 0x33, 0xc6, 0xad, 0x72, 0xc0, 0x29, 0xda, 0x41, 0x2e +}; +static const char kRfc5769SampleMsgWithAuthUsername[] = + "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83\xe3\x82\xaf\xe3\x82\xb9"; +static const char kRfc5769SampleMsgWithAuthPassword[] = "TheMatrIX"; +static const char kRfc5769SampleMsgWithAuthNonce[] = + "f//499k954d6OL34oL9FSTvy64sA"; +static const char kRfc5769SampleMsgWithAuthRealm[] = "example.org"; + +// 2.1. Sample Request +static const unsigned char kRfc5769SampleRequest[] = { + 0x00, 0x01, 0x00, 0x58, // Request type and message length + 0x21, 0x12, 0xa4, 0x42, // Magic cookie + 0xb7, 0xe7, 0xa7, 0x01, // } + 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID + 0xfa, 0x87, 0xdf, 0xae, // } + 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header + 0x53, 0x54, 0x55, 0x4e, // } + 0x20, 0x74, 0x65, 0x73, // } User-agent... + 0x74, 0x20, 0x63, 0x6c, // } ...name + 0x69, 0x65, 0x6e, 0x74, // } + 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header + 0x6e, 0x00, 0x01, 0xff, // ICE priority value + 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header + 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker... + 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control + 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header + 0x65, 0x76, 0x74, 0x6a, // } + 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes) + 0x59, 0x20, 0x20, 0x20, // } + 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header + 0x9a, 0xea, 0xa7, 0x0c, // } + 0xbf, 0xd8, 0xcb, 0x56, // } + 0x78, 0x1e, 0xf2, 0xb5, // } HMAC-SHA1 fingerprint + 0xb2, 0xd3, 0xf2, 0x49, // } + 0xc1, 0xb5, 0x71, 0xa2, // } + 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header + 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint +}; + +// 2.1. Sample Request +static const unsigned char kSampleRequestMI32[] = { + 0x00, 0x01, 0x00, 0x48, // Request type and message length + 0x21, 0x12, 0xa4, 0x42, // Magic cookie + 0xb7, 0xe7, 0xa7, 0x01, // } + 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID + 0xfa, 0x87, 0xdf, 0xae, // } + 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header + 0x53, 0x54, 0x55, 0x4e, // } + 0x20, 0x74, 0x65, 0x73, // } User-agent... + 0x74, 0x20, 0x63, 0x6c, // } ...name + 0x69, 0x65, 0x6e, 0x74, // } + 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header + 0x6e, 0x00, 0x01, 0xff, // ICE priority value + 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header + 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker... + 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control + 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header + 0x65, 0x76, 0x74, 0x6a, // } + 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes) + 0x59, 0x20, 0x20, 0x20, // } + 0xC0, 0x60, 0x00, 0x04, // MESSAGE-INTEGRITY-32 attribute header + 0x45, 0x45, 0xce, 0x7c, // } HMAC-SHA1 fingerprint (first 32 bit) + 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header + 0xe5, 0x7a, 0x3b, 0xcf // CRC32 fingerprint +}; + +// 2.2. Sample IPv4 Response +static const unsigned char kRfc5769SampleResponse[] = { + 0x01, 0x01, 0x00, 0x3c, // Response type and message length + 0x21, 0x12, 0xa4, 0x42, // Magic cookie + 0xb7, 0xe7, 0xa7, 0x01, // } + 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID + 0xfa, 0x87, 0xdf, 0xae, // } + 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header + 0x74, 0x65, 0x73, 0x74, // } + 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name + 0x74, 0x6f, 0x72, 0x20, // } + 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header + 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port + 0xe1, 0x12, 0xa6, 0x43, // Xor'd mapped IPv4 address + 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header + 0x2b, 0x91, 0xf5, 0x99, // } + 0xfd, 0x9e, 0x90, 0xc3, // } + 0x8c, 0x74, 0x89, 0xf9, // } HMAC-SHA1 fingerprint + 0x2a, 0xf9, 0xba, 0x53, // } + 0xf0, 0x6b, 0xe7, 0xd7, // } + 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header + 0xc0, 0x7d, 0x4c, 0x96 // CRC32 fingerprint +}; + +// 2.3. Sample IPv6 Response +static const unsigned char kRfc5769SampleResponseIPv6[] = { + 0x01, 0x01, 0x00, 0x48, // Response type and message length + 0x21, 0x12, 0xa4, 0x42, // Magic cookie + 0xb7, 0xe7, 0xa7, 0x01, // } + 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID + 0xfa, 0x87, 0xdf, 0xae, // } + 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header + 0x74, 0x65, 0x73, 0x74, // } + 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name + 0x74, 0x6f, 0x72, 0x20, // } + 0x00, 0x20, 0x00, 0x14, // XOR-MAPPED-ADDRESS attribute header + 0x00, 0x02, 0xa1, 0x47, // Address family (IPv6) and xor'd mapped port. + 0x01, 0x13, 0xa9, 0xfa, // } + 0xa5, 0xd3, 0xf1, 0x79, // } Xor'd mapped IPv6 address + 0xbc, 0x25, 0xf4, 0xb5, // } + 0xbe, 0xd2, 0xb9, 0xd9, // } + 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header + 0xa3, 0x82, 0x95, 0x4e, // } + 0x4b, 0xe6, 0x7b, 0xf1, // } + 0x17, 0x84, 0xc9, 0x7c, // } HMAC-SHA1 fingerprint + 0x82, 0x92, 0xc2, 0x75, // } + 0xbf, 0xe3, 0xed, 0x41, // } + 0x80, 0x28, 0x00, 0x04, // FINGERPRINT attribute header + 0xc8, 0xfb, 0x0b, 0x4c // CRC32 fingerprint +}; + +// 2.4. Sample Request with Long-Term Authentication +static const unsigned char kRfc5769SampleRequestLongTermAuth[] = { + 0x00, 0x01, 0x00, 0x60, // Request type and message length + 0x21, 0x12, 0xa4, 0x42, // Magic cookie + 0x78, 0xad, 0x34, 0x33, // } + 0xc6, 0xad, 0x72, 0xc0, // } Transaction ID + 0x29, 0xda, 0x41, 0x2e, // } + 0x00, 0x06, 0x00, 0x12, // USERNAME attribute header + 0xe3, 0x83, 0x9e, 0xe3, // } + 0x83, 0x88, 0xe3, 0x83, // } + 0xaa, 0xe3, 0x83, 0x83, // } Username value (18 bytes) and padding (2 bytes) + 0xe3, 0x82, 0xaf, 0xe3, // } + 0x82, 0xb9, 0x00, 0x00, // } + 0x00, 0x15, 0x00, 0x1c, // NONCE attribute header + 0x66, 0x2f, 0x2f, 0x34, // } + 0x39, 0x39, 0x6b, 0x39, // } + 0x35, 0x34, 0x64, 0x36, // } + 0x4f, 0x4c, 0x33, 0x34, // } Nonce value + 0x6f, 0x4c, 0x39, 0x46, // } + 0x53, 0x54, 0x76, 0x79, // } + 0x36, 0x34, 0x73, 0x41, // } + 0x00, 0x14, 0x00, 0x0b, // REALM attribute header + 0x65, 0x78, 0x61, 0x6d, // } + 0x70, 0x6c, 0x65, 0x2e, // } Realm value (11 bytes) and padding (1 byte) + 0x6f, 0x72, 0x67, 0x00, // } + 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY attribute header + 0xf6, 0x70, 0x24, 0x65, // } + 0x6d, 0xd6, 0x4a, 0x3e, // } + 0x02, 0xb8, 0xe0, 0x71, // } HMAC-SHA1 fingerprint + 0x2e, 0x85, 0xc9, 0xa2, // } + 0x8c, 0xa8, 0x96, 0x66 // } +}; + +// Length parameter is changed to 0x38 from 0x58. +// AddMessageIntegrity will add MI information and update the length param +// accordingly. +static const unsigned char kRfc5769SampleRequestWithoutMI[] = { + 0x00, 0x01, 0x00, 0x38, // Request type and message length + 0x21, 0x12, 0xa4, 0x42, // Magic cookie + 0xb7, 0xe7, 0xa7, 0x01, // } + 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID + 0xfa, 0x87, 0xdf, 0xae, // } + 0x80, 0x22, 0x00, 0x10, // SOFTWARE attribute header + 0x53, 0x54, 0x55, 0x4e, // } + 0x20, 0x74, 0x65, 0x73, // } User-agent... + 0x74, 0x20, 0x63, 0x6c, // } ...name + 0x69, 0x65, 0x6e, 0x74, // } + 0x00, 0x24, 0x00, 0x04, // PRIORITY attribute header + 0x6e, 0x00, 0x01, 0xff, // ICE priority value + 0x80, 0x29, 0x00, 0x08, // ICE-CONTROLLED attribute header + 0x93, 0x2f, 0xf9, 0xb1, // } Pseudo-random tie breaker... + 0x51, 0x26, 0x3b, 0x36, // } ...for ICE control + 0x00, 0x06, 0x00, 0x09, // USERNAME attribute header + 0x65, 0x76, 0x74, 0x6a, // } + 0x3a, 0x68, 0x36, 0x76, // } Username (9 bytes) and padding (3 bytes) + 0x59, 0x20, 0x20, 0x20 // } +}; + +// This HMAC differs from the RFC 5769 SampleRequest message. This differs +// because spec uses 0x20 for the padding where as our implementation uses 0. +static const unsigned char kCalculatedHmac1[] = { + 0x79, 0x07, 0xc2, 0xd2, // } + 0xed, 0xbf, 0xea, 0x48, // } + 0x0e, 0x4c, 0x76, 0xd8, // } HMAC-SHA1 fingerprint + 0x29, 0x62, 0xd5, 0xc3, // } + 0x74, 0x2a, 0xf9, 0xe3 // } +}; + +// This truncated HMAC differs from kCalculatedHmac1 +// above since the sum is computed including header +// and the header is different since the message is shorter +// than when MESSAGE-INTEGRITY is used. +static const unsigned char kCalculatedHmac1_32[] = { + 0xda, 0x39, 0xde, 0x5d, // } +}; + +// Length parameter is changed to 0x1c from 0x3c. +// AddMessageIntegrity will add MI information and update the length param +// accordingly. +static const unsigned char kRfc5769SampleResponseWithoutMI[] = { + 0x01, 0x01, 0x00, 0x1c, // Response type and message length + 0x21, 0x12, 0xa4, 0x42, // Magic cookie + 0xb7, 0xe7, 0xa7, 0x01, // } + 0xbc, 0x34, 0xd6, 0x86, // } Transaction ID + 0xfa, 0x87, 0xdf, 0xae, // } + 0x80, 0x22, 0x00, 0x0b, // SOFTWARE attribute header + 0x74, 0x65, 0x73, 0x74, // } + 0x20, 0x76, 0x65, 0x63, // } UTF-8 server name + 0x74, 0x6f, 0x72, 0x20, // } + 0x00, 0x20, 0x00, 0x08, // XOR-MAPPED-ADDRESS attribute header + 0x00, 0x01, 0xa1, 0x47, // Address family (IPv4) and xor'd mapped port + 0xe1, 0x12, 0xa6, 0x43 // Xor'd mapped IPv4 address +}; + +// This HMAC differs from the RFC 5769 SampleResponse message. This differs +// because spec uses 0x20 for the padding where as our implementation uses 0. +static const unsigned char kCalculatedHmac2[] = { + 0x5d, 0x6b, 0x58, 0xbe, // } + 0xad, 0x94, 0xe0, 0x7e, // } + 0xef, 0x0d, 0xfc, 0x12, // } HMAC-SHA1 fingerprint + 0x82, 0xa2, 0xbd, 0x08, // } + 0x43, 0x14, 0x10, 0x28 // } +}; + +// This truncated HMAC differs from kCalculatedHmac2 +// above since the sum is computed including header +// and the header is different since the message is shorter +// than when MESSAGE-INTEGRITY is used. +static const unsigned char kCalculatedHmac2_32[] = { + 0xe7, 0x5c, 0xd3, 0x16, // } +}; + +// clang-format on + +// A transaction ID without the 'magic cookie' portion +// pjnat's test programs use this transaction ID a lot. +const unsigned char kTestTransactionId1[] = {0x029, 0x01f, 0x0cd, 0x07c, + 0x0ba, 0x058, 0x0ab, 0x0d7, + 0x0f2, 0x041, 0x001, 0x000}; + +// They use this one sometimes too. +const unsigned char kTestTransactionId2[] = {0x0e3, 0x0a9, 0x046, 0x0e1, + 0x07c, 0x000, 0x0c2, 0x062, + 0x054, 0x008, 0x001, 0x000}; + +const in6_addr kIPv6TestAddress1 = { + {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x00, 0xbe, 0x30, 0x5b, 0xff, + 0xfe, 0xe5, 0x00, 0xc3}}}; +const in6_addr kIPv6TestAddress2 = { + {{0x24, 0x01, 0xfa, 0x00, 0x00, 0x04, 0x10, 0x12, 0x06, 0x0c, 0xce, 0xff, + 0xfe, 0x1f, 0x61, 0xa4}}}; + +#ifdef WEBRTC_POSIX +const in_addr kIPv4TestAddress1 = {0xe64417ac}; +#elif defined WEBRTC_WIN +// Windows in_addr has a union with a uchar[] array first. +const in_addr kIPv4TestAddress1 = {{{0x0ac, 0x017, 0x044, 0x0e6}}}; +#endif +const char kTestUserName1[] = "abcdefgh"; +const char kTestUserName2[] = "abc"; +const char kTestErrorReason[] = "Unauthorized"; +const int kTestErrorClass = 4; +const int kTestErrorNumber = 1; +const int kTestErrorCode = 401; + +const int kTestMessagePort1 = 59977; +const int kTestMessagePort2 = 47233; +const int kTestMessagePort3 = 56743; +const int kTestMessagePort4 = 40444; + +#define ReadStunMessage(X, Y) ReadStunMessageTestCase(X, Y, sizeof(Y)); + +// Test that the GetStun*Type and IsStun*Type methods work as expected. +TEST_F(StunTest, MessageTypes) { + EXPECT_EQ(STUN_BINDING_RESPONSE, + GetStunSuccessResponseType(STUN_BINDING_REQUEST)); + EXPECT_EQ(STUN_BINDING_ERROR_RESPONSE, + GetStunErrorResponseType(STUN_BINDING_REQUEST)); + EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_INDICATION)); + EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_RESPONSE)); + EXPECT_EQ(-1, GetStunSuccessResponseType(STUN_BINDING_ERROR_RESPONSE)); + EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_INDICATION)); + EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_RESPONSE)); + EXPECT_EQ(-1, GetStunErrorResponseType(STUN_BINDING_ERROR_RESPONSE)); + + int types[] = {STUN_BINDING_REQUEST, STUN_BINDING_INDICATION, + STUN_BINDING_RESPONSE, STUN_BINDING_ERROR_RESPONSE}; + for (size_t i = 0; i < arraysize(types); ++i) { + EXPECT_EQ(i == 0U, IsStunRequestType(types[i])); + EXPECT_EQ(i == 1U, IsStunIndicationType(types[i])); + EXPECT_EQ(i == 2U, IsStunSuccessResponseType(types[i])); + EXPECT_EQ(i == 3U, IsStunErrorResponseType(types[i])); + EXPECT_EQ(1, types[i] & 0xFEEF); + } +} + +TEST_F(StunTest, ReadMessageWithIPv4AddressAttribute) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4MappedAddress); + CheckStunHeader(msg, STUN_BINDING_RESPONSE, size); + CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength); + + const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS); + rtc::IPAddress test_address(kIPv4TestAddress1); + CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4, + test_address); +} + +TEST_F(StunTest, ReadMessageWithIPv4XorAddressAttribute) { + StunMessage msg; + StunMessage msg2; + size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress); + CheckStunHeader(msg, STUN_BINDING_RESPONSE, size); + CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength); + + const StunAddressAttribute* addr = + msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); + rtc::IPAddress test_address(kIPv4TestAddress1); + CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3, + test_address); +} + +TEST_F(StunTest, ReadMessageWithIPv6AddressAttribute) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress); + CheckStunHeader(msg, STUN_BINDING_REQUEST, size); + CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength); + + rtc::IPAddress test_address(kIPv6TestAddress1); + + const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS); + CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2, + test_address); +} + +TEST_F(StunTest, ReadMessageWithInvalidAddressAttribute) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress); + CheckStunHeader(msg, STUN_BINDING_REQUEST, size); + CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength); + + rtc::IPAddress test_address(kIPv6TestAddress1); + + const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS); + CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort2, + test_address); +} + +TEST_F(StunTest, ReadMessageWithIPv6XorAddressAttribute) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress); + + rtc::IPAddress test_address(kIPv6TestAddress1); + + CheckStunHeader(msg, STUN_BINDING_RESPONSE, size); + CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength); + + const StunAddressAttribute* addr = + msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); + CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1, + test_address); +} + +// Read the RFC5389 fields from the RFC5769 sample STUN request. +TEST_F(StunTest, ReadRfc5769RequestMessage) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kRfc5769SampleRequest); + CheckStunHeader(msg, STUN_BINDING_REQUEST, size); + CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId, + kStunTransactionIdLength); + + const StunByteStringAttribute* software = + msg.GetByteString(STUN_ATTR_SOFTWARE); + ASSERT_TRUE(software != NULL); + EXPECT_EQ(kRfc5769SampleMsgClientSoftware, software->string_view()); + + const StunByteStringAttribute* username = + msg.GetByteString(STUN_ATTR_USERNAME); + ASSERT_TRUE(username != NULL); + EXPECT_EQ(kRfc5769SampleMsgUsername, username->string_view()); + + // Actual M-I value checked in a later test. + ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL); + + // Fingerprint checked in a later test, but double-check the value here. + const StunUInt32Attribute* fingerprint = msg.GetUInt32(STUN_ATTR_FINGERPRINT); + ASSERT_TRUE(fingerprint != NULL); + EXPECT_EQ(0xe57a3bcf, fingerprint->value()); +} + +// Read the RFC5389 fields from the RFC5769 sample STUN response. +TEST_F(StunTest, ReadRfc5769ResponseMessage) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kRfc5769SampleResponse); + CheckStunHeader(msg, STUN_BINDING_RESPONSE, size); + CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId, + kStunTransactionIdLength); + + const StunByteStringAttribute* software = + msg.GetByteString(STUN_ATTR_SOFTWARE); + ASSERT_TRUE(software != NULL); + EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->string_view()); + + const StunAddressAttribute* mapped_address = + msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); + ASSERT_TRUE(mapped_address != NULL); + EXPECT_EQ(kRfc5769SampleMsgMappedAddress, mapped_address->GetAddress()); + + // Actual M-I and fingerprint checked in later tests. + ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL); + ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL); +} + +// Read the RFC5389 fields from the RFC5769 sample STUN response for IPv6. +TEST_F(StunTest, ReadRfc5769ResponseMessageIPv6) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kRfc5769SampleResponseIPv6); + CheckStunHeader(msg, STUN_BINDING_RESPONSE, size); + CheckStunTransactionID(msg, kRfc5769SampleMsgTransactionId, + kStunTransactionIdLength); + + const StunByteStringAttribute* software = + msg.GetByteString(STUN_ATTR_SOFTWARE); + ASSERT_TRUE(software != NULL); + EXPECT_EQ(kRfc5769SampleMsgServerSoftware, software->string_view()); + + const StunAddressAttribute* mapped_address = + msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); + ASSERT_TRUE(mapped_address != NULL); + EXPECT_EQ(kRfc5769SampleMsgIPv6MappedAddress, mapped_address->GetAddress()); + + // Actual M-I and fingerprint checked in later tests. + ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL); + ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) != NULL); +} + +// Read the RFC5389 fields from the RFC5769 sample STUN response with auth. +TEST_F(StunTest, ReadRfc5769RequestMessageLongTermAuth) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kRfc5769SampleRequestLongTermAuth); + CheckStunHeader(msg, STUN_BINDING_REQUEST, size); + CheckStunTransactionID(msg, kRfc5769SampleMsgWithAuthTransactionId, + kStunTransactionIdLength); + + const StunByteStringAttribute* username = + msg.GetByteString(STUN_ATTR_USERNAME); + ASSERT_TRUE(username != NULL); + EXPECT_EQ(kRfc5769SampleMsgWithAuthUsername, username->string_view()); + + const StunByteStringAttribute* nonce = msg.GetByteString(STUN_ATTR_NONCE); + ASSERT_TRUE(nonce != NULL); + EXPECT_EQ(kRfc5769SampleMsgWithAuthNonce, nonce->string_view()); + + const StunByteStringAttribute* realm = msg.GetByteString(STUN_ATTR_REALM); + ASSERT_TRUE(realm != NULL); + EXPECT_EQ(kRfc5769SampleMsgWithAuthRealm, realm->string_view()); + + // No fingerprint, actual M-I checked in later tests. + ASSERT_TRUE(msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY) != NULL); + ASSERT_TRUE(msg.GetUInt32(STUN_ATTR_FINGERPRINT) == NULL); +} + +// The RFC3489 packet in this test is the same as +// kStunMessageWithIPv4MappedAddress, but with a different value where the +// magic cookie was. +TEST_F(StunTest, ReadLegacyMessage) { + unsigned char rfc3489_packet[sizeof(kStunMessageWithIPv4MappedAddress)]; + memcpy(rfc3489_packet, kStunMessageWithIPv4MappedAddress, + sizeof(kStunMessageWithIPv4MappedAddress)); + // Overwrite the magic cookie here. + memcpy(&rfc3489_packet[4], "ABCD", 4); + + StunMessage msg; + size_t size = ReadStunMessage(&msg, rfc3489_packet); + CheckStunHeader(msg, STUN_BINDING_RESPONSE, size); + CheckStunTransactionID(msg, &rfc3489_packet[4], kStunTransactionIdLength + 4); + + const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS); + rtc::IPAddress test_address(kIPv4TestAddress1); + CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort4, + test_address); +} + +TEST_F(StunTest, SetIPv6XorAddressAttributeOwner) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kStunMessageWithIPv6XorMappedAddress); + + rtc::IPAddress test_address(kIPv6TestAddress1); + + CheckStunHeader(msg, STUN_BINDING_RESPONSE, size); + CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength); + + const StunAddressAttribute* addr = + msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); + CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV6, kTestMessagePort1, + test_address); + + // Owner with a different transaction ID. + StunMessage msg2(STUN_INVALID_MESSAGE_TYPE, "ABCDABCDABCD"); + StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL); + addr2.SetIP(addr->ipaddr()); + addr2.SetPort(addr->port()); + addr2.SetOwner(&msg2); + // The internal IP address shouldn't change. + ASSERT_EQ(addr2.ipaddr(), addr->ipaddr()); + + rtc::ByteBufferWriter correct_buf; + rtc::ByteBufferWriter wrong_buf; + EXPECT_TRUE(addr->Write(&correct_buf)); + EXPECT_TRUE(addr2.Write(&wrong_buf)); + // But when written out, the buffers should look different. + ASSERT_NE(0, + memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length())); + // And when reading a known good value, the address should be wrong. + rtc::ByteBufferReader read_buf(correct_buf); + addr2.Read(&read_buf); + ASSERT_NE(addr->ipaddr(), addr2.ipaddr()); + addr2.SetIP(addr->ipaddr()); + addr2.SetPort(addr->port()); + // Try writing with no owner at all, should fail and write nothing. + addr2.SetOwner(NULL); + ASSERT_EQ(addr2.ipaddr(), addr->ipaddr()); + wrong_buf.Clear(); + EXPECT_FALSE(addr2.Write(&wrong_buf)); + ASSERT_EQ(0U, wrong_buf.Length()); +} + +TEST_F(StunTest, SetIPv4XorAddressAttributeOwner) { + // Unlike the IPv6XorAddressAttributeOwner test, IPv4 XOR address attributes + // should _not_ be affected by a change in owner. IPv4 XOR address uses the + // magic cookie value which is fixed. + StunMessage msg; + size_t size = ReadStunMessage(&msg, kStunMessageWithIPv4XorMappedAddress); + + rtc::IPAddress test_address(kIPv4TestAddress1); + + CheckStunHeader(msg, STUN_BINDING_RESPONSE, size); + CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength); + + const StunAddressAttribute* addr = + msg.GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); + CheckStunAddressAttribute(addr, STUN_ADDRESS_IPV4, kTestMessagePort3, + test_address); + + // Owner with a different transaction ID. + StunMessage msg2(STUN_INVALID_MESSAGE_TYPE, "ABCDABCDABCD"); + StunXorAddressAttribute addr2(STUN_ATTR_XOR_MAPPED_ADDRESS, 20, NULL); + addr2.SetIP(addr->ipaddr()); + addr2.SetPort(addr->port()); + addr2.SetOwner(&msg2); + // The internal IP address shouldn't change. + ASSERT_EQ(addr2.ipaddr(), addr->ipaddr()); + + rtc::ByteBufferWriter correct_buf; + rtc::ByteBufferWriter wrong_buf; + EXPECT_TRUE(addr->Write(&correct_buf)); + EXPECT_TRUE(addr2.Write(&wrong_buf)); + // The same address data should be written. + ASSERT_EQ(0, + memcmp(correct_buf.Data(), wrong_buf.Data(), wrong_buf.Length())); + // And an attribute should be able to un-XOR an address belonging to a message + // with a different transaction ID. + rtc::ByteBufferReader read_buf(correct_buf); + EXPECT_TRUE(addr2.Read(&read_buf)); + ASSERT_EQ(addr->ipaddr(), addr2.ipaddr()); + + // However, no owner is still an error, should fail and write nothing. + addr2.SetOwner(NULL); + ASSERT_EQ(addr2.ipaddr(), addr->ipaddr()); + wrong_buf.Clear(); + EXPECT_FALSE(addr2.Write(&wrong_buf)); +} + +TEST_F(StunTest, CreateIPv6AddressAttribute) { + rtc::IPAddress test_ip(kIPv6TestAddress2); + + auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); + rtc::SocketAddress test_addr(test_ip, kTestMessagePort2); + addr->SetAddress(test_addr); + + CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, kTestMessagePort2, + test_ip); +} + +TEST_F(StunTest, CreateIPv4AddressAttribute) { + struct in_addr test_in_addr; + test_in_addr.s_addr = 0xBEB0B0BE; + rtc::IPAddress test_ip(test_in_addr); + + auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); + rtc::SocketAddress test_addr(test_ip, kTestMessagePort2); + addr->SetAddress(test_addr); + + CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV4, kTestMessagePort2, + test_ip); +} + +// Test that we don't care what order we set the parts of an address +TEST_F(StunTest, CreateAddressInArbitraryOrder) { + auto addr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS); + // Port first + addr->SetPort(kTestMessagePort1); + addr->SetIP(rtc::IPAddress(kIPv4TestAddress1)); + ASSERT_EQ(kTestMessagePort1, addr->port()); + ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr->ipaddr()); + + auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS); + // IP first + addr2->SetIP(rtc::IPAddress(kIPv4TestAddress1)); + addr2->SetPort(kTestMessagePort2); + ASSERT_EQ(kTestMessagePort2, addr2->port()); + ASSERT_EQ(rtc::IPAddress(kIPv4TestAddress1), addr2->ipaddr()); +} + +TEST_F(StunTest, WriteMessageWithIPv6AddressAttribute) { + size_t size = sizeof(kStunMessageWithIPv6MappedAddress); + + rtc::IPAddress test_ip(kIPv6TestAddress1); + + StunMessage msg( + STUN_BINDING_REQUEST, + std::string(reinterpret_cast<const char*>(kTestTransactionId1), + kStunTransactionIdLength)); + CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength); + + auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); + rtc::SocketAddress test_addr(test_ip, kTestMessagePort2); + addr->SetAddress(test_addr); + msg.AddAttribute(std::move(addr)); + + CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20)); + + rtc::ByteBufferWriter out; + EXPECT_TRUE(msg.Write(&out)); + ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6MappedAddress)); + int len1 = static_cast<int>(out.Length()); + rtc::ByteBufferReader read_buf(out); + std::string bytes; + read_buf.ReadString(&bytes, len1); + ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv6MappedAddress, len1)); +} + +TEST_F(StunTest, WriteMessageWithIPv4AddressAttribute) { + size_t size = sizeof(kStunMessageWithIPv4MappedAddress); + + rtc::IPAddress test_ip(kIPv4TestAddress1); + + StunMessage msg( + STUN_BINDING_RESPONSE, + std::string(reinterpret_cast<const char*>(kTestTransactionId1), + kStunTransactionIdLength)); + CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength); + + auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); + rtc::SocketAddress test_addr(test_ip, kTestMessagePort4); + addr->SetAddress(test_addr); + msg.AddAttribute(std::move(addr)); + + CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20)); + + rtc::ByteBufferWriter out; + EXPECT_TRUE(msg.Write(&out)); + ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4MappedAddress)); + int len1 = static_cast<int>(out.Length()); + rtc::ByteBufferReader read_buf(out); + std::string bytes; + read_buf.ReadString(&bytes, len1); + ASSERT_EQ(0, memcmp(bytes.c_str(), kStunMessageWithIPv4MappedAddress, len1)); +} + +TEST_F(StunTest, WriteMessageWithIPv6XorAddressAttribute) { + size_t size = sizeof(kStunMessageWithIPv6XorMappedAddress); + + rtc::IPAddress test_ip(kIPv6TestAddress1); + + StunMessage msg( + STUN_BINDING_RESPONSE, + std::string(reinterpret_cast<const char*>(kTestTransactionId2), + kStunTransactionIdLength)); + CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength); + + auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); + rtc::SocketAddress test_addr(test_ip, kTestMessagePort1); + addr->SetAddress(test_addr); + msg.AddAttribute(std::move(addr)); + + CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20)); + + rtc::ByteBufferWriter out; + EXPECT_TRUE(msg.Write(&out)); + ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv6XorMappedAddress)); + int len1 = static_cast<int>(out.Length()); + rtc::ByteBufferReader read_buf(out); + std::string bytes; + read_buf.ReadString(&bytes, len1); + ASSERT_EQ(0, + memcmp(bytes.c_str(), kStunMessageWithIPv6XorMappedAddress, len1)); +} + +TEST_F(StunTest, WriteMessageWithIPv4XoreAddressAttribute) { + size_t size = sizeof(kStunMessageWithIPv4XorMappedAddress); + + rtc::IPAddress test_ip(kIPv4TestAddress1); + + StunMessage msg( + STUN_BINDING_RESPONSE, + std::string(reinterpret_cast<const char*>(kTestTransactionId1), + kStunTransactionIdLength)); + CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength); + + auto addr = StunAttribute::CreateXorAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); + rtc::SocketAddress test_addr(test_ip, kTestMessagePort3); + addr->SetAddress(test_addr); + msg.AddAttribute(std::move(addr)); + + CheckStunHeader(msg, STUN_BINDING_RESPONSE, (size - 20)); + + rtc::ByteBufferWriter out; + EXPECT_TRUE(msg.Write(&out)); + ASSERT_EQ(out.Length(), sizeof(kStunMessageWithIPv4XorMappedAddress)); + int len1 = static_cast<int>(out.Length()); + rtc::ByteBufferReader read_buf(out); + std::string bytes; + read_buf.ReadString(&bytes, len1); + ASSERT_EQ(0, + memcmp(bytes.c_str(), kStunMessageWithIPv4XorMappedAddress, len1)); +} + +TEST_F(StunTest, ReadByteStringAttribute) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kStunMessageWithByteStringAttribute); + + CheckStunHeader(msg, STUN_BINDING_REQUEST, size); + CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength); + const StunByteStringAttribute* username = + msg.GetByteString(STUN_ATTR_USERNAME); + ASSERT_TRUE(username != NULL); + EXPECT_EQ(kTestUserName1, username->string_view()); +} + +TEST_F(StunTest, ReadPaddedByteStringAttribute) { + StunMessage msg; + size_t size = + ReadStunMessage(&msg, kStunMessageWithPaddedByteStringAttribute); + ASSERT_NE(0U, size); + CheckStunHeader(msg, STUN_BINDING_REQUEST, size); + CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength); + const StunByteStringAttribute* username = + msg.GetByteString(STUN_ATTR_USERNAME); + ASSERT_TRUE(username != NULL); + EXPECT_EQ(kTestUserName2, username->string_view()); +} + +TEST_F(StunTest, ReadErrorCodeAttribute) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kStunMessageWithErrorAttribute); + + CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, size); + CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength); + const StunErrorCodeAttribute* errorcode = msg.GetErrorCode(); + ASSERT_TRUE(errorcode != NULL); + EXPECT_EQ(kTestErrorClass, errorcode->eclass()); + EXPECT_EQ(kTestErrorNumber, errorcode->number()); + EXPECT_EQ(kTestErrorReason, errorcode->reason()); + EXPECT_EQ(kTestErrorCode, errorcode->code()); + EXPECT_EQ(kTestErrorCode, msg.GetErrorCodeValue()); +} + +// Test that GetErrorCodeValue returns STUN_ERROR_GLOBAL_FAILURE if the message +// in question doesn't have an error code attribute, rather than crashing. +TEST_F(StunTest, GetErrorCodeValueWithNoErrorAttribute) { + StunMessage msg; + ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress); + EXPECT_EQ(STUN_ERROR_GLOBAL_FAILURE, msg.GetErrorCodeValue()); +} + +TEST_F(StunTest, ReadMessageWithAUInt16ListAttribute) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kStunMessageWithUInt16ListAttribute); + CheckStunHeader(msg, STUN_BINDING_REQUEST, size); + const StunUInt16ListAttribute* types = msg.GetUnknownAttributes(); + ASSERT_TRUE(types != NULL); + EXPECT_EQ(3U, types->Size()); + EXPECT_EQ(0x1U, types->GetType(0)); + EXPECT_EQ(0x1000U, types->GetType(1)); + EXPECT_EQ(0xAB0CU, types->GetType(2)); +} + +TEST_F(StunTest, ReadMessageWithAnUnknownAttribute) { + StunMessage msg; + size_t size = ReadStunMessage(&msg, kStunMessageWithUnknownAttribute); + CheckStunHeader(msg, STUN_BINDING_REQUEST, size); + + // Parsing should have succeeded and there should be a USERNAME attribute + const StunByteStringAttribute* username = + msg.GetByteString(STUN_ATTR_USERNAME); + ASSERT_TRUE(username != NULL); + EXPECT_EQ(kTestUserName2, username->string_view()); +} + +TEST_F(StunTest, WriteMessageWithAnErrorCodeAttribute) { + size_t size = sizeof(kStunMessageWithErrorAttribute); + + StunMessage msg( + STUN_BINDING_ERROR_RESPONSE, + std::string(reinterpret_cast<const char*>(kTestTransactionId1), + kStunTransactionIdLength)); + CheckStunTransactionID(msg, kTestTransactionId1, kStunTransactionIdLength); + auto errorcode = StunAttribute::CreateErrorCode(); + errorcode->SetCode(kTestErrorCode); + errorcode->SetReason(kTestErrorReason); + msg.AddAttribute(std::move(errorcode)); + CheckStunHeader(msg, STUN_BINDING_ERROR_RESPONSE, (size - 20)); + + rtc::ByteBufferWriter out; + EXPECT_TRUE(msg.Write(&out)); + ASSERT_EQ(size, out.Length()); + // No padding. + ASSERT_EQ(0, memcmp(out.Data(), kStunMessageWithErrorAttribute, size)); +} + +TEST_F(StunTest, WriteMessageWithAUInt16ListAttribute) { + size_t size = sizeof(kStunMessageWithUInt16ListAttribute); + + StunMessage msg( + STUN_BINDING_REQUEST, + std::string(reinterpret_cast<const char*>(kTestTransactionId2), + kStunTransactionIdLength)); + CheckStunTransactionID(msg, kTestTransactionId2, kStunTransactionIdLength); + auto list = StunAttribute::CreateUnknownAttributes(); + list->AddType(0x1U); + list->AddType(0x1000U); + list->AddType(0xAB0CU); + msg.AddAttribute(std::move(list)); + CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20)); + + rtc::ByteBufferWriter out; + EXPECT_TRUE(msg.Write(&out)); + ASSERT_EQ(size, out.Length()); + // Check everything up to the padding. + ASSERT_EQ(0, + memcmp(out.Data(), kStunMessageWithUInt16ListAttribute, size - 2)); +} + +// Test that we fail to read messages with invalid lengths. +void CheckFailureToRead(const unsigned char* testcase, size_t length) { + StunMessage msg; + const char* input = reinterpret_cast<const char*>(testcase); + rtc::ByteBufferReader buf(input, length); + ASSERT_FALSE(msg.Read(&buf)); +} + +TEST_F(StunTest, FailToReadInvalidMessages) { + CheckFailureToRead(kStunMessageWithZeroLength, + kRealLengthOfInvalidLengthTestCases); + CheckFailureToRead(kStunMessageWithSmallLength, + kRealLengthOfInvalidLengthTestCases); + CheckFailureToRead(kStunMessageWithExcessLength, + kRealLengthOfInvalidLengthTestCases); +} + +// Test that we properly fail to read a non-STUN message. +TEST_F(StunTest, FailToReadRtcpPacket) { + CheckFailureToRead(kRtcpPacket, sizeof(kRtcpPacket)); +} + +// Check our STUN message validation code against the RFC5769 test messages. +TEST_F(StunTest, ValidateMessageIntegrity) { + // Try the messages from RFC 5769. + EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kRfc5769SampleRequest), + sizeof(kRfc5769SampleRequest), kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kRfc5769SampleRequest), + sizeof(kRfc5769SampleRequest), "InvalidPassword")); + + EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kRfc5769SampleResponse), + sizeof(kRfc5769SampleResponse), kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kRfc5769SampleResponse), + sizeof(kRfc5769SampleResponse), "InvalidPassword")); + + EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6), + sizeof(kRfc5769SampleResponseIPv6), kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6), + sizeof(kRfc5769SampleResponseIPv6), "InvalidPassword")); + + // We first need to compute the key for the long-term authentication HMAC. + std::string key; + ComputeStunCredentialHash(kRfc5769SampleMsgWithAuthUsername, + kRfc5769SampleMsgWithAuthRealm, + kRfc5769SampleMsgWithAuthPassword, &key); + EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth), + sizeof(kRfc5769SampleRequestLongTermAuth), key)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kRfc5769SampleRequestLongTermAuth), + sizeof(kRfc5769SampleRequestLongTermAuth), "InvalidPassword")); + + // Try some edge cases. + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kStunMessageWithZeroLength), + sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kStunMessageWithExcessLength), + sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kStunMessageWithSmallLength), + sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword)); + + // Again, but with the lengths matching what is claimed in the headers. + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kStunMessageWithZeroLength), + kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]), + kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kStunMessageWithExcessLength), + kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]), + kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kStunMessageWithSmallLength), + kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]), + kRfc5769SampleMsgPassword)); + + // Check that a too-short HMAC doesn't cause buffer overflow. + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd), + sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword)); + + // Test that munging a single bit anywhere in the message causes the + // message-integrity check to fail, unless it is after the M-I attribute. + char buf[sizeof(kRfc5769SampleRequest)]; + memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest)); + for (size_t i = 0; i < sizeof(buf); ++i) { + buf[i] ^= 0x01; + if (i > 0) + buf[i - 1] ^= 0x01; + EXPECT_EQ(i >= sizeof(buf) - 8, + StunMessage::ValidateMessageIntegrityForTesting( + buf, sizeof(buf), kRfc5769SampleMsgPassword)); + } +} + +// Validate that we generate correct MESSAGE-INTEGRITY attributes. +// Note the use of IceMessage instead of StunMessage; this is necessary because +// the RFC5769 test messages used include attributes not found in basic STUN. +TEST_F(StunTest, AddMessageIntegrity) { + IceMessage msg; + rtc::ByteBufferReader buf( + reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI), + sizeof(kRfc5769SampleRequestWithoutMI)); + EXPECT_TRUE(msg.Read(&buf)); + EXPECT_TRUE(msg.AddMessageIntegrity(kRfc5769SampleMsgPassword)); + const StunByteStringAttribute* mi_attr = + msg.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY); + EXPECT_EQ(20U, mi_attr->length()); + EXPECT_EQ( + 0, memcmp(mi_attr->bytes(), kCalculatedHmac1, sizeof(kCalculatedHmac1))); + + rtc::ByteBufferWriter buf1; + EXPECT_TRUE(msg.Write(&buf1)); + EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), + kRfc5769SampleMsgPassword)); + + IceMessage msg2; + rtc::ByteBufferReader buf2( + reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI), + sizeof(kRfc5769SampleResponseWithoutMI)); + EXPECT_TRUE(msg2.Read(&buf2)); + EXPECT_TRUE(msg2.AddMessageIntegrity(kRfc5769SampleMsgPassword)); + const StunByteStringAttribute* mi_attr2 = + msg2.GetByteString(STUN_ATTR_MESSAGE_INTEGRITY); + EXPECT_EQ(20U, mi_attr2->length()); + EXPECT_EQ( + 0, memcmp(mi_attr2->bytes(), kCalculatedHmac2, sizeof(kCalculatedHmac2))); + + rtc::ByteBufferWriter buf3; + EXPECT_TRUE(msg2.Write(&buf3)); + EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(buf3.Data()), buf3.Length(), + kRfc5769SampleMsgPassword)); +} + +// Check our STUN message validation code against the RFC5769 test messages. +TEST_F(StunTest, ValidateMessageIntegrity32) { + // Try the messages from RFC 5769. + EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(kSampleRequestMI32), + sizeof(kSampleRequestMI32), kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(kSampleRequestMI32), + sizeof(kSampleRequestMI32), "InvalidPassword")); + + // Try some edge cases. + EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(kStunMessageWithZeroLength), + sizeof(kStunMessageWithZeroLength), kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(kStunMessageWithExcessLength), + sizeof(kStunMessageWithExcessLength), kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(kStunMessageWithSmallLength), + sizeof(kStunMessageWithSmallLength), kRfc5769SampleMsgPassword)); + + // Again, but with the lengths matching what is claimed in the headers. + EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(kStunMessageWithZeroLength), + kStunHeaderSize + rtc::GetBE16(&kStunMessageWithZeroLength[2]), + kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(kStunMessageWithExcessLength), + kStunHeaderSize + rtc::GetBE16(&kStunMessageWithExcessLength[2]), + kRfc5769SampleMsgPassword)); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(kStunMessageWithSmallLength), + kStunHeaderSize + rtc::GetBE16(&kStunMessageWithSmallLength[2]), + kRfc5769SampleMsgPassword)); + + // Check that a too-short HMAC doesn't cause buffer overflow. + EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(kStunMessageWithBadHmacAtEnd), + sizeof(kStunMessageWithBadHmacAtEnd), kRfc5769SampleMsgPassword)); + + // Test that munging a single bit anywhere in the message causes the + // message-integrity check to fail, unless it is after the M-I attribute. + char buf[sizeof(kSampleRequestMI32)]; + memcpy(buf, kSampleRequestMI32, sizeof(kSampleRequestMI32)); + for (size_t i = 0; i < sizeof(buf); ++i) { + buf[i] ^= 0x01; + if (i > 0) + buf[i - 1] ^= 0x01; + EXPECT_EQ(i >= sizeof(buf) - 8, + StunMessage::ValidateMessageIntegrity32ForTesting( + buf, sizeof(buf), kRfc5769SampleMsgPassword)); + } +} + +// Validate that we generate correct MESSAGE-INTEGRITY-32 attributes. +TEST_F(StunTest, AddMessageIntegrity32) { + IceMessage msg; + rtc::ByteBufferReader buf( + reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI), + sizeof(kRfc5769SampleRequestWithoutMI)); + EXPECT_TRUE(msg.Read(&buf)); + EXPECT_TRUE(msg.AddMessageIntegrity32(kRfc5769SampleMsgPassword)); + const StunByteStringAttribute* mi_attr = + msg.GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32); + EXPECT_EQ(4U, mi_attr->length()); + EXPECT_EQ(0, memcmp(mi_attr->bytes(), kCalculatedHmac1_32, + sizeof(kCalculatedHmac1_32))); + + rtc::ByteBufferWriter buf1; + EXPECT_TRUE(msg.Write(&buf1)); + EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), + kRfc5769SampleMsgPassword)); + + IceMessage msg2; + rtc::ByteBufferReader buf2( + reinterpret_cast<const char*>(kRfc5769SampleResponseWithoutMI), + sizeof(kRfc5769SampleResponseWithoutMI)); + EXPECT_TRUE(msg2.Read(&buf2)); + EXPECT_TRUE(msg2.AddMessageIntegrity32(kRfc5769SampleMsgPassword)); + const StunByteStringAttribute* mi_attr2 = + msg2.GetByteString(STUN_ATTR_GOOG_MESSAGE_INTEGRITY_32); + EXPECT_EQ(4U, mi_attr2->length()); + EXPECT_EQ(0, memcmp(mi_attr2->bytes(), kCalculatedHmac2_32, + sizeof(kCalculatedHmac2_32))); + + rtc::ByteBufferWriter buf3; + EXPECT_TRUE(msg2.Write(&buf3)); + EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(buf3.Data()), buf3.Length(), + kRfc5769SampleMsgPassword)); +} + +// Validate that the message validates if both MESSAGE-INTEGRITY-32 and +// MESSAGE-INTEGRITY are present in the message. +// This is not expected to be used, but is not forbidden. +TEST_F(StunTest, AddMessageIntegrity32AndMessageIntegrity) { + IceMessage msg; + auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); + attr->CopyBytes("keso", sizeof("keso")); + msg.AddAttribute(std::move(attr)); + msg.AddMessageIntegrity32("password1"); + msg.AddMessageIntegrity("password2"); + + rtc::ByteBufferWriter buf1; + EXPECT_TRUE(msg.Write(&buf1)); + EXPECT_TRUE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password1")); + EXPECT_TRUE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password2")); + + EXPECT_FALSE(StunMessage::ValidateMessageIntegrity32ForTesting( + reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password2")); + EXPECT_FALSE(StunMessage::ValidateMessageIntegrityForTesting( + reinterpret_cast<const char*>(buf1.Data()), buf1.Length(), "password1")); +} + +// Check our STUN message validation code against the RFC5769 test messages. +TEST_F(StunTest, ValidateFingerprint) { + EXPECT_TRUE(StunMessage::ValidateFingerprint( + reinterpret_cast<const char*>(kRfc5769SampleRequest), + sizeof(kRfc5769SampleRequest))); + EXPECT_TRUE(StunMessage::ValidateFingerprint( + reinterpret_cast<const char*>(kRfc5769SampleResponse), + sizeof(kRfc5769SampleResponse))); + EXPECT_TRUE(StunMessage::ValidateFingerprint( + reinterpret_cast<const char*>(kRfc5769SampleResponseIPv6), + sizeof(kRfc5769SampleResponseIPv6))); + + EXPECT_FALSE(StunMessage::ValidateFingerprint( + reinterpret_cast<const char*>(kStunMessageWithZeroLength), + sizeof(kStunMessageWithZeroLength))); + EXPECT_FALSE(StunMessage::ValidateFingerprint( + reinterpret_cast<const char*>(kStunMessageWithExcessLength), + sizeof(kStunMessageWithExcessLength))); + EXPECT_FALSE(StunMessage::ValidateFingerprint( + reinterpret_cast<const char*>(kStunMessageWithSmallLength), + sizeof(kStunMessageWithSmallLength))); + + // Test that munging a single bit anywhere in the message causes the + // fingerprint check to fail. + char buf[sizeof(kRfc5769SampleRequest)]; + memcpy(buf, kRfc5769SampleRequest, sizeof(kRfc5769SampleRequest)); + for (size_t i = 0; i < sizeof(buf); ++i) { + buf[i] ^= 0x01; + if (i > 0) + buf[i - 1] ^= 0x01; + EXPECT_FALSE(StunMessage::ValidateFingerprint(buf, sizeof(buf))); + } + // Put them all back to normal and the check should pass again. + buf[sizeof(buf) - 1] ^= 0x01; + EXPECT_TRUE(StunMessage::ValidateFingerprint(buf, sizeof(buf))); +} + +TEST_F(StunTest, AddFingerprint) { + IceMessage msg; + rtc::ByteBufferReader buf( + reinterpret_cast<const char*>(kRfc5769SampleRequestWithoutMI), + sizeof(kRfc5769SampleRequestWithoutMI)); + EXPECT_TRUE(msg.Read(&buf)); + EXPECT_TRUE(msg.AddFingerprint()); + + rtc::ByteBufferWriter buf1; + EXPECT_TRUE(msg.Write(&buf1)); + EXPECT_TRUE(StunMessage::ValidateFingerprint( + reinterpret_cast<const char*>(buf1.Data()), buf1.Length())); +} + +// Sample "GTURN" relay message. +// clang-format off +// clang formatting doesn't respect inline comments. +static const unsigned char kRelayMessage[] = { + 0x00, 0x01, 0x00, 88, // message header + 0x21, 0x12, 0xA4, 0x42, // magic cookie + '0', '1', '2', '3', // transaction id + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 0x00, 0x01, 0x00, 8, // mapped address + 0x00, 0x01, 0x00, 13, + 0x00, 0x00, 0x00, 17, + 0x00, 0x06, 0x00, 12, // username + 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', + 0x00, 0x0d, 0x00, 4, // lifetime + 0x00, 0x00, 0x00, 11, + 0x00, 0x0f, 0x00, 4, // magic cookie + 0x72, 0xc6, 0x4b, 0xc6, + 0x00, 0x10, 0x00, 4, // bandwidth + 0x00, 0x00, 0x00, 6, + 0x00, 0x11, 0x00, 8, // destination address + 0x00, 0x01, 0x00, 13, + 0x00, 0x00, 0x00, 17, + 0x00, 0x12, 0x00, 8, // source address 2 + 0x00, 0x01, 0x00, 13, + 0x00, 0x00, 0x00, 17, + 0x00, 0x13, 0x00, 7, // data + 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 0 // DATA must be padded per rfc5766. +}; +// clang-format on + +// Test that we can read the GTURN-specific fields. +TEST_F(StunTest, ReadRelayMessage) { + RelayMessage msg; + + const char* input = reinterpret_cast<const char*>(kRelayMessage); + size_t size = sizeof(kRelayMessage); + rtc::ByteBufferReader buf(input, size); + EXPECT_TRUE(msg.Read(&buf)); + + EXPECT_EQ(STUN_BINDING_REQUEST, msg.type()); + EXPECT_EQ(size - 20, msg.length()); + EXPECT_EQ("0123456789ab", msg.transaction_id()); + + RelayMessage msg2(STUN_BINDING_REQUEST, "0123456789ab"); + + in_addr legacy_in_addr; + legacy_in_addr.s_addr = htonl(17U); + rtc::IPAddress legacy_ip(legacy_in_addr); + + const StunAddressAttribute* addr = msg.GetAddress(STUN_ATTR_MAPPED_ADDRESS); + ASSERT_TRUE(addr != NULL); + EXPECT_EQ(1, addr->family()); + EXPECT_EQ(13, addr->port()); + EXPECT_EQ(legacy_ip, addr->ipaddr()); + + auto addr2 = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); + addr2->SetPort(13); + addr2->SetIP(legacy_ip); + msg2.AddAttribute(std::move(addr2)); + + const StunByteStringAttribute* bytes = msg.GetByteString(STUN_ATTR_USERNAME); + ASSERT_TRUE(bytes != NULL); + EXPECT_EQ(12U, bytes->length()); + EXPECT_EQ("abcdefghijkl", bytes->string_view()); + + auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); + bytes2->CopyBytes("abcdefghijkl"); + msg2.AddAttribute(std::move(bytes2)); + + const StunUInt32Attribute* uval = msg.GetUInt32(STUN_ATTR_LIFETIME); + ASSERT_TRUE(uval != NULL); + EXPECT_EQ(11U, uval->value()); + + auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME); + uval2->SetValue(11); + msg2.AddAttribute(std::move(uval2)); + + bytes = msg.GetByteString(STUN_ATTR_MAGIC_COOKIE); + ASSERT_TRUE(bytes != NULL); + EXPECT_EQ(4U, bytes->length()); + EXPECT_EQ(0, memcmp(bytes->bytes(), TURN_MAGIC_COOKIE_VALUE, + sizeof(TURN_MAGIC_COOKIE_VALUE))); + + bytes2 = StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE); + bytes2->CopyBytes(reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE), + sizeof(TURN_MAGIC_COOKIE_VALUE)); + msg2.AddAttribute(std::move(bytes2)); + + uval = msg.GetUInt32(STUN_ATTR_BANDWIDTH); + ASSERT_TRUE(uval != NULL); + EXPECT_EQ(6U, uval->value()); + + uval2 = StunAttribute::CreateUInt32(STUN_ATTR_BANDWIDTH); + uval2->SetValue(6); + msg2.AddAttribute(std::move(uval2)); + + addr = msg.GetAddress(STUN_ATTR_DESTINATION_ADDRESS); + ASSERT_TRUE(addr != NULL); + EXPECT_EQ(1, addr->family()); + EXPECT_EQ(13, addr->port()); + EXPECT_EQ(legacy_ip, addr->ipaddr()); + + addr2 = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS); + addr2->SetPort(13); + addr2->SetIP(legacy_ip); + msg2.AddAttribute(std::move(addr2)); + + addr = msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2); + ASSERT_TRUE(addr != NULL); + EXPECT_EQ(1, addr->family()); + EXPECT_EQ(13, addr->port()); + EXPECT_EQ(legacy_ip, addr->ipaddr()); + + addr2 = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2); + addr2->SetPort(13); + addr2->SetIP(legacy_ip); + msg2.AddAttribute(std::move(addr2)); + + bytes = msg.GetByteString(STUN_ATTR_DATA); + ASSERT_TRUE(bytes != NULL); + EXPECT_EQ(7U, bytes->length()); + EXPECT_EQ("abcdefg", bytes->string_view()); + + bytes2 = StunAttribute::CreateByteString(STUN_ATTR_DATA); + bytes2->CopyBytes("abcdefg"); + msg2.AddAttribute(std::move(bytes2)); + + rtc::ByteBufferWriter out; + EXPECT_TRUE(msg.Write(&out)); + EXPECT_EQ(size, out.Length()); + size_t len1 = out.Length(); + rtc::ByteBufferReader read_buf(out); + std::string outstring; + read_buf.ReadString(&outstring, len1); + EXPECT_EQ(0, memcmp(outstring.c_str(), input, len1)); + + rtc::ByteBufferWriter out2; + EXPECT_TRUE(msg2.Write(&out2)); + EXPECT_EQ(size, out2.Length()); + size_t len2 = out2.Length(); + rtc::ByteBufferReader read_buf2(out2); + std::string outstring2; + read_buf2.ReadString(&outstring2, len2); + EXPECT_EQ(0, memcmp(outstring2.c_str(), input, len2)); +} + +// Test that we can remove attribute from a message. +TEST_F(StunTest, RemoveAttribute) { + StunMessage msg; + + // Removing something that does exist should return nullptr. + EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr); + + { + auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); + attr->CopyBytes("kes", sizeof("kes")); + msg.AddAttribute(std::move(attr)); + } + + size_t len = msg.length(); + { + auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME); + ASSERT_NE(attr, nullptr); + EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME); + EXPECT_STREQ("kes", + static_cast<StunByteStringAttribute*>(attr.get())->bytes()); + EXPECT_LT(msg.length(), len); + } + + // Now add same attribute type twice. + { + auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); + attr->CopyBytes("kes", sizeof("kes")); + msg.AddAttribute(std::move(attr)); + } + + { + auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); + attr->CopyBytes("kenta", sizeof("kenta")); + msg.AddAttribute(std::move(attr)); + } + + // Remove should remove the last added occurrence. + { + auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME); + ASSERT_NE(attr, nullptr); + EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME); + EXPECT_STREQ("kenta", + static_cast<StunByteStringAttribute*>(attr.get())->bytes()); + } + + // Remove should remove the last added occurrence. + { + auto attr = msg.RemoveAttribute(STUN_ATTR_USERNAME); + ASSERT_NE(attr, nullptr); + EXPECT_EQ(attr->type(), STUN_ATTR_USERNAME); + EXPECT_STREQ("kes", + static_cast<StunByteStringAttribute*>(attr.get())->bytes()); + } + + // Removing something that does exist should return nullptr. + EXPECT_EQ(msg.RemoveAttribute(STUN_ATTR_USERNAME), nullptr); +} + +// Test that we can remove attribute from a message. +TEST_F(StunTest, ClearAttributes) { + StunMessage msg; + + auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); + attr->CopyBytes("kes", sizeof("kes")); + msg.AddAttribute(std::move(attr)); + size_t len = msg.length(); + + msg.ClearAttributes(); + EXPECT_EQ(msg.length(), len - /* 3 + 1 byte padding + header */ 8); + EXPECT_EQ(nullptr, msg.GetByteString(STUN_ATTR_USERNAME)); +} + +// Test CopyStunAttribute +TEST_F(StunTest, CopyAttribute) { + rtc::ByteBufferWriter buf; + rtc::ByteBufferWriter* buffer_ptrs[] = {&buf, nullptr}; + // Test both with and without supplied ByteBufferWriter. + for (auto buffer_ptr : buffer_ptrs) { + { // Test StunByteStringAttribute. + auto attr = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); + attr->CopyBytes("kes", sizeof("kes")); + + auto copy = CopyStunAttribute(*attr.get(), buffer_ptr); + ASSERT_EQ(copy->value_type(), STUN_VALUE_BYTE_STRING); + EXPECT_STREQ("kes", + static_cast<StunByteStringAttribute*>(copy.get())->bytes()); + } + + { // Test StunAddressAttribute. + rtc::IPAddress test_ip(kIPv6TestAddress2); + auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); + rtc::SocketAddress test_addr(test_ip, kTestMessagePort2); + addr->SetAddress(test_addr); + CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, + kTestMessagePort2, test_ip); + + auto copy = CopyStunAttribute(*addr.get(), buffer_ptr); + ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS); + CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()), + STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip); + } + + { // Test StunAddressAttribute. + rtc::IPAddress test_ip(kIPv6TestAddress2); + auto addr = StunAttribute::CreateAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); + rtc::SocketAddress test_addr(test_ip, kTestMessagePort2); + addr->SetAddress(test_addr); + CheckStunAddressAttribute(addr.get(), STUN_ADDRESS_IPV6, + kTestMessagePort2, test_ip); + + auto copy = CopyStunAttribute(*addr.get(), buffer_ptr); + ASSERT_EQ(copy->value_type(), STUN_VALUE_ADDRESS); + CheckStunAddressAttribute(static_cast<StunAddressAttribute*>(copy.get()), + STUN_ADDRESS_IPV6, kTestMessagePort2, test_ip); + } + } +} + +// Test Clone +TEST_F(StunTest, Clone) { + IceMessage msg(0, "0123456789ab"); + { + auto errorcode = StunAttribute::CreateErrorCode(); + errorcode->SetCode(kTestErrorCode); + errorcode->SetReason(kTestErrorReason); + msg.AddAttribute(std::move(errorcode)); + } + { + auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); + bytes2->CopyBytes("abcdefghijkl"); + msg.AddAttribute(std::move(bytes2)); + } + { + auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_RETRANSMIT_COUNT); + uval2->SetValue(11); + msg.AddAttribute(std::move(uval2)); + } + { + auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); + addr->SetIP(rtc::IPAddress(kIPv6TestAddress1)); + addr->SetPort(kTestMessagePort1); + msg.AddAttribute(std::move(addr)); + } + auto copy = msg.Clone(); + ASSERT_NE(nullptr, copy.get()); + + rtc::ByteBufferWriter out1; + EXPECT_TRUE(msg.Write(&out1)); + rtc::ByteBufferWriter out2; + EXPECT_TRUE(copy->Write(&out2)); + + ASSERT_EQ(out1.Length(), out2.Length()); + EXPECT_EQ(0, memcmp(out1.Data(), out2.Data(), out1.Length())); +} + +// Test EqualAttributes +TEST_F(StunTest, EqualAttributes) { + IceMessage msg; + { + auto errorcode = StunAttribute::CreateErrorCode(); + errorcode->SetCode(kTestErrorCode); + errorcode->SetReason(kTestErrorReason); + msg.AddAttribute(std::move(errorcode)); + } + { + auto bytes2 = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); + bytes2->CopyBytes("abcdefghijkl"); + msg.AddAttribute(std::move(bytes2)); + } + { + auto uval2 = StunAttribute::CreateUInt32(STUN_ATTR_RETRANSMIT_COUNT); + uval2->SetValue(11); + msg.AddAttribute(std::move(uval2)); + } + { + auto addr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); + addr->SetIP(rtc::IPAddress(kIPv6TestAddress1)); + addr->SetPort(kTestMessagePort1); + msg.AddAttribute(std::move(addr)); + } + auto copy = msg.Clone(); + ASSERT_NE(nullptr, copy.get()); + + EXPECT_TRUE(copy->EqualAttributes(&msg, [](int type) { return true; })); + + { + auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE); + attr->CopyBytes("keso"); + msg.AddAttribute(std::move(attr)); + EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; })); + EXPECT_TRUE(copy->EqualAttributes( + &msg, [](int type) { return type != STUN_ATTR_NONCE; })); + } + + { + auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE); + attr->CopyBytes("keso"); + copy->AddAttribute(std::move(attr)); + EXPECT_TRUE(copy->EqualAttributes(&msg, [](int type) { return true; })); + } + { + copy->RemoveAttribute(STUN_ATTR_NONCE); + auto attr = StunAttribute::CreateByteString(STUN_ATTR_NONCE); + attr->CopyBytes("kent"); + copy->AddAttribute(std::move(attr)); + EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; })); + EXPECT_TRUE(copy->EqualAttributes( + &msg, [](int type) { return type != STUN_ATTR_NONCE; })); + } + + { + msg.RemoveAttribute(STUN_ATTR_NONCE); + EXPECT_FALSE(copy->EqualAttributes(&msg, [](int type) { return true; })); + EXPECT_TRUE(copy->EqualAttributes( + &msg, [](int type) { return type != STUN_ATTR_NONCE; })); + } +} + +TEST_F(StunTest, ReduceTransactionIdIsHostOrderIndependent) { + const std::string transaction_id = "abcdefghijkl"; + StunMessage message(0, transaction_id); + uint32_t reduced_transaction_id = message.reduced_transaction_id(); + EXPECT_EQ(reduced_transaction_id, 1835954016u); +} + +TEST_F(StunTest, GoogMiscInfo) { + StunMessage msg(STUN_BINDING_REQUEST, "ABCDEFGHIJKL"); + const size_t size = + /* msg header */ 20 + + /* attr header */ 4 + + /* 3 * 2 rounded to multiple of 4 */ 8; + auto list = + StunAttribute::CreateUInt16ListAttribute(STUN_ATTR_GOOG_MISC_INFO); + list->AddTypeAtIndex(0, 0x1U); + list->AddTypeAtIndex(3, 0x1000U); + list->AddTypeAtIndex(2, 0xAB0CU); + msg.AddAttribute(std::move(list)); + CheckStunHeader(msg, STUN_BINDING_REQUEST, (size - 20)); + + rtc::ByteBufferWriter out; + EXPECT_TRUE(msg.Write(&out)); + ASSERT_EQ(size, out.Length()); + + size_t read_size = ReadStunMessageTestCase( + &msg, reinterpret_cast<const unsigned char*>(out.Data()), out.Length()); + ASSERT_EQ(read_size + 20, size); + CheckStunHeader(msg, STUN_BINDING_REQUEST, read_size); + const StunUInt16ListAttribute* types = + msg.GetUInt16List(STUN_ATTR_GOOG_MISC_INFO); + ASSERT_TRUE(types != NULL); + EXPECT_EQ(4U, types->Size()); + EXPECT_EQ(0x1U, types->GetType(0)); + EXPECT_EQ(0x0U, types->GetType(1)); + EXPECT_EQ(0x1000U, types->GetType(3)); + EXPECT_EQ(0xAB0CU, types->GetType(2)); +} + +TEST_F(StunTest, IsStunMethod) { + int methods[] = {STUN_BINDING_REQUEST}; + EXPECT_TRUE(StunMessage::IsStunMethod( + methods, reinterpret_cast<const char*>(kRfc5769SampleRequest), + sizeof(kRfc5769SampleRequest))); +} + +TEST_F(StunTest, SizeRestrictionOnAttributes) { + StunMessage msg(STUN_BINDING_REQUEST, "ABCDEFGHIJKL"); + auto long_username = StunAttribute::CreateByteString(STUN_ATTR_USERNAME); + std::string long_string(509, 'x'); + long_username->CopyBytes(long_string.c_str(), long_string.size()); + msg.AddAttribute(std::move(long_username)); + rtc::ByteBufferWriter out; + ASSERT_FALSE(msg.Write(&out)); +} + +TEST_F(StunTest, ValidateMessageIntegrityWithParser) { + webrtc::metrics::Reset(); // Ensure counters start from zero. + // Try the messages from RFC 5769. + StunMessage message; + rtc::ByteBufferReader reader( + reinterpret_cast<const char*>(kRfc5769SampleRequest), + sizeof(kRfc5769SampleRequest)); + EXPECT_TRUE(message.Read(&reader)); + EXPECT_EQ(message.ValidateMessageIntegrity(kRfc5769SampleMsgPassword), + StunMessage::IntegrityStatus::kIntegrityOk); + EXPECT_EQ(webrtc::metrics::NumEvents( + "WebRTC.Stun.Integrity.Request", + static_cast<int>(StunMessage::IntegrityStatus::kIntegrityOk)), + 1); + EXPECT_EQ(message.RevalidateMessageIntegrity("Invalid password"), + StunMessage::IntegrityStatus::kIntegrityBad); + EXPECT_EQ(webrtc::metrics::NumEvents( + "WebRTC.Stun.Integrity.Request", + static_cast<int>(StunMessage::IntegrityStatus::kIntegrityBad)), + 1); + EXPECT_EQ(webrtc::metrics::NumSamples("WebRTC.Stun.Integrity.Request"), 2); +} + +} // namespace cricket diff --git a/third_party/libwebrtc/api/transport/test/create_feedback_generator.cc b/third_party/libwebrtc/api/transport/test/create_feedback_generator.cc new file mode 100644 index 0000000000..7c83823ce4 --- /dev/null +++ b/third_party/libwebrtc/api/transport/test/create_feedback_generator.cc @@ -0,0 +1,23 @@ +/* + * Copyright 2019 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 "api/transport/test/create_feedback_generator.h" + +#include <memory> + +#include "test/network/feedback_generator.h" + +namespace webrtc { + +std::unique_ptr<FeedbackGenerator> CreateFeedbackGenerator( + FeedbackGenerator::Config confg) { + return std::make_unique<FeedbackGeneratorImpl>(confg); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/transport/test/create_feedback_generator.h b/third_party/libwebrtc/api/transport/test/create_feedback_generator.h new file mode 100644 index 0000000000..a1a2226496 --- /dev/null +++ b/third_party/libwebrtc/api/transport/test/create_feedback_generator.h @@ -0,0 +1,21 @@ +/* + * Copyright 2019 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 API_TRANSPORT_TEST_CREATE_FEEDBACK_GENERATOR_H_ +#define API_TRANSPORT_TEST_CREATE_FEEDBACK_GENERATOR_H_ + +#include <memory> + +#include "api/transport/test/feedback_generator_interface.h" + +namespace webrtc { +std::unique_ptr<FeedbackGenerator> CreateFeedbackGenerator( + FeedbackGenerator::Config confg); +} // namespace webrtc +#endif // API_TRANSPORT_TEST_CREATE_FEEDBACK_GENERATOR_H_ diff --git a/third_party/libwebrtc/api/transport/test/feedback_generator_interface.h b/third_party/libwebrtc/api/transport/test/feedback_generator_interface.h new file mode 100644 index 0000000000..6e5118cbf4 --- /dev/null +++ b/third_party/libwebrtc/api/transport/test/feedback_generator_interface.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 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 API_TRANSPORT_TEST_FEEDBACK_GENERATOR_INTERFACE_H_ +#define API_TRANSPORT_TEST_FEEDBACK_GENERATOR_INTERFACE_H_ + +#include <vector> + +#include "api/test/simulated_network.h" +#include "api/transport/network_types.h" + +namespace webrtc { +class FeedbackGenerator { + public: + struct Config { + BuiltInNetworkBehaviorConfig send_link; + BuiltInNetworkBehaviorConfig return_link; + TimeDelta feedback_interval = TimeDelta::Millis(50); + DataSize feedback_packet_size = DataSize::Bytes(20); + }; + virtual ~FeedbackGenerator() = default; + virtual Timestamp Now() = 0; + virtual void Sleep(TimeDelta duration) = 0; + virtual void SendPacket(size_t size) = 0; + virtual std::vector<TransportPacketsFeedback> PopFeedback() = 0; + virtual void SetSendConfig(BuiltInNetworkBehaviorConfig config) = 0; + virtual void SetReturnConfig(BuiltInNetworkBehaviorConfig config) = 0; + virtual void SetSendLinkCapacity(DataRate capacity) = 0; +}; +} // namespace webrtc +#endif // API_TRANSPORT_TEST_FEEDBACK_GENERATOR_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/transport/test/mock_network_control.h b/third_party/libwebrtc/api/transport/test/mock_network_control.h new file mode 100644 index 0000000000..f613004fb7 --- /dev/null +++ b/third_party/libwebrtc/api/transport/test/mock_network_control.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019 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 API_TRANSPORT_TEST_MOCK_NETWORK_CONTROL_H_ +#define API_TRANSPORT_TEST_MOCK_NETWORK_CONTROL_H_ + +#include "api/transport/network_control.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockNetworkStateEstimator : public NetworkStateEstimator { + public: + MOCK_METHOD(absl::optional<NetworkStateEstimate>, + GetCurrentEstimate, + (), + (override)); + MOCK_METHOD(void, + OnTransportPacketsFeedback, + (const TransportPacketsFeedback&), + (override)); + MOCK_METHOD(void, OnReceivedPacket, (const PacketResult&), (override)); + MOCK_METHOD(void, OnRouteChange, (const NetworkRouteChange&), (override)); +}; + +} // namespace webrtc + +#endif // API_TRANSPORT_TEST_MOCK_NETWORK_CONTROL_H_ diff --git a/third_party/libwebrtc/api/transport_api_gn/moz.build b/third_party/libwebrtc/api/transport_api_gn/moz.build new file mode 100644 index 0000000000..5335c2c519 --- /dev/null +++ b/third_party/libwebrtc/api/transport_api_gn/moz.build @@ -0,0 +1,217 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/call/transport.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("transport_api_gn") diff --git a/third_party/libwebrtc/api/turn_customizer.h b/third_party/libwebrtc/api/turn_customizer.h new file mode 100644 index 0000000000..8d569b36d2 --- /dev/null +++ b/third_party/libwebrtc/api/turn_customizer.h @@ -0,0 +1,46 @@ +/* + * Copyright 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. + */ + +#ifndef API_TURN_CUSTOMIZER_H_ +#define API_TURN_CUSTOMIZER_H_ + +#include <stdlib.h> + +#include "api/transport/stun.h" + +namespace cricket { +class PortInterface; +} // namespace cricket + +namespace webrtc { + +class TurnCustomizer { + public: + // This is called before a TURN message is sent. + // This could be used to add implementation specific attributes to a request. + virtual void MaybeModifyOutgoingStunMessage( + cricket::PortInterface* port, + cricket::StunMessage* message) = 0; + + // TURN can send data using channel data messages or Send indication. + // This method should return false if `data` should be sent using + // a Send indication instead of a ChannelData message, even if a + // channel is bound. + virtual bool AllowChannelData(cricket::PortInterface* port, + const void* data, + size_t size, + bool payload) = 0; + + virtual ~TurnCustomizer() {} +}; + +} // namespace webrtc + +#endif // API_TURN_CUSTOMIZER_H_ diff --git a/third_party/libwebrtc/api/uma_metrics.h b/third_party/libwebrtc/api/uma_metrics.h new file mode 100644 index 0000000000..a63159e849 --- /dev/null +++ b/third_party/libwebrtc/api/uma_metrics.h @@ -0,0 +1,194 @@ +/* + * Copyright 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. + */ + +// This file contains enums related to Chrome UMA histograms. See +// https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md#requirements +// for requirements when adding or changing metrics. + +#ifndef API_UMA_METRICS_H_ +#define API_UMA_METRICS_H_ + +namespace webrtc { + +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum PeerConnectionAddressFamilyCounter { + kPeerConnection_IPv4 = 0, + kPeerConnection_IPv6 = 1, + kBestConnections_IPv4 = 2, + kBestConnections_IPv6 = 3, + kPeerConnectionAddressFamilyCounter_Max +}; + +// This enum defines types for UMA samples, which will have a range. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum PeerConnectionMetricsName { + kNetworkInterfaces_IPv4 = 0, // Number of IPv4 interfaces. + kNetworkInterfaces_IPv6 = 1, // Number of IPv6 interfaces. + kTimeToConnect = 2, // In milliseconds. + kLocalCandidates_IPv4 = 3, // Number of IPv4 local candidates. + kLocalCandidates_IPv6 = 4, // Number of IPv6 local candidates. + kPeerConnectionMetricsName_Max +}; + +// The IceCandidatePairType has the format of +// <local_candidate_type>_<remote_candidate_type>. It is recorded based on the +// type of candidate pair used when the PeerConnection first goes to a completed +// state. When BUNDLE is enabled, only the first transport gets recorded. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum IceCandidatePairType { + // HostHost is deprecated. It was replaced with the set of types at the bottom + // to report private or public host IP address. + kIceCandidatePairHostHost = 0, + kIceCandidatePairHostSrflx = 1, + kIceCandidatePairHostRelay = 2, + kIceCandidatePairHostPrflx = 3, + kIceCandidatePairSrflxHost = 4, + kIceCandidatePairSrflxSrflx = 5, + kIceCandidatePairSrflxRelay = 6, + kIceCandidatePairSrflxPrflx = 7, + kIceCandidatePairRelayHost = 8, + kIceCandidatePairRelaySrflx = 9, + kIceCandidatePairRelayRelay = 10, + kIceCandidatePairRelayPrflx = 11, + kIceCandidatePairPrflxHost = 12, + kIceCandidatePairPrflxSrflx = 13, + kIceCandidatePairPrflxRelay = 14, + + // The following 9 types tell whether local and remote hosts have hostname, + // private or public IP addresses. + kIceCandidatePairHostPrivateHostPrivate = 15, + kIceCandidatePairHostPrivateHostPublic = 16, + kIceCandidatePairHostPublicHostPrivate = 17, + kIceCandidatePairHostPublicHostPublic = 18, + kIceCandidatePairHostNameHostName = 19, + kIceCandidatePairHostNameHostPrivate = 20, + kIceCandidatePairHostNameHostPublic = 21, + kIceCandidatePairHostPrivateHostName = 22, + kIceCandidatePairHostPublicHostName = 23, + kIceCandidatePairMax +}; + +// The difference between PeerConnectionEnumCounter and +// PeerConnectionMetricsName is that the "EnumCounter" is only counting the +// occurrences of events, while "Name" has a value associated with it which is +// used to form a histogram. + +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum KeyExchangeProtocolMedia { + kEnumCounterKeyProtocolMediaTypeDtlsAudio = 0, + kEnumCounterKeyProtocolMediaTypeDtlsVideo = 1, + kEnumCounterKeyProtocolMediaTypeDtlsData = 2, + kEnumCounterKeyProtocolMediaTypeSdesAudio = 3, + kEnumCounterKeyProtocolMediaTypeSdesVideo = 4, + kEnumCounterKeyProtocolMediaTypeSdesData = 5, + kEnumCounterKeyProtocolMediaTypeMax +}; + +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum SdpSemanticRequested { + kSdpSemanticRequestDefault = 0, + kSdpSemanticRequestPlanB = 1, + kSdpSemanticRequestUnifiedPlan = 2, + kSdpSemanticRequestMax +}; + +// Metric for counting the outcome of adding an ICE candidate +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum AddIceCandidateResult { + kAddIceCandidateSuccess = 0, + kAddIceCandidateFailClosed = 1, + kAddIceCandidateFailNoRemoteDescription = 2, + kAddIceCandidateFailNullCandidate = 3, + kAddIceCandidateFailNotValid = 4, + kAddIceCandidateFailNotReady = 5, + kAddIceCandidateFailInAddition = 6, + kAddIceCandidateFailNotUsable = 7, + kAddIceCandidateMax +}; + +// Metric for recording which api surface was used to enable simulcast. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum SimulcastApiVersion { + kSimulcastApiVersionNone = 0, + kSimulcastApiVersionLegacy = 1, + kSimulcastApiVersionSpecCompliant = 2, + kSimulcastApiVersionMax +}; + +// Metrics for reporting usage of BUNDLE. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum BundleUsage { + // There are no m-lines in the SDP, only a session description. + kBundleUsageEmpty = 0, + // Only a data channel is negotiated but BUNDLE is not negotiated. + kBundleUsageNoBundleDatachannelOnly = 1, + // BUNDLE is not negotiated and there is at most one m-line per media type, + kBundleUsageNoBundleSimple = 2, + // BUNDLE is not negotiated and there are multiple m-lines per media type, + kBundleUsageNoBundleComplex = 3, + // Only a data channel is negotiated and BUNDLE is negotiated. + kBundleUsageBundleDatachannelOnly = 4, + // BUNDLE is negotiated but there is at most one m-line per media type, + kBundleUsageBundleSimple = 5, + // BUNDLE is negotiated and there are multiple m-lines per media type, + kBundleUsageBundleComplex = 6, + // Legacy plan-b metrics. + kBundleUsageNoBundlePlanB = 7, + kBundleUsageBundlePlanB = 8, + kBundleUsageMax +}; + +// Metrics for reporting configured BUNDLE policy, mapping directly to +// https://w3c.github.io/webrtc-pc/#rtcbundlepolicy-enum +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum BundlePolicyUsage { + kBundlePolicyUsageBalanced = 0, + kBundlePolicyUsageMaxBundle = 1, + kBundlePolicyUsageMaxCompat = 2, + kBundlePolicyUsageMax +}; + +// Metrics for provisional answers as described in +// https://datatracker.ietf.org/doc/html/rfc8829#section-4.1.10.1 +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum ProvisionalAnswerUsage { + kProvisionalAnswerNotUsed = 0, + kProvisionalAnswerLocal = 1, + kProvisionalAnswerRemote = 2, + kProvisionalAnswerMax +}; + +// Metrics for RTCRtpMuxPolicy. The only defined value is +// https://w3c.github.io/webrtc-pc/#rtcrtcpmuxpolicy-enum +// "require" but there is a legacy option "negotiate" which +// was removed from the spec. +enum RtcpMuxPolicyUsage { + kRtcpMuxPolicyUsageRequire = 0, + kRtcpMuxPolicyUsageNegotiate = 1, + kRtcpMuxPolicyUsageMax +}; + +// When adding new metrics please consider using the style described in +// https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md#usage +// instead of the legacy enums used above. + +} // namespace webrtc + +#endif // API_UMA_METRICS_H_ diff --git a/third_party/libwebrtc/api/units/BUILD.gn b/third_party/libwebrtc/api/units/BUILD.gn new file mode 100644 index 0000000000..45cdcd3097 --- /dev/null +++ b/third_party/libwebrtc/api/units/BUILD.gn @@ -0,0 +1,111 @@ +# 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. + +import("../../webrtc.gni") + +rtc_library("data_rate") { + visibility = [ "*" ] + sources = [ + "data_rate.cc", + "data_rate.h", + ] + + deps = [ + ":data_size", + ":frequency", + ":time_delta", + "..:array_view", + "../../rtc_base:checks", + "../../rtc_base:stringutils", + "../../rtc_base/units:unit_base", + ] +} + +rtc_library("data_size") { + visibility = [ "*" ] + sources = [ + "data_size.cc", + "data_size.h", + ] + + deps = [ + "..:array_view", + "../../rtc_base:checks", + "../../rtc_base:stringutils", + "../../rtc_base/units:unit_base", + ] +} + +rtc_library("time_delta") { + visibility = [ "*" ] + sources = [ + "time_delta.cc", + "time_delta.h", + ] + + deps = [ + "..:array_view", + "../../rtc_base:checks", + "../../rtc_base:stringutils", + "../../rtc_base/units:unit_base", + ] +} + +rtc_library("frequency") { + visibility = [ "*" ] + sources = [ + "frequency.cc", + "frequency.h", + ] + + deps = [ + ":time_delta", + "..:array_view", + "../../rtc_base:checks", + "../../rtc_base:stringutils", + "../../rtc_base/units:unit_base", + ] +} + +rtc_library("timestamp") { + visibility = [ "*" ] + sources = [ + "timestamp.cc", + "timestamp.h", + ] + + deps = [ + ":time_delta", + "..:array_view", + "../../rtc_base:checks", + "../../rtc_base:stringutils", + "../../rtc_base/units:unit_base", + ] +} + +if (rtc_include_tests) { + rtc_library("units_unittests") { + testonly = true + sources = [ + "data_rate_unittest.cc", + "data_size_unittest.cc", + "frequency_unittest.cc", + "time_delta_unittest.cc", + "timestamp_unittest.cc", + ] + deps = [ + ":data_rate", + ":data_size", + ":frequency", + ":time_delta", + ":timestamp", + "../../rtc_base:logging", + "../../test:test_support", + ] + } +} diff --git a/third_party/libwebrtc/api/units/OWNERS b/third_party/libwebrtc/api/units/OWNERS new file mode 100644 index 0000000000..53e076b20b --- /dev/null +++ b/third_party/libwebrtc/api/units/OWNERS @@ -0,0 +1 @@ +srte@webrtc.org diff --git a/third_party/libwebrtc/api/units/data_rate.cc b/third_party/libwebrtc/api/units/data_rate.cc new file mode 100644 index 0000000000..f9586c5f40 --- /dev/null +++ b/third_party/libwebrtc/api/units/data_rate.cc @@ -0,0 +1,34 @@ +/* + * 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 "api/units/data_rate.h" + +#include "api/array_view.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +std::string ToString(DataRate value) { + char buf[64]; + rtc::SimpleStringBuilder sb(buf); + if (value.IsPlusInfinity()) { + sb << "+inf bps"; + } else if (value.IsMinusInfinity()) { + sb << "-inf bps"; + } else { + if (value.bps() == 0 || value.bps() % 1000 != 0) { + sb << value.bps() << " bps"; + } else { + sb << value.kbps() << " kbps"; + } + } + return sb.str(); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/units/data_rate.h b/third_party/libwebrtc/api/units/data_rate.h new file mode 100644 index 0000000000..d813c61156 --- /dev/null +++ b/third_party/libwebrtc/api/units/data_rate.h @@ -0,0 +1,155 @@ +/* + * 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. + */ + +#ifndef API_UNITS_DATA_RATE_H_ +#define API_UNITS_DATA_RATE_H_ + +#ifdef WEBRTC_UNIT_TEST +#include <ostream> // no-presubmit-check TODO(webrtc:8982) +#endif // WEBRTC_UNIT_TEST + +#include <limits> +#include <string> +#include <type_traits> + +#include "api/units/data_size.h" +#include "api/units/frequency.h" +#include "api/units/time_delta.h" +#include "rtc_base/checks.h" +#include "rtc_base/units/unit_base.h" // IWYU pragma: export + +namespace webrtc { +// DataRate is a class that represents a given data rate. This can be used to +// represent bandwidth, encoding bitrate, etc. The internal storage is bits per +// second (bps). +class DataRate final : public rtc_units_impl::RelativeUnit<DataRate> { + public: + template <typename T> + static constexpr DataRate BitsPerSec(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromValue(value); + } + template <typename T> + static constexpr DataRate BytesPerSec(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromFraction(8, value); + } + template <typename T> + static constexpr DataRate KilobitsPerSec(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromFraction(1000, value); + } + static constexpr DataRate Infinity() { return PlusInfinity(); } + + DataRate() = delete; + + template <typename T = int64_t> + constexpr T bps() const { + return ToValue<T>(); + } + template <typename T = int64_t> + constexpr T bytes_per_sec() const { + return ToFraction<8, T>(); + } + template <typename T = int64_t> + constexpr T kbps() const { + return ToFraction<1000, T>(); + } + constexpr int64_t bps_or(int64_t fallback_value) const { + return ToValueOr(fallback_value); + } + constexpr int64_t kbps_or(int64_t fallback_value) const { + return ToFractionOr<1000>(fallback_value); + } + + private: + // Bits per second used internally to simplify debugging by making the value + // more recognizable. + friend class rtc_units_impl::UnitBase<DataRate>; + using RelativeUnit::RelativeUnit; + static constexpr bool one_sided = true; +}; + +namespace data_rate_impl { +inline constexpr int64_t Microbits(const DataSize& size) { + constexpr int64_t kMaxBeforeConversion = + std::numeric_limits<int64_t>::max() / 8000000; + RTC_DCHECK_LE(size.bytes(), kMaxBeforeConversion) + << "size is too large to be expressed in microbits"; + return size.bytes() * 8000000; +} + +inline constexpr int64_t MillibytePerSec(const DataRate& size) { + constexpr int64_t kMaxBeforeConversion = + std::numeric_limits<int64_t>::max() / (1000 / 8); + RTC_DCHECK_LE(size.bps(), kMaxBeforeConversion) + << "rate is too large to be expressed in microbytes per second"; + return size.bps() * (1000 / 8); +} +} // namespace data_rate_impl + +inline constexpr DataRate operator/(const DataSize size, + const TimeDelta duration) { + return DataRate::BitsPerSec(data_rate_impl::Microbits(size) / duration.us()); +} +inline constexpr TimeDelta operator/(const DataSize size, const DataRate rate) { + return TimeDelta::Micros(data_rate_impl::Microbits(size) / rate.bps()); +} +inline constexpr DataSize operator*(const DataRate rate, + const TimeDelta duration) { + int64_t microbits = rate.bps() * duration.us(); + return DataSize::Bytes((microbits + 4000000) / 8000000); +} +inline constexpr DataSize operator*(const TimeDelta duration, + const DataRate rate) { + return rate * duration; +} + +inline constexpr DataSize operator/(const DataRate rate, + const Frequency frequency) { + int64_t millihertz = frequency.millihertz<int64_t>(); + // Note that the value is truncated here reather than rounded, potentially + // introducing an error of .5 bytes if rounding were expected. + return DataSize::Bytes(data_rate_impl::MillibytePerSec(rate) / millihertz); +} +inline constexpr Frequency operator/(const DataRate rate, const DataSize size) { + return Frequency::MilliHertz(data_rate_impl::MillibytePerSec(rate) / + size.bytes()); +} +inline constexpr DataRate operator*(const DataSize size, + const Frequency frequency) { + RTC_DCHECK(frequency.IsZero() || + size.bytes() <= std::numeric_limits<int64_t>::max() / 8 / + frequency.millihertz<int64_t>()); + int64_t millibits_per_second = + size.bytes() * 8 * frequency.millihertz<int64_t>(); + return DataRate::BitsPerSec((millibits_per_second + 500) / 1000); +} +inline constexpr DataRate operator*(const Frequency frequency, + const DataSize size) { + return size * frequency; +} + +std::string ToString(DataRate value); +inline std::string ToLogString(DataRate value) { + return ToString(value); +} + +#ifdef WEBRTC_UNIT_TEST +inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) + std::ostream& stream, // no-presubmit-check TODO(webrtc:8982) + DataRate value) { + return stream << ToString(value); +} +#endif // WEBRTC_UNIT_TEST + +} // namespace webrtc + +#endif // API_UNITS_DATA_RATE_H_ diff --git a/third_party/libwebrtc/api/units/data_rate_gn/moz.build b/third_party/libwebrtc/api/units/data_rate_gn/moz.build new file mode 100644 index 0000000000..de76b8e11c --- /dev/null +++ b/third_party/libwebrtc/api/units/data_rate_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/units/data_rate.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("data_rate_gn") diff --git a/third_party/libwebrtc/api/units/data_rate_unittest.cc b/third_party/libwebrtc/api/units/data_rate_unittest.cc new file mode 100644 index 0000000000..f77b3702d4 --- /dev/null +++ b/third_party/libwebrtc/api/units/data_rate_unittest.cc @@ -0,0 +1,197 @@ +/* + * 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 "api/units/data_rate.h" + +#include "rtc_base/logging.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { + +TEST(DataRateTest, CompilesWithChecksAndLogs) { + DataRate a = DataRate::KilobitsPerSec(300); + DataRate b = DataRate::KilobitsPerSec(210); + RTC_CHECK_GT(a, b); + RTC_LOG(LS_INFO) << a; +} + +TEST(DataRateTest, ConstExpr) { + constexpr int64_t kValue = 12345; + constexpr DataRate kDataRateZero = DataRate::Zero(); + constexpr DataRate kDataRateInf = DataRate::Infinity(); + static_assert(kDataRateZero.IsZero(), ""); + static_assert(kDataRateInf.IsInfinite(), ""); + static_assert(kDataRateInf.bps_or(-1) == -1, ""); + static_assert(kDataRateInf > kDataRateZero, ""); + + constexpr DataRate kDataRateBps = DataRate::BitsPerSec(kValue); + constexpr DataRate kDataRateKbps = DataRate::KilobitsPerSec(kValue); + static_assert(kDataRateBps.bps<double>() == kValue, ""); + static_assert(kDataRateBps.bps_or(0) == kValue, ""); + static_assert(kDataRateKbps.kbps_or(0) == kValue, ""); +} + +TEST(DataRateTest, GetBackSameValues) { + const int64_t kValue = 123 * 8; + EXPECT_EQ(DataRate::BitsPerSec(kValue).bps(), kValue); + EXPECT_EQ(DataRate::KilobitsPerSec(kValue).kbps(), kValue); +} + +TEST(DataRateTest, GetDifferentPrefix) { + const int64_t kValue = 123 * 8000; + EXPECT_EQ(DataRate::BitsPerSec(kValue).kbps(), kValue / 1000); +} + +TEST(DataRateTest, IdentityChecks) { + const int64_t kValue = 3000; + EXPECT_TRUE(DataRate::Zero().IsZero()); + EXPECT_FALSE(DataRate::BitsPerSec(kValue).IsZero()); + + EXPECT_TRUE(DataRate::Infinity().IsInfinite()); + EXPECT_FALSE(DataRate::Zero().IsInfinite()); + EXPECT_FALSE(DataRate::BitsPerSec(kValue).IsInfinite()); + + EXPECT_FALSE(DataRate::Infinity().IsFinite()); + EXPECT_TRUE(DataRate::BitsPerSec(kValue).IsFinite()); + EXPECT_TRUE(DataRate::Zero().IsFinite()); +} + +TEST(DataRateTest, ComparisonOperators) { + const int64_t kSmall = 450; + const int64_t kLarge = 451; + const DataRate small = DataRate::BitsPerSec(kSmall); + const DataRate large = DataRate::BitsPerSec(kLarge); + + EXPECT_EQ(DataRate::Zero(), DataRate::BitsPerSec(0)); + EXPECT_EQ(DataRate::Infinity(), DataRate::Infinity()); + EXPECT_EQ(small, small); + EXPECT_LE(small, small); + EXPECT_GE(small, small); + EXPECT_NE(small, large); + EXPECT_LE(small, large); + EXPECT_LT(small, large); + EXPECT_GE(large, small); + EXPECT_GT(large, small); + EXPECT_LT(DataRate::Zero(), small); + EXPECT_GT(DataRate::Infinity(), large); +} + +TEST(DataRateTest, ConvertsToAndFromDouble) { + const int64_t kValue = 128; + const double kDoubleValue = static_cast<double>(kValue); + const double kDoubleKbps = kValue * 1e-3; + const double kFloatKbps = static_cast<float>(kDoubleKbps); + + EXPECT_EQ(DataRate::BitsPerSec(kValue).bps<double>(), kDoubleValue); + EXPECT_EQ(DataRate::BitsPerSec(kValue).kbps<double>(), kDoubleKbps); + EXPECT_EQ(DataRate::BitsPerSec(kValue).kbps<float>(), kFloatKbps); + EXPECT_EQ(DataRate::BitsPerSec(kDoubleValue).bps(), kValue); + EXPECT_EQ(DataRate::KilobitsPerSec(kDoubleKbps).bps(), kValue); + + const double kInfinity = std::numeric_limits<double>::infinity(); + EXPECT_EQ(DataRate::Infinity().bps<double>(), kInfinity); + EXPECT_TRUE(DataRate::BitsPerSec(kInfinity).IsInfinite()); + EXPECT_TRUE(DataRate::KilobitsPerSec(kInfinity).IsInfinite()); +} +TEST(DataRateTest, Clamping) { + const DataRate upper = DataRate::KilobitsPerSec(800); + const DataRate lower = DataRate::KilobitsPerSec(100); + const DataRate under = DataRate::KilobitsPerSec(100); + const DataRate inside = DataRate::KilobitsPerSec(500); + const DataRate over = DataRate::KilobitsPerSec(1000); + EXPECT_EQ(under.Clamped(lower, upper), lower); + EXPECT_EQ(inside.Clamped(lower, upper), inside); + EXPECT_EQ(over.Clamped(lower, upper), upper); + + DataRate mutable_rate = lower; + mutable_rate.Clamp(lower, upper); + EXPECT_EQ(mutable_rate, lower); + mutable_rate = inside; + mutable_rate.Clamp(lower, upper); + EXPECT_EQ(mutable_rate, inside); + mutable_rate = over; + mutable_rate.Clamp(lower, upper); + EXPECT_EQ(mutable_rate, upper); +} + +TEST(DataRateTest, MathOperations) { + const int64_t kValueA = 450; + const int64_t kValueB = 267; + const DataRate rate_a = DataRate::BitsPerSec(kValueA); + const DataRate rate_b = DataRate::BitsPerSec(kValueB); + const int32_t kInt32Value = 123; + const double kFloatValue = 123.0; + + EXPECT_EQ((rate_a + rate_b).bps(), kValueA + kValueB); + EXPECT_EQ((rate_a - rate_b).bps(), kValueA - kValueB); + + EXPECT_EQ((rate_a * kValueB).bps(), kValueA * kValueB); + EXPECT_EQ((rate_a * kInt32Value).bps(), kValueA * kInt32Value); + EXPECT_EQ((rate_a * kFloatValue).bps(), kValueA * kFloatValue); + + EXPECT_EQ(rate_a / rate_b, static_cast<double>(kValueA) / kValueB); + + EXPECT_EQ((rate_a / 10).bps(), kValueA / 10); + EXPECT_NEAR((rate_a / 0.5).bps(), kValueA * 2, 1); + + DataRate mutable_rate = DataRate::BitsPerSec(kValueA); + mutable_rate += rate_b; + EXPECT_EQ(mutable_rate.bps(), kValueA + kValueB); + mutable_rate -= rate_a; + EXPECT_EQ(mutable_rate.bps(), kValueB); +} + +TEST(UnitConversionTest, DataRateAndDataSizeAndTimeDelta) { + const int64_t kSeconds = 5; + const int64_t kBitsPerSecond = 440; + const int64_t kBytes = 44000; + const TimeDelta delta_a = TimeDelta::Seconds(kSeconds); + const DataRate rate_b = DataRate::BitsPerSec(kBitsPerSecond); + const DataSize size_c = DataSize::Bytes(kBytes); + EXPECT_EQ((delta_a * rate_b).bytes(), kSeconds * kBitsPerSecond / 8); + EXPECT_EQ((rate_b * delta_a).bytes(), kSeconds * kBitsPerSecond / 8); + EXPECT_EQ((size_c / delta_a).bps(), kBytes * 8 / kSeconds); + EXPECT_EQ((size_c / rate_b).seconds(), kBytes * 8 / kBitsPerSecond); +} + +TEST(UnitConversionTest, DataRateAndDataSizeAndFrequency) { + const int64_t kHertz = 30; + const int64_t kBitsPerSecond = 96000; + const int64_t kBytes = 1200; + const Frequency freq_a = Frequency::Hertz(kHertz); + const DataRate rate_b = DataRate::BitsPerSec(kBitsPerSecond); + const DataSize size_c = DataSize::Bytes(kBytes); + EXPECT_EQ((freq_a * size_c).bps(), kHertz * kBytes * 8); + EXPECT_EQ((size_c * freq_a).bps(), kHertz * kBytes * 8); + EXPECT_EQ((rate_b / size_c).hertz<int64_t>(), kBitsPerSecond / kBytes / 8); + EXPECT_EQ((rate_b / freq_a).bytes(), kBitsPerSecond / kHertz / 8); +} + +TEST(UnitConversionDeathTest, DivisionFailsOnLargeSize) { + // Note that the failure is expected since the current implementation is + // implementated in a way that does not support division of large sizes. If + // the implementation is changed, this test can safely be removed. + const int64_t kJustSmallEnoughForDivision = + std::numeric_limits<int64_t>::max() / 8000000; + const DataSize large_size = DataSize::Bytes(kJustSmallEnoughForDivision); + const DataRate data_rate = DataRate::KilobitsPerSec(100); + const TimeDelta time_delta = TimeDelta::Millis(100); + EXPECT_TRUE((large_size / data_rate).IsFinite()); + EXPECT_TRUE((large_size / time_delta).IsFinite()); +#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) && RTC_DCHECK_IS_ON + const int64_t kToolargeForDivision = kJustSmallEnoughForDivision + 1; + const DataSize too_large_size = DataSize::Bytes(kToolargeForDivision); + EXPECT_DEATH(too_large_size / data_rate, ""); + EXPECT_DEATH(too_large_size / time_delta, ""); +#endif // GTEST_HAS_DEATH_TEST && !!defined(WEBRTC_ANDROID) && RTC_DCHECK_IS_ON +} +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/units/data_size.cc b/third_party/libwebrtc/api/units/data_size.cc new file mode 100644 index 0000000000..45487dfd83 --- /dev/null +++ b/third_party/libwebrtc/api/units/data_size.cc @@ -0,0 +1,30 @@ +/* + * 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 "api/units/data_size.h" + +#include "api/array_view.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +std::string ToString(DataSize value) { + char buf[64]; + rtc::SimpleStringBuilder sb(buf); + if (value.IsPlusInfinity()) { + sb << "+inf bytes"; + } else if (value.IsMinusInfinity()) { + sb << "-inf bytes"; + } else { + sb << value.bytes() << " bytes"; + } + return sb.str(); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/units/data_size.h b/third_party/libwebrtc/api/units/data_size.h new file mode 100644 index 0000000000..9df6434fb9 --- /dev/null +++ b/third_party/libwebrtc/api/units/data_size.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#ifndef API_UNITS_DATA_SIZE_H_ +#define API_UNITS_DATA_SIZE_H_ + +#ifdef WEBRTC_UNIT_TEST +#include <ostream> // no-presubmit-check TODO(webrtc:8982) +#endif // WEBRTC_UNIT_TEST + +#include <string> +#include <type_traits> + +#include "rtc_base/units/unit_base.h" // IWYU pragma: export + +namespace webrtc { +// DataSize is a class represeting a count of bytes. +class DataSize final : public rtc_units_impl::RelativeUnit<DataSize> { + public: + template <typename T> + static constexpr DataSize Bytes(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromValue(value); + } + static constexpr DataSize Infinity() { return PlusInfinity(); } + + DataSize() = delete; + + template <typename T = int64_t> + constexpr T bytes() const { + return ToValue<T>(); + } + + constexpr int64_t bytes_or(int64_t fallback_value) const { + return ToValueOr(fallback_value); + } + + private: + friend class rtc_units_impl::UnitBase<DataSize>; + using RelativeUnit::RelativeUnit; + static constexpr bool one_sided = true; +}; + +std::string ToString(DataSize value); +inline std::string ToLogString(DataSize value) { + return ToString(value); +} + +#ifdef WEBRTC_UNIT_TEST +inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) + std::ostream& stream, // no-presubmit-check TODO(webrtc:8982) + DataSize value) { + return stream << ToString(value); +} +#endif // WEBRTC_UNIT_TEST + +} // namespace webrtc + +#endif // API_UNITS_DATA_SIZE_H_ diff --git a/third_party/libwebrtc/api/units/data_size_gn/moz.build b/third_party/libwebrtc/api/units/data_size_gn/moz.build new file mode 100644 index 0000000000..dc54ce4f15 --- /dev/null +++ b/third_party/libwebrtc/api/units/data_size_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/units/data_size.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("data_size_gn") diff --git a/third_party/libwebrtc/api/units/data_size_unittest.cc b/third_party/libwebrtc/api/units/data_size_unittest.cc new file mode 100644 index 0000000000..eb8d98c1f0 --- /dev/null +++ b/third_party/libwebrtc/api/units/data_size_unittest.cc @@ -0,0 +1,110 @@ +/* + * 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 "api/units/data_size.h" + +#include <limits> + +#include "test/gtest.h" + +namespace webrtc { +namespace test { + +TEST(DataSizeTest, ConstExpr) { + constexpr int64_t kValue = 12345; + constexpr DataSize kDataSizeZero = DataSize::Zero(); + constexpr DataSize kDataSizeInf = DataSize::Infinity(); + static_assert(kDataSizeZero.IsZero(), ""); + static_assert(kDataSizeInf.IsInfinite(), ""); + static_assert(kDataSizeInf.bytes_or(-1) == -1, ""); + static_assert(kDataSizeInf > kDataSizeZero, ""); + + constexpr DataSize kDataSize = DataSize::Bytes(kValue); + static_assert(kDataSize.bytes_or(-1) == kValue, ""); + + EXPECT_EQ(kDataSize.bytes(), kValue); +} + +TEST(DataSizeTest, GetBackSameValues) { + const int64_t kValue = 123 * 8; + EXPECT_EQ(DataSize::Bytes(kValue).bytes(), kValue); +} + +TEST(DataSizeTest, IdentityChecks) { + const int64_t kValue = 3000; + EXPECT_TRUE(DataSize::Zero().IsZero()); + EXPECT_FALSE(DataSize::Bytes(kValue).IsZero()); + + EXPECT_TRUE(DataSize::Infinity().IsInfinite()); + EXPECT_FALSE(DataSize::Zero().IsInfinite()); + EXPECT_FALSE(DataSize::Bytes(kValue).IsInfinite()); + + EXPECT_FALSE(DataSize::Infinity().IsFinite()); + EXPECT_TRUE(DataSize::Bytes(kValue).IsFinite()); + EXPECT_TRUE(DataSize::Zero().IsFinite()); +} + +TEST(DataSizeTest, ComparisonOperators) { + const int64_t kSmall = 450; + const int64_t kLarge = 451; + const DataSize small = DataSize::Bytes(kSmall); + const DataSize large = DataSize::Bytes(kLarge); + + EXPECT_EQ(DataSize::Zero(), DataSize::Bytes(0)); + EXPECT_EQ(DataSize::Infinity(), DataSize::Infinity()); + EXPECT_EQ(small, small); + EXPECT_LE(small, small); + EXPECT_GE(small, small); + EXPECT_NE(small, large); + EXPECT_LE(small, large); + EXPECT_LT(small, large); + EXPECT_GE(large, small); + EXPECT_GT(large, small); + EXPECT_LT(DataSize::Zero(), small); + EXPECT_GT(DataSize::Infinity(), large); +} + +TEST(DataSizeTest, ConvertsToAndFromDouble) { + const int64_t kValue = 128; + const double kDoubleValue = static_cast<double>(kValue); + + EXPECT_EQ(DataSize::Bytes(kValue).bytes<double>(), kDoubleValue); + EXPECT_EQ(DataSize::Bytes(kDoubleValue).bytes(), kValue); + + const double kInfinity = std::numeric_limits<double>::infinity(); + EXPECT_EQ(DataSize::Infinity().bytes<double>(), kInfinity); + EXPECT_TRUE(DataSize::Bytes(kInfinity).IsInfinite()); +} + +TEST(DataSizeTest, MathOperations) { + const int64_t kValueA = 450; + const int64_t kValueB = 267; + const DataSize size_a = DataSize::Bytes(kValueA); + const DataSize size_b = DataSize::Bytes(kValueB); + EXPECT_EQ((size_a + size_b).bytes(), kValueA + kValueB); + EXPECT_EQ((size_a - size_b).bytes(), kValueA - kValueB); + + const int32_t kInt32Value = 123; + const double kFloatValue = 123.0; + EXPECT_EQ((size_a * kValueB).bytes(), kValueA * kValueB); + EXPECT_EQ((size_a * kInt32Value).bytes(), kValueA * kInt32Value); + EXPECT_EQ((size_a * kFloatValue).bytes(), kValueA * kFloatValue); + + EXPECT_EQ((size_a / 10).bytes(), kValueA / 10); + EXPECT_EQ(size_a / size_b, static_cast<double>(kValueA) / kValueB); + + DataSize mutable_size = DataSize::Bytes(kValueA); + mutable_size += size_b; + EXPECT_EQ(mutable_size.bytes(), kValueA + kValueB); + mutable_size -= size_a; + EXPECT_EQ(mutable_size.bytes(), kValueB); +} +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/units/frequency.cc b/third_party/libwebrtc/api/units/frequency.cc new file mode 100644 index 0000000000..2d938a2814 --- /dev/null +++ b/third_party/libwebrtc/api/units/frequency.cc @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 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 "api/units/frequency.h" + +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { +std::string ToString(Frequency value) { + char buf[64]; + rtc::SimpleStringBuilder sb(buf); + if (value.IsPlusInfinity()) { + sb << "+inf Hz"; + } else if (value.IsMinusInfinity()) { + sb << "-inf Hz"; + } else if (value.millihertz<int64_t>() % 1000 != 0) { + sb.AppendFormat("%.3f Hz", value.hertz<double>()); + } else { + sb << value.hertz<int64_t>() << " Hz"; + } + return sb.str(); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/units/frequency.h b/third_party/libwebrtc/api/units/frequency.h new file mode 100644 index 0000000000..06081e4c0d --- /dev/null +++ b/third_party/libwebrtc/api/units/frequency.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2019 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 API_UNITS_FREQUENCY_H_ +#define API_UNITS_FREQUENCY_H_ + +#ifdef WEBRTC_UNIT_TEST +#include <ostream> // no-presubmit-check TODO(webrtc:8982) +#endif // WEBRTC_UNIT_TEST + +#include <cstdlib> +#include <limits> +#include <string> +#include <type_traits> + +#include "api/units/time_delta.h" +#include "rtc_base/units/unit_base.h" // IWYU pragma: export + +namespace webrtc { + +class Frequency final : public rtc_units_impl::RelativeUnit<Frequency> { + public: + template <typename T> + static constexpr Frequency MilliHertz(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromValue(value); + } + template <typename T> + static constexpr Frequency Hertz(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromFraction(1'000, value); + } + template <typename T> + static constexpr Frequency KiloHertz(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromFraction(1'000'000, value); + } + + Frequency() = delete; + + template <typename T = int64_t> + constexpr T hertz() const { + return ToFraction<1000, T>(); + } + template <typename T = int64_t> + constexpr T millihertz() const { + return ToValue<T>(); + } + + private: + friend class rtc_units_impl::UnitBase<Frequency>; + using RelativeUnit::RelativeUnit; + static constexpr bool one_sided = true; +}; + +inline constexpr Frequency operator/(int64_t nominator, + const TimeDelta& interval) { + constexpr int64_t kKiloPerMicro = 1000 * 1000000; + RTC_DCHECK_LE(nominator, std::numeric_limits<int64_t>::max() / kKiloPerMicro); + RTC_CHECK(interval.IsFinite()); + RTC_CHECK(!interval.IsZero()); + return Frequency::MilliHertz(nominator * kKiloPerMicro / interval.us()); +} + +inline constexpr TimeDelta operator/(int64_t nominator, + const Frequency& frequency) { + constexpr int64_t kMegaPerMilli = 1000000 * 1000; + RTC_DCHECK_LE(nominator, std::numeric_limits<int64_t>::max() / kMegaPerMilli); + RTC_CHECK(frequency.IsFinite()); + RTC_CHECK(!frequency.IsZero()); + return TimeDelta::Micros(nominator * kMegaPerMilli / frequency.millihertz()); +} + +inline constexpr double operator*(Frequency frequency, TimeDelta time_delta) { + return frequency.hertz<double>() * time_delta.seconds<double>(); +} +inline constexpr double operator*(TimeDelta time_delta, Frequency frequency) { + return frequency * time_delta; +} + +std::string ToString(Frequency value); +inline std::string ToLogString(Frequency value) { + return ToString(value); +} + +#ifdef WEBRTC_UNIT_TEST +inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) + std::ostream& stream, // no-presubmit-check TODO(webrtc:8982) + Frequency value) { + return stream << ToString(value); +} +#endif // WEBRTC_UNIT_TEST + +} // namespace webrtc +#endif // API_UNITS_FREQUENCY_H_ diff --git a/third_party/libwebrtc/api/units/frequency_gn/moz.build b/third_party/libwebrtc/api/units/frequency_gn/moz.build new file mode 100644 index 0000000000..3c84c283b8 --- /dev/null +++ b/third_party/libwebrtc/api/units/frequency_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/units/frequency.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("frequency_gn") diff --git a/third_party/libwebrtc/api/units/frequency_unittest.cc b/third_party/libwebrtc/api/units/frequency_unittest.cc new file mode 100644 index 0000000000..1260c2107d --- /dev/null +++ b/third_party/libwebrtc/api/units/frequency_unittest.cc @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2019 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 "api/units/frequency.h" + +#include <limits> + +#include "test/gtest.h" + +namespace webrtc { +namespace test { +TEST(FrequencyTest, ConstExpr) { + constexpr Frequency kFrequencyZero = Frequency::Zero(); + constexpr Frequency kFrequencyPlusInf = Frequency::PlusInfinity(); + constexpr Frequency kFrequencyMinusInf = Frequency::MinusInfinity(); + static_assert(kFrequencyZero.IsZero(), ""); + static_assert(kFrequencyPlusInf.IsPlusInfinity(), ""); + static_assert(kFrequencyMinusInf.IsMinusInfinity(), ""); + + static_assert(kFrequencyPlusInf > kFrequencyZero, ""); +} + +TEST(FrequencyTest, GetBackSameValues) { + const int64_t kValue = 31; + EXPECT_EQ(Frequency::Hertz(kValue).hertz<int64_t>(), kValue); + EXPECT_EQ(Frequency::Zero().hertz<int64_t>(), 0); +} + +TEST(FrequencyTest, GetDifferentPrefix) { + const int64_t kValue = 30000; + EXPECT_EQ(Frequency::MilliHertz(kValue).hertz<int64_t>(), kValue / 1000); + EXPECT_EQ(Frequency::Hertz(kValue).millihertz(), kValue * 1000); + EXPECT_EQ(Frequency::KiloHertz(kValue).hertz(), kValue * 1000); +} + +TEST(FrequencyTest, IdentityChecks) { + const int64_t kValue = 31; + EXPECT_TRUE(Frequency::Zero().IsZero()); + EXPECT_FALSE(Frequency::Hertz(kValue).IsZero()); + + EXPECT_TRUE(Frequency::PlusInfinity().IsInfinite()); + EXPECT_TRUE(Frequency::MinusInfinity().IsInfinite()); + EXPECT_FALSE(Frequency::Zero().IsInfinite()); + EXPECT_FALSE(Frequency::Hertz(kValue).IsInfinite()); + + EXPECT_FALSE(Frequency::PlusInfinity().IsFinite()); + EXPECT_FALSE(Frequency::MinusInfinity().IsFinite()); + EXPECT_TRUE(Frequency::Hertz(kValue).IsFinite()); + EXPECT_TRUE(Frequency::Zero().IsFinite()); + + EXPECT_TRUE(Frequency::PlusInfinity().IsPlusInfinity()); + EXPECT_FALSE(Frequency::MinusInfinity().IsPlusInfinity()); + + EXPECT_TRUE(Frequency::MinusInfinity().IsMinusInfinity()); + EXPECT_FALSE(Frequency::PlusInfinity().IsMinusInfinity()); +} + +TEST(FrequencyTest, ComparisonOperators) { + const int64_t kSmall = 42; + const int64_t kLarge = 45; + const Frequency small = Frequency::Hertz(kSmall); + const Frequency large = Frequency::Hertz(kLarge); + + EXPECT_EQ(Frequency::Zero(), Frequency::Hertz(0)); + EXPECT_EQ(Frequency::PlusInfinity(), Frequency::PlusInfinity()); + EXPECT_EQ(small, Frequency::Hertz(kSmall)); + EXPECT_LE(small, Frequency::Hertz(kSmall)); + EXPECT_GE(small, Frequency::Hertz(kSmall)); + EXPECT_NE(small, Frequency::Hertz(kLarge)); + EXPECT_LE(small, Frequency::Hertz(kLarge)); + EXPECT_LT(small, Frequency::Hertz(kLarge)); + EXPECT_GE(large, Frequency::Hertz(kSmall)); + EXPECT_GT(large, Frequency::Hertz(kSmall)); + EXPECT_LT(Frequency::Zero(), small); + + EXPECT_GT(Frequency::PlusInfinity(), large); + EXPECT_LT(Frequency::MinusInfinity(), Frequency::Zero()); +} + +TEST(FrequencyTest, Clamping) { + const Frequency upper = Frequency::Hertz(800); + const Frequency lower = Frequency::Hertz(100); + const Frequency under = Frequency::Hertz(100); + const Frequency inside = Frequency::Hertz(500); + const Frequency over = Frequency::Hertz(1000); + EXPECT_EQ(under.Clamped(lower, upper), lower); + EXPECT_EQ(inside.Clamped(lower, upper), inside); + EXPECT_EQ(over.Clamped(lower, upper), upper); + + Frequency mutable_frequency = lower; + mutable_frequency.Clamp(lower, upper); + EXPECT_EQ(mutable_frequency, lower); + mutable_frequency = inside; + mutable_frequency.Clamp(lower, upper); + EXPECT_EQ(mutable_frequency, inside); + mutable_frequency = over; + mutable_frequency.Clamp(lower, upper); + EXPECT_EQ(mutable_frequency, upper); +} + +TEST(FrequencyTest, MathOperations) { + const int64_t kValueA = 457; + const int64_t kValueB = 260; + const Frequency frequency_a = Frequency::Hertz(kValueA); + const Frequency frequency_b = Frequency::Hertz(kValueB); + EXPECT_EQ((frequency_a + frequency_b).hertz<int64_t>(), kValueA + kValueB); + EXPECT_EQ((frequency_a - frequency_b).hertz<int64_t>(), kValueA - kValueB); + + EXPECT_EQ((Frequency::Hertz(kValueA) * kValueB).hertz<int64_t>(), + kValueA * kValueB); + + EXPECT_EQ((frequency_b / 10).hertz<int64_t>(), kValueB / 10); + EXPECT_EQ(frequency_b / frequency_a, static_cast<double>(kValueB) / kValueA); + + Frequency mutable_frequency = Frequency::Hertz(kValueA); + mutable_frequency += Frequency::Hertz(kValueB); + EXPECT_EQ(mutable_frequency, Frequency::Hertz(kValueA + kValueB)); + mutable_frequency -= Frequency::Hertz(kValueB); + EXPECT_EQ(mutable_frequency, Frequency::Hertz(kValueA)); +} +TEST(FrequencyTest, Rounding) { + const Frequency freq_high = Frequency::Hertz(23.976); + EXPECT_EQ(freq_high.hertz(), 24); + EXPECT_EQ(freq_high.RoundDownTo(Frequency::Hertz(1)), Frequency::Hertz(23)); + EXPECT_EQ(freq_high.RoundTo(Frequency::Hertz(1)), Frequency::Hertz(24)); + EXPECT_EQ(freq_high.RoundUpTo(Frequency::Hertz(1)), Frequency::Hertz(24)); + + const Frequency freq_low = Frequency::Hertz(23.4); + EXPECT_EQ(freq_low.hertz(), 23); + EXPECT_EQ(freq_low.RoundDownTo(Frequency::Hertz(1)), Frequency::Hertz(23)); + EXPECT_EQ(freq_low.RoundTo(Frequency::Hertz(1)), Frequency::Hertz(23)); + EXPECT_EQ(freq_low.RoundUpTo(Frequency::Hertz(1)), Frequency::Hertz(24)); +} + +TEST(FrequencyTest, InfinityOperations) { + const double kValue = 267; + const Frequency finite = Frequency::Hertz(kValue); + EXPECT_TRUE((Frequency::PlusInfinity() + finite).IsPlusInfinity()); + EXPECT_TRUE((Frequency::PlusInfinity() - finite).IsPlusInfinity()); + EXPECT_TRUE((finite + Frequency::PlusInfinity()).IsPlusInfinity()); + EXPECT_TRUE((finite - Frequency::MinusInfinity()).IsPlusInfinity()); + + EXPECT_TRUE((Frequency::MinusInfinity() + finite).IsMinusInfinity()); + EXPECT_TRUE((Frequency::MinusInfinity() - finite).IsMinusInfinity()); + EXPECT_TRUE((finite + Frequency::MinusInfinity()).IsMinusInfinity()); + EXPECT_TRUE((finite - Frequency::PlusInfinity()).IsMinusInfinity()); +} + +TEST(UnitConversionTest, TimeDeltaAndFrequency) { + EXPECT_EQ(1 / Frequency::Hertz(50), TimeDelta::Millis(20)); + EXPECT_EQ(1 / TimeDelta::Millis(20), Frequency::Hertz(50)); + EXPECT_EQ(Frequency::KiloHertz(200) * TimeDelta::Millis(2), 400.0); +} +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/units/time_delta.cc b/third_party/libwebrtc/api/units/time_delta.cc new file mode 100644 index 0000000000..31bf3e0106 --- /dev/null +++ b/third_party/libwebrtc/api/units/time_delta.cc @@ -0,0 +1,36 @@ +/* + * 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 "api/units/time_delta.h" + +#include "api/array_view.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +std::string ToString(TimeDelta value) { + char buf[64]; + rtc::SimpleStringBuilder sb(buf); + if (value.IsPlusInfinity()) { + sb << "+inf ms"; + } else if (value.IsMinusInfinity()) { + sb << "-inf ms"; + } else { + if (value.us() == 0 || (value.us() % 1000) != 0) + sb << value.us() << " us"; + else if (value.ms() % 1000 != 0) + sb << value.ms() << " ms"; + else + sb << value.seconds() << " s"; + } + return sb.str(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/units/time_delta.h b/third_party/libwebrtc/api/units/time_delta.h new file mode 100644 index 0000000000..5981e32dce --- /dev/null +++ b/third_party/libwebrtc/api/units/time_delta.h @@ -0,0 +1,110 @@ +/* + * 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. + */ + +#ifndef API_UNITS_TIME_DELTA_H_ +#define API_UNITS_TIME_DELTA_H_ + +#ifdef WEBRTC_UNIT_TEST +#include <ostream> // no-presubmit-check TODO(webrtc:8982) +#endif // WEBRTC_UNIT_TEST + +#include <cstdlib> +#include <string> +#include <type_traits> + +#include "rtc_base/units/unit_base.h" // IWYU pragma: export + +namespace webrtc { + +// TimeDelta represents the difference between two timestamps. Commonly this can +// be a duration. However since two Timestamps are not guaranteed to have the +// same epoch (they might come from different computers, making exact +// synchronisation infeasible), the duration covered by a TimeDelta can be +// undefined. To simplify usage, it can be constructed and converted to +// different units, specifically seconds (s), milliseconds (ms) and +// microseconds (us). +class TimeDelta final : public rtc_units_impl::RelativeUnit<TimeDelta> { + public: + template <typename T> + static constexpr TimeDelta Minutes(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return Seconds(value * 60); + } + template <typename T> + static constexpr TimeDelta Seconds(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromFraction(1'000'000, value); + } + template <typename T> + static constexpr TimeDelta Millis(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromFraction(1'000, value); + } + template <typename T> + static constexpr TimeDelta Micros(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromValue(value); + } + + TimeDelta() = delete; + + template <typename T = int64_t> + constexpr T seconds() const { + return ToFraction<1000000, T>(); + } + template <typename T = int64_t> + constexpr T ms() const { + return ToFraction<1000, T>(); + } + template <typename T = int64_t> + constexpr T us() const { + return ToValue<T>(); + } + template <typename T = int64_t> + constexpr T ns() const { + return ToMultiple<1000, T>(); + } + + constexpr int64_t seconds_or(int64_t fallback_value) const { + return ToFractionOr<1000000>(fallback_value); + } + constexpr int64_t ms_or(int64_t fallback_value) const { + return ToFractionOr<1000>(fallback_value); + } + constexpr int64_t us_or(int64_t fallback_value) const { + return ToValueOr(fallback_value); + } + + constexpr TimeDelta Abs() const { + return us() < 0 ? TimeDelta::Micros(-us()) : *this; + } + + private: + friend class rtc_units_impl::UnitBase<TimeDelta>; + using RelativeUnit::RelativeUnit; + static constexpr bool one_sided = false; +}; + +std::string ToString(TimeDelta value); +inline std::string ToLogString(TimeDelta value) { + return ToString(value); +} + +#ifdef WEBRTC_UNIT_TEST +inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) + std::ostream& stream, // no-presubmit-check TODO(webrtc:8982) + TimeDelta value) { + return stream << ToString(value); +} +#endif // WEBRTC_UNIT_TEST + +} // namespace webrtc + +#endif // API_UNITS_TIME_DELTA_H_ diff --git a/third_party/libwebrtc/api/units/time_delta_gn/moz.build b/third_party/libwebrtc/api/units/time_delta_gn/moz.build new file mode 100644 index 0000000000..3fe57620d8 --- /dev/null +++ b/third_party/libwebrtc/api/units/time_delta_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/units/time_delta.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("time_delta_gn") diff --git a/third_party/libwebrtc/api/units/time_delta_unittest.cc b/third_party/libwebrtc/api/units/time_delta_unittest.cc new file mode 100644 index 0000000000..51a7aa233a --- /dev/null +++ b/third_party/libwebrtc/api/units/time_delta_unittest.cc @@ -0,0 +1,237 @@ +/* + * 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 "api/units/time_delta.h" + +#include <limits> + +#include "test/gtest.h" + +namespace webrtc { +namespace test { +TEST(TimeDeltaTest, ConstExpr) { + constexpr int64_t kValue = -12345; + constexpr TimeDelta kTimeDeltaZero = TimeDelta::Zero(); + constexpr TimeDelta kTimeDeltaPlusInf = TimeDelta::PlusInfinity(); + constexpr TimeDelta kTimeDeltaMinusInf = TimeDelta::MinusInfinity(); + static_assert(kTimeDeltaZero.IsZero(), ""); + static_assert(kTimeDeltaPlusInf.IsPlusInfinity(), ""); + static_assert(kTimeDeltaMinusInf.IsMinusInfinity(), ""); + static_assert(kTimeDeltaPlusInf.ms_or(-1) == -1, ""); + + static_assert(kTimeDeltaPlusInf > kTimeDeltaZero, ""); + + constexpr TimeDelta kTimeDeltaMinutes = TimeDelta::Minutes(kValue); + constexpr TimeDelta kTimeDeltaSeconds = TimeDelta::Seconds(kValue); + constexpr TimeDelta kTimeDeltaMs = TimeDelta::Millis(kValue); + constexpr TimeDelta kTimeDeltaUs = TimeDelta::Micros(kValue); + + static_assert(kTimeDeltaMinutes.seconds_or(0) == kValue * 60, ""); + static_assert(kTimeDeltaSeconds.seconds_or(0) == kValue, ""); + static_assert(kTimeDeltaMs.ms_or(0) == kValue, ""); + static_assert(kTimeDeltaUs.us_or(0) == kValue, ""); +} + +TEST(TimeDeltaTest, GetBackSameValues) { + const int64_t kValue = 499; + for (int sign = -1; sign <= 1; ++sign) { + int64_t value = kValue * sign; + EXPECT_EQ(TimeDelta::Millis(value).ms(), value); + EXPECT_EQ(TimeDelta::Micros(value).us(), value); + EXPECT_EQ(TimeDelta::Seconds(value).seconds(), value); + EXPECT_EQ(TimeDelta::Seconds(value).seconds(), value); + } + EXPECT_EQ(TimeDelta::Zero().us(), 0); +} + +TEST(TimeDeltaTest, GetDifferentPrefix) { + const int64_t kValue = 3000000; + EXPECT_EQ(TimeDelta::Micros(kValue).seconds(), kValue / 1000000); + EXPECT_EQ(TimeDelta::Millis(kValue).seconds(), kValue / 1000); + EXPECT_EQ(TimeDelta::Micros(kValue).ms(), kValue / 1000); + EXPECT_EQ(TimeDelta::Minutes(kValue / 60).seconds(), kValue); + + EXPECT_EQ(TimeDelta::Millis(kValue).us(), kValue * 1000); + EXPECT_EQ(TimeDelta::Seconds(kValue).ms(), kValue * 1000); + EXPECT_EQ(TimeDelta::Seconds(kValue).us(), kValue * 1000000); + EXPECT_EQ(TimeDelta::Minutes(kValue / 60).seconds(), kValue); +} + +TEST(TimeDeltaTest, IdentityChecks) { + const int64_t kValue = 3000; + EXPECT_TRUE(TimeDelta::Zero().IsZero()); + EXPECT_FALSE(TimeDelta::Millis(kValue).IsZero()); + + EXPECT_TRUE(TimeDelta::PlusInfinity().IsInfinite()); + EXPECT_TRUE(TimeDelta::MinusInfinity().IsInfinite()); + EXPECT_FALSE(TimeDelta::Zero().IsInfinite()); + EXPECT_FALSE(TimeDelta::Millis(-kValue).IsInfinite()); + EXPECT_FALSE(TimeDelta::Millis(kValue).IsInfinite()); + + EXPECT_FALSE(TimeDelta::PlusInfinity().IsFinite()); + EXPECT_FALSE(TimeDelta::MinusInfinity().IsFinite()); + EXPECT_TRUE(TimeDelta::Millis(-kValue).IsFinite()); + EXPECT_TRUE(TimeDelta::Millis(kValue).IsFinite()); + EXPECT_TRUE(TimeDelta::Zero().IsFinite()); + + EXPECT_TRUE(TimeDelta::PlusInfinity().IsPlusInfinity()); + EXPECT_FALSE(TimeDelta::MinusInfinity().IsPlusInfinity()); + + EXPECT_TRUE(TimeDelta::MinusInfinity().IsMinusInfinity()); + EXPECT_FALSE(TimeDelta::PlusInfinity().IsMinusInfinity()); +} + +TEST(TimeDeltaTest, ComparisonOperators) { + const int64_t kSmall = 450; + const int64_t kLarge = 451; + const TimeDelta small = TimeDelta::Millis(kSmall); + const TimeDelta large = TimeDelta::Millis(kLarge); + + EXPECT_EQ(TimeDelta::Zero(), TimeDelta::Millis(0)); + EXPECT_EQ(TimeDelta::PlusInfinity(), TimeDelta::PlusInfinity()); + EXPECT_EQ(small, TimeDelta::Millis(kSmall)); + EXPECT_LE(small, TimeDelta::Millis(kSmall)); + EXPECT_GE(small, TimeDelta::Millis(kSmall)); + EXPECT_NE(small, TimeDelta::Millis(kLarge)); + EXPECT_LE(small, TimeDelta::Millis(kLarge)); + EXPECT_LT(small, TimeDelta::Millis(kLarge)); + EXPECT_GE(large, TimeDelta::Millis(kSmall)); + EXPECT_GT(large, TimeDelta::Millis(kSmall)); + EXPECT_LT(TimeDelta::Zero(), small); + EXPECT_GT(TimeDelta::Zero(), TimeDelta::Millis(-kSmall)); + EXPECT_GT(TimeDelta::Zero(), TimeDelta::Millis(-kSmall)); + + EXPECT_GT(TimeDelta::PlusInfinity(), large); + EXPECT_LT(TimeDelta::MinusInfinity(), TimeDelta::Zero()); +} + +TEST(TimeDeltaTest, Clamping) { + const TimeDelta upper = TimeDelta::Millis(800); + const TimeDelta lower = TimeDelta::Millis(100); + const TimeDelta under = TimeDelta::Millis(100); + const TimeDelta inside = TimeDelta::Millis(500); + const TimeDelta over = TimeDelta::Millis(1000); + EXPECT_EQ(under.Clamped(lower, upper), lower); + EXPECT_EQ(inside.Clamped(lower, upper), inside); + EXPECT_EQ(over.Clamped(lower, upper), upper); + + TimeDelta mutable_delta = lower; + mutable_delta.Clamp(lower, upper); + EXPECT_EQ(mutable_delta, lower); + mutable_delta = inside; + mutable_delta.Clamp(lower, upper); + EXPECT_EQ(mutable_delta, inside); + mutable_delta = over; + mutable_delta.Clamp(lower, upper); + EXPECT_EQ(mutable_delta, upper); +} + +TEST(TimeDeltaTest, CanBeInititializedFromLargeInt) { + const int kMaxInt = std::numeric_limits<int>::max(); + EXPECT_EQ(TimeDelta::Seconds(kMaxInt).us(), + static_cast<int64_t>(kMaxInt) * 1000000); + EXPECT_EQ(TimeDelta::Millis(kMaxInt).us(), + static_cast<int64_t>(kMaxInt) * 1000); +} + +TEST(TimeDeltaTest, ConvertsToAndFromDouble) { + const int64_t kMicros = 17017; + const double kNanosDouble = kMicros * 1e3; + const double kMicrosDouble = kMicros; + const double kMillisDouble = kMicros * 1e-3; + const double kSecondsDouble = kMillisDouble * 1e-3; + + EXPECT_EQ(TimeDelta::Micros(kMicros).seconds<double>(), kSecondsDouble); + EXPECT_EQ(TimeDelta::Seconds(kSecondsDouble).us(), kMicros); + + EXPECT_EQ(TimeDelta::Micros(kMicros).ms<double>(), kMillisDouble); + EXPECT_EQ(TimeDelta::Millis(kMillisDouble).us(), kMicros); + + EXPECT_EQ(TimeDelta::Micros(kMicros).us<double>(), kMicrosDouble); + EXPECT_EQ(TimeDelta::Micros(kMicrosDouble).us(), kMicros); + + EXPECT_NEAR(TimeDelta::Micros(kMicros).ns<double>(), kNanosDouble, 1); + + const double kPlusInfinity = std::numeric_limits<double>::infinity(); + const double kMinusInfinity = -kPlusInfinity; + + EXPECT_EQ(TimeDelta::PlusInfinity().seconds<double>(), kPlusInfinity); + EXPECT_EQ(TimeDelta::MinusInfinity().seconds<double>(), kMinusInfinity); + EXPECT_EQ(TimeDelta::PlusInfinity().ms<double>(), kPlusInfinity); + EXPECT_EQ(TimeDelta::MinusInfinity().ms<double>(), kMinusInfinity); + EXPECT_EQ(TimeDelta::PlusInfinity().us<double>(), kPlusInfinity); + EXPECT_EQ(TimeDelta::MinusInfinity().us<double>(), kMinusInfinity); + EXPECT_EQ(TimeDelta::PlusInfinity().ns<double>(), kPlusInfinity); + EXPECT_EQ(TimeDelta::MinusInfinity().ns<double>(), kMinusInfinity); + + EXPECT_TRUE(TimeDelta::Seconds(kPlusInfinity).IsPlusInfinity()); + EXPECT_TRUE(TimeDelta::Seconds(kMinusInfinity).IsMinusInfinity()); + EXPECT_TRUE(TimeDelta::Millis(kPlusInfinity).IsPlusInfinity()); + EXPECT_TRUE(TimeDelta::Millis(kMinusInfinity).IsMinusInfinity()); + EXPECT_TRUE(TimeDelta::Micros(kPlusInfinity).IsPlusInfinity()); + EXPECT_TRUE(TimeDelta::Micros(kMinusInfinity).IsMinusInfinity()); +} + +TEST(TimeDeltaTest, MathOperations) { + const int64_t kValueA = 267; + const int64_t kValueB = 450; + const TimeDelta delta_a = TimeDelta::Millis(kValueA); + const TimeDelta delta_b = TimeDelta::Millis(kValueB); + EXPECT_EQ((delta_a + delta_b).ms(), kValueA + kValueB); + EXPECT_EQ((delta_a - delta_b).ms(), kValueA - kValueB); + + EXPECT_EQ((delta_b / 10).ms(), kValueB / 10); + EXPECT_EQ(delta_b / delta_a, static_cast<double>(kValueB) / kValueA); + + EXPECT_EQ(TimeDelta::Micros(-kValueA).Abs().us(), kValueA); + EXPECT_EQ(TimeDelta::Micros(kValueA).Abs().us(), kValueA); + + TimeDelta mutable_delta = TimeDelta::Millis(kValueA); + mutable_delta += TimeDelta::Millis(kValueB); + EXPECT_EQ(mutable_delta, TimeDelta::Millis(kValueA + kValueB)); + mutable_delta -= TimeDelta::Millis(kValueB); + EXPECT_EQ(mutable_delta, TimeDelta::Millis(kValueA)); +} + +TEST(TimeDeltaTest, MultiplyByScalar) { + const TimeDelta kValue = TimeDelta::Micros(267); + const int64_t kInt64 = 450; + const int32_t kInt32 = 123; + const size_t kUnsignedInt = 125; + const double kFloat = 123.0; + + EXPECT_EQ((kValue * kInt64).us(), kValue.us() * kInt64); + EXPECT_EQ(kValue * kInt64, kInt64 * kValue); + + EXPECT_EQ((kValue * kInt32).us(), kValue.us() * kInt32); + EXPECT_EQ(kValue * kInt32, kInt32 * kValue); + + EXPECT_EQ((kValue * kUnsignedInt).us(), kValue.us() * int64_t{kUnsignedInt}); + EXPECT_EQ(kValue * kUnsignedInt, kUnsignedInt * kValue); + + EXPECT_DOUBLE_EQ((kValue * kFloat).us(), kValue.us() * kFloat); + EXPECT_EQ(kValue * kFloat, kFloat * kValue); +} + +TEST(TimeDeltaTest, InfinityOperations) { + const int64_t kValue = 267; + const TimeDelta finite = TimeDelta::Millis(kValue); + EXPECT_TRUE((TimeDelta::PlusInfinity() + finite).IsPlusInfinity()); + EXPECT_TRUE((TimeDelta::PlusInfinity() - finite).IsPlusInfinity()); + EXPECT_TRUE((finite + TimeDelta::PlusInfinity()).IsPlusInfinity()); + EXPECT_TRUE((finite - TimeDelta::MinusInfinity()).IsPlusInfinity()); + + EXPECT_TRUE((TimeDelta::MinusInfinity() + finite).IsMinusInfinity()); + EXPECT_TRUE((TimeDelta::MinusInfinity() - finite).IsMinusInfinity()); + EXPECT_TRUE((finite + TimeDelta::MinusInfinity()).IsMinusInfinity()); + EXPECT_TRUE((finite - TimeDelta::PlusInfinity()).IsMinusInfinity()); +} +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/units/timestamp.cc b/third_party/libwebrtc/api/units/timestamp.cc new file mode 100644 index 0000000000..fc4f419596 --- /dev/null +++ b/third_party/libwebrtc/api/units/timestamp.cc @@ -0,0 +1,34 @@ +/* + * 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 "api/units/timestamp.h" + +#include "api/array_view.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { +std::string ToString(Timestamp value) { + char buf[64]; + rtc::SimpleStringBuilder sb(buf); + if (value.IsPlusInfinity()) { + sb << "+inf ms"; + } else if (value.IsMinusInfinity()) { + sb << "-inf ms"; + } else { + if (value.us() == 0 || (value.us() % 1000) != 0) + sb << value.us() << " us"; + else if (value.ms() % 1000 != 0) + sb << value.ms() << " ms"; + else + sb << value.seconds() << " s"; + } + return sb.str(); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/units/timestamp.h b/third_party/libwebrtc/api/units/timestamp.h new file mode 100644 index 0000000000..8aabe05cad --- /dev/null +++ b/third_party/libwebrtc/api/units/timestamp.h @@ -0,0 +1,139 @@ +/* + * 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. + */ + +#ifndef API_UNITS_TIMESTAMP_H_ +#define API_UNITS_TIMESTAMP_H_ + +#ifdef WEBRTC_UNIT_TEST +#include <ostream> // no-presubmit-check TODO(webrtc:8982) +#endif // WEBRTC_UNIT_TEST + +#include <string> +#include <type_traits> + +#include "api/units/time_delta.h" +#include "rtc_base/checks.h" +#include "rtc_base/units/unit_base.h" // IWYU pragma: export + +namespace webrtc { +// Timestamp represents the time that has passed since some unspecified epoch. +// The epoch is assumed to be before any represented timestamps, this means that +// negative values are not valid. The most notable feature is that the +// difference of two Timestamps results in a TimeDelta. +class Timestamp final : public rtc_units_impl::UnitBase<Timestamp> { + public: + template <typename T> + static constexpr Timestamp Seconds(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromFraction(1'000'000, value); + } + template <typename T> + static constexpr Timestamp Millis(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromFraction(1'000, value); + } + template <typename T> + static constexpr Timestamp Micros(T value) { + static_assert(std::is_arithmetic<T>::value, ""); + return FromValue(value); + } + + Timestamp() = delete; + + template <typename T = int64_t> + constexpr T seconds() const { + return ToFraction<1000000, T>(); + } + template <typename T = int64_t> + constexpr T ms() const { + return ToFraction<1000, T>(); + } + template <typename T = int64_t> + constexpr T us() const { + return ToValue<T>(); + } + + constexpr int64_t seconds_or(int64_t fallback_value) const { + return ToFractionOr<1000000>(fallback_value); + } + constexpr int64_t ms_or(int64_t fallback_value) const { + return ToFractionOr<1000>(fallback_value); + } + constexpr int64_t us_or(int64_t fallback_value) const { + return ToValueOr(fallback_value); + } + + constexpr Timestamp operator+(const TimeDelta delta) const { + if (IsPlusInfinity() || delta.IsPlusInfinity()) { + RTC_DCHECK(!IsMinusInfinity()); + RTC_DCHECK(!delta.IsMinusInfinity()); + return PlusInfinity(); + } else if (IsMinusInfinity() || delta.IsMinusInfinity()) { + RTC_DCHECK(!IsPlusInfinity()); + RTC_DCHECK(!delta.IsPlusInfinity()); + return MinusInfinity(); + } + return Timestamp::Micros(us() + delta.us()); + } + constexpr Timestamp operator-(const TimeDelta delta) const { + if (IsPlusInfinity() || delta.IsMinusInfinity()) { + RTC_DCHECK(!IsMinusInfinity()); + RTC_DCHECK(!delta.IsPlusInfinity()); + return PlusInfinity(); + } else if (IsMinusInfinity() || delta.IsPlusInfinity()) { + RTC_DCHECK(!IsPlusInfinity()); + RTC_DCHECK(!delta.IsMinusInfinity()); + return MinusInfinity(); + } + return Timestamp::Micros(us() - delta.us()); + } + constexpr TimeDelta operator-(const Timestamp other) const { + if (IsPlusInfinity() || other.IsMinusInfinity()) { + RTC_DCHECK(!IsMinusInfinity()); + RTC_DCHECK(!other.IsPlusInfinity()); + return TimeDelta::PlusInfinity(); + } else if (IsMinusInfinity() || other.IsPlusInfinity()) { + RTC_DCHECK(!IsPlusInfinity()); + RTC_DCHECK(!other.IsMinusInfinity()); + return TimeDelta::MinusInfinity(); + } + return TimeDelta::Micros(us() - other.us()); + } + constexpr Timestamp& operator-=(const TimeDelta delta) { + *this = *this - delta; + return *this; + } + constexpr Timestamp& operator+=(const TimeDelta delta) { + *this = *this + delta; + return *this; + } + + private: + friend class rtc_units_impl::UnitBase<Timestamp>; + using UnitBase::UnitBase; + static constexpr bool one_sided = true; +}; + +std::string ToString(Timestamp value); +inline std::string ToLogString(Timestamp value) { + return ToString(value); +} + +#ifdef WEBRTC_UNIT_TEST +inline std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982) + std::ostream& stream, // no-presubmit-check TODO(webrtc:8982) + Timestamp value) { + return stream << ToString(value); +} +#endif // WEBRTC_UNIT_TEST + +} // namespace webrtc + +#endif // API_UNITS_TIMESTAMP_H_ diff --git a/third_party/libwebrtc/api/units/timestamp_gn/moz.build b/third_party/libwebrtc/api/units/timestamp_gn/moz.build new file mode 100644 index 0000000000..a869cbcd71 --- /dev/null +++ b/third_party/libwebrtc/api/units/timestamp_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/units/timestamp.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("timestamp_gn") diff --git a/third_party/libwebrtc/api/units/timestamp_unittest.cc b/third_party/libwebrtc/api/units/timestamp_unittest.cc new file mode 100644 index 0000000000..43b2985d43 --- /dev/null +++ b/third_party/libwebrtc/api/units/timestamp_unittest.cc @@ -0,0 +1,162 @@ +/* + * 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 <limits> + +#include "api/units/timestamp.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { +TEST(TimestampTest, ConstExpr) { + constexpr int64_t kValue = 12345; + constexpr Timestamp kTimestampInf = Timestamp::PlusInfinity(); + static_assert(kTimestampInf.IsInfinite(), ""); + static_assert(kTimestampInf.ms_or(-1) == -1, ""); + + constexpr Timestamp kTimestampSeconds = Timestamp::Seconds(kValue); + constexpr Timestamp kTimestampMs = Timestamp::Millis(kValue); + constexpr Timestamp kTimestampUs = Timestamp::Micros(kValue); + + static_assert(kTimestampSeconds.seconds_or(0) == kValue, ""); + static_assert(kTimestampMs.ms_or(0) == kValue, ""); + static_assert(kTimestampUs.us_or(0) == kValue, ""); + + static_assert(kTimestampMs > kTimestampUs, ""); + + EXPECT_EQ(kTimestampSeconds.seconds(), kValue); + EXPECT_EQ(kTimestampMs.ms(), kValue); + EXPECT_EQ(kTimestampUs.us(), kValue); +} + +TEST(TimestampTest, GetBackSameValues) { + const int64_t kValue = 499; + EXPECT_EQ(Timestamp::Millis(kValue).ms(), kValue); + EXPECT_EQ(Timestamp::Micros(kValue).us(), kValue); + EXPECT_EQ(Timestamp::Seconds(kValue).seconds(), kValue); +} + +TEST(TimestampTest, GetDifferentPrefix) { + const int64_t kValue = 3000000; + EXPECT_EQ(Timestamp::Micros(kValue).seconds(), kValue / 1000000); + EXPECT_EQ(Timestamp::Millis(kValue).seconds(), kValue / 1000); + EXPECT_EQ(Timestamp::Micros(kValue).ms(), kValue / 1000); + + EXPECT_EQ(Timestamp::Millis(kValue).us(), kValue * 1000); + EXPECT_EQ(Timestamp::Seconds(kValue).ms(), kValue * 1000); + EXPECT_EQ(Timestamp::Seconds(kValue).us(), kValue * 1000000); +} + +TEST(TimestampTest, IdentityChecks) { + const int64_t kValue = 3000; + + EXPECT_TRUE(Timestamp::PlusInfinity().IsInfinite()); + EXPECT_TRUE(Timestamp::MinusInfinity().IsInfinite()); + EXPECT_FALSE(Timestamp::Millis(kValue).IsInfinite()); + + EXPECT_FALSE(Timestamp::PlusInfinity().IsFinite()); + EXPECT_FALSE(Timestamp::MinusInfinity().IsFinite()); + EXPECT_TRUE(Timestamp::Millis(kValue).IsFinite()); + + EXPECT_TRUE(Timestamp::PlusInfinity().IsPlusInfinity()); + EXPECT_FALSE(Timestamp::MinusInfinity().IsPlusInfinity()); + + EXPECT_TRUE(Timestamp::MinusInfinity().IsMinusInfinity()); + EXPECT_FALSE(Timestamp::PlusInfinity().IsMinusInfinity()); +} + +TEST(TimestampTest, ComparisonOperators) { + const int64_t kSmall = 450; + const int64_t kLarge = 451; + + EXPECT_EQ(Timestamp::PlusInfinity(), Timestamp::PlusInfinity()); + EXPECT_GE(Timestamp::PlusInfinity(), Timestamp::PlusInfinity()); + EXPECT_GT(Timestamp::PlusInfinity(), Timestamp::Millis(kLarge)); + EXPECT_EQ(Timestamp::Millis(kSmall), Timestamp::Millis(kSmall)); + EXPECT_LE(Timestamp::Millis(kSmall), Timestamp::Millis(kSmall)); + EXPECT_GE(Timestamp::Millis(kSmall), Timestamp::Millis(kSmall)); + EXPECT_NE(Timestamp::Millis(kSmall), Timestamp::Millis(kLarge)); + EXPECT_LE(Timestamp::Millis(kSmall), Timestamp::Millis(kLarge)); + EXPECT_LT(Timestamp::Millis(kSmall), Timestamp::Millis(kLarge)); + EXPECT_GE(Timestamp::Millis(kLarge), Timestamp::Millis(kSmall)); + EXPECT_GT(Timestamp::Millis(kLarge), Timestamp::Millis(kSmall)); +} + +TEST(TimestampTest, CanBeInititializedFromLargeInt) { + const int kMaxInt = std::numeric_limits<int>::max(); + EXPECT_EQ(Timestamp::Seconds(kMaxInt).us(), + static_cast<int64_t>(kMaxInt) * 1000000); + EXPECT_EQ(Timestamp::Millis(kMaxInt).us(), + static_cast<int64_t>(kMaxInt) * 1000); +} + +TEST(TimestampTest, ConvertsToAndFromDouble) { + const int64_t kMicros = 17017; + const double kMicrosDouble = kMicros; + const double kMillisDouble = kMicros * 1e-3; + const double kSecondsDouble = kMillisDouble * 1e-3; + + EXPECT_EQ(Timestamp::Micros(kMicros).seconds<double>(), kSecondsDouble); + EXPECT_EQ(Timestamp::Seconds(kSecondsDouble).us(), kMicros); + + EXPECT_EQ(Timestamp::Micros(kMicros).ms<double>(), kMillisDouble); + EXPECT_EQ(Timestamp::Millis(kMillisDouble).us(), kMicros); + + EXPECT_EQ(Timestamp::Micros(kMicros).us<double>(), kMicrosDouble); + EXPECT_EQ(Timestamp::Micros(kMicrosDouble).us(), kMicros); + + const double kPlusInfinity = std::numeric_limits<double>::infinity(); + const double kMinusInfinity = -kPlusInfinity; + + EXPECT_EQ(Timestamp::PlusInfinity().seconds<double>(), kPlusInfinity); + EXPECT_EQ(Timestamp::MinusInfinity().seconds<double>(), kMinusInfinity); + EXPECT_EQ(Timestamp::PlusInfinity().ms<double>(), kPlusInfinity); + EXPECT_EQ(Timestamp::MinusInfinity().ms<double>(), kMinusInfinity); + EXPECT_EQ(Timestamp::PlusInfinity().us<double>(), kPlusInfinity); + EXPECT_EQ(Timestamp::MinusInfinity().us<double>(), kMinusInfinity); + + EXPECT_TRUE(Timestamp::Seconds(kPlusInfinity).IsPlusInfinity()); + EXPECT_TRUE(Timestamp::Seconds(kMinusInfinity).IsMinusInfinity()); + EXPECT_TRUE(Timestamp::Millis(kPlusInfinity).IsPlusInfinity()); + EXPECT_TRUE(Timestamp::Millis(kMinusInfinity).IsMinusInfinity()); + EXPECT_TRUE(Timestamp::Micros(kPlusInfinity).IsPlusInfinity()); + EXPECT_TRUE(Timestamp::Micros(kMinusInfinity).IsMinusInfinity()); +} + +TEST(UnitConversionTest, TimestampAndTimeDeltaMath) { + const int64_t kValueA = 267; + const int64_t kValueB = 450; + const Timestamp time_a = Timestamp::Millis(kValueA); + const Timestamp time_b = Timestamp::Millis(kValueB); + const TimeDelta delta_a = TimeDelta::Millis(kValueA); + const TimeDelta delta_b = TimeDelta::Millis(kValueB); + + EXPECT_EQ((time_a - time_b), TimeDelta::Millis(kValueA - kValueB)); + EXPECT_EQ((time_b - delta_a), Timestamp::Millis(kValueB - kValueA)); + EXPECT_EQ((time_b + delta_a), Timestamp::Millis(kValueB + kValueA)); + + Timestamp mutable_time = time_a; + mutable_time += delta_b; + EXPECT_EQ(mutable_time, time_a + delta_b); + mutable_time -= delta_b; + EXPECT_EQ(mutable_time, time_a); +} + +TEST(UnitConversionTest, InfinityOperations) { + const int64_t kValue = 267; + const Timestamp finite_time = Timestamp::Millis(kValue); + const TimeDelta finite_delta = TimeDelta::Millis(kValue); + EXPECT_TRUE((Timestamp::PlusInfinity() + finite_delta).IsInfinite()); + EXPECT_TRUE((Timestamp::PlusInfinity() - finite_delta).IsInfinite()); + EXPECT_TRUE((finite_time + TimeDelta::PlusInfinity()).IsInfinite()); + EXPECT_TRUE((finite_time - TimeDelta::MinusInfinity()).IsInfinite()); +} +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/BUILD.gn b/third_party/libwebrtc/api/video/BUILD.gn new file mode 100644 index 0000000000..5d1aa2a1a3 --- /dev/null +++ b/third_party/libwebrtc/api/video/BUILD.gn @@ -0,0 +1,421 @@ +# 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. + +import("../../webrtc.gni") +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +rtc_library("video_rtp_headers") { + visibility = [ "*" ] + sources = [ + "color_space.cc", + "color_space.h", + "hdr_metadata.cc", + "hdr_metadata.h", + "video_content_type.cc", + "video_content_type.h", + "video_rotation.h", + "video_timing.cc", + "video_timing.h", + ] + + deps = [ + "..:array_view", + "../../rtc_base:logging", + "../../rtc_base:safe_conversions", + "../../rtc_base:stringutils", + "../../rtc_base/system:rtc_export", + "../units:data_rate", + "../units:time_delta", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/container:inlined_vector", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("video_frame") { + visibility = [ "*" ] + sources = [ + "i420_buffer.cc", + "i420_buffer.h", + "i422_buffer.cc", + "i422_buffer.h", + "i444_buffer.cc", + "i444_buffer.h", + "nv12_buffer.cc", + "nv12_buffer.h", + "video_codec_type.h", + "video_frame.cc", + "video_frame.h", + "video_frame_buffer.cc", + "video_frame_buffer.h", + "video_sink_interface.h", + "video_source_interface.cc", + "video_source_interface.h", + ] + + deps = [ + ":video_rtp_headers", + "..:array_view", + "..:make_ref_counted", + "..:rtp_packet_info", + "..:scoped_refptr", + "..:video_track_source_constraints", + "../../rtc_base:checks", + "../../rtc_base:refcount", + "../../rtc_base:timeutils", + "../../rtc_base/memory:aligned_malloc", + "../../rtc_base/system:rtc_export", + "//third_party/libyuv", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +if (is_android) { + java_cpp_enum("video_frame_enums") { + sources = [ "video_frame_buffer.h" ] + } +} + +rtc_library("video_frame_i010") { + visibility = [ "*" ] + sources = [ + "i010_buffer.cc", + "i010_buffer.h", + "i210_buffer.cc", + "i210_buffer.h", + "i410_buffer.cc", + "i410_buffer.h", + ] + deps = [ + ":video_frame", + ":video_rtp_headers", + "..:make_ref_counted", + "..:scoped_refptr", + "../../rtc_base:checks", + "../../rtc_base:refcount", + "../../rtc_base/memory:aligned_malloc", + "//third_party/libyuv", + ] +} + +rtc_source_set("recordable_encoded_frame") { + visibility = [ "*" ] + sources = [ "recordable_encoded_frame.h" ] + + deps = [ + ":encoded_image", + ":video_frame", + ":video_rtp_headers", + "..:array_view", + "..:make_ref_counted", + "..:scoped_refptr", + "../units:timestamp", + ] +} + +rtc_source_set("video_frame_type") { + visibility = [ "*" ] + sources = [ "video_frame_type.h" ] +} + +rtc_source_set("render_resolution") { + visibility = [ "*" ] + public = [ "render_resolution.h" ] +} + +rtc_source_set("resolution") { + visibility = [ "*" ] + public = [ "resolution.h" ] +} + +rtc_library("encoded_image") { + visibility = [ "*" ] + sources = [ + "encoded_image.cc", + "encoded_image.h", + ] + deps = [ + ":video_codec_constants", + ":video_frame", + ":video_frame_type", + ":video_rtp_headers", + "..:refcountedbase", + "..:rtp_packet_info", + "..:scoped_refptr", + "../../rtc_base:checks", + "../../rtc_base:refcount", + "../../rtc_base/system:rtc_export", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("encoded_frame") { + visibility = [ "*" ] + sources = [ + "encoded_frame.cc", + "encoded_frame.h", + ] + + deps = [ + "../../modules/video_coding:encoded_frame", + "../units:timestamp", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("rtp_video_frame_assembler") { + visibility = [ "*" ] + sources = [ + "rtp_video_frame_assembler.cc", + "rtp_video_frame_assembler.h", + ] + + deps = [ + ":encoded_frame", + "../../modules/rtp_rtcp:rtp_rtcp", + "../../modules/rtp_rtcp:rtp_rtcp_format", + "../../modules/video_coding:packet_buffer", + "../../modules/video_coding:video_coding", + "../../rtc_base:logging", + "../../rtc_base:rtc_numerics", + ] + + absl_deps = [ + "//third_party/abseil-cpp/absl/container:inlined_vector", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("rtp_video_frame_assembler_unittests") { + testonly = true + sources = [ "rtp_video_frame_assembler_unittests.cc" ] + + deps = [ + ":rtp_video_frame_assembler", + "..:array_view", + "../../modules/rtp_rtcp:rtp_packetizer_av1_test_helper", + "../../modules/rtp_rtcp:rtp_rtcp", + "../../modules/rtp_rtcp:rtp_rtcp_format", + "../../test:test_support", + ] +} + +rtc_source_set("video_codec_constants") { + visibility = [ "*" ] + sources = [ "video_codec_constants.h" ] + deps = [] +} + +rtc_library("video_bitrate_allocation") { + visibility = [ "*" ] + sources = [ + "video_bitrate_allocation.cc", + "video_bitrate_allocation.h", + ] + deps = [ + ":video_codec_constants", + "../../rtc_base:checks", + "../../rtc_base:safe_conversions", + "../../rtc_base:stringutils", + "../../rtc_base/system:rtc_export", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_source_set("video_layers_allocation") { + visibility = [ "*" ] + sources = [ "video_layers_allocation.h" ] + deps = [ "../units:data_rate" ] + absl_deps = [ "//third_party/abseil-cpp/absl/container:inlined_vector" ] +} + +rtc_library("video_bitrate_allocator") { + visibility = [ "*" ] + sources = [ + "video_bitrate_allocator.cc", + "video_bitrate_allocator.h", + ] + deps = [ + ":video_bitrate_allocation", + "../units:data_rate", + ] +} + +rtc_source_set("video_bitrate_allocator_factory") { + visibility = [ "*" ] + sources = [ "video_bitrate_allocator_factory.h" ] + deps = [ + ":video_bitrate_allocator", + "../video_codecs:video_codecs_api", + ] +} + +rtc_source_set("video_stream_decoder") { + visibility = [ "*" ] + sources = [ "video_stream_decoder.h" ] + + deps = [ + ":encoded_frame", + ":video_frame", + ":video_rtp_headers", + "../task_queue", + "../units:time_delta", + "../video_codecs:video_codecs_api", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("video_stream_decoder_create") { + visibility = [ "*" ] + sources = [ + "video_stream_decoder_create.cc", + "video_stream_decoder_create.h", + ] + + deps = [ + ":video_stream_decoder", + "../../api:field_trials_view", + "../../video:video_stream_decoder_impl", + "../task_queue", + "../video_codecs:video_codecs_api", + ] +} + +rtc_library("video_adaptation") { + visibility = [ "*" ] + sources = [ + "video_adaptation_counters.cc", + "video_adaptation_counters.h", + "video_adaptation_reason.h", + ] + + deps = [ + "../../rtc_base:checks", + "../../rtc_base:stringutils", + ] +} + +rtc_source_set("video_stream_encoder") { + visibility = [ "*" ] + sources = [ "video_stream_encoder_settings.h" ] + + deps = [ + ":video_adaptation", + ":video_bitrate_allocation", + ":video_bitrate_allocator", + ":video_bitrate_allocator_factory", + ":video_codec_constants", + ":video_frame", + ":video_layers_allocation", + "..:rtp_parameters", + "..:scoped_refptr", + "../:fec_controller_api", + "../:rtp_parameters", + "../adaptation:resource_adaptation_api", + "../units:data_rate", + "../video_codecs:video_codecs_api", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_source_set("video_frame_metadata") { + visibility = [ "*" ] + sources = [ + "video_frame_metadata.cc", + "video_frame_metadata.h", + ] + deps = [ + ":video_frame", + ":video_frame_type", + ":video_rtp_headers", + "..:array_view", + "../../modules/video_coding:codec_globals_headers", + "../../rtc_base/system:rtc_export", + "../transport/rtp:dependency_descriptor", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/container:inlined_vector", + "//third_party/abseil-cpp/absl/types:optional", + "//third_party/abseil-cpp/absl/types:variant", + ] +} + +rtc_library("builtin_video_bitrate_allocator_factory") { + visibility = [ "*" ] + sources = [ + "builtin_video_bitrate_allocator_factory.cc", + "builtin_video_bitrate_allocator_factory.h", + ] + + deps = [ + ":video_bitrate_allocation", + ":video_bitrate_allocator", + ":video_bitrate_allocator_factory", + "../../api:scoped_refptr", + "../../media:rtc_media_base", + "../../modules/video_coding:video_coding_utility", + "../../modules/video_coding/svc:svc_rate_allocator", + "../video_codecs:video_codecs_api", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/base:core_headers" ] +} + +rtc_library("frame_buffer") { + visibility = [ "*" ] + sources = [ + "frame_buffer.cc", + "frame_buffer.h", + ] + deps = [ + "../../api:field_trials_view", + "../../api/units:timestamp", + "../../api/video:encoded_frame", + "../../modules/video_coding:video_coding_utility", + "../../rtc_base:logging", + "../../rtc_base:rtc_numerics", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/container:inlined_vector", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("frame_buffer_unittest") { + testonly = true + sources = [ "frame_buffer_unittest.cc" ] + + deps = [ + ":frame_buffer", + "../../api/video:encoded_frame", + "../../test:fake_encoded_frame", + "../../test:field_trial", + "../../test:scoped_key_value_config", + "../../test:test_support", + ] +} + +if (rtc_include_tests) { + rtc_library("video_unittests") { + testonly = true + sources = [ "video_stream_decoder_create_unittest.cc" ] + deps = [ + ":video_frame_metadata", + ":video_frame_type", + ":video_stream_decoder_create", + "../../modules/rtp_rtcp:rtp_video_header", + "../../test:test_support", + "../task_queue:default_task_queue_factory", + "../video_codecs:builtin_video_decoder_factory", + ] + } +} diff --git a/third_party/libwebrtc/api/video/DEPS b/third_party/libwebrtc/api/video/DEPS new file mode 100644 index 0000000000..c84299f943 --- /dev/null +++ b/third_party/libwebrtc/api/video/DEPS @@ -0,0 +1,77 @@ +specific_include_rules = { + # Until the new VideoStreamDecoder is implemented the current decoding + # pipeline will be used, and therefore EncodedFrame needs to inherit + # VCMEncodedFrame. + "encoded_frame.h": [ + "+modules/video_coding/encoded_frame.h", + ], + + "encoded_image\.h" : [ + "+rtc_base/ref_count.h", + ], + + "i010_buffer\.h": [ + "+rtc_base/memory/aligned_malloc.h", + ], + + "i210_buffer\.h": [ + "+rtc_base/memory/aligned_malloc.h", + ], + + "i410_buffer\.h": [ + "+rtc_base/memory/aligned_malloc.h", + ], + + "i420_buffer\.h": [ + "+rtc_base/memory/aligned_malloc.h", + ], + + "i422_buffer\.h": [ + "+rtc_base/memory/aligned_malloc.h", + ], + + "i444_buffer\.h": [ + "+rtc_base/memory/aligned_malloc.h", + ], + + "nv12_buffer\.h": [ + "+rtc_base/memory/aligned_malloc.h", + ], + + "recordable_encoded_frame\.h": [ + "+rtc_base/ref_count.h", + ], + + "video_frame\.h": [ + ], + + "video_frame_buffer\.h": [ + "+rtc_base/ref_count.h", + ], + + "video_frame_metadata\.h": [ + "+modules/video_coding/codecs/h264/include/h264_globals.h", + "+modules/video_coding/codecs/vp8/include/vp8_globals.h", + "+modules/video_coding/codecs/vp9/include/vp9_globals.h", + ], + + "video_stream_decoder_create.cc": [ + "+video/video_stream_decoder_impl.h", + ], + + "video_stream_encoder_create.cc": [ + "+video/video_stream_encoder.h", + ], + + "rtp_video_frame_assembler.h": [ + "+modules/rtp_rtcp/source/rtp_packet_received.h", + ], + + "frame_buffer.h": [ + "+modules/video_coding/utility/decoded_frames_history.h", + ], + + "video_frame_matchers\.h": [ + "+test/gmock.h", + ], +} diff --git a/third_party/libwebrtc/api/video/OWNERS b/third_party/libwebrtc/api/video/OWNERS new file mode 100644 index 0000000000..49b62f3780 --- /dev/null +++ b/third_party/libwebrtc/api/video/OWNERS @@ -0,0 +1,5 @@ +brandtr@webrtc.org +magjed@webrtc.org +philipel@webrtc.org + +per-file video_timing.h=ilnik@webrtc.org diff --git a/third_party/libwebrtc/api/video/builtin_video_bitrate_allocator_factory.cc b/third_party/libwebrtc/api/video/builtin_video_bitrate_allocator_factory.cc new file mode 100644 index 0000000000..4c24a0e75d --- /dev/null +++ b/third_party/libwebrtc/api/video/builtin_video_bitrate_allocator_factory.cc @@ -0,0 +1,50 @@ +/* + * 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 "api/video/builtin_video_bitrate_allocator_factory.h" + +#include <memory> + +#include "absl/base/macros.h" +#include "api/video/video_bitrate_allocator.h" +#include "api/video_codecs/video_codec.h" +#include "modules/video_coding/svc/svc_rate_allocator.h" +#include "modules/video_coding/utility/simulcast_rate_allocator.h" + +namespace webrtc { + +namespace { + +class BuiltinVideoBitrateAllocatorFactory + : public VideoBitrateAllocatorFactory { + public: + BuiltinVideoBitrateAllocatorFactory() = default; + ~BuiltinVideoBitrateAllocatorFactory() override = default; + + std::unique_ptr<VideoBitrateAllocator> CreateVideoBitrateAllocator( + const VideoCodec& codec) override { + switch (codec.codecType) { + case kVideoCodecAV1: + case kVideoCodecVP9: + return std::make_unique<SvcRateAllocator>(codec); + default: + return std::make_unique<SimulcastRateAllocator>(codec); + } + } +}; + +} // namespace + +std::unique_ptr<VideoBitrateAllocatorFactory> +CreateBuiltinVideoBitrateAllocatorFactory() { + return std::make_unique<BuiltinVideoBitrateAllocatorFactory>(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/builtin_video_bitrate_allocator_factory.h b/third_party/libwebrtc/api/video/builtin_video_bitrate_allocator_factory.h new file mode 100644 index 0000000000..ac880a0863 --- /dev/null +++ b/third_party/libwebrtc/api/video/builtin_video_bitrate_allocator_factory.h @@ -0,0 +1,25 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_BUILTIN_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_ +#define API_VIDEO_BUILTIN_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_ + +#include <memory> + +#include "api/video/video_bitrate_allocator_factory.h" + +namespace webrtc { + +std::unique_ptr<VideoBitrateAllocatorFactory> +CreateBuiltinVideoBitrateAllocatorFactory(); + +} // namespace webrtc + +#endif // API_VIDEO_BUILTIN_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_ diff --git a/third_party/libwebrtc/api/video/builtin_video_bitrate_allocator_factory_gn/moz.build b/third_party/libwebrtc/api/video/builtin_video_bitrate_allocator_factory_gn/moz.build new file mode 100644 index 0000000000..40823f2355 --- /dev/null +++ b/third_party/libwebrtc/api/video/builtin_video_bitrate_allocator_factory_gn/moz.build @@ -0,0 +1,233 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video/builtin_video_bitrate_allocator_factory.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "GLESv2", + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("builtin_video_bitrate_allocator_factory_gn") diff --git a/third_party/libwebrtc/api/video/color_space.cc b/third_party/libwebrtc/api/video/color_space.cc new file mode 100644 index 0000000000..a0cd32edb2 --- /dev/null +++ b/third_party/libwebrtc/api/video/color_space.cc @@ -0,0 +1,187 @@ +/* + * 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 "api/video/color_space.h" + +namespace webrtc { +namespace { +// Try to convert `enum_value` into the enum class T. `enum_bitmask` is created +// by the funciton below. Returns true if conversion was successful, false +// otherwise. +template <typename T> +bool SetFromUint8(uint8_t enum_value, uint64_t enum_bitmask, T* out) { + if ((enum_value < 64) && ((enum_bitmask >> enum_value) & 1)) { + *out = static_cast<T>(enum_value); + return true; + } + return false; +} + +// This function serves as an assert for the constexpr function below. It's on +// purpose not declared as constexpr so that it causes a build problem if enum +// values of 64 or above are used. The bitmask and the code generating it would +// have to be extended if the standard is updated to include enum values >= 64. +int EnumMustBeLessThan64() { + return -1; +} + +template <typename T, size_t N> +constexpr int MakeMask(const int index, const int length, T (&values)[N]) { + return length > 1 + ? (MakeMask(index, 1, values) + + MakeMask(index + 1, length - 1, values)) + : (static_cast<uint8_t>(values[index]) < 64 + ? (uint64_t{1} << static_cast<uint8_t>(values[index])) + : EnumMustBeLessThan64()); +} + +// Create a bitmask where each bit corresponds to one potential enum value. +// `values` should be an array listing all possible enum values. The bit is set +// to one if the corresponding enum exists. Only works for enums with values +// less than 64. +template <typename T, size_t N> +constexpr uint64_t CreateEnumBitmask(T (&values)[N]) { + return MakeMask(0, N, values); +} + +bool SetChromaSitingFromUint8(uint8_t enum_value, + ColorSpace::ChromaSiting* chroma_siting) { + constexpr ColorSpace::ChromaSiting kChromaSitings[] = { + ColorSpace::ChromaSiting::kUnspecified, + ColorSpace::ChromaSiting::kCollocated, ColorSpace::ChromaSiting::kHalf}; + constexpr uint64_t enum_bitmask = CreateEnumBitmask(kChromaSitings); + + return SetFromUint8(enum_value, enum_bitmask, chroma_siting); +} + +} // namespace + +ColorSpace::ColorSpace() = default; +ColorSpace::ColorSpace(const ColorSpace& other) = default; +ColorSpace::ColorSpace(ColorSpace&& other) = default; +ColorSpace& ColorSpace::operator=(const ColorSpace& other) = default; + +ColorSpace::ColorSpace(PrimaryID primaries, + TransferID transfer, + MatrixID matrix, + RangeID range) + : ColorSpace(primaries, + transfer, + matrix, + range, + ChromaSiting::kUnspecified, + ChromaSiting::kUnspecified, + nullptr) {} + +ColorSpace::ColorSpace(PrimaryID primaries, + TransferID transfer, + MatrixID matrix, + RangeID range, + ChromaSiting chroma_siting_horz, + ChromaSiting chroma_siting_vert, + const HdrMetadata* hdr_metadata) + : primaries_(primaries), + transfer_(transfer), + matrix_(matrix), + range_(range), + chroma_siting_horizontal_(chroma_siting_horz), + chroma_siting_vertical_(chroma_siting_vert), + hdr_metadata_(hdr_metadata ? absl::make_optional(*hdr_metadata) + : absl::nullopt) {} + +ColorSpace::PrimaryID ColorSpace::primaries() const { + return primaries_; +} + +ColorSpace::TransferID ColorSpace::transfer() const { + return transfer_; +} + +ColorSpace::MatrixID ColorSpace::matrix() const { + return matrix_; +} + +ColorSpace::RangeID ColorSpace::range() const { + return range_; +} + +ColorSpace::ChromaSiting ColorSpace::chroma_siting_horizontal() const { + return chroma_siting_horizontal_; +} + +ColorSpace::ChromaSiting ColorSpace::chroma_siting_vertical() const { + return chroma_siting_vertical_; +} + +const HdrMetadata* ColorSpace::hdr_metadata() const { + return hdr_metadata_ ? &*hdr_metadata_ : nullptr; +} + +bool ColorSpace::set_primaries_from_uint8(uint8_t enum_value) { + constexpr PrimaryID kPrimaryIds[] = { + PrimaryID::kBT709, PrimaryID::kUnspecified, PrimaryID::kBT470M, + PrimaryID::kBT470BG, PrimaryID::kSMPTE170M, PrimaryID::kSMPTE240M, + PrimaryID::kFILM, PrimaryID::kBT2020, PrimaryID::kSMPTEST428, + PrimaryID::kSMPTEST431, PrimaryID::kSMPTEST432, PrimaryID::kJEDECP22}; + constexpr uint64_t enum_bitmask = CreateEnumBitmask(kPrimaryIds); + + return SetFromUint8(enum_value, enum_bitmask, &primaries_); +} + +bool ColorSpace::set_transfer_from_uint8(uint8_t enum_value) { + constexpr TransferID kTransferIds[] = { + TransferID::kBT709, TransferID::kUnspecified, + TransferID::kGAMMA22, TransferID::kGAMMA28, + TransferID::kSMPTE170M, TransferID::kSMPTE240M, + TransferID::kLINEAR, TransferID::kLOG, + TransferID::kLOG_SQRT, TransferID::kIEC61966_2_4, + TransferID::kBT1361_ECG, TransferID::kIEC61966_2_1, + TransferID::kBT2020_10, TransferID::kBT2020_12, + TransferID::kSMPTEST2084, TransferID::kSMPTEST428, + TransferID::kARIB_STD_B67}; + constexpr uint64_t enum_bitmask = CreateEnumBitmask(kTransferIds); + + return SetFromUint8(enum_value, enum_bitmask, &transfer_); +} + +bool ColorSpace::set_matrix_from_uint8(uint8_t enum_value) { + constexpr MatrixID kMatrixIds[] = { + MatrixID::kRGB, MatrixID::kBT709, MatrixID::kUnspecified, + MatrixID::kFCC, MatrixID::kBT470BG, MatrixID::kSMPTE170M, + MatrixID::kSMPTE240M, MatrixID::kYCOCG, MatrixID::kBT2020_NCL, + MatrixID::kBT2020_CL, MatrixID::kSMPTE2085, MatrixID::kCDNCLS, + MatrixID::kCDCLS, MatrixID::kBT2100_ICTCP}; + constexpr uint64_t enum_bitmask = CreateEnumBitmask(kMatrixIds); + + return SetFromUint8(enum_value, enum_bitmask, &matrix_); +} + +bool ColorSpace::set_range_from_uint8(uint8_t enum_value) { + constexpr RangeID kRangeIds[] = {RangeID::kInvalid, RangeID::kLimited, + RangeID::kFull, RangeID::kDerived}; + constexpr uint64_t enum_bitmask = CreateEnumBitmask(kRangeIds); + + return SetFromUint8(enum_value, enum_bitmask, &range_); +} + +bool ColorSpace::set_chroma_siting_horizontal_from_uint8(uint8_t enum_value) { + return SetChromaSitingFromUint8(enum_value, &chroma_siting_horizontal_); +} + +bool ColorSpace::set_chroma_siting_vertical_from_uint8(uint8_t enum_value) { + return SetChromaSitingFromUint8(enum_value, &chroma_siting_vertical_); +} + +void ColorSpace::set_hdr_metadata(const HdrMetadata* hdr_metadata) { + hdr_metadata_ = + hdr_metadata ? absl::make_optional(*hdr_metadata) : absl::nullopt; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/color_space.h b/third_party/libwebrtc/api/video/color_space.h new file mode 100644 index 0000000000..a7ad86b016 --- /dev/null +++ b/third_party/libwebrtc/api/video/color_space.h @@ -0,0 +1,178 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_COLOR_SPACE_H_ +#define API_VIDEO_COLOR_SPACE_H_ + +#include <stdint.h> + +#include "absl/types/optional.h" +#include "api/video/hdr_metadata.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// This class represents color information as specified in T-REC H.273, +// available from https://www.itu.int/rec/T-REC-H.273. +// +// WebRTC's supported codecs: +// - VP9 supports color profiles, see VP9 Bitstream & Decoding Process +// Specification Version 0.6 Section 7.2.2 "Color config semantics" available +// from https://www.webmproject.org. +// - VP8 only supports BT.601, see +// https://tools.ietf.org/html/rfc6386#section-9.2 +// - H264 uses the exact same representation as T-REC H.273. See T-REC-H.264 +// E.2.1, "VUI parameters semantics", available from +// https://www.itu.int/rec/T-REC-H.264. + +class RTC_EXPORT ColorSpace { + public: + enum class PrimaryID : uint8_t { + // The indices are equal to the values specified in T-REC H.273 Table 2. + kBT709 = 1, + kUnspecified = 2, + kBT470M = 4, + kBT470BG = 5, + kSMPTE170M = 6, // Identical to BT601 + kSMPTE240M = 7, + kFILM = 8, + kBT2020 = 9, + kSMPTEST428 = 10, + kSMPTEST431 = 11, + kSMPTEST432 = 12, + kJEDECP22 = 22, // Identical to EBU3213-E + // When adding/removing entries here, please make sure to do the + // corresponding change to kPrimaryIds. + }; + + enum class TransferID : uint8_t { + // The indices are equal to the values specified in T-REC H.273 Table 3. + kBT709 = 1, + kUnspecified = 2, + kGAMMA22 = 4, + kGAMMA28 = 5, + kSMPTE170M = 6, + kSMPTE240M = 7, + kLINEAR = 8, + kLOG = 9, + kLOG_SQRT = 10, + kIEC61966_2_4 = 11, + kBT1361_ECG = 12, + kIEC61966_2_1 = 13, + kBT2020_10 = 14, + kBT2020_12 = 15, + kSMPTEST2084 = 16, + kSMPTEST428 = 17, + kARIB_STD_B67 = 18, + // When adding/removing entries here, please make sure to do the + // corresponding change to kTransferIds. + }; + + enum class MatrixID : uint8_t { + // The indices are equal to the values specified in T-REC H.273 Table 4. + kRGB = 0, + kBT709 = 1, + kUnspecified = 2, + kFCC = 4, + kBT470BG = 5, + kSMPTE170M = 6, + kSMPTE240M = 7, + kYCOCG = 8, + kBT2020_NCL = 9, + kBT2020_CL = 10, + kSMPTE2085 = 11, + kCDNCLS = 12, + kCDCLS = 13, + kBT2100_ICTCP = 14, + // When adding/removing entries here, please make sure to do the + // corresponding change to kMatrixIds. + }; + + enum class RangeID { + // The indices are equal to the values specified at + // https://www.webmproject.org/docs/container/#colour for the element Range. + kInvalid = 0, + // Limited Rec. 709 color range with RGB values ranging from 16 to 235. + kLimited = 1, + // Full RGB color range with RGB valees from 0 to 255. + kFull = 2, + // Range is defined by MatrixCoefficients/TransferCharacteristics. + kDerived = 3, + // When adding/removing entries here, please make sure to do the + // corresponding change to kRangeIds. + }; + + enum class ChromaSiting { + // Chroma siting specifies how chroma is subsampled relative to the luma + // samples in a YUV video frame. + // The indices are equal to the values specified at + // https://www.webmproject.org/docs/container/#colour for the element + // ChromaSitingVert and ChromaSitingHorz. + kUnspecified = 0, + kCollocated = 1, + kHalf = 2, + // When adding/removing entries here, please make sure to do the + // corresponding change to kChromaSitings. + }; + + ColorSpace(); + ColorSpace(const ColorSpace& other); + ColorSpace(ColorSpace&& other); + ColorSpace& operator=(const ColorSpace& other); + ColorSpace(PrimaryID primaries, + TransferID transfer, + MatrixID matrix, + RangeID range); + ColorSpace(PrimaryID primaries, + TransferID transfer, + MatrixID matrix, + RangeID range, + ChromaSiting chroma_siting_horizontal, + ChromaSiting chroma_siting_vertical, + const HdrMetadata* hdr_metadata); + friend bool operator==(const ColorSpace& lhs, const ColorSpace& rhs) { + return lhs.primaries_ == rhs.primaries_ && lhs.transfer_ == rhs.transfer_ && + lhs.matrix_ == rhs.matrix_ && lhs.range_ == rhs.range_ && + lhs.chroma_siting_horizontal_ == rhs.chroma_siting_horizontal_ && + lhs.chroma_siting_vertical_ == rhs.chroma_siting_vertical_ && + lhs.hdr_metadata_ == rhs.hdr_metadata_; + } + friend bool operator!=(const ColorSpace& lhs, const ColorSpace& rhs) { + return !(lhs == rhs); + } + + PrimaryID primaries() const; + TransferID transfer() const; + MatrixID matrix() const; + RangeID range() const; + ChromaSiting chroma_siting_horizontal() const; + ChromaSiting chroma_siting_vertical() const; + const HdrMetadata* hdr_metadata() const; + + bool set_primaries_from_uint8(uint8_t enum_value); + bool set_transfer_from_uint8(uint8_t enum_value); + bool set_matrix_from_uint8(uint8_t enum_value); + bool set_range_from_uint8(uint8_t enum_value); + bool set_chroma_siting_horizontal_from_uint8(uint8_t enum_value); + bool set_chroma_siting_vertical_from_uint8(uint8_t enum_value); + void set_hdr_metadata(const HdrMetadata* hdr_metadata); + + private: + PrimaryID primaries_ = PrimaryID::kUnspecified; + TransferID transfer_ = TransferID::kUnspecified; + MatrixID matrix_ = MatrixID::kUnspecified; + RangeID range_ = RangeID::kInvalid; + ChromaSiting chroma_siting_horizontal_ = ChromaSiting::kUnspecified; + ChromaSiting chroma_siting_vertical_ = ChromaSiting::kUnspecified; + absl::optional<HdrMetadata> hdr_metadata_; +}; + +} // namespace webrtc +#endif // API_VIDEO_COLOR_SPACE_H_ diff --git a/third_party/libwebrtc/api/video/encoded_frame.cc b/third_party/libwebrtc/api/video/encoded_frame.cc new file mode 100644 index 0000000000..c5e2abbbb4 --- /dev/null +++ b/third_party/libwebrtc/api/video/encoded_frame.cc @@ -0,0 +1,33 @@ +/* + * 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 "api/video/encoded_frame.h" + +#include "absl/types/optional.h" + +namespace webrtc { + +absl::optional<Timestamp> EncodedFrame::ReceivedTimestamp() const { + return ReceivedTime() >= 0 + ? absl::make_optional(Timestamp::Millis(ReceivedTime())) + : absl::nullopt; +} + +absl::optional<Timestamp> EncodedFrame::RenderTimestamp() const { + return RenderTimeMs() >= 0 + ? absl::make_optional(Timestamp::Millis(RenderTimeMs())) + : absl::nullopt; +} + +bool EncodedFrame::delayed_by_retransmission() const { + return false; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/encoded_frame.h b/third_party/libwebrtc/api/video/encoded_frame.h new file mode 100644 index 0000000000..66aee227bb --- /dev/null +++ b/third_party/libwebrtc/api/video/encoded_frame.h @@ -0,0 +1,74 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_ENCODED_FRAME_H_ +#define API_VIDEO_ENCODED_FRAME_H_ + +#include <stddef.h> +#include <stdint.h> + +#include "absl/types/optional.h" +#include "api/units/timestamp.h" +#include "modules/video_coding/encoded_frame.h" + +namespace webrtc { + +// TODO(philipel): Remove webrtc::VCMEncodedFrame inheritance. +// TODO(philipel): Move transport specific info out of EncodedFrame. +// NOTE: This class is still under development and may change without notice. +class EncodedFrame : public webrtc::VCMEncodedFrame { + public: + static const uint8_t kMaxFrameReferences = 5; + + EncodedFrame() = default; + EncodedFrame(const EncodedFrame&) = default; + virtual ~EncodedFrame() {} + + // When this frame was received. + // TODO(bugs.webrtc.org/13756): Use Timestamp instead of int. + virtual int64_t ReceivedTime() const = 0; + // Returns a Timestamp from `ReceivedTime`, or nullopt if there is no receive + // time. + absl::optional<webrtc::Timestamp> ReceivedTimestamp() const; + + // When this frame should be rendered. + // TODO(bugs.webrtc.org/13756): Use Timestamp instead of int. + virtual int64_t RenderTime() const = 0; + // Returns a Timestamp from `RenderTime`, or nullopt if there is no + // render time. + absl::optional<webrtc::Timestamp> RenderTimestamp() const; + + // This information is currently needed by the timing calculation class. + // TODO(philipel): Remove this function when a new timing class has + // been implemented. + virtual bool delayed_by_retransmission() const; + + bool is_keyframe() const { return num_references == 0; } + + void SetId(int64_t id) { id_ = id; } + int64_t Id() const { return id_; } + + // TODO(philipel): Add simple modify/access functions to prevent adding too + // many `references`. + size_t num_references = 0; + int64_t references[kMaxFrameReferences]; + // Is this subframe the last one in the superframe (In RTP stream that would + // mean that the last packet has a marker bit set). + bool is_last_spatial_layer = true; + + private: + // The ID of the frame is determined from RTP level information. The IDs are + // used to describe order and dependencies between frames. + int64_t id_ = -1; +}; + +} // namespace webrtc + +#endif // API_VIDEO_ENCODED_FRAME_H_ diff --git a/third_party/libwebrtc/api/video/encoded_frame_gn/moz.build b/third_party/libwebrtc/api/video/encoded_frame_gn/moz.build new file mode 100644 index 0000000000..f5aee8c8e8 --- /dev/null +++ b/third_party/libwebrtc/api/video/encoded_frame_gn/moz.build @@ -0,0 +1,232 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video/encoded_frame.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("encoded_frame_gn") diff --git a/third_party/libwebrtc/api/video/encoded_image.cc b/third_party/libwebrtc/api/video/encoded_image.cc new file mode 100644 index 0000000000..ff61994dee --- /dev/null +++ b/third_party/libwebrtc/api/video/encoded_image.cc @@ -0,0 +1,99 @@ +/* + * 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 "api/video/encoded_image.h" + +#include <stdlib.h> +#include <string.h> + +namespace webrtc { + +EncodedImageBuffer::EncodedImageBuffer(size_t size) : size_(size) { + buffer_ = static_cast<uint8_t*>(malloc(size)); +} + +EncodedImageBuffer::EncodedImageBuffer(const uint8_t* data, size_t size) + : EncodedImageBuffer(size) { + memcpy(buffer_, data, size); +} + +EncodedImageBuffer::~EncodedImageBuffer() { + free(buffer_); +} + +// static +rtc::scoped_refptr<EncodedImageBuffer> EncodedImageBuffer::Create(size_t size) { + return rtc::make_ref_counted<EncodedImageBuffer>(size); +} +// static +rtc::scoped_refptr<EncodedImageBuffer> EncodedImageBuffer::Create( + const uint8_t* data, + size_t size) { + return rtc::make_ref_counted<EncodedImageBuffer>(data, size); +} + +const uint8_t* EncodedImageBuffer::data() const { + return buffer_; +} +uint8_t* EncodedImageBuffer::data() { + return buffer_; +} +size_t EncodedImageBuffer::size() const { + return size_; +} + +void EncodedImageBuffer::Realloc(size_t size) { + // Calling realloc with size == 0 is equivalent to free, and returns nullptr. + // Which is confusing on systems where malloc(0) doesn't return a nullptr. + // More specifically, it breaks expectations of + // VCMSessionInfo::UpdateDataPointers. + RTC_DCHECK(size > 0); + buffer_ = static_cast<uint8_t*>(realloc(buffer_, size)); + size_ = size; +} + +EncodedImage::EncodedImage() = default; + +EncodedImage::EncodedImage(EncodedImage&&) = default; +EncodedImage::EncodedImage(const EncodedImage&) = default; + +EncodedImage::~EncodedImage() = default; + +EncodedImage& EncodedImage::operator=(EncodedImage&&) = default; +EncodedImage& EncodedImage::operator=(const EncodedImage&) = default; + +void EncodedImage::SetEncodeTime(int64_t encode_start_ms, + int64_t encode_finish_ms) { + timing_.encode_start_ms = encode_start_ms; + timing_.encode_finish_ms = encode_finish_ms; +} + +absl::optional<size_t> EncodedImage::SpatialLayerFrameSize( + int spatial_index) const { + RTC_DCHECK_GE(spatial_index, 0); + RTC_DCHECK_LE(spatial_index, spatial_index_.value_or(0)); + + auto it = spatial_layer_frame_size_bytes_.find(spatial_index); + if (it == spatial_layer_frame_size_bytes_.end()) { + return absl::nullopt; + } + + return it->second; +} + +void EncodedImage::SetSpatialLayerFrameSize(int spatial_index, + size_t size_bytes) { + RTC_DCHECK_GE(spatial_index, 0); + RTC_DCHECK_LE(spatial_index, spatial_index_.value_or(0)); + RTC_DCHECK_GE(size_bytes, 0); + spatial_layer_frame_size_bytes_[spatial_index] = size_bytes; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/encoded_image.h b/third_party/libwebrtc/api/video/encoded_image.h new file mode 100644 index 0000000000..dae790c46c --- /dev/null +++ b/third_party/libwebrtc/api/video/encoded_image.h @@ -0,0 +1,226 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_ENCODED_IMAGE_H_ +#define API_VIDEO_ENCODED_IMAGE_H_ + +#include <stdint.h> + +#include <map> +#include <utility> + +#include "absl/types/optional.h" +#include "api/rtp_packet_infos.h" +#include "api/scoped_refptr.h" +#include "api/video/color_space.h" +#include "api/video/video_codec_constants.h" +#include "api/video/video_content_type.h" +#include "api/video/video_frame_type.h" +#include "api/video/video_rotation.h" +#include "api/video/video_timing.h" +#include "rtc_base/checks.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Abstract interface for buffer storage. Intended to support buffers owned by +// external encoders with special release requirements, e.g, java encoders with +// releaseOutputBuffer. +class EncodedImageBufferInterface : public rtc::RefCountInterface { + public: + virtual const uint8_t* data() const = 0; + // TODO(bugs.webrtc.org/9378): Make interface essentially read-only, delete + // this non-const data method. + virtual uint8_t* data() = 0; + virtual size_t size() const = 0; +}; + +// Basic implementation of EncodedImageBufferInterface. +class RTC_EXPORT EncodedImageBuffer : public EncodedImageBufferInterface { + public: + static rtc::scoped_refptr<EncodedImageBuffer> Create() { return Create(0); } + static rtc::scoped_refptr<EncodedImageBuffer> Create(size_t size); + static rtc::scoped_refptr<EncodedImageBuffer> Create(const uint8_t* data, + size_t size); + + const uint8_t* data() const override; + uint8_t* data() override; + size_t size() const override; + void Realloc(size_t t); + + protected: + explicit EncodedImageBuffer(size_t size); + EncodedImageBuffer(const uint8_t* data, size_t size); + ~EncodedImageBuffer(); + + size_t size_; + uint8_t* buffer_; +}; + +// TODO(bug.webrtc.org/9378): This is a legacy api class, which is slowly being +// cleaned up. Direct use of its members is strongly discouraged. +class RTC_EXPORT EncodedImage { + public: + EncodedImage(); + EncodedImage(EncodedImage&&); + EncodedImage(const EncodedImage&); + + ~EncodedImage(); + + EncodedImage& operator=(EncodedImage&&); + EncodedImage& operator=(const EncodedImage&); + + // TODO(bugs.webrtc.org/9378): Change style to timestamp(), set_timestamp(), + // for consistency with the VideoFrame class. Set frame timestamp (90kHz). + void SetTimestamp(uint32_t timestamp) { timestamp_rtp_ = timestamp; } + + // Get frame timestamp (90kHz). + uint32_t Timestamp() const { return timestamp_rtp_; } + + void SetEncodeTime(int64_t encode_start_ms, int64_t encode_finish_ms); + + int64_t NtpTimeMs() const { return ntp_time_ms_; } + + absl::optional<int> SpatialIndex() const { return spatial_index_; } + void SetSpatialIndex(absl::optional<int> spatial_index) { + RTC_DCHECK_GE(spatial_index.value_or(0), 0); + RTC_DCHECK_LT(spatial_index.value_or(0), kMaxSpatialLayers); + spatial_index_ = spatial_index; + } + + absl::optional<int> TemporalIndex() const { return temporal_index_; } + void SetTemporalIndex(absl::optional<int> temporal_index) { + RTC_DCHECK_GE(temporal_index_.value_or(0), 0); + RTC_DCHECK_LT(temporal_index_.value_or(0), kMaxTemporalStreams); + temporal_index_ = temporal_index; + } + + // These methods can be used to set/get size of subframe with spatial index + // `spatial_index` on encoded frames that consist of multiple spatial layers. + absl::optional<size_t> SpatialLayerFrameSize(int spatial_index) const; + void SetSpatialLayerFrameSize(int spatial_index, size_t size_bytes); + + const webrtc::ColorSpace* ColorSpace() const { + return color_space_ ? &*color_space_ : nullptr; + } + void SetColorSpace(const absl::optional<webrtc::ColorSpace>& color_space) { + color_space_ = color_space; + } + + // These methods along with the private member video_frame_tracking_id_ are + // meant for media quality testing purpose only. + absl::optional<uint16_t> VideoFrameTrackingId() const { + return video_frame_tracking_id_; + } + void SetVideoFrameTrackingId(absl::optional<uint16_t> tracking_id) { + video_frame_tracking_id_ = tracking_id; + } + + const RtpPacketInfos& PacketInfos() const { return packet_infos_; } + void SetPacketInfos(RtpPacketInfos packet_infos) { + packet_infos_ = std::move(packet_infos); + } + + bool RetransmissionAllowed() const { return retransmission_allowed_; } + void SetRetransmissionAllowed(bool retransmission_allowed) { + retransmission_allowed_ = retransmission_allowed; + } + + size_t size() const { return size_; } + void set_size(size_t new_size) { + // Allow set_size(0) even if we have no buffer. + RTC_DCHECK_LE(new_size, new_size == 0 ? 0 : capacity()); + size_ = new_size; + } + + void SetEncodedData( + rtc::scoped_refptr<EncodedImageBufferInterface> encoded_data) { + encoded_data_ = encoded_data; + size_ = encoded_data->size(); + } + + void ClearEncodedData() { + encoded_data_ = nullptr; + size_ = 0; + } + + rtc::scoped_refptr<EncodedImageBufferInterface> GetEncodedData() const { + return encoded_data_; + } + + const uint8_t* data() const { + return encoded_data_ ? encoded_data_->data() : nullptr; + } + + // Returns whether the encoded image can be considered to be of target + // quality. + bool IsAtTargetQuality() const { return at_target_quality_; } + + // Sets that the encoded image can be considered to be of target quality to + // true or false. + void SetAtTargetQuality(bool at_target_quality) { + at_target_quality_ = at_target_quality; + } + + uint32_t _encodedWidth = 0; + uint32_t _encodedHeight = 0; + // NTP time of the capture time in local timebase in milliseconds. + // TODO(minyue): make this member private. + int64_t ntp_time_ms_ = 0; + int64_t capture_time_ms_ = 0; + VideoFrameType _frameType = VideoFrameType::kVideoFrameDelta; + VideoRotation rotation_ = kVideoRotation_0; + VideoContentType content_type_ = VideoContentType::UNSPECIFIED; + int qp_ = -1; // Quantizer value. + + // When an application indicates non-zero values here, it is taken as an + // indication that all future frames will be constrained with those limits + // until the application indicates a change again. + VideoPlayoutDelay playout_delay_; + + struct Timing { + uint8_t flags = VideoSendTiming::kInvalid; + int64_t encode_start_ms = 0; + int64_t encode_finish_ms = 0; + int64_t packetization_finish_ms = 0; + int64_t pacer_exit_ms = 0; + int64_t network_timestamp_ms = 0; + int64_t network2_timestamp_ms = 0; + int64_t receive_start_ms = 0; + int64_t receive_finish_ms = 0; + } timing_; + + private: + size_t capacity() const { return encoded_data_ ? encoded_data_->size() : 0; } + + rtc::scoped_refptr<EncodedImageBufferInterface> encoded_data_; + size_t size_ = 0; // Size of encoded frame data. + uint32_t timestamp_rtp_ = 0; + absl::optional<int> spatial_index_; + absl::optional<int> temporal_index_; + std::map<int, size_t> spatial_layer_frame_size_bytes_; + absl::optional<webrtc::ColorSpace> color_space_; + // This field is meant for media quality testing purpose only. When enabled it + // carries the webrtc::VideoFrame id field from the sender to the receiver. + absl::optional<uint16_t> video_frame_tracking_id_; + // Information about packets used to assemble this video frame. This is needed + // by `SourceTracker` when the frame is delivered to the RTCRtpReceiver's + // MediaStreamTrack, in order to implement getContributingSources(). See: + // https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-getcontributingsources + RtpPacketInfos packet_infos_; + bool retransmission_allowed_ = true; + // True if the encoded image can be considered to be of target quality. + bool at_target_quality_ = false; +}; + +} // namespace webrtc + +#endif // API_VIDEO_ENCODED_IMAGE_H_ diff --git a/third_party/libwebrtc/api/video/encoded_image_gn/moz.build b/third_party/libwebrtc/api/video/encoded_image_gn/moz.build new file mode 100644 index 0000000000..aebcf21b37 --- /dev/null +++ b/third_party/libwebrtc/api/video/encoded_image_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video/encoded_image.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("encoded_image_gn") diff --git a/third_party/libwebrtc/api/video/frame_buffer.cc b/third_party/libwebrtc/api/video/frame_buffer.cc new file mode 100644 index 0000000000..f5d93f5f76 --- /dev/null +++ b/third_party/libwebrtc/api/video/frame_buffer.cc @@ -0,0 +1,332 @@ +/* + * 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 "api/video/frame_buffer.h" + +#include <algorithm> + +#include "absl/algorithm/container.h" +#include "absl/container/inlined_vector.h" +#include "rtc_base/logging.h" +#include "rtc_base/numerics/sequence_number_util.h" +#include "rtc_base/trace_event.h" + +namespace webrtc { +namespace { +bool ValidReferences(const EncodedFrame& frame) { + // All references must point backwards, and duplicates are not allowed. + for (size_t i = 0; i < frame.num_references; ++i) { + if (frame.references[i] >= frame.Id()) + return false; + + for (size_t j = i + 1; j < frame.num_references; ++j) { + if (frame.references[i] == frame.references[j]) + return false; + } + } + + return true; +} + +// Since FrameBuffer::FrameInfo is private it can't be used in the function +// signature, hence the FrameIteratorT type. +template <typename FrameIteratorT> +rtc::ArrayView<const int64_t> GetReferences(const FrameIteratorT& it) { + return {it->second.encoded_frame->references, + std::min<size_t>(it->second.encoded_frame->num_references, + EncodedFrame::kMaxFrameReferences)}; +} + +template <typename FrameIteratorT> +int64_t GetFrameId(const FrameIteratorT& it) { + return it->first; +} + +template <typename FrameIteratorT> +uint32_t GetTimestamp(const FrameIteratorT& it) { + return it->second.encoded_frame->Timestamp(); +} + +template <typename FrameIteratorT> +bool IsLastFrameInTemporalUnit(const FrameIteratorT& it) { + return it->second.encoded_frame->is_last_spatial_layer; +} +} // namespace + +FrameBuffer::FrameBuffer(int max_size, + int max_decode_history, + const FieldTrialsView& field_trials) + : legacy_frame_id_jump_behavior_( + !field_trials.IsDisabled("WebRTC-LegacyFrameIdJumpBehavior")), + max_size_(max_size), + decoded_frame_history_(max_decode_history) {} + +bool FrameBuffer::InsertFrame(std::unique_ptr<EncodedFrame> frame) { + const uint32_t ssrc = + frame->PacketInfos().empty() ? 0 : frame->PacketInfos()[0].ssrc(); + if (!ValidReferences(*frame)) { + TRACE_EVENT2("webrtc", + "FrameBuffer::InsertFrame Frame dropped (Invalid references)", + "remote_ssrc", ssrc, "frame_id", frame->Id()); + RTC_DLOG(LS_WARNING) << "Frame " << frame->Id() + << " has invalid references, dropping frame."; + return false; + } + + if (frame->Id() <= decoded_frame_history_.GetLastDecodedFrameId()) { + if (legacy_frame_id_jump_behavior_ && frame->is_keyframe() && + AheadOf(frame->Timestamp(), + *decoded_frame_history_.GetLastDecodedFrameTimestamp())) { + TRACE_EVENT2("webrtc", + "FrameBuffer::InsertFrame Frames dropped (OOO + PicId jump)", + "remote_ssrc", ssrc, "frame_id", frame->Id()); + RTC_DLOG(LS_WARNING) + << "Keyframe " << frame->Id() + << " has newer timestamp but older picture id, clearing buffer."; + Clear(); + } else { + // Already decoded past this frame. + TRACE_EVENT2("webrtc", + "FrameBuffer::InsertFrame Frame dropped (Out of order)", + "remote_ssrc", ssrc, "frame_id", frame->Id()); + return false; + } + } + + if (frames_.size() == max_size_) { + if (frame->is_keyframe()) { + TRACE_EVENT2("webrtc", + "FrameBuffer::InsertFrame Frames dropped (KF + Full buffer)", + "remote_ssrc", ssrc, "frame_id", frame->Id()); + RTC_DLOG(LS_WARNING) << "Keyframe " << frame->Id() + << " inserted into full buffer, clearing buffer."; + Clear(); + } else { + // No space for this frame. + TRACE_EVENT2("webrtc", + "FrameBuffer::InsertFrame Frame dropped (Full buffer)", + "remote_ssrc", ssrc, "frame_id", frame->Id()); + return false; + } + } + + const int64_t frame_id = frame->Id(); + auto insert_res = frames_.emplace(frame_id, FrameInfo{std::move(frame)}); + if (!insert_res.second) { + // Frame has already been inserted. + return false; + } + + if (frames_.size() == max_size_) { + RTC_DLOG(LS_WARNING) << "Frame " << frame_id + << " inserted, buffer is now full."; + } + + PropagateContinuity(insert_res.first); + FindNextAndLastDecodableTemporalUnit(); + return true; +} + +absl::InlinedVector<std::unique_ptr<EncodedFrame>, 4> +FrameBuffer::ExtractNextDecodableTemporalUnit() { + absl::InlinedVector<std::unique_ptr<EncodedFrame>, 4> res; + if (!next_decodable_temporal_unit_) { + return res; + } + + auto end_it = std::next(next_decodable_temporal_unit_->last_frame); + for (auto it = next_decodable_temporal_unit_->first_frame; it != end_it; + ++it) { + decoded_frame_history_.InsertDecoded(GetFrameId(it), GetTimestamp(it)); + res.push_back(std::move(it->second.encoded_frame)); + } + + DropNextDecodableTemporalUnit(); + return res; +} + +void FrameBuffer::DropNextDecodableTemporalUnit() { + if (!next_decodable_temporal_unit_) { + return; + } + + auto end_it = std::next(next_decodable_temporal_unit_->last_frame); + + UpdateDroppedFramesAndDiscardedPackets(frames_.begin(), end_it); + + frames_.erase(frames_.begin(), end_it); + FindNextAndLastDecodableTemporalUnit(); +} + +void FrameBuffer::UpdateDroppedFramesAndDiscardedPackets(FrameIterator begin_it, + FrameIterator end_it) { + uint32_t dropped_ssrc = 0; + int64_t dropped_frame_id = 0; + unsigned int num_discarded_packets = 0; + unsigned int num_dropped_frames = + std::count_if(begin_it, end_it, [&](const auto& f) { + if (f.second.encoded_frame) { + const auto& packetInfos = f.second.encoded_frame->PacketInfos(); + dropped_frame_id = f.first; + if (!packetInfos.empty()) { + dropped_ssrc = packetInfos[0].ssrc(); + } + num_discarded_packets += packetInfos.size(); + } + return f.second.encoded_frame != nullptr; + }); + + if (num_dropped_frames > 0) { + TRACE_EVENT2("webrtc", "FrameBuffer Dropping Old Frames", "remote_ssrc", + dropped_ssrc, "frame_id", dropped_frame_id); + } + if (num_discarded_packets > 0) { + TRACE_EVENT2("webrtc", "FrameBuffer Discarding Old Packets", "remote_ssrc", + dropped_ssrc, "frame_id", dropped_frame_id); + } + + num_dropped_frames_ += num_dropped_frames; + num_discarded_packets_ += num_discarded_packets; +} + +absl::optional<int64_t> FrameBuffer::LastContinuousFrameId() const { + return last_continuous_frame_id_; +} + +absl::optional<int64_t> FrameBuffer::LastContinuousTemporalUnitFrameId() const { + return last_continuous_temporal_unit_frame_id_; +} + +absl::optional<FrameBuffer::DecodabilityInfo> +FrameBuffer::DecodableTemporalUnitsInfo() const { + return decodable_temporal_units_info_; +} + +int FrameBuffer::GetTotalNumberOfContinuousTemporalUnits() const { + return num_continuous_temporal_units_; +} +int FrameBuffer::GetTotalNumberOfDroppedFrames() const { + return num_dropped_frames_; +} +int FrameBuffer::GetTotalNumberOfDiscardedPackets() const { + return num_discarded_packets_; +} + +size_t FrameBuffer::CurrentSize() const { + return frames_.size(); +} + +bool FrameBuffer::IsContinuous(const FrameIterator& it) const { + for (int64_t reference : GetReferences(it)) { + if (decoded_frame_history_.WasDecoded(reference)) { + continue; + } + + auto reference_frame_it = frames_.find(reference); + if (reference_frame_it != frames_.end() && + reference_frame_it->second.continuous) { + continue; + } + + return false; + } + + return true; +} + +void FrameBuffer::PropagateContinuity(const FrameIterator& frame_it) { + for (auto it = frame_it; it != frames_.end(); ++it) { + if (!it->second.continuous) { + if (IsContinuous(it)) { + it->second.continuous = true; + if (last_continuous_frame_id_ < GetFrameId(it)) { + last_continuous_frame_id_ = GetFrameId(it); + } + if (IsLastFrameInTemporalUnit(it)) { + num_continuous_temporal_units_++; + if (last_continuous_temporal_unit_frame_id_ < GetFrameId(it)) { + last_continuous_temporal_unit_frame_id_ = GetFrameId(it); + } + } + } + } + } +} + +void FrameBuffer::FindNextAndLastDecodableTemporalUnit() { + next_decodable_temporal_unit_.reset(); + decodable_temporal_units_info_.reset(); + + if (!last_continuous_temporal_unit_frame_id_) { + return; + } + + FrameIterator first_frame_it = frames_.begin(); + FrameIterator last_frame_it = frames_.begin(); + absl::InlinedVector<int64_t, 4> frames_in_temporal_unit; + uint32_t last_decodable_temporal_unit_timestamp; + for (auto frame_it = frames_.begin(); frame_it != frames_.end();) { + if (GetFrameId(frame_it) > *last_continuous_temporal_unit_frame_id_) { + break; + } + + if (GetTimestamp(frame_it) != GetTimestamp(first_frame_it)) { + frames_in_temporal_unit.clear(); + first_frame_it = frame_it; + } + + frames_in_temporal_unit.push_back(GetFrameId(frame_it)); + + last_frame_it = frame_it++; + + if (IsLastFrameInTemporalUnit(last_frame_it)) { + bool temporal_unit_decodable = true; + for (auto it = first_frame_it; it != frame_it && temporal_unit_decodable; + ++it) { + for (int64_t reference : GetReferences(it)) { + if (!decoded_frame_history_.WasDecoded(reference) && + !absl::c_linear_search(frames_in_temporal_unit, reference)) { + // A frame in the temporal unit has a non-decoded reference outside + // the temporal unit, so it's not yet ready to be decoded. + temporal_unit_decodable = false; + break; + } + } + } + + if (temporal_unit_decodable) { + if (!next_decodable_temporal_unit_) { + next_decodable_temporal_unit_ = {first_frame_it, last_frame_it}; + } + + last_decodable_temporal_unit_timestamp = GetTimestamp(first_frame_it); + } + } + } + + if (next_decodable_temporal_unit_) { + decodable_temporal_units_info_ = { + .next_rtp_timestamp = + GetTimestamp(next_decodable_temporal_unit_->first_frame), + .last_rtp_timestamp = last_decodable_temporal_unit_timestamp}; + } +} + +void FrameBuffer::Clear() { + UpdateDroppedFramesAndDiscardedPackets(frames_.begin(), frames_.end()); + frames_.clear(); + next_decodable_temporal_unit_.reset(); + decodable_temporal_units_info_.reset(); + last_continuous_frame_id_.reset(); + last_continuous_temporal_unit_frame_id_.reset(); + decoded_frame_history_.Clear(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/frame_buffer.h b/third_party/libwebrtc/api/video/frame_buffer.h new file mode 100644 index 0000000000..81fd12da58 --- /dev/null +++ b/third_party/libwebrtc/api/video/frame_buffer.h @@ -0,0 +1,110 @@ +/* + * 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 API_VIDEO_FRAME_BUFFER_H_ +#define API_VIDEO_FRAME_BUFFER_H_ + +#include <map> +#include <memory> +#include <utility> + +#include "absl/container/inlined_vector.h" +#include "absl/types/optional.h" +#include "api/field_trials_view.h" +#include "api/video/encoded_frame.h" +#include "modules/video_coding/utility/decoded_frames_history.h" + +namespace webrtc { +// The high level idea of the FrameBuffer is to order frames received from the +// network into a decodable stream. Frames are order by frame ID, and grouped +// into temporal units by timestamp. A temporal unit is decodable after all +// referenced frames outside the unit has been decoded, and a temporal unit is +// continuous if all referenced frames are directly or indirectly decodable. +// The FrameBuffer is thread-unsafe. +class FrameBuffer { + public: + struct DecodabilityInfo { + uint32_t next_rtp_timestamp; + uint32_t last_rtp_timestamp; + }; + + // The `max_size` determines the maximum number of frames the buffer will + // store, and max_decode_history determines how far back (by frame ID) the + // buffer will store if a frame was decoded or not. + FrameBuffer(int max_size, + int max_decode_history, + // TODO(hta): remove field trials! + const FieldTrialsView& field_trials); + FrameBuffer(const FrameBuffer&) = delete; + FrameBuffer& operator=(const FrameBuffer&) = delete; + ~FrameBuffer() = default; + + // Inserted frames may only reference backwards, and must have no duplicate + // references. Frame insertion will fail if `frame` is a duplicate, has + // already been decoded, invalid, or if the buffer is full and the frame is + // not a keyframe. Returns true if the frame was successfully inserted. + bool InsertFrame(std::unique_ptr<EncodedFrame> frame); + + // Mark all frames belonging to the next decodable temporal unit as decoded + // and returns them. + absl::InlinedVector<std::unique_ptr<EncodedFrame>, 4> + ExtractNextDecodableTemporalUnit(); + + // Drop all frames in the next decodable unit. + void DropNextDecodableTemporalUnit(); + + absl::optional<int64_t> LastContinuousFrameId() const; + absl::optional<int64_t> LastContinuousTemporalUnitFrameId() const; + absl::optional<DecodabilityInfo> DecodableTemporalUnitsInfo() const; + + int GetTotalNumberOfContinuousTemporalUnits() const; + int GetTotalNumberOfDroppedFrames() const; + int GetTotalNumberOfDiscardedPackets() const; + size_t CurrentSize() const; + + private: + struct FrameInfo { + std::unique_ptr<EncodedFrame> encoded_frame; + bool continuous = false; + }; + + using FrameMap = std::map<int64_t, FrameInfo>; + using FrameIterator = FrameMap::iterator; + + struct TemporalUnit { + // Both first and last are inclusive. + FrameIterator first_frame; + FrameIterator last_frame; + }; + + bool IsContinuous(const FrameIterator& it) const; + void PropagateContinuity(const FrameIterator& frame_it); + void FindNextAndLastDecodableTemporalUnit(); + void Clear(); + void UpdateDroppedFramesAndDiscardedPackets(FrameIterator begin_it, + FrameIterator end_it); + + const bool legacy_frame_id_jump_behavior_; + const size_t max_size_; + FrameMap frames_; + absl::optional<TemporalUnit> next_decodable_temporal_unit_; + absl::optional<DecodabilityInfo> decodable_temporal_units_info_; + absl::optional<int64_t> last_continuous_frame_id_; + absl::optional<int64_t> last_continuous_temporal_unit_frame_id_; + video_coding::DecodedFramesHistory decoded_frame_history_; + + int num_continuous_temporal_units_ = 0; + int num_dropped_frames_ = 0; + int num_discarded_packets_ = 0; +}; + +} // namespace webrtc + +#endif // API_VIDEO_FRAME_BUFFER_H_ diff --git a/third_party/libwebrtc/api/video/frame_buffer_gn/moz.build b/third_party/libwebrtc/api/video/frame_buffer_gn/moz.build new file mode 100644 index 0000000000..b4c504524c --- /dev/null +++ b/third_party/libwebrtc/api/video/frame_buffer_gn/moz.build @@ -0,0 +1,232 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video/frame_buffer.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("frame_buffer_gn") diff --git a/third_party/libwebrtc/api/video/frame_buffer_unittest.cc b/third_party/libwebrtc/api/video/frame_buffer_unittest.cc new file mode 100644 index 0000000000..92e2f67540 --- /dev/null +++ b/third_party/libwebrtc/api/video/frame_buffer_unittest.cc @@ -0,0 +1,393 @@ +/* + * 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 "api/video/frame_buffer.h" + +#include <vector> + +#include "api/video/encoded_frame.h" +#include "test/fake_encoded_frame.h" +#include "test/gmock.h" +#include "test/gtest.h" +#include "test/scoped_key_value_config.h" + +namespace webrtc { +namespace { + +using ::testing::ElementsAre; +using ::testing::Eq; +using ::testing::IsEmpty; +using ::testing::Matches; + +MATCHER_P(FrameWithId, id, "") { + return Matches(Eq(id))(arg->Id()); +} + +TEST(FrameBuffer3Test, RejectInvalidRefs) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + // Ref must be less than the id of this frame. + EXPECT_FALSE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(0).Id(0).Refs({0}).AsLast().Build())); + EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt)); + + // Duplicate ids are also invalid. + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_FALSE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).Refs({1, 1}).AsLast().Build())); + EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1)); +} + +TEST(FrameBuffer3Test, LastContinuousUpdatesOnInsertedFrames) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(absl::nullopt)); + EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt)); + + EXPECT_TRUE( + buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build())); + EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1)); + EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt)); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).AsLast().Build())); + EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(2)); + EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2)); +} + +TEST(FrameBuffer3Test, LastContinuousFrameReordering) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(30).Id(3).Refs({2}).AsLast().Build())); + EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(1)); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build())); + EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(3)); +} + +TEST(FrameBuffer3Test, LastContinuousTemporalUnit) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + + EXPECT_TRUE( + buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build())); + EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt)); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).AsLast().Build())); + EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(2)); +} + +TEST(FrameBuffer3Test, LastContinuousTemporalUnitReordering) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + + EXPECT_TRUE( + buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(3).Refs({1}).Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(4).Refs({2, 3}).AsLast().Build())); + EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(absl::nullopt)); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).AsLast().Build())); + EXPECT_THAT(buffer.LastContinuousTemporalUnitFrameId(), Eq(4)); +} + +TEST(FrameBuffer3Test, NextDecodable) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + + EXPECT_THAT(buffer.DecodableTemporalUnitsInfo(), Eq(absl::nullopt)); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(10U)); +} + +TEST(FrameBuffer3Test, AdvanceNextDecodableOnExtraction) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(30).Id(3).Refs({2}).AsLast().Build())); + EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(10U)); + + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(1))); + EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(20U)); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(2))); + EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(30U)); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(3))); +} + +TEST(FrameBuffer3Test, AdvanceLastDecodableOnExtraction) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build())); + EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->last_rtp_timestamp, Eq(10U)); + + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(1))); + EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->last_rtp_timestamp, Eq(30U)); +} + +TEST(FrameBuffer3Test, FrameUpdatesNextDecodable) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).AsLast().Build())); + EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(20U)); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_THAT(buffer.DecodableTemporalUnitsInfo()->next_rtp_timestamp, Eq(10U)); +} + +TEST(FrameBuffer3Test, KeyframeClearsFullBuffer) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/5, /*max_decode_history=*/10, + field_trials); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(30).Id(3).Refs({2}).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(40).Id(4).Refs({3}).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(50).Id(5).Refs({4}).AsLast().Build())); + EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5)); + + // Frame buffer is full + EXPECT_FALSE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(60).Id(6).Refs({5}).AsLast().Build())); + EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(5)); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(70).Id(7).AsLast().Build())); + EXPECT_THAT(buffer.LastContinuousFrameId(), Eq(7)); +} + +TEST(FrameBuffer3Test, DropNextDecodableTemporalUnit) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build())); + + buffer.ExtractNextDecodableTemporalUnit(); + buffer.DropNextDecodableTemporalUnit(); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(3))); +} + +TEST(FrameBuffer3Test, OldFramesAreIgnored) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build())); + + buffer.ExtractNextDecodableTemporalUnit(); + buffer.ExtractNextDecodableTemporalUnit(); + + EXPECT_FALSE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_FALSE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build())); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(3))); +} + +TEST(FrameBuffer3Test, ReturnFullTemporalUnitKSVC) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + EXPECT_TRUE( + buffer.InsertFrame(test::FakeFrameBuilder().Time(10).Id(1).Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(2).Refs({1}).Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(3).Refs({2}).AsLast().Build())); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(1), FrameWithId(2), FrameWithId(3))); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(4).Refs({3}).AsLast().Build())); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(4))); +} + +TEST(FrameBuffer3Test, InterleavedStream) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(30).Id(3).Refs({1}).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(40).Id(4).Refs({2}).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(50).Id(5).Refs({3}).AsLast().Build())); + + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(1))); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(2))); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(3))); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(4))); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(5))); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(70).Id(7).Refs({5}).AsLast().Build())); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(7))); + EXPECT_FALSE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(60).Id(6).Refs({4}).AsLast().Build())); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty()); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(90).Id(9).Refs({7}).AsLast().Build())); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(9))); +} + +TEST(FrameBuffer3Test, LegacyFrameIdJumpBehavior) { + { + test::ScopedKeyValueConfig field_trials( + "WebRTC-LegacyFrameIdJumpBehavior/Disabled/"); + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(3).AsLast().Build())); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(3))); + EXPECT_FALSE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(30).Id(2).AsLast().Build())); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty()); + } + + { + // WebRTC-LegacyFrameIdJumpBehavior is disabled by default. + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(3).AsLast().Build())); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(3))); + EXPECT_FALSE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(30).Id(2).Refs({1}).AsLast().Build())); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), IsEmpty()); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(40).Id(1).AsLast().Build())); + EXPECT_THAT(buffer.ExtractNextDecodableTemporalUnit(), + ElementsAre(FrameWithId(1))); + } +} + +TEST(FrameBuffer3Test, TotalNumberOfContinuousTemporalUnits) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(0)); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1)); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).Build())); + EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1)); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(40).Id(4).Refs({2}).Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(40).Id(5).Refs({3, 4}).AsLast().Build())); + EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(1)); + + // Reordered + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(3).Refs({2}).AsLast().Build())); + EXPECT_THAT(buffer.GetTotalNumberOfContinuousTemporalUnits(), Eq(3)); +} + +TEST(FrameBuffer3Test, TotalNumberOfDroppedFrames) { + test::ScopedKeyValueConfig field_trials; + FrameBuffer buffer(/*max_frame_slots=*/10, /*max_decode_history=*/100, + field_trials); + EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0)); + + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(10).Id(1).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(2).Refs({1}).Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(20).Id(3).Refs({2}).AsLast().Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(40).Id(4).Refs({1}).Build())); + EXPECT_TRUE(buffer.InsertFrame( + test::FakeFrameBuilder().Time(40).Id(5).Refs({4}).AsLast().Build())); + + buffer.ExtractNextDecodableTemporalUnit(); + EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(0)); + + buffer.DropNextDecodableTemporalUnit(); + EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(2)); + + buffer.ExtractNextDecodableTemporalUnit(); + EXPECT_THAT(buffer.GetTotalNumberOfDroppedFrames(), Eq(2)); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/hdr_metadata.cc b/third_party/libwebrtc/api/video/hdr_metadata.cc new file mode 100644 index 0000000000..e2a669c98a --- /dev/null +++ b/third_party/libwebrtc/api/video/hdr_metadata.cc @@ -0,0 +1,21 @@ +/* + * 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 "api/video/hdr_metadata.h" + +namespace webrtc { + +HdrMasteringMetadata::Chromaticity::Chromaticity() = default; + +HdrMasteringMetadata::HdrMasteringMetadata() = default; + +HdrMetadata::HdrMetadata() = default; + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/hdr_metadata.h b/third_party/libwebrtc/api/video/hdr_metadata.h new file mode 100644 index 0000000000..e9001a2c80 --- /dev/null +++ b/third_party/libwebrtc/api/video/hdr_metadata.h @@ -0,0 +1,105 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_HDR_METADATA_H_ +#define API_VIDEO_HDR_METADATA_H_ + +namespace webrtc { + +// SMPTE ST 2086 mastering metadata, +// see https://ieeexplore.ieee.org/document/8353899. +struct HdrMasteringMetadata { + struct Chromaticity { + Chromaticity(); + + bool operator==(const Chromaticity& rhs) const { + return x == rhs.x && y == rhs.y; + } + + bool Validate() const { + return x >= 0.0 && x <= 1.0 && y >= 0.0 && y <= 1.0; + } + + // xy chromaticity coordinates must be calculated as specified in ISO + // 11664-3:2012 Section 7, and must be specified with four decimal places. + // The x coordinate should be in the range [0.0001, 0.7400] and the y + // coordinate should be in the range [0.0001, 0.8400]. Valid range [0.0000, + // 1.0000]. + float x = 0.0f; + float y = 0.0f; + }; + + HdrMasteringMetadata(); + + bool operator==(const HdrMasteringMetadata& rhs) const { + return ((primary_r == rhs.primary_r) && (primary_g == rhs.primary_g) && + (primary_b == rhs.primary_b) && (white_point == rhs.white_point) && + (luminance_max == rhs.luminance_max) && + (luminance_min == rhs.luminance_min)); + } + + bool Validate() const { + return luminance_max >= 0.0 && luminance_max <= 20000.0 && + luminance_min >= 0.0 && luminance_min <= 5.0 && + primary_r.Validate() && primary_g.Validate() && + primary_b.Validate() && white_point.Validate(); + } + + // The nominal primaries of the mastering display. + Chromaticity primary_r; + Chromaticity primary_g; + Chromaticity primary_b; + + // The nominal chromaticity of the white point of the mastering display. + Chromaticity white_point; + + // The nominal maximum display luminance of the mastering display. Specified + // in the unit candela/m2. The value should be in the range [5, 10000] with + // zero decimal places. Valid range [0, 20000]. + float luminance_max = 0.0f; + + // The nominal minimum display luminance of the mastering display. Specified + // in the unit candela/m2. The value should be in the range [0.0001, 5.0000] + // with four decimal places. Valid range [0.0000, 5.0000]. + float luminance_min = 0.0f; +}; + +// High dynamic range (HDR) metadata common for HDR10 and WebM/VP9-based HDR +// formats. This struct replicates the HDRMetadata struct defined in +// https://cs.chromium.org/chromium/src/media/base/hdr_metadata.h +struct HdrMetadata { + HdrMetadata(); + + bool operator==(const HdrMetadata& rhs) const { + return ( + (max_content_light_level == rhs.max_content_light_level) && + (max_frame_average_light_level == rhs.max_frame_average_light_level) && + (mastering_metadata == rhs.mastering_metadata)); + } + + bool Validate() const { + return max_content_light_level >= 0 && max_content_light_level <= 20000 && + max_frame_average_light_level >= 0 && + max_frame_average_light_level <= 20000 && + mastering_metadata.Validate(); + } + + HdrMasteringMetadata mastering_metadata; + // Max content light level (CLL), i.e. maximum brightness level present in the + // stream, in nits. 1 nit = 1 candela/m2. Valid range [0, 20000]. + int max_content_light_level = 0; + // Max frame-average light level (FALL), i.e. maximum average brightness of + // the brightest frame in the stream, in nits. Valid range [0, 20000]. + int max_frame_average_light_level = 0; +}; + +} // namespace webrtc + +#endif // API_VIDEO_HDR_METADATA_H_ diff --git a/third_party/libwebrtc/api/video/i010_buffer.cc b/third_party/libwebrtc/api/video/i010_buffer.cc new file mode 100644 index 0000000000..d78e854eb9 --- /dev/null +++ b/third_party/libwebrtc/api/video/i010_buffer.cc @@ -0,0 +1,213 @@ +/* + * 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 "api/video/i010_buffer.h" + +#include <utility> + +#include "api/make_ref_counted.h" +#include "api/video/i420_buffer.h" +#include "rtc_base/checks.h" +#include "third_party/libyuv/include/libyuv/convert.h" +#include "third_party/libyuv/include/libyuv/scale.h" + +// Aligning pointer to 64 bytes for improved performance, e.g. use SIMD. +static const int kBufferAlignment = 64; +static const int kBytesPerPixel = 2; + +namespace webrtc { + +namespace { + +int I010DataSize(int height, int stride_y, int stride_u, int stride_v) { + return kBytesPerPixel * + (stride_y * height + (stride_u + stride_v) * ((height + 1) / 2)); +} + +} // namespace + +I010Buffer::I010Buffer(int width, + int height, + int stride_y, + int stride_u, + int stride_v) + : width_(width), + height_(height), + stride_y_(stride_y), + stride_u_(stride_u), + stride_v_(stride_v), + data_(static_cast<uint16_t*>( + AlignedMalloc(I010DataSize(height, stride_y, stride_u, stride_v), + kBufferAlignment))) { + RTC_DCHECK_GT(width, 0); + RTC_DCHECK_GT(height, 0); + RTC_DCHECK_GE(stride_y, width); + RTC_DCHECK_GE(stride_u, (width + 1) / 2); + RTC_DCHECK_GE(stride_v, (width + 1) / 2); +} + +I010Buffer::~I010Buffer() {} + +// static +rtc::scoped_refptr<I010Buffer> I010Buffer::Create(int width, int height) { + return rtc::make_ref_counted<I010Buffer>(width, height, width, + (width + 1) / 2, (width + 1) / 2); +} + +// static +rtc::scoped_refptr<I010Buffer> I010Buffer::Copy( + const I010BufferInterface& source) { + const int width = source.width(); + const int height = source.height(); + rtc::scoped_refptr<I010Buffer> buffer = Create(width, height); + int res = libyuv::I010Copy( + source.DataY(), source.StrideY(), source.DataU(), source.StrideU(), + source.DataV(), source.StrideV(), buffer->MutableDataY(), + buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(), + buffer->MutableDataV(), buffer->StrideV(), width, height); + RTC_DCHECK_EQ(res, 0); + + return buffer; +} + +// static +rtc::scoped_refptr<I010Buffer> I010Buffer::Copy( + const I420BufferInterface& source) { + const int width = source.width(); + const int height = source.height(); + rtc::scoped_refptr<I010Buffer> buffer = Create(width, height); + int res = libyuv::I420ToI010( + source.DataY(), source.StrideY(), source.DataU(), source.StrideU(), + source.DataV(), source.StrideV(), buffer->MutableDataY(), + buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(), + buffer->MutableDataV(), buffer->StrideV(), width, height); + RTC_DCHECK_EQ(res, 0); + + return buffer; +} + +// static +rtc::scoped_refptr<I010Buffer> I010Buffer::Rotate( + const I010BufferInterface& src, + VideoRotation rotation) { + if (rotation == webrtc::kVideoRotation_0) + return Copy(src); + + RTC_CHECK(src.DataY()); + RTC_CHECK(src.DataU()); + RTC_CHECK(src.DataV()); + int rotated_width = src.width(); + int rotated_height = src.height(); + if (rotation == webrtc::kVideoRotation_90 || + rotation == webrtc::kVideoRotation_270) { + std::swap(rotated_width, rotated_height); + } + + rtc::scoped_refptr<webrtc::I010Buffer> buffer = + Create(rotated_width, rotated_height); + + int res = libyuv::I010Rotate( + src.DataY(), src.StrideY(), src.DataU(), src.StrideU(), src.DataV(), + src.StrideV(), buffer->MutableDataY(), buffer->StrideY(), + buffer->MutableDataU(), buffer->StrideU(), buffer->MutableDataV(), + buffer->StrideV(), src.width(), src.height(), + static_cast<libyuv::RotationMode>(rotation)); + RTC_DCHECK_EQ(res, 0); + + return buffer; +} + +rtc::scoped_refptr<I420BufferInterface> I010Buffer::ToI420() { + rtc::scoped_refptr<I420Buffer> i420_buffer = + I420Buffer::Create(width(), height()); + int res = libyuv::I010ToI420( + DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(), + i420_buffer->MutableDataY(), i420_buffer->StrideY(), + i420_buffer->MutableDataU(), i420_buffer->StrideU(), + i420_buffer->MutableDataV(), i420_buffer->StrideV(), width(), height()); + RTC_DCHECK_EQ(res, 0); + + return i420_buffer; +} + +int I010Buffer::width() const { + return width_; +} + +int I010Buffer::height() const { + return height_; +} + +const uint16_t* I010Buffer::DataY() const { + return data_.get(); +} +const uint16_t* I010Buffer::DataU() const { + return data_.get() + stride_y_ * height_; +} +const uint16_t* I010Buffer::DataV() const { + return data_.get() + stride_y_ * height_ + stride_u_ * ((height_ + 1) / 2); +} + +int I010Buffer::StrideY() const { + return stride_y_; +} +int I010Buffer::StrideU() const { + return stride_u_; +} +int I010Buffer::StrideV() const { + return stride_v_; +} + +uint16_t* I010Buffer::MutableDataY() { + return const_cast<uint16_t*>(DataY()); +} +uint16_t* I010Buffer::MutableDataU() { + return const_cast<uint16_t*>(DataU()); +} +uint16_t* I010Buffer::MutableDataV() { + return const_cast<uint16_t*>(DataV()); +} + +void I010Buffer::CropAndScaleFrom(const I010BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height) { + RTC_CHECK_LE(crop_width, src.width()); + RTC_CHECK_LE(crop_height, src.height()); + RTC_CHECK_LE(crop_width + offset_x, src.width()); + RTC_CHECK_LE(crop_height + offset_y, src.height()); + RTC_CHECK_GE(offset_x, 0); + RTC_CHECK_GE(offset_y, 0); + + // Make sure offset is even so that u/v plane becomes aligned. + const int uv_offset_x = offset_x / 2; + const int uv_offset_y = offset_y / 2; + offset_x = uv_offset_x * 2; + offset_y = uv_offset_y * 2; + + const uint16_t* y_plane = src.DataY() + src.StrideY() * offset_y + offset_x; + const uint16_t* u_plane = + src.DataU() + src.StrideU() * uv_offset_y + uv_offset_x; + const uint16_t* v_plane = + src.DataV() + src.StrideV() * uv_offset_y + uv_offset_x; + int res = libyuv::I420Scale_16( + y_plane, src.StrideY(), u_plane, src.StrideU(), v_plane, src.StrideV(), + crop_width, crop_height, MutableDataY(), StrideY(), MutableDataU(), + StrideU(), MutableDataV(), StrideV(), width(), height(), + libyuv::kFilterBox); + + RTC_DCHECK_EQ(res, 0); +} + +void I010Buffer::ScaleFrom(const I010BufferInterface& src) { + CropAndScaleFrom(src, 0, 0, src.width(), src.height()); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/i010_buffer.h b/third_party/libwebrtc/api/video/i010_buffer.h new file mode 100644 index 0000000000..11e0879fec --- /dev/null +++ b/third_party/libwebrtc/api/video/i010_buffer.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015 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 API_VIDEO_I010_BUFFER_H_ +#define API_VIDEO_I010_BUFFER_H_ + +#include <stdint.h> + +#include <memory> + +#include "api/scoped_refptr.h" +#include "api/video/video_frame_buffer.h" +#include "api/video/video_rotation.h" +#include "rtc_base/memory/aligned_malloc.h" + +namespace webrtc { + +// Plain I010 buffer in standard memory. +class I010Buffer : public I010BufferInterface { + public: + // Create a new buffer. + static rtc::scoped_refptr<I010Buffer> Create(int width, int height); + + // Create a new buffer and copy the pixel data. + static rtc::scoped_refptr<I010Buffer> Copy(const I010BufferInterface& buffer); + + // Convert and put I420 buffer into a new buffer. + static rtc::scoped_refptr<I010Buffer> Copy(const I420BufferInterface& buffer); + + // Return a rotated copy of `src`. + static rtc::scoped_refptr<I010Buffer> Rotate(const I010BufferInterface& src, + VideoRotation rotation); + + // VideoFrameBuffer implementation. + rtc::scoped_refptr<I420BufferInterface> ToI420() override; + + // PlanarYuv16BBuffer implementation. + int width() const override; + int height() const override; + const uint16_t* DataY() const override; + const uint16_t* DataU() const override; + const uint16_t* DataV() const override; + int StrideY() const override; + int StrideU() const override; + int StrideV() const override; + + uint16_t* MutableDataY(); + uint16_t* MutableDataU(); + uint16_t* MutableDataV(); + + // Scale the cropped area of `src` to the size of `this` buffer, and + // write the result into `this`. + void CropAndScaleFrom(const I010BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height); + + // Scale all of `src` to the size of `this` buffer, with no cropping. + void ScaleFrom(const I010BufferInterface& src); + + protected: + I010Buffer(int width, int height, int stride_y, int stride_u, int stride_v); + ~I010Buffer() override; + + private: + const int width_; + const int height_; + const int stride_y_; + const int stride_u_; + const int stride_v_; + const std::unique_ptr<uint16_t, AlignedFreeDeleter> data_; +}; + +} // namespace webrtc + +#endif // API_VIDEO_I010_BUFFER_H_ diff --git a/third_party/libwebrtc/api/video/i210_buffer.cc b/third_party/libwebrtc/api/video/i210_buffer.cc new file mode 100644 index 0000000000..c83c8a0c0b --- /dev/null +++ b/third_party/libwebrtc/api/video/i210_buffer.cc @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2022 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 "api/video/i210_buffer.h" + +#include <utility> + +#include "api/make_ref_counted.h" +#include "api/video/i420_buffer.h" +#include "api/video/i422_buffer.h" +#include "rtc_base/checks.h" +#include "third_party/libyuv/include/libyuv/convert.h" +#include "third_party/libyuv/include/libyuv/scale.h" + +// Aligning pointer to 64 bytes for improved performance, e.g. use SIMD. +static const int kBufferAlignment = 64; +static const int kBytesPerPixel = 2; + +namespace webrtc { + +namespace { + +int I210DataSize(int height, int stride_y, int stride_u, int stride_v) { + return kBytesPerPixel * + (stride_y * height + stride_u * height + stride_v * height); +} + +} // namespace + +I210Buffer::I210Buffer(int width, + int height, + int stride_y, + int stride_u, + int stride_v) + : width_(width), + height_(height), + stride_y_(stride_y), + stride_u_(stride_u), + stride_v_(stride_v), + data_(static_cast<uint16_t*>( + AlignedMalloc(I210DataSize(height, stride_y, stride_u, stride_v), + kBufferAlignment))) { + RTC_DCHECK_GT(width, 0); + RTC_DCHECK_GT(height, 0); + RTC_DCHECK_GE(stride_y, width); + RTC_DCHECK_GE(stride_u, (width + 1) / 2); + RTC_DCHECK_GE(stride_v, (width + 1) / 2); +} + +I210Buffer::~I210Buffer() {} + +// static +rtc::scoped_refptr<I210Buffer> I210Buffer::Create(int width, int height) { + return rtc::make_ref_counted<I210Buffer>(width, height, width, + (width + 1) / 2, (width + 1) / 2); +} + +// static +rtc::scoped_refptr<I210Buffer> I210Buffer::Copy( + const I210BufferInterface& source) { + const int width = source.width(); + const int height = source.height(); + rtc::scoped_refptr<I210Buffer> buffer = Create(width, height); + RTC_CHECK_EQ( + 0, libyuv::I210Copy( + source.DataY(), source.StrideY(), source.DataU(), source.StrideU(), + source.DataV(), source.StrideV(), buffer->MutableDataY(), + buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(), + buffer->MutableDataV(), buffer->StrideV(), width, height)); + return buffer; +} + +// static +rtc::scoped_refptr<I210Buffer> I210Buffer::Copy( + const I420BufferInterface& source) { + const int width = source.width(); + const int height = source.height(); + auto i422buffer = I422Buffer::Copy(source); + rtc::scoped_refptr<I210Buffer> buffer = Create(width, height); + RTC_CHECK_EQ(0, libyuv::I422ToI210(i422buffer->DataY(), i422buffer->StrideY(), + i422buffer->DataU(), i422buffer->StrideU(), + i422buffer->DataV(), i422buffer->StrideV(), + buffer->MutableDataY(), buffer->StrideY(), + buffer->MutableDataU(), buffer->StrideU(), + buffer->MutableDataV(), buffer->StrideV(), + width, height)); + return buffer; +} + +// static +rtc::scoped_refptr<I210Buffer> I210Buffer::Rotate( + const I210BufferInterface& src, + VideoRotation rotation) { + RTC_CHECK(src.DataY()); + RTC_CHECK(src.DataU()); + RTC_CHECK(src.DataV()); + + int rotated_width = src.width(); + int rotated_height = src.height(); + if (rotation == webrtc::kVideoRotation_90 || + rotation == webrtc::kVideoRotation_270) { + std::swap(rotated_width, rotated_height); + } + + rtc::scoped_refptr<webrtc::I210Buffer> buffer = + I210Buffer::Create(rotated_width, rotated_height); + + RTC_CHECK_EQ(0, + libyuv::I210Rotate( + src.DataY(), src.StrideY(), src.DataU(), src.StrideU(), + src.DataV(), src.StrideV(), buffer->MutableDataY(), + buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(), + buffer->MutableDataV(), buffer->StrideV(), src.width(), + src.height(), static_cast<libyuv::RotationMode>(rotation))); + + return buffer; +} + +rtc::scoped_refptr<I420BufferInterface> I210Buffer::ToI420() { + rtc::scoped_refptr<I420Buffer> i420_buffer = + I420Buffer::Create(width(), height()); + libyuv::I210ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(), + i420_buffer->MutableDataY(), i420_buffer->StrideY(), + i420_buffer->MutableDataU(), i420_buffer->StrideU(), + i420_buffer->MutableDataV(), i420_buffer->StrideV(), + width(), height()); + return i420_buffer; +} + +int I210Buffer::width() const { + return width_; +} + +int I210Buffer::height() const { + return height_; +} + +const uint16_t* I210Buffer::DataY() const { + return data_.get(); +} +const uint16_t* I210Buffer::DataU() const { + return data_.get() + stride_y_ * height_; +} +const uint16_t* I210Buffer::DataV() const { + return data_.get() + stride_y_ * height_ + stride_u_ * height_; +} + +int I210Buffer::StrideY() const { + return stride_y_; +} +int I210Buffer::StrideU() const { + return stride_u_; +} +int I210Buffer::StrideV() const { + return stride_v_; +} + +uint16_t* I210Buffer::MutableDataY() { + return const_cast<uint16_t*>(DataY()); +} +uint16_t* I210Buffer::MutableDataU() { + return const_cast<uint16_t*>(DataU()); +} +uint16_t* I210Buffer::MutableDataV() { + return const_cast<uint16_t*>(DataV()); +} + +void I210Buffer::CropAndScaleFrom(const I210BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height) { + RTC_CHECK_LE(crop_width, src.width()); + RTC_CHECK_LE(crop_height, src.height()); + RTC_CHECK_LE(crop_width + offset_x, src.width()); + RTC_CHECK_LE(crop_height + offset_y, src.height()); + RTC_CHECK_GE(offset_x, 0); + RTC_CHECK_GE(offset_y, 0); + RTC_CHECK_GE(crop_width, 0); + RTC_CHECK_GE(crop_height, 0); + + // Make sure offset is even so that u/v plane becomes aligned. + const int uv_offset_x = offset_x / 2; + const int uv_offset_y = offset_y; + offset_x = uv_offset_x * 2; + + const uint16_t* y_plane = src.DataY() + src.StrideY() * offset_y + offset_x; + const uint16_t* u_plane = + src.DataU() + src.StrideU() * uv_offset_y + uv_offset_x; + const uint16_t* v_plane = + src.DataV() + src.StrideV() * uv_offset_y + uv_offset_x; + int res = libyuv::I422Scale_16( + y_plane, src.StrideY(), u_plane, src.StrideU(), v_plane, src.StrideV(), + crop_width, crop_height, MutableDataY(), StrideY(), MutableDataU(), + StrideU(), MutableDataV(), StrideV(), width(), height(), + libyuv::kFilterBox); + + RTC_DCHECK_EQ(res, 0); +} + +void I210Buffer::ScaleFrom(const I210BufferInterface& src) { + CropAndScaleFrom(src, 0, 0, src.width(), src.height()); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/i210_buffer.h b/third_party/libwebrtc/api/video/i210_buffer.h new file mode 100644 index 0000000000..e3b6452b95 --- /dev/null +++ b/third_party/libwebrtc/api/video/i210_buffer.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_I210_BUFFER_H_ +#define API_VIDEO_I210_BUFFER_H_ + +#include <stdint.h> + +#include <memory> + +#include "api/scoped_refptr.h" +#include "api/video/video_frame_buffer.h" +#include "api/video/video_rotation.h" +#include "rtc_base/memory/aligned_malloc.h" + +namespace webrtc { + +// Plain I210 (yuv 422 planar 10 bits) buffer in standard memory. +class I210Buffer : public I210BufferInterface { + public: + // Create a new buffer. + static rtc::scoped_refptr<I210Buffer> Create(int width, int height); + + // Create a new buffer and copy the pixel data. + static rtc::scoped_refptr<I210Buffer> Copy(const I210BufferInterface& buffer); + + // Convert and put I420 buffer into a new buffer. + static rtc::scoped_refptr<I210Buffer> Copy(const I420BufferInterface& buffer); + + // Return a rotated copy of `src`. + static rtc::scoped_refptr<I210Buffer> Rotate(const I210BufferInterface& src, + VideoRotation rotation); + + // VideoFrameBuffer implementation. + rtc::scoped_refptr<I420BufferInterface> ToI420() override; + + // PlanarYuv16BBuffer implementation. + int width() const override; + int height() const override; + const uint16_t* DataY() const override; + const uint16_t* DataU() const override; + const uint16_t* DataV() const override; + int StrideY() const override; + int StrideU() const override; + int StrideV() const override; + + uint16_t* MutableDataY(); + uint16_t* MutableDataU(); + uint16_t* MutableDataV(); + + // Scale the cropped area of `src` to the size of `this` buffer, and + // write the result into `this`. + void CropAndScaleFrom(const I210BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height); + + // Scale all of `src` to the size of `this` buffer, with no cropping. + void ScaleFrom(const I210BufferInterface& src); + + protected: + I210Buffer(int width, int height, int stride_y, int stride_u, int stride_v); + ~I210Buffer() override; + + private: + const int width_; + const int height_; + const int stride_y_; + const int stride_u_; + const int stride_v_; + const std::unique_ptr<uint16_t, AlignedFreeDeleter> data_; +}; + +} // namespace webrtc + +#endif // API_VIDEO_I210_BUFFER_H_ diff --git a/third_party/libwebrtc/api/video/i410_buffer.cc b/third_party/libwebrtc/api/video/i410_buffer.cc new file mode 100644 index 0000000000..1b0d4fdb5c --- /dev/null +++ b/third_party/libwebrtc/api/video/i410_buffer.cc @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2023 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 "api/video/i410_buffer.h" + +#include <string.h> + +#include <algorithm> +#include <utility> + +#include "api/make_ref_counted.h" +#include "api/video/i420_buffer.h" +#include "rtc_base/checks.h" +#include "third_party/libyuv/include/libyuv/convert.h" +#include "third_party/libyuv/include/libyuv/planar_functions.h" +#include "third_party/libyuv/include/libyuv/scale.h" + +// Aligning pointer to 64 bytes for improved performance, e.g. use SIMD. +static const int kBufferAlignment = 64; +static const int kBytesPerPixel = 2; + +namespace webrtc { + +namespace { + +int I410DataSize(int height, int stride_y, int stride_u, int stride_v) { + return kBytesPerPixel * + (stride_y * height + stride_u * height + stride_v * height); +} + +} // namespace + +I410Buffer::I410Buffer(int width, int height) + : I410Buffer(width, height, width, width, width) {} + +I410Buffer::I410Buffer(int width, + int height, + int stride_y, + int stride_u, + int stride_v) + : width_(width), + height_(height), + stride_y_(stride_y), + stride_u_(stride_u), + stride_v_(stride_v), + data_(static_cast<uint16_t*>( + AlignedMalloc(I410DataSize(height, stride_y, stride_u, stride_v), + kBufferAlignment))) { + RTC_DCHECK_GT(width, 0); + RTC_DCHECK_GT(height, 0); + RTC_DCHECK_GE(stride_y, width); + RTC_DCHECK_GE(stride_u, width); + RTC_DCHECK_GE(stride_v, width); +} + +I410Buffer::~I410Buffer() {} + +// static +rtc::scoped_refptr<I410Buffer> I410Buffer::Create(int width, int height) { + return rtc::make_ref_counted<I410Buffer>(width, height); +} + +// static +rtc::scoped_refptr<I410Buffer> I410Buffer::Create(int width, + int height, + int stride_y, + int stride_u, + int stride_v) { + return rtc::make_ref_counted<I410Buffer>(width, height, stride_y, stride_u, + stride_v); +} + +// static +rtc::scoped_refptr<I410Buffer> I410Buffer::Copy( + const I410BufferInterface& source) { + return Copy(source.width(), source.height(), source.DataY(), source.StrideY(), + source.DataU(), source.StrideU(), source.DataV(), + source.StrideV()); +} + +// static +rtc::scoped_refptr<I410Buffer> I410Buffer::Copy(int width, + int height, + const uint16_t* data_y, + int stride_y, + const uint16_t* data_u, + int stride_u, + const uint16_t* data_v, + int stride_v) { + // Note: May use different strides than the input data. + rtc::scoped_refptr<I410Buffer> buffer = Create(width, height); + int res = libyuv::I410Copy(data_y, stride_y, data_u, stride_u, data_v, + stride_v, buffer->MutableDataY(), + buffer->StrideY(), buffer->MutableDataU(), + buffer->StrideU(), buffer->MutableDataV(), + buffer->StrideV(), width, height); + RTC_DCHECK_EQ(res, 0); + + return buffer; +} + +// static +rtc::scoped_refptr<I410Buffer> I410Buffer::Rotate( + const I410BufferInterface& src, + VideoRotation rotation) { + RTC_CHECK(src.DataY()); + RTC_CHECK(src.DataU()); + RTC_CHECK(src.DataV()); + + int rotated_width = src.width(); + int rotated_height = src.height(); + if (rotation == webrtc::kVideoRotation_90 || + rotation == webrtc::kVideoRotation_270) { + std::swap(rotated_width, rotated_height); + } + + rtc::scoped_refptr<webrtc::I410Buffer> buffer = + I410Buffer::Create(rotated_width, rotated_height); + + int res = libyuv::I410Rotate( + src.DataY(), src.StrideY(), src.DataU(), src.StrideU(), src.DataV(), + src.StrideV(), buffer->MutableDataY(), buffer->StrideY(), + buffer->MutableDataU(), buffer->StrideU(), buffer->MutableDataV(), + buffer->StrideV(), src.width(), src.height(), + static_cast<libyuv::RotationMode>(rotation)); + RTC_DCHECK_EQ(res, 0); + + return buffer; +} + +rtc::scoped_refptr<I420BufferInterface> I410Buffer::ToI420() { + rtc::scoped_refptr<I420Buffer> i420_buffer = + I420Buffer::Create(width(), height()); + int res = libyuv::I410ToI420( + DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(), + i420_buffer->MutableDataY(), i420_buffer->StrideY(), + i420_buffer->MutableDataU(), i420_buffer->StrideU(), + i420_buffer->MutableDataV(), i420_buffer->StrideV(), width(), height()); + RTC_DCHECK_EQ(res, 0); + + return i420_buffer; +} + +void I410Buffer::InitializeData() { + memset(data_.get(), 0, + I410DataSize(height_, stride_y_, stride_u_, stride_v_)); +} + +int I410Buffer::width() const { + return width_; +} + +int I410Buffer::height() const { + return height_; +} + +const uint16_t* I410Buffer::DataY() const { + return data_.get(); +} +const uint16_t* I410Buffer::DataU() const { + return data_.get() + stride_y_ * height_; +} +const uint16_t* I410Buffer::DataV() const { + return data_.get() + stride_y_ * height_ + stride_u_ * height_; +} + +int I410Buffer::StrideY() const { + return stride_y_; +} +int I410Buffer::StrideU() const { + return stride_u_; +} +int I410Buffer::StrideV() const { + return stride_v_; +} + +uint16_t* I410Buffer::MutableDataY() { + return const_cast<uint16_t*>(DataY()); +} +uint16_t* I410Buffer::MutableDataU() { + return const_cast<uint16_t*>(DataU()); +} +uint16_t* I410Buffer::MutableDataV() { + return const_cast<uint16_t*>(DataV()); +} + +void I410Buffer::CropAndScaleFrom(const I410BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height) { + RTC_CHECK_LE(crop_width, src.width()); + RTC_CHECK_LE(crop_height, src.height()); + RTC_CHECK_LE(crop_width + offset_x, src.width()); + RTC_CHECK_LE(crop_height + offset_y, src.height()); + RTC_CHECK_GE(offset_x, 0); + RTC_CHECK_GE(offset_y, 0); + + const uint16_t* y_plane = src.DataY() + src.StrideY() * offset_y + offset_x; + const uint16_t* u_plane = src.DataU() + src.StrideU() * offset_y + offset_x; + const uint16_t* v_plane = src.DataV() + src.StrideV() * offset_y + offset_x; + int res = libyuv::I444Scale_16( + y_plane, src.StrideY(), u_plane, src.StrideU(), v_plane, src.StrideV(), + crop_width, crop_height, MutableDataY(), StrideY(), MutableDataU(), + StrideU(), MutableDataV(), StrideV(), width(), height(), + libyuv::kFilterBox); + + RTC_DCHECK_EQ(res, 0); +} + +void I410Buffer::ScaleFrom(const I410BufferInterface& src) { + CropAndScaleFrom(src, 0, 0, src.width(), src.height()); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/i410_buffer.h b/third_party/libwebrtc/api/video/i410_buffer.h new file mode 100644 index 0000000000..1c0cd86c12 --- /dev/null +++ b/third_party/libwebrtc/api/video/i410_buffer.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2023 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 API_VIDEO_I410_BUFFER_H_ +#define API_VIDEO_I410_BUFFER_H_ + +#include <stdint.h> + +#include <memory> + +#include "api/scoped_refptr.h" +#include "api/video/video_frame_buffer.h" +#include "api/video/video_rotation.h" +#include "rtc_base/memory/aligned_malloc.h" + +namespace webrtc { + +// Plain I410 (yuv 444 planar 10 bits) buffer in standard memory. +class RTC_EXPORT I410Buffer : public I410BufferInterface { + public: + static rtc::scoped_refptr<I410Buffer> Create(int width, int height); + static rtc::scoped_refptr<I410Buffer> Create(int width, + int height, + int stride_y, + int stride_u, + int stride_v); + + // Create a new buffer and copy the pixel data. + static rtc::scoped_refptr<I410Buffer> Copy(const I410BufferInterface& buffer); + + static rtc::scoped_refptr<I410Buffer> Copy(int width, + int height, + const uint16_t* data_y, + int stride_y, + const uint16_t* data_u, + int stride_u, + const uint16_t* data_v, + int stride_v); + + // Returns a rotated copy of |src|. + static rtc::scoped_refptr<I410Buffer> Rotate(const I410BufferInterface& src, + VideoRotation rotation); + + rtc::scoped_refptr<I420BufferInterface> ToI420() final; + const I420BufferInterface* GetI420() const final { return nullptr; } + + // Sets all three planes to all zeros. Used to work around for + // quirks in memory checkers + // (https://bugs.chromium.org/p/libyuv/issues/detail?id=377) and + // ffmpeg (http://crbug.com/390941). + // TODO(https://crbug.com/390941): Deprecated. Should be deleted if/when those + // issues are resolved in a better way. Or in the mean time, use SetBlack. + void InitializeData(); + + int width() const override; + int height() const override; + const uint16_t* DataY() const override; + const uint16_t* DataU() const override; + const uint16_t* DataV() const override; + + int StrideY() const override; + int StrideU() const override; + int StrideV() const override; + + uint16_t* MutableDataY(); + uint16_t* MutableDataU(); + uint16_t* MutableDataV(); + + // Scale the cropped area of |src| to the size of |this| buffer, and + // write the result into |this|. + void CropAndScaleFrom(const I410BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height); + + // Scale all of `src` to the size of `this` buffer, with no cropping. + void ScaleFrom(const I410BufferInterface& src); + + protected: + I410Buffer(int width, int height); + I410Buffer(int width, int height, int stride_y, int stride_u, int stride_v); + + ~I410Buffer() override; + + private: + const int width_; + const int height_; + const int stride_y_; + const int stride_u_; + const int stride_v_; + const std::unique_ptr<uint16_t, AlignedFreeDeleter> data_; +}; + +} // namespace webrtc + +#endif // API_VIDEO_I410_BUFFER_H_ diff --git a/third_party/libwebrtc/api/video/i420_buffer.cc b/third_party/libwebrtc/api/video/i420_buffer.cc new file mode 100644 index 0000000000..bf7fc06ee9 --- /dev/null +++ b/third_party/libwebrtc/api/video/i420_buffer.cc @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2015 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 "api/video/i420_buffer.h" + +#include <string.h> + +#include <algorithm> +#include <utility> + +#include "api/make_ref_counted.h" +#include "rtc_base/checks.h" +#include "third_party/libyuv/include/libyuv/convert.h" +#include "third_party/libyuv/include/libyuv/planar_functions.h" +#include "third_party/libyuv/include/libyuv/scale.h" + +// Aligning pointer to 64 bytes for improved performance, e.g. use SIMD. +static const int kBufferAlignment = 64; + +namespace webrtc { + +namespace { + +int I420DataSize(int height, int stride_y, int stride_u, int stride_v) { + return stride_y * height + (stride_u + stride_v) * ((height + 1) / 2); +} + +} // namespace + +I420Buffer::I420Buffer(int width, int height) + : I420Buffer(width, height, width, (width + 1) / 2, (width + 1) / 2) {} + +I420Buffer::I420Buffer(int width, + int height, + int stride_y, + int stride_u, + int stride_v) + : width_(width), + height_(height), + stride_y_(stride_y), + stride_u_(stride_u), + stride_v_(stride_v), + data_(static_cast<uint8_t*>( + AlignedMalloc(I420DataSize(height, stride_y, stride_u, stride_v), + kBufferAlignment))) { + RTC_DCHECK_GT(width, 0); + RTC_DCHECK_GT(height, 0); + RTC_DCHECK_GE(stride_y, width); + RTC_DCHECK_GE(stride_u, (width + 1) / 2); + RTC_DCHECK_GE(stride_v, (width + 1) / 2); +} + +I420Buffer::~I420Buffer() {} + +// static +rtc::scoped_refptr<I420Buffer> I420Buffer::Create(int width, int height) { + return rtc::make_ref_counted<I420Buffer>(width, height); +} + +// static +rtc::scoped_refptr<I420Buffer> I420Buffer::Create(int width, + int height, + int stride_y, + int stride_u, + int stride_v) { + return rtc::make_ref_counted<I420Buffer>(width, height, stride_y, stride_u, + stride_v); +} + +// static +rtc::scoped_refptr<I420Buffer> I420Buffer::Copy( + const I420BufferInterface& source) { + return Copy(source.width(), source.height(), source.DataY(), source.StrideY(), + source.DataU(), source.StrideU(), source.DataV(), + source.StrideV()); +} + +// static +rtc::scoped_refptr<I420Buffer> I420Buffer::Copy(int width, + int height, + const uint8_t* data_y, + int stride_y, + const uint8_t* data_u, + int stride_u, + const uint8_t* data_v, + int stride_v) { + // Note: May use different strides than the input data. + rtc::scoped_refptr<I420Buffer> buffer = Create(width, height); + RTC_CHECK_EQ(0, libyuv::I420Copy(data_y, stride_y, data_u, stride_u, data_v, + stride_v, buffer->MutableDataY(), + buffer->StrideY(), buffer->MutableDataU(), + buffer->StrideU(), buffer->MutableDataV(), + buffer->StrideV(), width, height)); + return buffer; +} + +// static +rtc::scoped_refptr<I420Buffer> I420Buffer::Rotate( + const I420BufferInterface& src, + VideoRotation rotation) { + RTC_CHECK(src.DataY()); + RTC_CHECK(src.DataU()); + RTC_CHECK(src.DataV()); + + int rotated_width = src.width(); + int rotated_height = src.height(); + if (rotation == webrtc::kVideoRotation_90 || + rotation == webrtc::kVideoRotation_270) { + std::swap(rotated_width, rotated_height); + } + + rtc::scoped_refptr<webrtc::I420Buffer> buffer = + I420Buffer::Create(rotated_width, rotated_height); + + RTC_CHECK_EQ(0, + libyuv::I420Rotate( + src.DataY(), src.StrideY(), src.DataU(), src.StrideU(), + src.DataV(), src.StrideV(), buffer->MutableDataY(), + buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(), + buffer->MutableDataV(), buffer->StrideV(), src.width(), + src.height(), static_cast<libyuv::RotationMode>(rotation))); + + return buffer; +} + +void I420Buffer::InitializeData() { + memset(data_.get(), 0, + I420DataSize(height_, stride_y_, stride_u_, stride_v_)); +} + +int I420Buffer::width() const { + return width_; +} + +int I420Buffer::height() const { + return height_; +} + +const uint8_t* I420Buffer::DataY() const { + return data_.get(); +} +const uint8_t* I420Buffer::DataU() const { + return data_.get() + stride_y_ * height_; +} +const uint8_t* I420Buffer::DataV() const { + return data_.get() + stride_y_ * height_ + stride_u_ * ((height_ + 1) / 2); +} + +int I420Buffer::StrideY() const { + return stride_y_; +} +int I420Buffer::StrideU() const { + return stride_u_; +} +int I420Buffer::StrideV() const { + return stride_v_; +} + +uint8_t* I420Buffer::MutableDataY() { + return const_cast<uint8_t*>(DataY()); +} +uint8_t* I420Buffer::MutableDataU() { + return const_cast<uint8_t*>(DataU()); +} +uint8_t* I420Buffer::MutableDataV() { + return const_cast<uint8_t*>(DataV()); +} + +// static +void I420Buffer::SetBlack(I420Buffer* buffer) { + RTC_CHECK(libyuv::I420Rect(buffer->MutableDataY(), buffer->StrideY(), + buffer->MutableDataU(), buffer->StrideU(), + buffer->MutableDataV(), buffer->StrideV(), 0, 0, + buffer->width(), buffer->height(), 0, 128, + 128) == 0); +} + +void I420Buffer::CropAndScaleFrom(const I420BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height) { + RTC_CHECK_LE(crop_width, src.width()); + RTC_CHECK_LE(crop_height, src.height()); + RTC_CHECK_LE(crop_width + offset_x, src.width()); + RTC_CHECK_LE(crop_height + offset_y, src.height()); + RTC_CHECK_GE(offset_x, 0); + RTC_CHECK_GE(offset_y, 0); + + // Make sure offset is even so that u/v plane becomes aligned. + const int uv_offset_x = offset_x / 2; + const int uv_offset_y = offset_y / 2; + offset_x = uv_offset_x * 2; + offset_y = uv_offset_y * 2; + + const uint8_t* y_plane = src.DataY() + src.StrideY() * offset_y + offset_x; + const uint8_t* u_plane = + src.DataU() + src.StrideU() * uv_offset_y + uv_offset_x; + const uint8_t* v_plane = + src.DataV() + src.StrideV() * uv_offset_y + uv_offset_x; + int res = + libyuv::I420Scale(y_plane, src.StrideY(), u_plane, src.StrideU(), v_plane, + src.StrideV(), crop_width, crop_height, MutableDataY(), + StrideY(), MutableDataU(), StrideU(), MutableDataV(), + StrideV(), width(), height(), libyuv::kFilterBox); + + RTC_DCHECK_EQ(res, 0); +} + +void I420Buffer::CropAndScaleFrom(const I420BufferInterface& src) { + const int crop_width = + height() > 0 ? std::min(src.width(), width() * src.height() / height()) + : src.width(); + const int crop_height = + width() > 0 ? std::min(src.height(), height() * src.width() / width()) + : src.height(); + + CropAndScaleFrom(src, (src.width() - crop_width) / 2, + (src.height() - crop_height) / 2, crop_width, crop_height); +} + +void I420Buffer::ScaleFrom(const I420BufferInterface& src) { + CropAndScaleFrom(src, 0, 0, src.width(), src.height()); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/i420_buffer.h b/third_party/libwebrtc/api/video/i420_buffer.h new file mode 100644 index 0000000000..b337489657 --- /dev/null +++ b/third_party/libwebrtc/api/video/i420_buffer.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015 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 API_VIDEO_I420_BUFFER_H_ +#define API_VIDEO_I420_BUFFER_H_ + +#include <stdint.h> + +#include <memory> + +#include "api/scoped_refptr.h" +#include "api/video/video_frame_buffer.h" +#include "api/video/video_rotation.h" +#include "rtc_base/memory/aligned_malloc.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Plain I420 buffer in standard memory. +class RTC_EXPORT I420Buffer : public I420BufferInterface { + public: + static rtc::scoped_refptr<I420Buffer> Create(int width, int height); + static rtc::scoped_refptr<I420Buffer> Create(int width, + int height, + int stride_y, + int stride_u, + int stride_v); + + // Create a new buffer and copy the pixel data. + static rtc::scoped_refptr<I420Buffer> Copy(const I420BufferInterface& buffer); + // Deprecated. + static rtc::scoped_refptr<I420Buffer> Copy(const VideoFrameBuffer& buffer) { + return Copy(*buffer.GetI420()); + } + + static rtc::scoped_refptr<I420Buffer> Copy(int width, + int height, + const uint8_t* data_y, + int stride_y, + const uint8_t* data_u, + int stride_u, + const uint8_t* data_v, + int stride_v); + + // Returns a rotated copy of `src`. + static rtc::scoped_refptr<I420Buffer> Rotate(const I420BufferInterface& src, + VideoRotation rotation); + // Deprecated. + static rtc::scoped_refptr<I420Buffer> Rotate(const VideoFrameBuffer& src, + VideoRotation rotation) { + return Rotate(*src.GetI420(), rotation); + } + + // Sets the buffer to all black. + static void SetBlack(I420Buffer* buffer); + + // Sets all three planes to all zeros. Used to work around for + // quirks in memory checkers + // (https://bugs.chromium.org/p/libyuv/issues/detail?id=377) and + // ffmpeg (http://crbug.com/390941). + // TODO(https://crbug.com/390941): Deprecated. Should be deleted if/when those + // issues are resolved in a better way. Or in the mean time, use SetBlack. + void InitializeData(); + + int width() const override; + int height() const override; + const uint8_t* DataY() const override; + const uint8_t* DataU() const override; + const uint8_t* DataV() const override; + + int StrideY() const override; + int StrideU() const override; + int StrideV() const override; + + uint8_t* MutableDataY(); + uint8_t* MutableDataU(); + uint8_t* MutableDataV(); + + // Scale the cropped area of `src` to the size of `this` buffer, and + // write the result into `this`. + void CropAndScaleFrom(const I420BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height); + + // The common case of a center crop, when needed to adjust the + // aspect ratio without distorting the image. + void CropAndScaleFrom(const I420BufferInterface& src); + + // Scale all of `src` to the size of `this` buffer, with no cropping. + void ScaleFrom(const I420BufferInterface& src); + + protected: + I420Buffer(int width, int height); + I420Buffer(int width, int height, int stride_y, int stride_u, int stride_v); + + ~I420Buffer() override; + + private: + const int width_; + const int height_; + const int stride_y_; + const int stride_u_; + const int stride_v_; + const std::unique_ptr<uint8_t, AlignedFreeDeleter> data_; +}; + +} // namespace webrtc + +#endif // API_VIDEO_I420_BUFFER_H_ diff --git a/third_party/libwebrtc/api/video/i422_buffer.cc b/third_party/libwebrtc/api/video/i422_buffer.cc new file mode 100644 index 0000000000..fddc1b57fd --- /dev/null +++ b/third_party/libwebrtc/api/video/i422_buffer.cc @@ -0,0 +1,237 @@ +/* + * 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 "api/video/i422_buffer.h" + +#include <string.h> + +#include <algorithm> +#include <utility> + +#include "api/make_ref_counted.h" +#include "api/video/i420_buffer.h" +#include "rtc_base/checks.h" +#include "third_party/libyuv/include/libyuv/convert.h" +#include "third_party/libyuv/include/libyuv/planar_functions.h" +#include "third_party/libyuv/include/libyuv/scale.h" + +// Aligning pointer to 64 bytes for improved performance, e.g. use SIMD. +static const int kBufferAlignment = 64; + +namespace webrtc { + +namespace { + +int I422DataSize(int height, int stride_y, int stride_u, int stride_v) { + return stride_y * height + stride_u * height + stride_v * height; +} +} // namespace + +I422Buffer::I422Buffer(int width, int height) + : I422Buffer(width, height, width, (width + 1) / 2, (width + 1) / 2) {} + +I422Buffer::I422Buffer(int width, + int height, + int stride_y, + int stride_u, + int stride_v) + : width_(width), + height_(height), + stride_y_(stride_y), + stride_u_(stride_u), + stride_v_(stride_v), + data_(static_cast<uint8_t*>( + AlignedMalloc(I422DataSize(height, stride_y, stride_u, stride_v), + kBufferAlignment))) { + RTC_DCHECK_GT(width, 0); + RTC_DCHECK_GT(height, 0); + RTC_DCHECK_GE(stride_y, width); + RTC_DCHECK_GE(stride_u, (width + 1) / 2); + RTC_DCHECK_GE(stride_v, (width + 1) / 2); +} + +I422Buffer::~I422Buffer() {} + +// static +rtc::scoped_refptr<I422Buffer> I422Buffer::Create(int width, int height) { + return rtc::make_ref_counted<I422Buffer>(width, height); +} + +// static +rtc::scoped_refptr<I422Buffer> I422Buffer::Create(int width, + int height, + int stride_y, + int stride_u, + int stride_v) { + return rtc::make_ref_counted<I422Buffer>(width, height, stride_y, stride_u, + stride_v); +} + +// static +rtc::scoped_refptr<I422Buffer> I422Buffer::Copy( + const I422BufferInterface& source) { + return Copy(source.width(), source.height(), source.DataY(), source.StrideY(), + source.DataU(), source.StrideU(), source.DataV(), + source.StrideV()); +} + +// static +rtc::scoped_refptr<I422Buffer> I422Buffer::Copy( + const I420BufferInterface& source) { + const int width = source.width(); + const int height = source.height(); + rtc::scoped_refptr<I422Buffer> buffer = Create(width, height); + int res = libyuv::I420ToI422( + source.DataY(), source.StrideY(), source.DataU(), source.StrideU(), + source.DataV(), source.StrideV(), buffer->MutableDataY(), + buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(), + buffer->MutableDataV(), buffer->StrideV(), width, height); + RTC_DCHECK_EQ(res, 0); + + return buffer; +} + +// static +rtc::scoped_refptr<I422Buffer> I422Buffer::Copy(int width, + int height, + const uint8_t* data_y, + int stride_y, + const uint8_t* data_u, + int stride_u, + const uint8_t* data_v, + int stride_v) { + // Note: May use different strides than the input data. + rtc::scoped_refptr<I422Buffer> buffer = Create(width, height); + int res = libyuv::I422Copy(data_y, stride_y, data_u, stride_u, data_v, + stride_v, buffer->MutableDataY(), + buffer->StrideY(), buffer->MutableDataU(), + buffer->StrideU(), buffer->MutableDataV(), + buffer->StrideV(), width, height); + RTC_DCHECK_EQ(res, 0); + + return buffer; +} + +// static +rtc::scoped_refptr<I422Buffer> I422Buffer::Rotate( + const I422BufferInterface& src, + VideoRotation rotation) { + RTC_CHECK(src.DataY()); + RTC_CHECK(src.DataU()); + RTC_CHECK(src.DataV()); + + int rotated_width = src.width(); + int rotated_height = src.height(); + if (rotation == webrtc::kVideoRotation_90 || + rotation == webrtc::kVideoRotation_270) { + std::swap(rotated_width, rotated_height); + } + + rtc::scoped_refptr<webrtc::I422Buffer> buffer = + I422Buffer::Create(rotated_width, rotated_height); + + int res = libyuv::I422Rotate( + src.DataY(), src.StrideY(), src.DataU(), src.StrideU(), src.DataV(), + src.StrideV(), buffer->MutableDataY(), buffer->StrideY(), + buffer->MutableDataU(), buffer->StrideU(), buffer->MutableDataV(), + buffer->StrideV(), src.width(), src.height(), + static_cast<libyuv::RotationMode>(rotation)); + RTC_DCHECK_EQ(res, 0); + + return buffer; +} + +rtc::scoped_refptr<I420BufferInterface> I422Buffer::ToI420() { + rtc::scoped_refptr<I420Buffer> i420_buffer = + I420Buffer::Create(width(), height()); + int res = libyuv::I422ToI420( + DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(), + i420_buffer->MutableDataY(), i420_buffer->StrideY(), + i420_buffer->MutableDataU(), i420_buffer->StrideU(), + i420_buffer->MutableDataV(), i420_buffer->StrideV(), width(), height()); + RTC_DCHECK_EQ(res, 0); + + return i420_buffer; +} + +void I422Buffer::InitializeData() { + memset(data_.get(), 0, + I422DataSize(height_, stride_y_, stride_u_, stride_v_)); +} + +int I422Buffer::width() const { + return width_; +} + +int I422Buffer::height() const { + return height_; +} + +const uint8_t* I422Buffer::DataY() const { + return data_.get(); +} +const uint8_t* I422Buffer::DataU() const { + return data_.get() + stride_y_ * height_; +} +const uint8_t* I422Buffer::DataV() const { + return data_.get() + stride_y_ * height_ + stride_u_ * height_; +} + +int I422Buffer::StrideY() const { + return stride_y_; +} +int I422Buffer::StrideU() const { + return stride_u_; +} +int I422Buffer::StrideV() const { + return stride_v_; +} + +uint8_t* I422Buffer::MutableDataY() { + return const_cast<uint8_t*>(DataY()); +} +uint8_t* I422Buffer::MutableDataU() { + return const_cast<uint8_t*>(DataU()); +} +uint8_t* I422Buffer::MutableDataV() { + return const_cast<uint8_t*>(DataV()); +} + +void I422Buffer::CropAndScaleFrom(const I422BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height) { + RTC_CHECK_LE(crop_width, src.width()); + RTC_CHECK_LE(crop_height, src.height()); + RTC_CHECK_LE(crop_width + offset_x, src.width()); + RTC_CHECK_LE(crop_height + offset_y, src.height()); + RTC_CHECK_GE(offset_x, 0); + RTC_CHECK_GE(offset_y, 0); + + // Make sure offset is even so that u/v plane becomes aligned. + const int uv_offset_x = offset_x / 2; + const int uv_offset_y = offset_y; + offset_x = uv_offset_x * 2; + + const uint8_t* y_plane = src.DataY() + src.StrideY() * offset_y + offset_x; + const uint8_t* u_plane = + src.DataU() + src.StrideU() * uv_offset_y + uv_offset_x; + const uint8_t* v_plane = + src.DataV() + src.StrideV() * uv_offset_y + uv_offset_x; + + int res = + libyuv::I422Scale(y_plane, src.StrideY(), u_plane, src.StrideU(), v_plane, + src.StrideV(), crop_width, crop_height, MutableDataY(), + StrideY(), MutableDataU(), StrideU(), MutableDataV(), + StrideV(), width(), height(), libyuv::kFilterBox); + RTC_DCHECK_EQ(res, 0); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/i422_buffer.h b/third_party/libwebrtc/api/video/i422_buffer.h new file mode 100644 index 0000000000..600b4ecea7 --- /dev/null +++ b/third_party/libwebrtc/api/video/i422_buffer.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015 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 API_VIDEO_I422_BUFFER_H_ +#define API_VIDEO_I422_BUFFER_H_ + +#include <stdint.h> + +#include <memory> + +#include "api/scoped_refptr.h" +#include "api/video/video_frame_buffer.h" +#include "api/video/video_rotation.h" +#include "rtc_base/memory/aligned_malloc.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Plain I422 buffer in standard memory. +class RTC_EXPORT I422Buffer : public I422BufferInterface { + public: + static rtc::scoped_refptr<I422Buffer> Create(int width, int height); + static rtc::scoped_refptr<I422Buffer> Create(int width, + int height, + int stride_y, + int stride_u, + int stride_v); + + // Create a new buffer and copy the pixel data. + static rtc::scoped_refptr<I422Buffer> Copy(const I422BufferInterface& buffer); + /// Convert and put I420 buffer into a new buffer. + static rtc::scoped_refptr<I422Buffer> Copy(const I420BufferInterface& buffer); + + static rtc::scoped_refptr<I422Buffer> Copy(int width, + int height, + const uint8_t* data_y, + int stride_y, + const uint8_t* data_u, + int stride_u, + const uint8_t* data_v, + int stride_v); + + // Returns a rotated copy of `src`. + static rtc::scoped_refptr<I422Buffer> Rotate(const I422BufferInterface& src, + VideoRotation rotation); + + rtc::scoped_refptr<I420BufferInterface> ToI420() final; + const I420BufferInterface* GetI420() const final { return nullptr; } + + // Sets the buffer to all black. + static void SetBlack(I422Buffer* buffer); + + // Sets all three planes to all zeros. Used to work around for + // quirks in memory checkers + // (https://bugs.chromium.org/p/libyuv/issues/detail?id=377) and + // ffmpeg (http://crbug.com/390941). + // TODO(https://crbug.com/390941): Deprecated. Should be deleted if/when those + // issues are resolved in a better way. Or in the mean time, use SetBlack. + void InitializeData(); + + int width() const override; + int height() const override; + const uint8_t* DataY() const override; + const uint8_t* DataU() const override; + const uint8_t* DataV() const override; + + int StrideY() const override; + int StrideU() const override; + int StrideV() const override; + + uint8_t* MutableDataY(); + uint8_t* MutableDataU(); + uint8_t* MutableDataV(); + + // Scale the cropped area of `src` to the size of `this` buffer, and + // write the result into `this`. + void CropAndScaleFrom(const I422BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height); + + // The common case of a center crop, when needed to adjust the + // aspect ratio without distorting the image. + void CropAndScaleFrom(const I422BufferInterface& src); + + // Scale all of `src` to the size of `this` buffer, with no cropping. + void ScaleFrom(const I422BufferInterface& src); + + protected: + I422Buffer(int width, int height); + I422Buffer(int width, int height, int stride_y, int stride_u, int stride_v); + + ~I422Buffer() override; + + private: + const int width_; + const int height_; + const int stride_y_; + const int stride_u_; + const int stride_v_; + const std::unique_ptr<uint8_t, AlignedFreeDeleter> data_; +}; + +} // namespace webrtc + +#endif // API_VIDEO_I422_BUFFER_H_ diff --git a/third_party/libwebrtc/api/video/i444_buffer.cc b/third_party/libwebrtc/api/video/i444_buffer.cc new file mode 100644 index 0000000000..98e892308f --- /dev/null +++ b/third_party/libwebrtc/api/video/i444_buffer.cc @@ -0,0 +1,211 @@ +/* + * 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 "api/video/i444_buffer.h" + +#include <string.h> + +#include <algorithm> +#include <utility> + +#include "api/make_ref_counted.h" +#include "api/video/i420_buffer.h" +#include "rtc_base/checks.h" +#include "third_party/libyuv/include/libyuv/convert.h" +#include "third_party/libyuv/include/libyuv/planar_functions.h" +#include "third_party/libyuv/include/libyuv/scale.h" + +// Aligning pointer to 64 bytes for improved performance, e.g. use SIMD. +static const int kBufferAlignment = 64; + +namespace webrtc { + +namespace { + +int I444DataSize(int height, int stride_y, int stride_u, int stride_v) { + return stride_y * height + stride_u * height + stride_v * height; +} + +} // namespace + +I444Buffer::I444Buffer(int width, int height) + : I444Buffer(width, height, width, (width), (width)) {} + +I444Buffer::I444Buffer(int width, + int height, + int stride_y, + int stride_u, + int stride_v) + : width_(width), + height_(height), + stride_y_(stride_y), + stride_u_(stride_u), + stride_v_(stride_v), + data_(static_cast<uint8_t*>( + AlignedMalloc(I444DataSize(height, stride_y, stride_u, stride_v), + kBufferAlignment))) { + RTC_DCHECK_GT(width, 0); + RTC_DCHECK_GT(height, 0); + RTC_DCHECK_GE(stride_y, width); + RTC_DCHECK_GE(stride_u, (width)); + RTC_DCHECK_GE(stride_v, (width)); +} + +I444Buffer::~I444Buffer() {} + +// static +rtc::scoped_refptr<I444Buffer> I444Buffer::Create(int width, int height) { + return rtc::make_ref_counted<I444Buffer>(width, height); +} + +// static +rtc::scoped_refptr<I444Buffer> I444Buffer::Create(int width, + int height, + int stride_y, + int stride_u, + int stride_v) { + return rtc::make_ref_counted<I444Buffer>(width, height, stride_y, stride_u, + stride_v); +} + +// static +rtc::scoped_refptr<I444Buffer> I444Buffer::Copy( + const I444BufferInterface& source) { + return Copy(source.width(), source.height(), source.DataY(), source.StrideY(), + source.DataU(), source.StrideU(), source.DataV(), + source.StrideV()); +} + +// static +rtc::scoped_refptr<I444Buffer> I444Buffer::Copy(int width, + int height, + const uint8_t* data_y, + int stride_y, + const uint8_t* data_u, + int stride_u, + const uint8_t* data_v, + int stride_v) { + // Note: May use different strides than the input data. + rtc::scoped_refptr<I444Buffer> buffer = Create(width, height); + RTC_CHECK_EQ(0, libyuv::I444Copy(data_y, stride_y, data_u, stride_u, data_v, + stride_v, buffer->MutableDataY(), + buffer->StrideY(), buffer->MutableDataU(), + buffer->StrideU(), buffer->MutableDataV(), + buffer->StrideV(), width, height)); + return buffer; +} + +// static +rtc::scoped_refptr<I444Buffer> I444Buffer::Rotate( + const I444BufferInterface& src, + VideoRotation rotation) { + RTC_CHECK(src.DataY()); + RTC_CHECK(src.DataU()); + RTC_CHECK(src.DataV()); + + int rotated_width = src.width(); + int rotated_height = src.height(); + if (rotation == webrtc::kVideoRotation_90 || + rotation == webrtc::kVideoRotation_270) { + std::swap(rotated_width, rotated_height); + } + + rtc::scoped_refptr<webrtc::I444Buffer> buffer = + I444Buffer::Create(rotated_width, rotated_height); + + RTC_CHECK_EQ(0, + libyuv::I444Rotate( + src.DataY(), src.StrideY(), src.DataU(), src.StrideU(), + src.DataV(), src.StrideV(), buffer->MutableDataY(), + buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(), + buffer->MutableDataV(), buffer->StrideV(), src.width(), + src.height(), static_cast<libyuv::RotationMode>(rotation))); + + return buffer; +} + +rtc::scoped_refptr<I420BufferInterface> I444Buffer::ToI420() { + rtc::scoped_refptr<I420Buffer> i420_buffer = + I420Buffer::Create(width(), height()); + libyuv::I444ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(), + i420_buffer->MutableDataY(), i420_buffer->StrideY(), + i420_buffer->MutableDataU(), i420_buffer->StrideU(), + i420_buffer->MutableDataV(), i420_buffer->StrideV(), + width(), height()); + return i420_buffer; +} + +void I444Buffer::InitializeData() { + memset(data_.get(), 0, + I444DataSize(height_, stride_y_, stride_u_, stride_v_)); +} + +int I444Buffer::width() const { + return width_; +} + +int I444Buffer::height() const { + return height_; +} + +const uint8_t* I444Buffer::DataY() const { + return data_.get(); +} +const uint8_t* I444Buffer::DataU() const { + return data_.get() + stride_y_ * height_; +} +const uint8_t* I444Buffer::DataV() const { + return data_.get() + stride_y_ * height_ + stride_u_ * ((height_)); +} + +int I444Buffer::StrideY() const { + return stride_y_; +} +int I444Buffer::StrideU() const { + return stride_u_; +} +int I444Buffer::StrideV() const { + return stride_v_; +} + +uint8_t* I444Buffer::MutableDataY() { + return const_cast<uint8_t*>(DataY()); +} +uint8_t* I444Buffer::MutableDataU() { + return const_cast<uint8_t*>(DataU()); +} +uint8_t* I444Buffer::MutableDataV() { + return const_cast<uint8_t*>(DataV()); +} + +void I444Buffer::CropAndScaleFrom(const I444BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height) { + RTC_CHECK_LE(crop_width, src.width()); + RTC_CHECK_LE(crop_height, src.height()); + RTC_CHECK_LE(crop_width + offset_x, src.width()); + RTC_CHECK_LE(crop_height + offset_y, src.height()); + RTC_CHECK_GE(offset_x, 0); + RTC_CHECK_GE(offset_y, 0); + + const uint8_t* y_plane = src.DataY() + src.StrideY() * offset_y + offset_x; + const uint8_t* u_plane = src.DataU() + src.StrideU() * offset_y + offset_x; + const uint8_t* v_plane = src.DataV() + src.StrideV() * offset_y + offset_x; + int res = + libyuv::I444Scale(y_plane, src.StrideY(), u_plane, src.StrideU(), v_plane, + src.StrideV(), crop_width, crop_height, MutableDataY(), + StrideY(), MutableDataU(), StrideU(), MutableDataV(), + StrideV(), width(), height(), libyuv::kFilterBox); + + RTC_DCHECK_EQ(res, 0); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/i444_buffer.h b/third_party/libwebrtc/api/video/i444_buffer.h new file mode 100644 index 0000000000..f1e3f63114 --- /dev/null +++ b/third_party/libwebrtc/api/video/i444_buffer.h @@ -0,0 +1,104 @@ +/* + * 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 API_VIDEO_I444_BUFFER_H_ +#define API_VIDEO_I444_BUFFER_H_ + +#include <stdint.h> + +#include <memory> + +#include "api/scoped_refptr.h" +#include "api/video/video_frame_buffer.h" +#include "api/video/video_rotation.h" +#include "rtc_base/memory/aligned_malloc.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Plain I444 buffer in standard memory. +// I444 represents an image with in YUV format withouth any chroma subsampling. +// https://en.wikipedia.org/wiki/Chroma_subsampling#4:4:4 +class RTC_EXPORT I444Buffer : public I444BufferInterface { + public: + static rtc::scoped_refptr<I444Buffer> Create(int width, int height); + static rtc::scoped_refptr<I444Buffer> Create(int width, + int height, + int stride_y, + int stride_u, + int stride_v); + + // Create a new buffer and copy the pixel data. + static rtc::scoped_refptr<I444Buffer> Copy(const I444BufferInterface& buffer); + + static rtc::scoped_refptr<I444Buffer> Copy(int width, + int height, + const uint8_t* data_y, + int stride_y, + const uint8_t* data_u, + int stride_u, + const uint8_t* data_v, + int stride_v); + + // Returns a rotated copy of |src|. + static rtc::scoped_refptr<I444Buffer> Rotate(const I444BufferInterface& src, + VideoRotation rotation); + + rtc::scoped_refptr<I420BufferInterface> ToI420() final; + const I420BufferInterface* GetI420() const final { return nullptr; } + + // Sets all three planes to all zeros. Used to work around for + // quirks in memory checkers + // (https://bugs.chromium.org/p/libyuv/issues/detail?id=377) and + // ffmpeg (http://crbug.com/390941). + // TODO(https://crbug.com/390941): Deprecated. Should be deleted if/when those + // issues are resolved in a better way. Or in the mean time, use SetBlack. + void InitializeData(); + + int width() const override; + int height() const override; + const uint8_t* DataY() const override; + const uint8_t* DataU() const override; + const uint8_t* DataV() const override; + + int StrideY() const override; + int StrideU() const override; + int StrideV() const override; + + uint8_t* MutableDataY(); + uint8_t* MutableDataU(); + uint8_t* MutableDataV(); + + // Scale the cropped area of |src| to the size of |this| buffer, and + // write the result into |this|. + void CropAndScaleFrom(const I444BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height); + + protected: + I444Buffer(int width, int height); + I444Buffer(int width, int height, int stride_y, int stride_u, int stride_v); + + ~I444Buffer() override; + + private: + const int width_; + const int height_; + const int stride_y_; + const int stride_u_; + const int stride_v_; + const std::unique_ptr<uint8_t, AlignedFreeDeleter> data_; +}; + +} // namespace webrtc + +#endif // API_VIDEO_I444_BUFFER_H_ diff --git a/third_party/libwebrtc/api/video/nv12_buffer.cc b/third_party/libwebrtc/api/video/nv12_buffer.cc new file mode 100644 index 0000000000..ca9dcd8677 --- /dev/null +++ b/third_party/libwebrtc/api/video/nv12_buffer.cc @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2020 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 "api/video/nv12_buffer.h" + +#include "api/make_ref_counted.h" +#include "api/video/i420_buffer.h" +#include "rtc_base/checks.h" +#include "third_party/libyuv/include/libyuv/convert.h" +#include "third_party/libyuv/include/libyuv/scale.h" + +namespace webrtc { + +namespace { + +static const int kBufferAlignment = 64; + +int NV12DataSize(int height, int stride_y, int stride_uv) { + return stride_y * height + stride_uv * ((height + 1) / 2); +} + +} // namespace + +NV12Buffer::NV12Buffer(int width, int height) + : NV12Buffer(width, height, width, width + width % 2) {} + +NV12Buffer::NV12Buffer(int width, int height, int stride_y, int stride_uv) + : width_(width), + height_(height), + stride_y_(stride_y), + stride_uv_(stride_uv), + data_(static_cast<uint8_t*>( + AlignedMalloc(NV12DataSize(height_, stride_y_, stride_uv), + kBufferAlignment))) { + RTC_DCHECK_GT(width, 0); + RTC_DCHECK_GT(height, 0); + RTC_DCHECK_GE(stride_y, width); + RTC_DCHECK_GE(stride_uv, (width + width % 2)); +} + +NV12Buffer::~NV12Buffer() = default; + +// static +rtc::scoped_refptr<NV12Buffer> NV12Buffer::Create(int width, int height) { + return rtc::make_ref_counted<NV12Buffer>(width, height); +} + +// static +rtc::scoped_refptr<NV12Buffer> NV12Buffer::Create(int width, + int height, + int stride_y, + int stride_uv) { + return rtc::make_ref_counted<NV12Buffer>(width, height, stride_y, stride_uv); +} + +// static +rtc::scoped_refptr<NV12Buffer> NV12Buffer::Copy( + const I420BufferInterface& i420_buffer) { + rtc::scoped_refptr<NV12Buffer> buffer = + NV12Buffer::Create(i420_buffer.width(), i420_buffer.height()); + libyuv::I420ToNV12( + i420_buffer.DataY(), i420_buffer.StrideY(), i420_buffer.DataU(), + i420_buffer.StrideU(), i420_buffer.DataV(), i420_buffer.StrideV(), + buffer->MutableDataY(), buffer->StrideY(), buffer->MutableDataUV(), + buffer->StrideUV(), buffer->width(), buffer->height()); + return buffer; +} + +rtc::scoped_refptr<I420BufferInterface> NV12Buffer::ToI420() { + rtc::scoped_refptr<I420Buffer> i420_buffer = + I420Buffer::Create(width(), height()); + libyuv::NV12ToI420(DataY(), StrideY(), DataUV(), StrideUV(), + i420_buffer->MutableDataY(), i420_buffer->StrideY(), + i420_buffer->MutableDataU(), i420_buffer->StrideU(), + i420_buffer->MutableDataV(), i420_buffer->StrideV(), + width(), height()); + return i420_buffer; +} + +int NV12Buffer::width() const { + return width_; +} +int NV12Buffer::height() const { + return height_; +} + +int NV12Buffer::StrideY() const { + return stride_y_; +} +int NV12Buffer::StrideUV() const { + return stride_uv_; +} + +const uint8_t* NV12Buffer::DataY() const { + return data_.get(); +} + +const uint8_t* NV12Buffer::DataUV() const { + return data_.get() + UVOffset(); +} + +uint8_t* NV12Buffer::MutableDataY() { + return data_.get(); +} + +uint8_t* NV12Buffer::MutableDataUV() { + return data_.get() + UVOffset(); +} + +size_t NV12Buffer::UVOffset() const { + return stride_y_ * height_; +} + +void NV12Buffer::InitializeData() { + memset(data_.get(), 0, NV12DataSize(height_, stride_y_, stride_uv_)); +} + +void NV12Buffer::CropAndScaleFrom(const NV12BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height) { + RTC_CHECK_LE(crop_width, src.width()); + RTC_CHECK_LE(crop_height, src.height()); + RTC_CHECK_LE(crop_width + offset_x, src.width()); + RTC_CHECK_LE(crop_height + offset_y, src.height()); + RTC_CHECK_GE(offset_x, 0); + RTC_CHECK_GE(offset_y, 0); + + // Make sure offset is even so that u/v plane becomes aligned. + const int uv_offset_x = offset_x / 2; + const int uv_offset_y = offset_y / 2; + offset_x = uv_offset_x * 2; + offset_y = uv_offset_y * 2; + + const uint8_t* y_plane = src.DataY() + src.StrideY() * offset_y + offset_x; + const uint8_t* uv_plane = + src.DataUV() + src.StrideUV() * uv_offset_y + uv_offset_x * 2; + + int res = libyuv::NV12Scale(y_plane, src.StrideY(), uv_plane, src.StrideUV(), + crop_width, crop_height, MutableDataY(), + StrideY(), MutableDataUV(), StrideUV(), width(), + height(), libyuv::kFilterBox); + + RTC_DCHECK_EQ(res, 0); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/nv12_buffer.h b/third_party/libwebrtc/api/video/nv12_buffer.h new file mode 100644 index 0000000000..46a85f82e1 --- /dev/null +++ b/third_party/libwebrtc/api/video/nv12_buffer.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020 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 API_VIDEO_NV12_BUFFER_H_ +#define API_VIDEO_NV12_BUFFER_H_ + +#include <memory> +#include <utility> + +#include "api/scoped_refptr.h" +#include "api/video/video_frame_buffer.h" +#include "rtc_base/memory/aligned_malloc.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// NV12 is a biplanar encoding format, with full-resolution Y and +// half-resolution interleved UV. More information can be found at +// http://msdn.microsoft.com/library/windows/desktop/dd206750.aspx#nv12. +class RTC_EXPORT NV12Buffer : public NV12BufferInterface { + public: + static rtc::scoped_refptr<NV12Buffer> Create(int width, int height); + static rtc::scoped_refptr<NV12Buffer> Create(int width, + int height, + int stride_y, + int stride_uv); + static rtc::scoped_refptr<NV12Buffer> Copy( + const I420BufferInterface& i420_buffer); + + rtc::scoped_refptr<I420BufferInterface> ToI420() override; + + int width() const override; + int height() const override; + + int StrideY() const override; + int StrideUV() const override; + + const uint8_t* DataY() const override; + const uint8_t* DataUV() const override; + + uint8_t* MutableDataY(); + uint8_t* MutableDataUV(); + + // Sets all three planes to all zeros. Used to work around for + // quirks in memory checkers + // (https://bugs.chromium.org/p/libyuv/issues/detail?id=377) and + // ffmpeg (http://crbug.com/390941). + // TODO(https://crbug.com/390941): Deprecated. Should be deleted if/when those + // issues are resolved in a better way. Or in the mean time, use SetBlack. + void InitializeData(); + + // Scale the cropped area of `src` to the size of `this` buffer, and + // write the result into `this`. + void CropAndScaleFrom(const NV12BufferInterface& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height); + + protected: + NV12Buffer(int width, int height); + NV12Buffer(int width, int height, int stride_y, int stride_uv); + + ~NV12Buffer() override; + + private: + size_t UVOffset() const; + + const int width_; + const int height_; + const int stride_y_; + const int stride_uv_; + const std::unique_ptr<uint8_t, AlignedFreeDeleter> data_; +}; + +} // namespace webrtc + +#endif // API_VIDEO_NV12_BUFFER_H_ diff --git a/third_party/libwebrtc/api/video/recordable_encoded_frame.h b/third_party/libwebrtc/api/video/recordable_encoded_frame.h new file mode 100644 index 0000000000..47ea23f119 --- /dev/null +++ b/third_party/libwebrtc/api/video/recordable_encoded_frame.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019 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 API_VIDEO_RECORDABLE_ENCODED_FRAME_H_ +#define API_VIDEO_RECORDABLE_ENCODED_FRAME_H_ + +#include "api/array_view.h" +#include "api/scoped_refptr.h" +#include "api/units/timestamp.h" +#include "api/video/color_space.h" +#include "api/video/encoded_image.h" +#include "api/video/video_codec_type.h" + +namespace webrtc { + +// Interface for accessing recordable elements of an encoded frame. +class RecordableEncodedFrame { + public: + // Encoded resolution in pixels + // TODO(bugs.webrtc.org/12114) : remove in favor of Resolution. + struct EncodedResolution { + bool empty() const { return width == 0 && height == 0; } + + unsigned width = 0; + unsigned height = 0; + }; + + virtual ~RecordableEncodedFrame() = default; + + // Provides access to encoded data + virtual rtc::scoped_refptr<const EncodedImageBufferInterface> encoded_buffer() + const = 0; + + // Optionally returns the colorspace of the encoded frame. This can differ + // from the eventually decoded frame's colorspace. + virtual absl::optional<webrtc::ColorSpace> color_space() const = 0; + + // Returns the codec of the encoded frame + virtual VideoCodecType codec() const = 0; + + // Returns whether the encoded frame is a key frame + virtual bool is_key_frame() const = 0; + + // Returns the frame's encoded resolution. May be 0x0 if the frame + // doesn't contain resolution information + virtual EncodedResolution resolution() const = 0; + + // Returns the computed render time + virtual Timestamp render_time() const = 0; +}; + +} // namespace webrtc + +#endif // API_VIDEO_RECORDABLE_ENCODED_FRAME_H_ diff --git a/third_party/libwebrtc/api/video/recordable_encoded_frame_gn/moz.build b/third_party/libwebrtc/api/video/recordable_encoded_frame_gn/moz.build new file mode 100644 index 0000000000..af294ef3ca --- /dev/null +++ b/third_party/libwebrtc/api/video/recordable_encoded_frame_gn/moz.build @@ -0,0 +1,209 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("recordable_encoded_frame_gn") diff --git a/third_party/libwebrtc/api/video/render_resolution.h b/third_party/libwebrtc/api/video/render_resolution.h new file mode 100644 index 0000000000..fcf4f122d6 --- /dev/null +++ b/third_party/libwebrtc/api/video/render_resolution.h @@ -0,0 +1,46 @@ +/* + * 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 API_VIDEO_RENDER_RESOLUTION_H_ +#define API_VIDEO_RENDER_RESOLUTION_H_ + +namespace webrtc { + +// TODO(bugs.webrtc.org/12114) : remove in favor of Resolution. +class RenderResolution { + public: + constexpr RenderResolution() = default; + constexpr RenderResolution(int width, int height) + : width_(width), height_(height) {} + RenderResolution(const RenderResolution&) = default; + RenderResolution& operator=(const RenderResolution&) = default; + + friend bool operator==(const RenderResolution& lhs, + const RenderResolution& rhs) { + return lhs.width_ == rhs.width_ && lhs.height_ == rhs.height_; + } + friend bool operator!=(const RenderResolution& lhs, + const RenderResolution& rhs) { + return !(lhs == rhs); + } + + constexpr bool Valid() const { return width_ > 0 && height_ > 0; } + + constexpr int Width() const { return width_; } + constexpr int Height() const { return height_; } + + private: + int width_ = 0; + int height_ = 0; +}; + +} // namespace webrtc + +#endif // API_VIDEO_RENDER_RESOLUTION_H_ diff --git a/third_party/libwebrtc/api/video/render_resolution_gn/moz.build b/third_party/libwebrtc/api/video/render_resolution_gn/moz.build new file mode 100644 index 0000000000..5f97a983f8 --- /dev/null +++ b/third_party/libwebrtc/api/video/render_resolution_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("render_resolution_gn") diff --git a/third_party/libwebrtc/api/video/resolution.h b/third_party/libwebrtc/api/video/resolution.h new file mode 100644 index 0000000000..11ffef0b03 --- /dev/null +++ b/third_party/libwebrtc/api/video/resolution.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_RESOLUTION_H_ +#define API_VIDEO_RESOLUTION_H_ + +#include <utility> + +namespace webrtc { + +// A struct representing a video resolution in pixels. +struct Resolution { + int width = 0; + int height = 0; + + // Helper methods. + int PixelCount() const { return width * height; } + std::pair<int, int> ToPair() const { return std::make_pair(width, height); } +}; + +inline bool operator==(const Resolution& lhs, const Resolution& rhs) { + return lhs.width == rhs.width && lhs.height == rhs.height; +} + +inline bool operator!=(const Resolution& lhs, const Resolution& rhs) { + return !(lhs == rhs); +} + +} // namespace webrtc + +#endif // API_VIDEO_RESOLUTION_H_ diff --git a/third_party/libwebrtc/api/video/resolution_gn/moz.build b/third_party/libwebrtc/api/video/resolution_gn/moz.build new file mode 100644 index 0000000000..deafa478dd --- /dev/null +++ b/third_party/libwebrtc/api/video/resolution_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("resolution_gn") diff --git a/third_party/libwebrtc/api/video/rtp_video_frame_assembler.cc b/third_party/libwebrtc/api/video/rtp_video_frame_assembler.cc new file mode 100644 index 0000000000..b748534f3f --- /dev/null +++ b/third_party/libwebrtc/api/video/rtp_video_frame_assembler.cc @@ -0,0 +1,340 @@ +/* + * 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 "api/video/rtp_video_frame_assembler.h" + +#include <algorithm> +#include <cstdint> +#include <map> +#include <memory> +#include <utility> +#include <vector> + +#include "absl/container/inlined_vector.h" +#include "absl/types/optional.h" +#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h" +#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" +#include "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h" +#include "modules/rtp_rtcp/source/video_rtp_depacketizer_generic.h" +#include "modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h" +#include "modules/rtp_rtcp/source/video_rtp_depacketizer_raw.h" +#include "modules/rtp_rtcp/source/video_rtp_depacketizer_vp8.h" +#include "modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.h" +#include "modules/video_coding/frame_object.h" +#include "modules/video_coding/packet_buffer.h" +#include "modules/video_coding/rtp_frame_reference_finder.h" +#include "rtc_base/logging.h" +#include "rtc_base/numerics/sequence_number_unwrapper.h" + +namespace webrtc { +namespace { +std::unique_ptr<VideoRtpDepacketizer> CreateDepacketizer( + RtpVideoFrameAssembler::PayloadFormat payload_format) { + switch (payload_format) { + case RtpVideoFrameAssembler::kRaw: + return std::make_unique<VideoRtpDepacketizerRaw>(); + case RtpVideoFrameAssembler::kH264: + return std::make_unique<VideoRtpDepacketizerH264>(); + case RtpVideoFrameAssembler::kVp8: + return std::make_unique<VideoRtpDepacketizerVp8>(); + case RtpVideoFrameAssembler::kVp9: + return std::make_unique<VideoRtpDepacketizerVp9>(); + case RtpVideoFrameAssembler::kAv1: + return std::make_unique<VideoRtpDepacketizerAv1>(); + case RtpVideoFrameAssembler::kGeneric: + return std::make_unique<VideoRtpDepacketizerGeneric>(); + } + RTC_DCHECK_NOTREACHED(); + return nullptr; +} +} // namespace + +class RtpVideoFrameAssembler::Impl { + public: + explicit Impl(std::unique_ptr<VideoRtpDepacketizer> depacketizer); + ~Impl() = default; + + FrameVector InsertPacket(const RtpPacketReceived& packet); + + private: + using RtpFrameVector = + absl::InlinedVector<std::unique_ptr<RtpFrameObject>, 3>; + + RtpFrameVector AssembleFrames( + video_coding::PacketBuffer::InsertResult insert_result); + FrameVector FindReferences(RtpFrameVector frames); + FrameVector UpdateWithPadding(uint16_t seq_num); + bool ParseDependenciesDescriptorExtension(const RtpPacketReceived& rtp_packet, + RTPVideoHeader& video_header); + bool ParseGenericDescriptorExtension(const RtpPacketReceived& rtp_packet, + RTPVideoHeader& video_header); + void ClearOldData(uint16_t incoming_seq_num); + + std::unique_ptr<FrameDependencyStructure> video_structure_; + SeqNumUnwrapper<uint16_t> frame_id_unwrapper_; + absl::optional<int64_t> video_structure_frame_id_; + std::unique_ptr<VideoRtpDepacketizer> depacketizer_; + video_coding::PacketBuffer packet_buffer_; + RtpFrameReferenceFinder reference_finder_; +}; + +RtpVideoFrameAssembler::Impl::Impl( + std::unique_ptr<VideoRtpDepacketizer> depacketizer) + : depacketizer_(std::move(depacketizer)), + packet_buffer_(/*start_buffer_size=*/2048, /*max_buffer_size=*/2048) {} + +RtpVideoFrameAssembler::FrameVector RtpVideoFrameAssembler::Impl::InsertPacket( + const RtpPacketReceived& rtp_packet) { + if (rtp_packet.payload_size() == 0) { + ClearOldData(rtp_packet.SequenceNumber()); + return UpdateWithPadding(rtp_packet.SequenceNumber()); + } + + absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed_payload = + depacketizer_->Parse(rtp_packet.PayloadBuffer()); + + if (parsed_payload == absl::nullopt) { + return {}; + } + + if (rtp_packet.HasExtension<RtpDependencyDescriptorExtension>()) { + if (!ParseDependenciesDescriptorExtension(rtp_packet, + parsed_payload->video_header)) { + return {}; + } + } else if (rtp_packet.HasExtension<RtpGenericFrameDescriptorExtension00>()) { + if (!ParseGenericDescriptorExtension(rtp_packet, + parsed_payload->video_header)) { + return {}; + } + } + + parsed_payload->video_header.is_last_packet_in_frame |= rtp_packet.Marker(); + + auto packet = std::make_unique<video_coding::PacketBuffer::Packet>( + rtp_packet, parsed_payload->video_header); + packet->video_payload = std::move(parsed_payload->video_payload); + + ClearOldData(rtp_packet.SequenceNumber()); + return FindReferences( + AssembleFrames(packet_buffer_.InsertPacket(std::move(packet)))); +} + +void RtpVideoFrameAssembler::Impl::ClearOldData(uint16_t incoming_seq_num) { + constexpr uint16_t kOldSeqNumThreshold = 2000; + uint16_t old_seq_num = incoming_seq_num - kOldSeqNumThreshold; + packet_buffer_.ClearTo(old_seq_num); + reference_finder_.ClearTo(old_seq_num); +} + +RtpVideoFrameAssembler::Impl::RtpFrameVector +RtpVideoFrameAssembler::Impl::AssembleFrames( + video_coding::PacketBuffer::InsertResult insert_result) { + video_coding::PacketBuffer::Packet* first_packet = nullptr; + std::vector<rtc::ArrayView<const uint8_t>> payloads; + RtpFrameVector result; + + for (auto& packet : insert_result.packets) { + if (packet->is_first_packet_in_frame()) { + first_packet = packet.get(); + payloads.clear(); + } + payloads.emplace_back(packet->video_payload); + + if (packet->is_last_packet_in_frame()) { + rtc::scoped_refptr<EncodedImageBuffer> bitstream = + depacketizer_->AssembleFrame(payloads); + + if (!bitstream) { + continue; + } + + const video_coding::PacketBuffer::Packet& last_packet = *packet; + result.push_back(std::make_unique<RtpFrameObject>( + first_packet->seq_num, // + last_packet.seq_num, // + last_packet.marker_bit, // + /*times_nacked=*/0, // + /*first_packet_received_time=*/0, // + /*last_packet_received_time=*/0, // + first_packet->timestamp, // + /*ntp_time_ms=*/0, // + /*timing=*/VideoSendTiming(), // + first_packet->payload_type, // + first_packet->codec(), // + last_packet.video_header.rotation, // + last_packet.video_header.content_type, // + first_packet->video_header, // + last_packet.video_header.color_space, // + /*packet_infos=*/RtpPacketInfos(), // + std::move(bitstream))); + } + } + + return result; +} + +RtpVideoFrameAssembler::FrameVector +RtpVideoFrameAssembler::Impl::FindReferences(RtpFrameVector frames) { + FrameVector res; + for (auto& frame : frames) { + auto complete_frames = reference_finder_.ManageFrame(std::move(frame)); + for (std::unique_ptr<RtpFrameObject>& complete_frame : complete_frames) { + uint16_t rtp_seq_num_start = complete_frame->first_seq_num(); + uint16_t rtp_seq_num_end = complete_frame->last_seq_num(); + res.emplace_back(rtp_seq_num_start, rtp_seq_num_end, + std::move(complete_frame)); + } + } + return res; +} + +RtpVideoFrameAssembler::FrameVector +RtpVideoFrameAssembler::Impl::UpdateWithPadding(uint16_t seq_num) { + auto res = + FindReferences(AssembleFrames(packet_buffer_.InsertPadding(seq_num))); + auto ref_finder_update = reference_finder_.PaddingReceived(seq_num); + + for (std::unique_ptr<RtpFrameObject>& complete_frame : ref_finder_update) { + uint16_t rtp_seq_num_start = complete_frame->first_seq_num(); + uint16_t rtp_seq_num_end = complete_frame->last_seq_num(); + res.emplace_back(rtp_seq_num_start, rtp_seq_num_end, + std::move(complete_frame)); + } + + return res; +} + +bool RtpVideoFrameAssembler::Impl::ParseDependenciesDescriptorExtension( + const RtpPacketReceived& rtp_packet, + RTPVideoHeader& video_header) { + webrtc::DependencyDescriptor dependency_descriptor; + + if (!rtp_packet.GetExtension<RtpDependencyDescriptorExtension>( + video_structure_.get(), &dependency_descriptor)) { + // Descriptor is either malformed, or the template referenced is not in + // the `video_structure_` currently being held. + // TODO(bugs.webrtc.org/10342): Improve packet reordering behavior. + RTC_LOG(LS_WARNING) << "ssrc: " << rtp_packet.Ssrc() + << " Failed to parse dependency descriptor."; + return false; + } + + if (dependency_descriptor.attached_structure != nullptr && + !dependency_descriptor.first_packet_in_frame) { + RTC_LOG(LS_WARNING) << "ssrc: " << rtp_packet.Ssrc() + << "Invalid dependency descriptor: structure " + "attached to non first packet of a frame."; + return false; + } + + video_header.is_first_packet_in_frame = + dependency_descriptor.first_packet_in_frame; + video_header.is_last_packet_in_frame = + dependency_descriptor.last_packet_in_frame; + + int64_t frame_id = + frame_id_unwrapper_.Unwrap(dependency_descriptor.frame_number); + auto& generic_descriptor_info = video_header.generic.emplace(); + generic_descriptor_info.frame_id = frame_id; + generic_descriptor_info.spatial_index = + dependency_descriptor.frame_dependencies.spatial_id; + generic_descriptor_info.temporal_index = + dependency_descriptor.frame_dependencies.temporal_id; + + for (int fdiff : dependency_descriptor.frame_dependencies.frame_diffs) { + generic_descriptor_info.dependencies.push_back(frame_id - fdiff); + } + for (int cdiff : dependency_descriptor.frame_dependencies.chain_diffs) { + generic_descriptor_info.chain_diffs.push_back(frame_id - cdiff); + } + generic_descriptor_info.decode_target_indications = + dependency_descriptor.frame_dependencies.decode_target_indications; + if (dependency_descriptor.resolution) { + video_header.width = dependency_descriptor.resolution->Width(); + video_header.height = dependency_descriptor.resolution->Height(); + } + if (dependency_descriptor.active_decode_targets_bitmask.has_value()) { + generic_descriptor_info.active_decode_targets = + *dependency_descriptor.active_decode_targets_bitmask; + } + + // FrameDependencyStructure is sent in the dependency descriptor of the first + // packet of a key frame and is required to parse all subsequent packets until + // the next key frame. + if (dependency_descriptor.attached_structure) { + RTC_DCHECK(dependency_descriptor.first_packet_in_frame); + if (video_structure_frame_id_ > frame_id) { + RTC_LOG(LS_WARNING) + << "Arrived key frame with id " << frame_id << " and structure id " + << dependency_descriptor.attached_structure->structure_id + << " is older than the latest received key frame with id " + << *video_structure_frame_id_ << " and structure id " + << video_structure_->structure_id; + return false; + } + video_structure_ = std::move(dependency_descriptor.attached_structure); + video_structure_frame_id_ = frame_id; + video_header.frame_type = VideoFrameType::kVideoFrameKey; + } else { + video_header.frame_type = VideoFrameType::kVideoFrameDelta; + } + return true; +} + +bool RtpVideoFrameAssembler::Impl::ParseGenericDescriptorExtension( + const RtpPacketReceived& rtp_packet, + RTPVideoHeader& video_header) { + RtpGenericFrameDescriptor generic_frame_descriptor; + if (!rtp_packet.GetExtension<RtpGenericFrameDescriptorExtension00>( + &generic_frame_descriptor)) { + return false; + } + + video_header.is_first_packet_in_frame = + generic_frame_descriptor.FirstPacketInSubFrame(); + video_header.is_last_packet_in_frame = + generic_frame_descriptor.LastPacketInSubFrame(); + + if (generic_frame_descriptor.FirstPacketInSubFrame()) { + video_header.frame_type = + generic_frame_descriptor.FrameDependenciesDiffs().empty() + ? VideoFrameType::kVideoFrameKey + : VideoFrameType::kVideoFrameDelta; + + auto& generic_descriptor_info = video_header.generic.emplace(); + int64_t frame_id = + frame_id_unwrapper_.Unwrap(generic_frame_descriptor.FrameId()); + generic_descriptor_info.frame_id = frame_id; + generic_descriptor_info.spatial_index = + generic_frame_descriptor.SpatialLayer(); + generic_descriptor_info.temporal_index = + generic_frame_descriptor.TemporalLayer(); + for (uint16_t fdiff : generic_frame_descriptor.FrameDependenciesDiffs()) { + generic_descriptor_info.dependencies.push_back(frame_id - fdiff); + } + } + video_header.width = generic_frame_descriptor.Width(); + video_header.height = generic_frame_descriptor.Height(); + return true; +} + +RtpVideoFrameAssembler::RtpVideoFrameAssembler(PayloadFormat payload_format) + : impl_(std::make_unique<Impl>(CreateDepacketizer(payload_format))) {} + +RtpVideoFrameAssembler::~RtpVideoFrameAssembler() = default; + +RtpVideoFrameAssembler::FrameVector RtpVideoFrameAssembler::InsertPacket( + const RtpPacketReceived& packet) { + return impl_->InsertPacket(packet); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/rtp_video_frame_assembler.h b/third_party/libwebrtc/api/video/rtp_video_frame_assembler.h new file mode 100644 index 0000000000..83162cb818 --- /dev/null +++ b/third_party/libwebrtc/api/video/rtp_video_frame_assembler.h @@ -0,0 +1,76 @@ +/* + * 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 API_VIDEO_RTP_VIDEO_FRAME_ASSEMBLER_H_ +#define API_VIDEO_RTP_VIDEO_FRAME_ASSEMBLER_H_ + +#include <cstdint> +#include <memory> +#include <utility> + +#include "absl/container/inlined_vector.h" +#include "api/video/encoded_frame.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" + +namespace webrtc { +// The RtpVideoFrameAssembler takes RtpPacketReceived and assembles them into +// complete frames. A frame is considered complete when all packets of the frame +// has been received, the bitstream data has successfully extracted, an ID has +// been assigned, and all dependencies are known. Frame IDs are strictly +// monotonic in decode order, dependencies are expressed as frame IDs. +class RtpVideoFrameAssembler { + public: + // The RtpVideoFrameAssembler should return "RTP frames", but for now there + // is no good class for this purpose. For now return an EncodedFrame bundled + // with some minimal RTP information. + class AssembledFrame { + public: + AssembledFrame(uint16_t rtp_seq_num_start, + uint16_t rtp_seq_num_end, + std::unique_ptr<EncodedFrame> frame) + : rtp_seq_num_start_(rtp_seq_num_start), + rtp_seq_num_end_(rtp_seq_num_end), + frame_(std::move(frame)) {} + + uint16_t RtpSeqNumStart() const { return rtp_seq_num_start_; } + uint16_t RtpSeqNumEnd() const { return rtp_seq_num_end_; } + std::unique_ptr<EncodedFrame> ExtractFrame() { return std::move(frame_); } + + private: + uint16_t rtp_seq_num_start_; + uint16_t rtp_seq_num_end_; + std::unique_ptr<EncodedFrame> frame_; + }; + + // FrameVector is just a vector-like type of std::unique_ptr<EncodedFrame>. + // The vector type may change without notice. + using FrameVector = absl::InlinedVector<AssembledFrame, 3>; + enum PayloadFormat { kRaw, kH264, kVp8, kVp9, kAv1, kGeneric }; + + explicit RtpVideoFrameAssembler(PayloadFormat payload_format); + RtpVideoFrameAssembler(const RtpVideoFrameAssembler& other) = delete; + RtpVideoFrameAssembler& operator=(const RtpVideoFrameAssembler& other) = + delete; + ~RtpVideoFrameAssembler(); + + // Typically when a packet is inserted zero or one frame is completed. In the + // case of RTP packets being inserted out of order then sometime multiple + // frames could be completed from a single packet, hence the 'FrameVector' + // return type. + FrameVector InsertPacket(const RtpPacketReceived& packet); + + private: + class Impl; + std::unique_ptr<Impl> impl_; +}; + +} // namespace webrtc + +#endif // API_VIDEO_RTP_VIDEO_FRAME_ASSEMBLER_H_ diff --git a/third_party/libwebrtc/api/video/rtp_video_frame_assembler_unittests.cc b/third_party/libwebrtc/api/video/rtp_video_frame_assembler_unittests.cc new file mode 100644 index 0000000000..82defb8399 --- /dev/null +++ b/third_party/libwebrtc/api/video/rtp_video_frame_assembler_unittests.cc @@ -0,0 +1,583 @@ +/* + * 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 <vector> + +#include "api/array_view.h" +#include "api/video/rtp_video_frame_assembler.h" +#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h" +#include "modules/rtp_rtcp/source/rtp_format.h" +#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h" +#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" +#include "modules/rtp_rtcp/source/rtp_packetizer_av1_test_helper.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +using ::testing::ElementsAreArray; +using ::testing::Eq; +using ::testing::IsEmpty; +using ::testing::Matches; +using ::testing::SizeIs; +using ::testing::UnorderedElementsAre; +using ::testing::UnorderedElementsAreArray; +using PayloadFormat = RtpVideoFrameAssembler::PayloadFormat; + +class PacketBuilder { + public: + explicit PacketBuilder(PayloadFormat format) + : format_(format), packet_to_send_(&extension_manager_) {} + + PacketBuilder& WithSeqNum(uint16_t seq_num) { + seq_num_ = seq_num; + return *this; + } + + PacketBuilder& WithPayload(rtc::ArrayView<const uint8_t> payload) { + payload_.assign(payload.begin(), payload.end()); + return *this; + } + + PacketBuilder& WithVideoHeader(const RTPVideoHeader& video_header) { + video_header_ = video_header; + return *this; + } + + template <typename T, typename... Args> + PacketBuilder& WithExtension(int id, const Args&... args) { + extension_manager_.Register<T>(id); + packet_to_send_.IdentifyExtensions(extension_manager_); + packet_to_send_.SetExtension<T>(std::forward<const Args>(args)...); + return *this; + } + + RtpPacketReceived Build() { + auto packetizer = + RtpPacketizer::Create(GetVideoCodecType(), payload_, {}, video_header_); + packetizer->NextPacket(&packet_to_send_); + packet_to_send_.SetSequenceNumber(seq_num_); + + RtpPacketReceived received(&extension_manager_); + received.Parse(packet_to_send_.Buffer()); + return received; + } + + private: + absl::optional<VideoCodecType> GetVideoCodecType() { + switch (format_) { + case PayloadFormat::kRaw: { + return absl::nullopt; + } + case PayloadFormat::kH264: { + return kVideoCodecH264; + } + case PayloadFormat::kVp8: { + return kVideoCodecVP8; + } + case PayloadFormat::kVp9: { + return kVideoCodecVP9; + } + case PayloadFormat::kAv1: { + return kVideoCodecAV1; + } + case PayloadFormat::kGeneric: { + return kVideoCodecGeneric; + } + } + RTC_DCHECK_NOTREACHED(); + return absl::nullopt; + } + + const RtpVideoFrameAssembler::PayloadFormat format_; + uint16_t seq_num_ = 0; + std::vector<uint8_t> payload_; + RTPVideoHeader video_header_; + RtpPacketReceived::ExtensionManager extension_manager_; + RtpPacketToSend packet_to_send_; +}; + +RtpPacketReceived PaddingPacket(uint16_t seq_num) { + RtpPacketReceived padding_packet; + padding_packet.SetSequenceNumber(seq_num); + padding_packet.SetPadding(224); + return padding_packet; +} + +void AppendFrames(RtpVideoFrameAssembler::FrameVector from, + RtpVideoFrameAssembler::FrameVector& to) { + to.insert(to.end(), std::make_move_iterator(from.begin()), + std::make_move_iterator(from.end())); +} + +rtc::ArrayView<int64_t> References(const std::unique_ptr<EncodedFrame>& frame) { + return rtc::MakeArrayView(frame->references, frame->num_references); +} + +rtc::ArrayView<uint8_t> Payload(const std::unique_ptr<EncodedFrame>& frame) { + return rtc::ArrayView<uint8_t>(*frame->GetEncodedData()); +} + +TEST(RtpVideoFrameAssembler, Vp8Packetization) { + RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kVp8); + + // When sending VP8 over RTP parts of the payload is actually inspected at the + // RTP level. It just so happen that the initial 'V' sets the keyframe bit + // (0x01) to the correct value. + uint8_t kKeyframePayload[] = "Vp8Keyframe"; + ASSERT_EQ(kKeyframePayload[0] & 0x01, 0); + + uint8_t kDeltaframePayload[] = "SomeFrame"; + ASSERT_EQ(kDeltaframePayload[0] & 0x01, 1); + + RtpVideoFrameAssembler::FrameVector frames; + + RTPVideoHeader video_header; + auto& vp8_header = + video_header.video_type_header.emplace<RTPVideoHeaderVP8>(); + + vp8_header.pictureId = 10; + vp8_header.tl0PicIdx = 0; + AppendFrames(assembler.InsertPacket(PacketBuilder(PayloadFormat::kVp8) + .WithPayload(kKeyframePayload) + .WithVideoHeader(video_header) + .Build()), + frames); + + vp8_header.pictureId = 11; + vp8_header.tl0PicIdx = 1; + AppendFrames(assembler.InsertPacket(PacketBuilder(PayloadFormat::kVp8) + .WithPayload(kDeltaframePayload) + .WithVideoHeader(video_header) + .Build()), + frames); + + ASSERT_THAT(frames, SizeIs(2)); + + auto first_frame = frames[0].ExtractFrame(); + EXPECT_THAT(first_frame->Id(), Eq(10)); + EXPECT_THAT(References(first_frame), IsEmpty()); + EXPECT_THAT(Payload(first_frame), ElementsAreArray(kKeyframePayload)); + + auto second_frame = frames[1].ExtractFrame(); + EXPECT_THAT(second_frame->Id(), Eq(11)); + EXPECT_THAT(References(second_frame), UnorderedElementsAre(10)); + EXPECT_THAT(Payload(second_frame), ElementsAreArray(kDeltaframePayload)); +} + +TEST(RtpVideoFrameAssembler, Vp9Packetization) { + RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kVp9); + RtpVideoFrameAssembler::FrameVector frames; + + uint8_t kPayload[] = "SomePayload"; + + RTPVideoHeader video_header; + auto& vp9_header = + video_header.video_type_header.emplace<RTPVideoHeaderVP9>(); + vp9_header.InitRTPVideoHeaderVP9(); + + vp9_header.picture_id = 10; + vp9_header.tl0_pic_idx = 0; + AppendFrames(assembler.InsertPacket(PacketBuilder(PayloadFormat::kVp9) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .Build()), + frames); + + vp9_header.picture_id = 11; + vp9_header.tl0_pic_idx = 1; + vp9_header.inter_pic_predicted = true; + AppendFrames(assembler.InsertPacket(PacketBuilder(PayloadFormat::kVp9) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .Build()), + frames); + + ASSERT_THAT(frames, SizeIs(2)); + + auto first_frame = frames[0].ExtractFrame(); + EXPECT_THAT(first_frame->Id(), Eq(10)); + EXPECT_THAT(Payload(first_frame), ElementsAreArray(kPayload)); + EXPECT_THAT(References(first_frame), IsEmpty()); + + auto second_frame = frames[1].ExtractFrame(); + EXPECT_THAT(second_frame->Id(), Eq(11)); + EXPECT_THAT(Payload(second_frame), ElementsAreArray(kPayload)); + EXPECT_THAT(References(second_frame), UnorderedElementsAre(10)); +} + +TEST(RtpVideoFrameAssembler, Av1Packetization) { + RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kAv1); + RtpVideoFrameAssembler::FrameVector frames; + + auto kKeyframePayload = + BuildAv1Frame({Av1Obu(kAv1ObuTypeSequenceHeader).WithPayload({1, 2, 3}), + Av1Obu(kAv1ObuTypeFrame).WithPayload({4, 5, 6})}); + + auto kDeltaframePayload = + BuildAv1Frame({Av1Obu(kAv1ObuTypeFrame).WithPayload({7, 8, 9})}); + + RTPVideoHeader video_header; + + video_header.frame_type = VideoFrameType::kVideoFrameKey; + AppendFrames(assembler.InsertPacket(PacketBuilder(PayloadFormat::kAv1) + .WithPayload(kKeyframePayload) + .WithVideoHeader(video_header) + .WithSeqNum(20) + .Build()), + frames); + + AppendFrames(assembler.InsertPacket(PacketBuilder(PayloadFormat::kAv1) + .WithPayload(kDeltaframePayload) + .WithSeqNum(21) + .Build()), + frames); + + ASSERT_THAT(frames, SizeIs(2)); + + auto first_frame = frames[0].ExtractFrame(); + EXPECT_THAT(first_frame->Id(), Eq(20)); + EXPECT_THAT(Payload(first_frame), ElementsAreArray(kKeyframePayload)); + EXPECT_THAT(References(first_frame), IsEmpty()); + + auto second_frame = frames[1].ExtractFrame(); + EXPECT_THAT(second_frame->Id(), Eq(21)); + EXPECT_THAT(Payload(second_frame), ElementsAreArray(kDeltaframePayload)); + EXPECT_THAT(References(second_frame), UnorderedElementsAre(20)); +} + +TEST(RtpVideoFrameAssembler, RawPacketizationDependencyDescriptorExtension) { + RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kRaw); + RtpVideoFrameAssembler::FrameVector frames; + uint8_t kPayload[] = "SomePayload"; + + FrameDependencyStructure dependency_structure; + dependency_structure.num_decode_targets = 1; + dependency_structure.num_chains = 1; + dependency_structure.decode_target_protected_by_chain.push_back(0); + dependency_structure.templates.push_back( + FrameDependencyTemplate().S(0).T(0).Dtis("S").ChainDiffs({0})); + dependency_structure.templates.push_back( + FrameDependencyTemplate().S(0).T(0).Dtis("S").ChainDiffs({10}).FrameDiffs( + {10})); + + DependencyDescriptor dependency_descriptor; + + dependency_descriptor.frame_number = 10; + dependency_descriptor.frame_dependencies = dependency_structure.templates[0]; + dependency_descriptor.attached_structure = + std::make_unique<FrameDependencyStructure>(dependency_structure); + AppendFrames(assembler.InsertPacket( + PacketBuilder(PayloadFormat::kRaw) + .WithPayload(kPayload) + .WithExtension<RtpDependencyDescriptorExtension>( + 1, dependency_structure, dependency_descriptor) + .Build()), + frames); + + dependency_descriptor.frame_number = 20; + dependency_descriptor.frame_dependencies = dependency_structure.templates[1]; + dependency_descriptor.attached_structure.reset(); + AppendFrames(assembler.InsertPacket( + PacketBuilder(PayloadFormat::kRaw) + .WithPayload(kPayload) + .WithExtension<RtpDependencyDescriptorExtension>( + 1, dependency_structure, dependency_descriptor) + .Build()), + frames); + + ASSERT_THAT(frames, SizeIs(2)); + + auto first_frame = frames[0].ExtractFrame(); + EXPECT_THAT(first_frame->Id(), Eq(10)); + EXPECT_THAT(Payload(first_frame), ElementsAreArray(kPayload)); + EXPECT_THAT(References(first_frame), IsEmpty()); + + auto second_frame = frames[1].ExtractFrame(); + EXPECT_THAT(second_frame->Id(), Eq(20)); + EXPECT_THAT(Payload(second_frame), ElementsAreArray(kPayload)); + EXPECT_THAT(References(second_frame), UnorderedElementsAre(10)); +} + +TEST(RtpVideoFrameAssembler, RawPacketizationGenericDescriptor00Extension) { + RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kRaw); + RtpVideoFrameAssembler::FrameVector frames; + uint8_t kPayload[] = "SomePayload"; + + RtpGenericFrameDescriptor generic; + + generic.SetFirstPacketInSubFrame(true); + generic.SetLastPacketInSubFrame(true); + generic.SetFrameId(100); + AppendFrames( + assembler.InsertPacket( + PacketBuilder(PayloadFormat::kRaw) + .WithPayload(kPayload) + .WithExtension<RtpGenericFrameDescriptorExtension00>(1, generic) + .Build()), + frames); + + generic.SetFrameId(102); + generic.AddFrameDependencyDiff(2); + AppendFrames( + assembler.InsertPacket( + PacketBuilder(PayloadFormat::kRaw) + .WithPayload(kPayload) + .WithExtension<RtpGenericFrameDescriptorExtension00>(1, generic) + .Build()), + frames); + + ASSERT_THAT(frames, SizeIs(2)); + + auto first_frame = frames[0].ExtractFrame(); + EXPECT_THAT(first_frame->Id(), Eq(100)); + EXPECT_THAT(Payload(first_frame), ElementsAreArray(kPayload)); + EXPECT_THAT(References(first_frame), IsEmpty()); + + auto second_frame = frames[1].ExtractFrame(); + EXPECT_THAT(second_frame->Id(), Eq(102)); + EXPECT_THAT(Payload(second_frame), ElementsAreArray(kPayload)); + EXPECT_THAT(References(second_frame), UnorderedElementsAre(100)); +} + +TEST(RtpVideoFrameAssembler, RawPacketizationGenericPayloadDescriptor) { + RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kGeneric); + RtpVideoFrameAssembler::FrameVector frames; + uint8_t kPayload[] = "SomePayload"; + + RTPVideoHeader video_header; + + video_header.frame_type = VideoFrameType::kVideoFrameKey; + AppendFrames(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(123) + .Build()), + frames); + + video_header.frame_type = VideoFrameType::kVideoFrameDelta; + AppendFrames(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(124) + .Build()), + frames); + + ASSERT_THAT(frames, SizeIs(2)); + + auto first_frame = frames[0].ExtractFrame(); + EXPECT_THAT(first_frame->Id(), Eq(123)); + EXPECT_THAT(Payload(first_frame), ElementsAreArray(kPayload)); + EXPECT_THAT(References(first_frame), IsEmpty()); + + auto second_frame = frames[1].ExtractFrame(); + EXPECT_THAT(second_frame->Id(), Eq(124)); + EXPECT_THAT(Payload(second_frame), ElementsAreArray(kPayload)); + EXPECT_THAT(References(second_frame), UnorderedElementsAre(123)); +} + +TEST(RtpVideoFrameAssembler, Padding) { + RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kGeneric); + RtpVideoFrameAssembler::FrameVector frames; + uint8_t kPayload[] = "SomePayload"; + + RTPVideoHeader video_header; + + video_header.frame_type = VideoFrameType::kVideoFrameKey; + AppendFrames(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(123) + .Build()), + frames); + + video_header.frame_type = VideoFrameType::kVideoFrameDelta; + AppendFrames(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(125) + .Build()), + frames); + + ASSERT_THAT(frames, SizeIs(1)); + auto first_frame = frames[0].ExtractFrame(); + EXPECT_THAT(first_frame->Id(), Eq(123)); + EXPECT_THAT(Payload(first_frame), ElementsAreArray(kPayload)); + EXPECT_THAT(References(first_frame), IsEmpty()); + + AppendFrames(assembler.InsertPacket(PaddingPacket(/*seq_num=*/124)), frames); + + ASSERT_THAT(frames, SizeIs(2)); + auto second_frame = frames[1].ExtractFrame(); + EXPECT_THAT(second_frame->Id(), Eq(125)); + EXPECT_THAT(Payload(second_frame), ElementsAreArray(kPayload)); + EXPECT_THAT(References(second_frame), UnorderedElementsAre(123)); +} + +TEST(RtpVideoFrameAssembler, ClearOldPackets) { + RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kGeneric); + + // If we don't have a payload the packet will be counted as a padding packet. + uint8_t kPayload[] = "DontCare"; + + RTPVideoHeader video_header; + video_header.frame_type = VideoFrameType::kVideoFrameKey; + EXPECT_THAT(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(0) + .Build()), + SizeIs(1)); + + EXPECT_THAT(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(2000) + .Build()), + SizeIs(1)); + + EXPECT_THAT(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(0) + .Build()), + SizeIs(0)); + + EXPECT_THAT(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(1) + .Build()), + SizeIs(1)); +} + +TEST(RtpVideoFrameAssembler, ClearOldPacketsWithPadding) { + RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kGeneric); + uint8_t kPayload[] = "DontCare"; + + RTPVideoHeader video_header; + video_header.frame_type = VideoFrameType::kVideoFrameKey; + EXPECT_THAT(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(0) + .Build()), + SizeIs(1)); + + EXPECT_THAT(assembler.InsertPacket(PaddingPacket(/*seq_num=*/2000)), + SizeIs(0)); + + EXPECT_THAT(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(0) + .Build()), + SizeIs(0)); + + EXPECT_THAT(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(1) + .Build()), + SizeIs(1)); +} + +TEST(RtpVideoFrameAssembler, SeqNumStartAndSeqNumEndSet) { + RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kGeneric); + RtpVideoFrameAssembler::FrameVector frames; + uint8_t kPayload[] = + "Some payload that will get split into two when packetized."; + + RTPVideoHeader video_header; + video_header.frame_type = VideoFrameType::kVideoFrameKey; + RtpPacketizer::PayloadSizeLimits limits; + limits.max_payload_len = sizeof(kPayload) - 1; + + auto packetizer = + RtpPacketizer::Create(kVideoCodecGeneric, kPayload, limits, video_header); + ASSERT_THAT(packetizer->NumPackets(), Eq(2U)); + + RtpPacketReceived::ExtensionManager extension_manager; + { + RtpPacketToSend send_packet(&extension_manager); + packetizer->NextPacket(&send_packet); + send_packet.SetSequenceNumber(123); + RtpPacketReceived received_packet(&extension_manager); + received_packet.Parse(send_packet.Buffer()); + assembler.InsertPacket(received_packet); + } + + { + RtpPacketToSend send_packet(&extension_manager); + packetizer->NextPacket(&send_packet); + send_packet.SetSequenceNumber(124); + RtpPacketReceived received_packet(&extension_manager); + received_packet.Parse(send_packet.Buffer()); + AppendFrames(assembler.InsertPacket(received_packet), frames); + } + + ASSERT_THAT(frames, SizeIs(1)); + EXPECT_THAT(frames[0].RtpSeqNumStart(), Eq(123)); + EXPECT_THAT(frames[0].RtpSeqNumEnd(), Eq(124)); +} + +TEST(RtpVideoFrameAssembler, SeqNumStartAndSeqNumEndSetWhenPaddingReceived) { + RtpVideoFrameAssembler assembler(RtpVideoFrameAssembler::kGeneric); + RtpVideoFrameAssembler::FrameVector frames; + uint8_t kPayload[] = + "Some payload that will get split into two when packetized."; + + RTPVideoHeader video_header; + video_header.frame_type = VideoFrameType::kVideoFrameKey; + + EXPECT_THAT(assembler.InsertPacket(PacketBuilder(PayloadFormat::kGeneric) + .WithPayload(kPayload) + .WithVideoHeader(video_header) + .WithSeqNum(121) + .Build()), + SizeIs(1)); + + video_header.frame_type = VideoFrameType::kVideoFrameDelta; + RtpPacketReceived::ExtensionManager extension_manager; + RtpPacketizer::PayloadSizeLimits limits; + limits.max_payload_len = sizeof(kPayload) - 1; + + auto packetizer = + RtpPacketizer::Create(kVideoCodecGeneric, kPayload, limits, video_header); + ASSERT_THAT(packetizer->NumPackets(), Eq(2U)); + + { + RtpPacketToSend send_packet(&extension_manager); + packetizer->NextPacket(&send_packet); + send_packet.SetSequenceNumber(123); + RtpPacketReceived received_packet(&extension_manager); + received_packet.Parse(send_packet.Buffer()); + assembler.InsertPacket(received_packet); + } + + { + RtpPacketToSend send_packet(&extension_manager); + packetizer->NextPacket(&send_packet); + send_packet.SetSequenceNumber(124); + RtpPacketReceived received_packet(&extension_manager); + received_packet.Parse(send_packet.Buffer()); + assembler.InsertPacket(received_packet); + } + + AppendFrames(assembler.InsertPacket(PaddingPacket(/*seq_num=*/122)), frames); + + ASSERT_THAT(frames, SizeIs(1)); + EXPECT_THAT(frames[0].RtpSeqNumStart(), Eq(123)); + EXPECT_THAT(frames[0].RtpSeqNumEnd(), Eq(124)); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/test/BUILD.gn b/third_party/libwebrtc/api/video/test/BUILD.gn new file mode 100644 index 0000000000..60ec4b852f --- /dev/null +++ b/third_party/libwebrtc/api/video/test/BUILD.gn @@ -0,0 +1,56 @@ +# 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. + +import("../../../webrtc.gni") + +rtc_library("rtc_api_video_unittests") { + testonly = true + sources = [ + "color_space_unittest.cc", + "i210_buffer_unittest.cc", + "i410_buffer_unittest.cc", + "i422_buffer_unittest.cc", + "i444_buffer_unittest.cc", + "nv12_buffer_unittest.cc", + "video_adaptation_counters_unittest.cc", + "video_bitrate_allocation_unittest.cc", + ] + deps = [ + "..:video_adaptation", + "..:video_bitrate_allocation", + "..:video_frame", + "..:video_frame_i010", + "..:video_rtp_headers", + "../../../test:frame_utils", + "../../../test:test_support", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_source_set("mock_recordable_encoded_frame") { + testonly = true + visibility = [ "*" ] + sources = [ "mock_recordable_encoded_frame.h" ] + + deps = [ + "..:recordable_encoded_frame", + "../../../test:test_support", + ] +} + +rtc_source_set("video_frame_matchers") { + testonly = true + visibility = [ "*" ] + sources = [ "video_frame_matchers.h" ] + + deps = [ + "..:video_frame", + "../..:rtp_packet_info", + "../../../test:test_support", + ] +} diff --git a/third_party/libwebrtc/api/video/test/color_space_unittest.cc b/third_party/libwebrtc/api/video/test/color_space_unittest.cc new file mode 100644 index 0000000000..1d8b3a87f6 --- /dev/null +++ b/third_party/libwebrtc/api/video/test/color_space_unittest.cc @@ -0,0 +1,74 @@ +/* + * 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 "api/video/color_space.h" + +#include <stdint.h> + +#include "test/gtest.h" + +namespace webrtc { +TEST(ColorSpace, TestSettingPrimariesFromUint8) { + ColorSpace color_space; + EXPECT_TRUE(color_space.set_primaries_from_uint8( + static_cast<uint8_t>(ColorSpace::PrimaryID::kBT470BG))); + EXPECT_EQ(ColorSpace::PrimaryID::kBT470BG, color_space.primaries()); + EXPECT_FALSE(color_space.set_primaries_from_uint8(3)); + EXPECT_FALSE(color_space.set_primaries_from_uint8(23)); + EXPECT_FALSE(color_space.set_primaries_from_uint8(64)); +} + +TEST(ColorSpace, TestSettingTransferFromUint8) { + ColorSpace color_space; + EXPECT_TRUE(color_space.set_transfer_from_uint8( + static_cast<uint8_t>(ColorSpace::TransferID::kBT2020_10))); + EXPECT_EQ(ColorSpace::TransferID::kBT2020_10, color_space.transfer()); + EXPECT_FALSE(color_space.set_transfer_from_uint8(3)); + EXPECT_FALSE(color_space.set_transfer_from_uint8(19)); + EXPECT_FALSE(color_space.set_transfer_from_uint8(128)); +} + +TEST(ColorSpace, TestSettingMatrixFromUint8) { + ColorSpace color_space; + EXPECT_TRUE(color_space.set_matrix_from_uint8( + static_cast<uint8_t>(ColorSpace::MatrixID::kCDNCLS))); + EXPECT_EQ(ColorSpace::MatrixID::kCDNCLS, color_space.matrix()); + EXPECT_FALSE(color_space.set_matrix_from_uint8(3)); + EXPECT_FALSE(color_space.set_matrix_from_uint8(15)); + EXPECT_FALSE(color_space.set_matrix_from_uint8(255)); +} + +TEST(ColorSpace, TestSettingRangeFromUint8) { + ColorSpace color_space; + EXPECT_TRUE(color_space.set_range_from_uint8( + static_cast<uint8_t>(ColorSpace::RangeID::kFull))); + EXPECT_EQ(ColorSpace::RangeID::kFull, color_space.range()); + EXPECT_FALSE(color_space.set_range_from_uint8(4)); +} + +TEST(ColorSpace, TestSettingChromaSitingHorizontalFromUint8) { + ColorSpace color_space; + EXPECT_TRUE(color_space.set_chroma_siting_horizontal_from_uint8( + static_cast<uint8_t>(ColorSpace::ChromaSiting::kCollocated))); + EXPECT_EQ(ColorSpace::ChromaSiting::kCollocated, + color_space.chroma_siting_horizontal()); + EXPECT_FALSE(color_space.set_chroma_siting_horizontal_from_uint8(3)); +} + +TEST(ColorSpace, TestSettingChromaSitingVerticalFromUint8) { + ColorSpace color_space; + EXPECT_TRUE(color_space.set_chroma_siting_vertical_from_uint8( + static_cast<uint8_t>(ColorSpace::ChromaSiting::kHalf))); + EXPECT_EQ(ColorSpace::ChromaSiting::kHalf, + color_space.chroma_siting_vertical()); + EXPECT_FALSE(color_space.set_chroma_siting_vertical_from_uint8(3)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/test/i210_buffer_unittest.cc b/third_party/libwebrtc/api/video/test/i210_buffer_unittest.cc new file mode 100644 index 0000000000..aaa231b6d2 --- /dev/null +++ b/third_party/libwebrtc/api/video/test/i210_buffer_unittest.cc @@ -0,0 +1,126 @@ + +/* + * Copyright (c) 2022 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 "api/video/i210_buffer.h" + +#include "api/video/i420_buffer.h" +#include "test/frame_utils.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { + +namespace { + +int GetY(rtc::scoped_refptr<I210BufferInterface> buf, int col, int row) { + return buf->DataY()[row * buf->StrideY() + col]; +} + +int GetU(rtc::scoped_refptr<I210BufferInterface> buf, int col, int row) { + return buf->DataU()[row * buf->StrideU() + col]; +} + +int GetV(rtc::scoped_refptr<I210BufferInterface> buf, int col, int row) { + return buf->DataV()[row * buf->StrideV() + col]; +} + +void FillI210Buffer(rtc::scoped_refptr<I210Buffer> buf) { + const uint16_t Y = 4; + const uint16_t U = 8; + const uint16_t V = 16; + for (int row = 0; row < buf->height(); ++row) { + for (int col = 0; col < buf->width(); ++col) { + buf->MutableDataY()[row * buf->StrideY() + col] = Y; + } + } + for (int row = 0; row < buf->ChromaHeight(); ++row) { + for (int col = 0; col < buf->ChromaWidth(); ++col) { + buf->MutableDataU()[row * buf->StrideU() + col] = U; + buf->MutableDataV()[row * buf->StrideV() + col] = V; + } + } +} + +} // namespace + +TEST(I210BufferTest, InitialData) { + constexpr int stride = 3; + constexpr int halfstride = (stride + 1) >> 1; + constexpr int width = 3; + constexpr int halfwidth = (width + 1) >> 1; + constexpr int height = 3; + + rtc::scoped_refptr<I210Buffer> i210_buffer(I210Buffer::Create(width, height)); + EXPECT_EQ(width, i210_buffer->width()); + EXPECT_EQ(height, i210_buffer->height()); + EXPECT_EQ(stride, i210_buffer->StrideY()); + EXPECT_EQ(halfstride, i210_buffer->StrideU()); + EXPECT_EQ(halfstride, i210_buffer->StrideV()); + EXPECT_EQ(halfwidth, i210_buffer->ChromaWidth()); + EXPECT_EQ(height, i210_buffer->ChromaHeight()); +} + +TEST(I210BufferTest, ReadPixels) { + constexpr int width = 3; + constexpr int halfwidth = (width + 1) >> 1; + constexpr int height = 3; + + rtc::scoped_refptr<I210Buffer> i210_buffer(I210Buffer::Create(width, height)); + // Y = 4, U = 8, V = 16. + FillI210Buffer(i210_buffer); + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + EXPECT_EQ(4, GetY(i210_buffer, col, row)); + } + } + for (int row = 0; row < height; row++) { + for (int col = 0; col < halfwidth; col++) { + EXPECT_EQ(8, GetU(i210_buffer, col, row)); + EXPECT_EQ(16, GetV(i210_buffer, col, row)); + } + } +} + +TEST(I210BufferTest, ToI420) { + constexpr int width = 3; + constexpr int halfwidth = (width + 1) >> 1; + constexpr int height = 3; + constexpr int size = width * height; + constexpr int quartersize = (width + 1) / 2 * (height + 1) / 2; + rtc::scoped_refptr<I420Buffer> reference(I420Buffer::Create(width, height)); + memset(reference->MutableDataY(), 1, size); + memset(reference->MutableDataU(), 2, quartersize); + memset(reference->MutableDataV(), 4, quartersize); + + rtc::scoped_refptr<I210Buffer> i210_buffer(I210Buffer::Create(width, height)); + // Y = 4, U = 8, V = 16. + FillI210Buffer(i210_buffer); + + // Confirm YUV values are as expected. + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + EXPECT_EQ(4, GetY(i210_buffer, col, row)); + } + } + for (int row = 0; row < height; row++) { + for (int col = 0; col < halfwidth; col++) { + EXPECT_EQ(8, GetU(i210_buffer, col, row)); + EXPECT_EQ(16, GetV(i210_buffer, col, row)); + } + } + + rtc::scoped_refptr<I420BufferInterface> i420_buffer(i210_buffer->ToI420()); + EXPECT_TRUE(test::FrameBufsEqual(reference, i420_buffer)); + EXPECT_EQ(height, i420_buffer->height()); + EXPECT_EQ(width, i420_buffer->width()); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/test/i410_buffer_unittest.cc b/third_party/libwebrtc/api/video/test/i410_buffer_unittest.cc new file mode 100644 index 0000000000..c5d2d5bf2d --- /dev/null +++ b/third_party/libwebrtc/api/video/test/i410_buffer_unittest.cc @@ -0,0 +1,120 @@ + +/* + * Copyright (c) 2023 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 "api/video/i410_buffer.h" + +#include "api/video/i420_buffer.h" +#include "test/frame_utils.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { + +namespace { +constexpr uint16_t kYValue = 4; +constexpr uint16_t kUValue = 8; +constexpr uint16_t kVValue = 16; + +int GetY(rtc::scoped_refptr<I410BufferInterface> buf, int col, int row) { + return buf->DataY()[row * buf->StrideY() + col]; +} + +int GetU(rtc::scoped_refptr<I410BufferInterface> buf, int col, int row) { + return buf->DataU()[row * buf->StrideU() + col]; +} + +int GetV(rtc::scoped_refptr<I410BufferInterface> buf, int col, int row) { + return buf->DataV()[row * buf->StrideV() + col]; +} + +void FillI410Buffer(rtc::scoped_refptr<I410Buffer> buf) { + for (int row = 0; row < buf->height(); ++row) { + for (int col = 0; col < buf->width(); ++col) { + buf->MutableDataY()[row * buf->StrideY() + col] = kYValue; + buf->MutableDataU()[row * buf->StrideU() + col] = kUValue; + buf->MutableDataV()[row * buf->StrideV() + col] = kVValue; + } + } +} + +} // namespace + +TEST(I410BufferTest, InitialData) { + constexpr int stride = 3; + constexpr int width = 3; + constexpr int height = 3; + + rtc::scoped_refptr<I410Buffer> i410_buffer(I410Buffer::Create(width, height)); + EXPECT_EQ(width, i410_buffer->width()); + EXPECT_EQ(height, i410_buffer->height()); + EXPECT_EQ(stride, i410_buffer->StrideY()); + EXPECT_EQ(stride, i410_buffer->StrideU()); + EXPECT_EQ(stride, i410_buffer->StrideV()); + EXPECT_EQ(3, i410_buffer->ChromaWidth()); + EXPECT_EQ(3, i410_buffer->ChromaHeight()); +} + +TEST(I410BufferTest, ReadPixels) { + constexpr int width = 3; + constexpr int height = 3; + + rtc::scoped_refptr<I410Buffer> i410_buffer(I410Buffer::Create(width, height)); + FillI410Buffer(i410_buffer); + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + EXPECT_EQ(kYValue, GetY(i410_buffer, col, row)); + EXPECT_EQ(kUValue, GetU(i410_buffer, col, row)); + EXPECT_EQ(kVValue, GetV(i410_buffer, col, row)); + } + } +} + +TEST(I410BufferTest, ToI420) { + // libyuv I410ToI420 only handles correctly even sizes and skips last row/col + // if odd. + constexpr int width = 4; + constexpr int height = 4; + constexpr int size_y = width * height; + constexpr int size_u = (width + 1) / 2 * (height + 1) / 2; + constexpr int size_v = (width + 1) / 2 * (height + 1) / 2; + rtc::scoped_refptr<I420Buffer> reference(I420Buffer::Create(width, height)); + // I410 is 10-bit while I420 is 8 bit, so last 2 bits would be discarded. + memset(reference->MutableDataY(), kYValue >> 2, size_y); + memset(reference->MutableDataU(), kUValue >> 2, size_u); + memset(reference->MutableDataV(), kVValue >> 2, size_v); + + rtc::scoped_refptr<I410Buffer> i410_buffer(I410Buffer::Create(width, height)); + FillI410Buffer(i410_buffer); + + // Confirm YUV values are as expected. + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + EXPECT_EQ(kYValue, GetY(i410_buffer, col, row)); + EXPECT_EQ(kUValue, GetU(i410_buffer, col, row)); + EXPECT_EQ(kVValue, GetV(i410_buffer, col, row)); + } + } + + rtc::scoped_refptr<I420BufferInterface> i420_buffer(i410_buffer->ToI420()); + + // Confirm YUV values are as expected. + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + EXPECT_EQ(1, i420_buffer->DataY()[row * i420_buffer->StrideY() + col]); + } + } + + EXPECT_EQ(height, i420_buffer->height()); + EXPECT_EQ(width, i420_buffer->width()); + EXPECT_TRUE(test::FrameBufsEqual(reference, i420_buffer)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/test/i422_buffer_unittest.cc b/third_party/libwebrtc/api/video/test/i422_buffer_unittest.cc new file mode 100644 index 0000000000..499b268546 --- /dev/null +++ b/third_party/libwebrtc/api/video/test/i422_buffer_unittest.cc @@ -0,0 +1,128 @@ + +/* + * Copyright (c) 2022 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 "api/video/i422_buffer.h" + +#include "api/video/i420_buffer.h" +#include "test/frame_utils.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { + +namespace { +int GetY(rtc::scoped_refptr<I422BufferInterface> buf, int col, int row) { + return buf->DataY()[row * buf->StrideY() + col]; +} + +int GetU(rtc::scoped_refptr<I422BufferInterface> buf, int col, int row) { + return buf->DataU()[row * buf->StrideU() + col]; +} + +int GetV(rtc::scoped_refptr<I422BufferInterface> buf, int col, int row) { + return buf->DataV()[row * buf->StrideV() + col]; +} + +void FillI422Buffer(rtc::scoped_refptr<I422Buffer> buf) { + const uint8_t Y = 1; + const uint8_t U = 2; + const uint8_t V = 3; + for (int row = 0; row < buf->height(); ++row) { + for (int col = 0; col < buf->width(); ++col) { + buf->MutableDataY()[row * buf->StrideY() + col] = Y; + } + } + for (int row = 0; row < buf->ChromaHeight(); ++row) { + for (int col = 0; col < buf->ChromaWidth(); ++col) { + buf->MutableDataU()[row * buf->StrideU() + col] = U; + buf->MutableDataV()[row * buf->StrideV() + col] = V; + } + } +} + +} // namespace + +TEST(I422BufferTest, InitialData) { + constexpr int stride = 3; + constexpr int halfstride = (stride + 1) >> 1; + constexpr int width = 3; + constexpr int halfwidth = (width + 1) >> 1; + constexpr int height = 3; + + rtc::scoped_refptr<I422Buffer> i422_buffer(I422Buffer::Create(width, height)); + EXPECT_EQ(width, i422_buffer->width()); + EXPECT_EQ(height, i422_buffer->height()); + EXPECT_EQ(stride, i422_buffer->StrideY()); + EXPECT_EQ(halfstride, i422_buffer->StrideU()); + EXPECT_EQ(halfstride, i422_buffer->StrideV()); + EXPECT_EQ(halfwidth, i422_buffer->ChromaWidth()); + EXPECT_EQ(height, i422_buffer->ChromaHeight()); +} + +TEST(I422BufferTest, ReadPixels) { + constexpr int width = 3; + constexpr int halfwidth = (width + 1) >> 1; + constexpr int height = 3; + + rtc::scoped_refptr<I422Buffer> i422_buffer(I422Buffer::Create(width, height)); + // Y = 1, U = 2, V = 3. + FillI422Buffer(i422_buffer); + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + EXPECT_EQ(1, GetY(i422_buffer, col, row)); + } + } + for (int row = 0; row < height; row++) { + for (int col = 0; col < halfwidth; col++) { + EXPECT_EQ(2, GetU(i422_buffer, col, row)); + EXPECT_EQ(3, GetV(i422_buffer, col, row)); + } + } +} + +TEST(I422BufferTest, ToI420) { + constexpr int width = 3; + constexpr int halfwidth = (width + 1) >> 1; + constexpr int height = 3; + constexpr int size = width * height; + constexpr int halfsize = (width + 1) / 2 * height; + constexpr int quartersize = (width + 1) / 2 * (height + 1) / 2; + rtc::scoped_refptr<I420Buffer> reference(I420Buffer::Create(width, height)); + memset(reference->MutableDataY(), 8, size); + memset(reference->MutableDataU(), 4, quartersize); + memset(reference->MutableDataV(), 2, quartersize); + + rtc::scoped_refptr<I422Buffer> i422_buffer(I422Buffer::Create(width, height)); + // Convert the reference buffer to I422. + memset(i422_buffer->MutableDataY(), 8, size); + memset(i422_buffer->MutableDataU(), 4, halfsize); + memset(i422_buffer->MutableDataV(), 2, halfsize); + + // Confirm YUV values are as expected. + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + EXPECT_EQ(8, GetY(i422_buffer, col, row)); + } + } + for (int row = 0; row < height; row++) { + for (int col = 0; col < halfwidth; col++) { + EXPECT_EQ(4, GetU(i422_buffer, col, row)); + EXPECT_EQ(2, GetV(i422_buffer, col, row)); + } + } + + rtc::scoped_refptr<I420BufferInterface> i420_buffer(i422_buffer->ToI420()); + EXPECT_EQ(height, i420_buffer->height()); + EXPECT_EQ(width, i420_buffer->width()); + EXPECT_TRUE(test::FrameBufsEqual(reference, i420_buffer)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/test/i444_buffer_unittest.cc b/third_party/libwebrtc/api/video/test/i444_buffer_unittest.cc new file mode 100644 index 0000000000..9a1a9315aa --- /dev/null +++ b/third_party/libwebrtc/api/video/test/i444_buffer_unittest.cc @@ -0,0 +1,112 @@ + +/* + * 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 "api/video/i444_buffer.h" + +#include "api/video/i420_buffer.h" +#include "test/frame_utils.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { + +namespace { +int GetY(rtc::scoped_refptr<I444BufferInterface> buf, int col, int row) { + return buf->DataY()[row * buf->StrideY() + col]; +} + +int GetU(rtc::scoped_refptr<I444BufferInterface> buf, int col, int row) { + return buf->DataU()[row * buf->StrideU() + col]; +} + +int GetV(rtc::scoped_refptr<I444BufferInterface> buf, int col, int row) { + return buf->DataV()[row * buf->StrideV() + col]; +} + +void FillI444Buffer(rtc::scoped_refptr<I444Buffer> buf) { + const uint8_t Y = 1; + const uint8_t U = 2; + const uint8_t V = 3; + for (int row = 0; row < buf->height(); ++row) { + for (int col = 0; col < buf->width(); ++col) { + buf->MutableDataY()[row * buf->StrideY() + col] = Y; + buf->MutableDataU()[row * buf->StrideU() + col] = U; + buf->MutableDataV()[row * buf->StrideV() + col] = V; + } + } +} + +} // namespace + +TEST(I444BufferTest, InitialData) { + constexpr int stride = 3; + constexpr int width = 3; + constexpr int height = 3; + + rtc::scoped_refptr<I444Buffer> i444_buffer(I444Buffer::Create(width, height)); + EXPECT_EQ(width, i444_buffer->width()); + EXPECT_EQ(height, i444_buffer->height()); + EXPECT_EQ(stride, i444_buffer->StrideY()); + EXPECT_EQ(stride, i444_buffer->StrideU()); + EXPECT_EQ(stride, i444_buffer->StrideV()); + EXPECT_EQ(3, i444_buffer->ChromaWidth()); + EXPECT_EQ(3, i444_buffer->ChromaHeight()); +} + +TEST(I444BufferTest, ReadPixels) { + constexpr int width = 3; + constexpr int height = 3; + + rtc::scoped_refptr<I444Buffer> i444_buffer(I444Buffer::Create(width, height)); + // Y = 1, U = 2, V = 3. + FillI444Buffer(i444_buffer); + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + EXPECT_EQ(1, GetY(i444_buffer, col, row)); + EXPECT_EQ(2, GetU(i444_buffer, col, row)); + EXPECT_EQ(3, GetV(i444_buffer, col, row)); + } + } +} + +TEST(I444BufferTest, ToI420) { + constexpr int width = 3; + constexpr int height = 3; + constexpr int size_y = width * height; + constexpr int size_u = (width + 1) / 2 * (height + 1) / 2; + constexpr int size_v = (width + 1) / 2 * (height + 1) / 2; + rtc::scoped_refptr<I420Buffer> reference(I420Buffer::Create(width, height)); + memset(reference->MutableDataY(), 8, size_y); + memset(reference->MutableDataU(), 4, size_u); + memset(reference->MutableDataV(), 2, size_v); + + rtc::scoped_refptr<I444Buffer> i444_buffer(I444Buffer::Create(width, height)); + // Convert the reference buffer to I444. + memset(i444_buffer->MutableDataY(), 8, size_y); + memset(i444_buffer->MutableDataU(), 4, size_y); + memset(i444_buffer->MutableDataV(), 2, size_y); + + // Confirm YUV values are as expected. + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + EXPECT_EQ(8, GetY(i444_buffer, col, row)); + EXPECT_EQ(4, GetU(i444_buffer, col, row)); + EXPECT_EQ(2, GetV(i444_buffer, col, row)); + } + } + + rtc::scoped_refptr<I420BufferInterface> i420_buffer(i444_buffer->ToI420()); + EXPECT_EQ(height, i420_buffer->height()); + EXPECT_EQ(width, i420_buffer->width()); + EXPECT_TRUE(test::FrameBufsEqual(reference, i420_buffer)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/test/mock_recordable_encoded_frame.h b/third_party/libwebrtc/api/video/test/mock_recordable_encoded_frame.h new file mode 100644 index 0000000000..2178932d2a --- /dev/null +++ b/third_party/libwebrtc/api/video/test/mock_recordable_encoded_frame.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 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 API_VIDEO_TEST_MOCK_RECORDABLE_ENCODED_FRAME_H_ +#define API_VIDEO_TEST_MOCK_RECORDABLE_ENCODED_FRAME_H_ + +#include "api/video/recordable_encoded_frame.h" +#include "test/gmock.h" + +namespace webrtc { +class MockRecordableEncodedFrame : public RecordableEncodedFrame { + public: + MOCK_METHOD(rtc::scoped_refptr<const EncodedImageBufferInterface>, + encoded_buffer, + (), + (const, override)); + MOCK_METHOD(absl::optional<webrtc::ColorSpace>, + color_space, + (), + (const, override)); + MOCK_METHOD(VideoCodecType, codec, (), (const, override)); + MOCK_METHOD(bool, is_key_frame, (), (const, override)); + MOCK_METHOD(EncodedResolution, resolution, (), (const, override)); + MOCK_METHOD(Timestamp, render_time, (), (const, override)); +}; +} // namespace webrtc +#endif // API_VIDEO_TEST_MOCK_RECORDABLE_ENCODED_FRAME_H_ diff --git a/third_party/libwebrtc/api/video/test/nv12_buffer_unittest.cc b/third_party/libwebrtc/api/video/test/nv12_buffer_unittest.cc new file mode 100644 index 0000000000..d84adb5bf5 --- /dev/null +++ b/third_party/libwebrtc/api/video/test/nv12_buffer_unittest.cc @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2020 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 "api/video/nv12_buffer.h" + +#include "api/video/i420_buffer.h" +#include "test/frame_utils.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { + +namespace { +int GetY(rtc::scoped_refptr<NV12BufferInterface> buf, int col, int row) { + return buf->DataY()[row * buf->StrideY() + col]; +} + +int GetU(rtc::scoped_refptr<NV12BufferInterface> buf, int col, int row) { + return buf->DataUV()[(row / 2) * buf->StrideUV() + (col / 2) * 2]; +} + +int GetV(rtc::scoped_refptr<NV12BufferInterface> buf, int col, int row) { + return buf->DataUV()[(row / 2) * buf->StrideUV() + (col / 2) * 2 + 1]; +} + +void FillNV12Buffer(rtc::scoped_refptr<NV12Buffer> buf) { + const uint8_t Y = 1; + const uint8_t U = 2; + const uint8_t V = 3; + for (int row = 0; row < buf->height(); ++row) { + for (int col = 0; col < buf->width(); ++col) { + buf->MutableDataY()[row * buf->StrideY() + col] = Y; + } + } + // Fill interleaving UV values. + for (int row = 0; row < buf->ChromaHeight(); row++) { + for (int col = 0; col < buf->StrideUV(); col += 2) { + int uv_index = row * buf->StrideUV() + col; + buf->MutableDataUV()[uv_index] = U; + buf->MutableDataUV()[uv_index + 1] = V; + } + } +} + +} // namespace + +TEST(NV12BufferTest, InitialData) { + constexpr int stride_y = 3; + constexpr int stride_uv = 4; + constexpr int width = 3; + constexpr int height = 3; + + rtc::scoped_refptr<NV12Buffer> nv12_buffer(NV12Buffer::Create(width, height)); + EXPECT_EQ(width, nv12_buffer->width()); + EXPECT_EQ(height, nv12_buffer->height()); + EXPECT_EQ(stride_y, nv12_buffer->StrideY()); + EXPECT_EQ(stride_uv, nv12_buffer->StrideUV()); + EXPECT_EQ(2, nv12_buffer->ChromaWidth()); + EXPECT_EQ(2, nv12_buffer->ChromaHeight()); +} + +TEST(NV12BufferTest, ReadPixels) { + constexpr int width = 3; + constexpr int height = 3; + + rtc::scoped_refptr<NV12Buffer> nv12_buffer(NV12Buffer::Create(width, height)); + // Y = 1, U = 2, V = 3. + FillNV12Buffer(nv12_buffer); + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + EXPECT_EQ(1, GetY(nv12_buffer, col, row)); + EXPECT_EQ(2, GetU(nv12_buffer, col, row)); + EXPECT_EQ(3, GetV(nv12_buffer, col, row)); + } + } +} + +TEST(NV12BufferTest, ToI420) { + constexpr int width = 3; + constexpr int height = 3; + constexpr int size_y = width * height; + constexpr int size_u = (width + 1) / 2 * (height + 1) / 2; + constexpr int size_v = (width + 1) / 2 * (height + 1) / 2; + rtc::scoped_refptr<I420Buffer> reference(I420Buffer::Create(width, height)); + memset(reference->MutableDataY(), 8, size_y); + memset(reference->MutableDataU(), 4, size_u); + memset(reference->MutableDataV(), 2, size_v); + + rtc::scoped_refptr<NV12Buffer> nv12_buffer(NV12Buffer::Create(width, height)); + // Convert the reference buffer to NV12. + memset(nv12_buffer->MutableDataY(), 8, size_y); + // Interleaving u/v values. + for (int i = 0; i < size_u + size_v; i += 2) { + nv12_buffer->MutableDataUV()[i] = 4; + nv12_buffer->MutableDataUV()[i + 1] = 2; + } + // Confirm YUV values are as expected. + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + EXPECT_EQ(8, GetY(nv12_buffer, col, row)); + EXPECT_EQ(4, GetU(nv12_buffer, col, row)); + EXPECT_EQ(2, GetV(nv12_buffer, col, row)); + } + } + + rtc::scoped_refptr<I420BufferInterface> i420_buffer(nv12_buffer->ToI420()); + EXPECT_EQ(height, i420_buffer->height()); + EXPECT_EQ(width, i420_buffer->width()); + EXPECT_TRUE(test::FrameBufsEqual(reference, i420_buffer)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/test/video_adaptation_counters_unittest.cc b/third_party/libwebrtc/api/video/test/video_adaptation_counters_unittest.cc new file mode 100644 index 0000000000..a7d0bda7d2 --- /dev/null +++ b/third_party/libwebrtc/api/video/test/video_adaptation_counters_unittest.cc @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 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 "api/video/video_adaptation_counters.h" + +#include "test/gtest.h" + +namespace webrtc { + +TEST(AdaptationCountersTest, Addition) { + VideoAdaptationCounters a{0, 0}; + VideoAdaptationCounters b{1, 2}; + VideoAdaptationCounters total = a + b; + EXPECT_EQ(1, total.resolution_adaptations); + EXPECT_EQ(2, total.fps_adaptations); +} + +TEST(AdaptationCountersTest, Equality) { + VideoAdaptationCounters a{1, 2}; + VideoAdaptationCounters b{2, 1}; + EXPECT_EQ(a, a); + EXPECT_NE(a, b); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/test/video_bitrate_allocation_unittest.cc b/third_party/libwebrtc/api/video/test/video_bitrate_allocation_unittest.cc new file mode 100644 index 0000000000..8e66d4b0a1 --- /dev/null +++ b/third_party/libwebrtc/api/video/test/video_bitrate_allocation_unittest.cc @@ -0,0 +1,64 @@ +/* + * 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 "api/video/video_bitrate_allocation.h" + +#include <vector> + +#include "absl/types/optional.h" +#include "test/gtest.h" + +namespace webrtc { +TEST(VideoBitrateAllocation, SimulcastTargetBitrate) { + VideoBitrateAllocation bitrate; + bitrate.SetBitrate(0, 0, 10000); + bitrate.SetBitrate(0, 1, 20000); + bitrate.SetBitrate(1, 0, 40000); + bitrate.SetBitrate(1, 1, 80000); + + VideoBitrateAllocation layer0_bitrate; + layer0_bitrate.SetBitrate(0, 0, 10000); + layer0_bitrate.SetBitrate(0, 1, 20000); + + VideoBitrateAllocation layer1_bitrate; + layer1_bitrate.SetBitrate(0, 0, 40000); + layer1_bitrate.SetBitrate(0, 1, 80000); + + std::vector<absl::optional<VideoBitrateAllocation>> layer_allocations = + bitrate.GetSimulcastAllocations(); + + EXPECT_EQ(layer0_bitrate, layer_allocations[0]); + EXPECT_EQ(layer1_bitrate, layer_allocations[1]); +} + +TEST(VideoBitrateAllocation, SimulcastTargetBitrateWithInactiveStream) { + // Create bitrate allocation with bitrate only for the first and third stream. + VideoBitrateAllocation bitrate; + bitrate.SetBitrate(0, 0, 10000); + bitrate.SetBitrate(0, 1, 20000); + bitrate.SetBitrate(2, 0, 40000); + bitrate.SetBitrate(2, 1, 80000); + + VideoBitrateAllocation layer0_bitrate; + layer0_bitrate.SetBitrate(0, 0, 10000); + layer0_bitrate.SetBitrate(0, 1, 20000); + + VideoBitrateAllocation layer2_bitrate; + layer2_bitrate.SetBitrate(0, 0, 40000); + layer2_bitrate.SetBitrate(0, 1, 80000); + + std::vector<absl::optional<VideoBitrateAllocation>> layer_allocations = + bitrate.GetSimulcastAllocations(); + + EXPECT_EQ(layer0_bitrate, layer_allocations[0]); + EXPECT_FALSE(layer_allocations[1]); + EXPECT_EQ(layer2_bitrate, layer_allocations[2]); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/test/video_frame_matchers.h b/third_party/libwebrtc/api/video/test/video_frame_matchers.h new file mode 100644 index 0000000000..250459377b --- /dev/null +++ b/third_party/libwebrtc/api/video/test/video_frame_matchers.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_TEST_VIDEO_FRAME_MATCHERS_H_ +#define API_VIDEO_TEST_VIDEO_FRAME_MATCHERS_H_ + +#include "api/rtp_packet_infos.h" +#include "api/video/video_frame.h" +#include "test/gmock.h" + +namespace webrtc::test::video_frame_matchers { + +MATCHER_P(Rotation, rotation, "") { + return ::testing::Matches(::testing::Eq(rotation))(arg.rotation()); +} + +MATCHER_P(NtpTimestamp, ntp_ts, "") { + return arg.ntp_time_ms() == ntp_ts.ms(); +} + +MATCHER_P(PacketInfos, m, "") { + return ::testing::Matches(m)(arg.packet_infos()); +} + +} // namespace webrtc::test::video_frame_matchers + +#endif // API_VIDEO_TEST_VIDEO_FRAME_MATCHERS_H_ diff --git a/third_party/libwebrtc/api/video/video_adaptation_counters.cc b/third_party/libwebrtc/api/video/video_adaptation_counters.cc new file mode 100644 index 0000000000..df1769d5d4 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_adaptation_counters.cc @@ -0,0 +1,42 @@ +/* + * Copyright 2020 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 "api/video/video_adaptation_counters.h" + +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +bool VideoAdaptationCounters::operator==( + const VideoAdaptationCounters& rhs) const { + return fps_adaptations == rhs.fps_adaptations && + resolution_adaptations == rhs.resolution_adaptations; +} + +bool VideoAdaptationCounters::operator!=( + const VideoAdaptationCounters& rhs) const { + return !(rhs == *this); +} + +VideoAdaptationCounters VideoAdaptationCounters::operator+( + const VideoAdaptationCounters& other) const { + return VideoAdaptationCounters( + resolution_adaptations + other.resolution_adaptations, + fps_adaptations + other.fps_adaptations); +} + +std::string VideoAdaptationCounters::ToString() const { + rtc::StringBuilder ss; + ss << "{ res=" << resolution_adaptations << " fps=" << fps_adaptations + << " }"; + return ss.Release(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/video_adaptation_counters.h b/third_party/libwebrtc/api/video/video_adaptation_counters.h new file mode 100644 index 0000000000..2dea902f2f --- /dev/null +++ b/third_party/libwebrtc/api/video/video_adaptation_counters.h @@ -0,0 +1,46 @@ +/* + * Copyright 2020 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 API_VIDEO_VIDEO_ADAPTATION_COUNTERS_H_ +#define API_VIDEO_VIDEO_ADAPTATION_COUNTERS_H_ + +#include <string> + +#include "rtc_base/checks.h" + +namespace webrtc { + +// Counts the number of adaptations have resulted due to resource overuse. +// Today we can adapt resolution and fps. +struct VideoAdaptationCounters { + VideoAdaptationCounters() : resolution_adaptations(0), fps_adaptations(0) {} + VideoAdaptationCounters(int resolution_adaptations, int fps_adaptations) + : resolution_adaptations(resolution_adaptations), + fps_adaptations(fps_adaptations) { + RTC_DCHECK_GE(resolution_adaptations, 0); + RTC_DCHECK_GE(fps_adaptations, 0); + } + + int Total() const { return fps_adaptations + resolution_adaptations; } + + bool operator==(const VideoAdaptationCounters& rhs) const; + bool operator!=(const VideoAdaptationCounters& rhs) const; + + VideoAdaptationCounters operator+(const VideoAdaptationCounters& other) const; + + std::string ToString() const; + + int resolution_adaptations; + int fps_adaptations; +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_ADAPTATION_COUNTERS_H_ diff --git a/third_party/libwebrtc/api/video/video_adaptation_gn/moz.build b/third_party/libwebrtc/api/video/video_adaptation_gn/moz.build new file mode 100644 index 0000000000..3b4495f26c --- /dev/null +++ b/third_party/libwebrtc/api/video/video_adaptation_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video/video_adaptation_counters.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_adaptation_gn") diff --git a/third_party/libwebrtc/api/video/video_adaptation_reason.h b/third_party/libwebrtc/api/video/video_adaptation_reason.h new file mode 100644 index 0000000000..3b7fc36eed --- /dev/null +++ b/third_party/libwebrtc/api/video/video_adaptation_reason.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020 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 API_VIDEO_VIDEO_ADAPTATION_REASON_H_ +#define API_VIDEO_VIDEO_ADAPTATION_REASON_H_ + +namespace webrtc { + +enum class VideoAdaptationReason { kQuality, kCpu }; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_ADAPTATION_REASON_H_ diff --git a/third_party/libwebrtc/api/video/video_bitrate_allocation.cc b/third_party/libwebrtc/api/video/video_bitrate_allocation.cc new file mode 100644 index 0000000000..e189db1c19 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_bitrate_allocation.cc @@ -0,0 +1,185 @@ +/* + * 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 "api/video/video_bitrate_allocation.h" + +#include <cstdint> + +#include "rtc_base/checks.h" +#include "rtc_base/numerics/safe_conversions.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +VideoBitrateAllocation::VideoBitrateAllocation() + : sum_(0), is_bw_limited_(false) {} + +bool VideoBitrateAllocation::SetBitrate(size_t spatial_index, + size_t temporal_index, + uint32_t bitrate_bps) { + RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); + RTC_CHECK_LT(temporal_index, kMaxTemporalStreams); + int64_t new_bitrate_sum_bps = sum_; + absl::optional<uint32_t>& layer_bitrate = + bitrates_[spatial_index][temporal_index]; + if (layer_bitrate) { + RTC_DCHECK_LE(*layer_bitrate, sum_); + new_bitrate_sum_bps -= *layer_bitrate; + } + new_bitrate_sum_bps += bitrate_bps; + if (new_bitrate_sum_bps > kMaxBitrateBps) + return false; + + layer_bitrate = bitrate_bps; + sum_ = rtc::dchecked_cast<uint32_t>(new_bitrate_sum_bps); + return true; +} + +bool VideoBitrateAllocation::HasBitrate(size_t spatial_index, + size_t temporal_index) const { + RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); + RTC_CHECK_LT(temporal_index, kMaxTemporalStreams); + return bitrates_[spatial_index][temporal_index].has_value(); +} + +uint32_t VideoBitrateAllocation::GetBitrate(size_t spatial_index, + size_t temporal_index) const { + RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); + RTC_CHECK_LT(temporal_index, kMaxTemporalStreams); + return bitrates_[spatial_index][temporal_index].value_or(0); +} + +// Whether the specific spatial layers has the bitrate set in any of its +// temporal layers. +bool VideoBitrateAllocation::IsSpatialLayerUsed(size_t spatial_index) const { + RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); + for (size_t i = 0; i < kMaxTemporalStreams; ++i) { + if (bitrates_[spatial_index][i].has_value()) + return true; + } + return false; +} + +// Get the sum of all the temporal layer for a specific spatial layer. +uint32_t VideoBitrateAllocation::GetSpatialLayerSum( + size_t spatial_index) const { + RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); + return GetTemporalLayerSum(spatial_index, kMaxTemporalStreams - 1); +} + +uint32_t VideoBitrateAllocation::GetTemporalLayerSum( + size_t spatial_index, + size_t temporal_index) const { + RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); + RTC_CHECK_LT(temporal_index, kMaxTemporalStreams); + uint32_t sum = 0; + for (size_t i = 0; i <= temporal_index; ++i) { + sum += bitrates_[spatial_index][i].value_or(0); + } + return sum; +} + +std::vector<uint32_t> VideoBitrateAllocation::GetTemporalLayerAllocation( + size_t spatial_index) const { + RTC_CHECK_LT(spatial_index, kMaxSpatialLayers); + std::vector<uint32_t> temporal_rates; + + // Find the highest temporal layer with a defined bitrate in order to + // determine the size of the temporal layer allocation. + for (size_t i = kMaxTemporalStreams; i > 0; --i) { + if (bitrates_[spatial_index][i - 1].has_value()) { + temporal_rates.resize(i); + break; + } + } + + for (size_t i = 0; i < temporal_rates.size(); ++i) { + temporal_rates[i] = bitrates_[spatial_index][i].value_or(0); + } + + return temporal_rates; +} + +std::vector<absl::optional<VideoBitrateAllocation>> +VideoBitrateAllocation::GetSimulcastAllocations() const { + std::vector<absl::optional<VideoBitrateAllocation>> bitrates; + for (size_t si = 0; si < kMaxSpatialLayers; ++si) { + absl::optional<VideoBitrateAllocation> layer_bitrate; + if (IsSpatialLayerUsed(si)) { + layer_bitrate = VideoBitrateAllocation(); + for (int tl = 0; tl < kMaxTemporalStreams; ++tl) { + if (HasBitrate(si, tl)) + layer_bitrate->SetBitrate(0, tl, GetBitrate(si, tl)); + } + } + bitrates.push_back(layer_bitrate); + } + return bitrates; +} + +bool VideoBitrateAllocation::operator==( + const VideoBitrateAllocation& other) const { + for (size_t si = 0; si < kMaxSpatialLayers; ++si) { + for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) { + if (bitrates_[si][ti] != other.bitrates_[si][ti]) + return false; + } + } + return true; +} + +std::string VideoBitrateAllocation::ToString() const { + if (sum_ == 0) + return "VideoBitrateAllocation [ [] ]"; + + // Max string length in practice is 260, but let's have some overhead and + // round up to nearest power of two. + char string_buf[512]; + rtc::SimpleStringBuilder ssb(string_buf); + + ssb << "VideoBitrateAllocation ["; + uint32_t spatial_cumulator = 0; + for (size_t si = 0; si < kMaxSpatialLayers; ++si) { + RTC_DCHECK_LE(spatial_cumulator, sum_); + if (spatial_cumulator == sum_) + break; + + const uint32_t layer_sum = GetSpatialLayerSum(si); + if (layer_sum == sum_ && si == 0) { + ssb << " ["; + } else { + if (si > 0) + ssb << ","; + ssb << '\n' << " ["; + } + spatial_cumulator += layer_sum; + + uint32_t temporal_cumulator = 0; + for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) { + RTC_DCHECK_LE(temporal_cumulator, layer_sum); + if (temporal_cumulator == layer_sum) + break; + + if (ti > 0) + ssb << ", "; + + uint32_t bitrate = bitrates_[si][ti].value_or(0); + ssb << bitrate; + temporal_cumulator += bitrate; + } + ssb << "]"; + } + + RTC_DCHECK_EQ(spatial_cumulator, sum_); + ssb << " ]"; + return ssb.str(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/video_bitrate_allocation.h b/third_party/libwebrtc/api/video/video_bitrate_allocation.h new file mode 100644 index 0000000000..4feffa2e66 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_bitrate_allocation.h @@ -0,0 +1,96 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_BITRATE_ALLOCATION_H_ +#define API_VIDEO_VIDEO_BITRATE_ALLOCATION_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <limits> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/video/video_codec_constants.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Class that describes how video bitrate, in bps, is allocated across temporal +// and spatial layers. Not that bitrates are NOT cumulative. Depending on if +// layers are dependent or not, it is up to the user to aggregate. +// For each index, the bitrate can also both set and unset. This is used with a +// set bps = 0 to signal an explicit "turn off" signal. +class RTC_EXPORT VideoBitrateAllocation { + public: + static constexpr uint32_t kMaxBitrateBps = + std::numeric_limits<uint32_t>::max(); + VideoBitrateAllocation(); + + bool SetBitrate(size_t spatial_index, + size_t temporal_index, + uint32_t bitrate_bps); + + bool HasBitrate(size_t spatial_index, size_t temporal_index) const; + + uint32_t GetBitrate(size_t spatial_index, size_t temporal_index) const; + + // Whether the specific spatial layers has the bitrate set in any of its + // temporal layers. + bool IsSpatialLayerUsed(size_t spatial_index) const; + + // Get the sum of all the temporal layer for a specific spatial layer. + uint32_t GetSpatialLayerSum(size_t spatial_index) const; + + // Sum of bitrates of temporal layers, from layer 0 to `temporal_index` + // inclusive, of specified spatial layer `spatial_index`. Bitrates of lower + // spatial layers are not included. + uint32_t GetTemporalLayerSum(size_t spatial_index, + size_t temporal_index) const; + + // Returns a vector of the temporal layer bitrates for the specific spatial + // layer. Length of the returned vector is cropped to the highest temporal + // layer with a defined bitrate. + std::vector<uint32_t> GetTemporalLayerAllocation(size_t spatial_index) const; + + // Returns one VideoBitrateAllocation for each spatial layer. This is used to + // configure simulcast streams. Note that the length of the returned vector is + // always kMaxSpatialLayers, the optional is unset for unused layers. + std::vector<absl::optional<VideoBitrateAllocation>> GetSimulcastAllocations() + const; + + uint32_t get_sum_bps() const { return sum_; } // Sum of all bitrates. + uint32_t get_sum_kbps() const { + // Round down to not exceed the allocated bitrate. + return sum_ / 1000; + } + + bool operator==(const VideoBitrateAllocation& other) const; + inline bool operator!=(const VideoBitrateAllocation& other) const { + return !(*this == other); + } + + std::string ToString() const; + + // Indicates if the allocation has some layers/streams disabled due to + // low available bandwidth. + void set_bw_limited(bool limited) { is_bw_limited_ = limited; } + bool is_bw_limited() const { return is_bw_limited_; } + + private: + uint32_t sum_; + absl::optional<uint32_t> bitrates_[kMaxSpatialLayers][kMaxTemporalStreams]; + bool is_bw_limited_; +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_BITRATE_ALLOCATION_H_ diff --git a/third_party/libwebrtc/api/video/video_bitrate_allocation_gn/moz.build b/third_party/libwebrtc/api/video/video_bitrate_allocation_gn/moz.build new file mode 100644 index 0000000000..2c7b1f39e7 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_bitrate_allocation_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video/video_bitrate_allocation.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_bitrate_allocation_gn") diff --git a/third_party/libwebrtc/api/video/video_bitrate_allocator.cc b/third_party/libwebrtc/api/video/video_bitrate_allocator.cc new file mode 100644 index 0000000000..f4e843b348 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_bitrate_allocator.cc @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019 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 "api/video/video_bitrate_allocator.h" + +namespace webrtc { + +VideoBitrateAllocationParameters::VideoBitrateAllocationParameters( + uint32_t total_bitrate_bps, + uint32_t framerate) + : total_bitrate(DataRate::BitsPerSec(total_bitrate_bps)), + stable_bitrate(DataRate::BitsPerSec(total_bitrate_bps)), + framerate(static_cast<double>(framerate)) {} + +VideoBitrateAllocationParameters::VideoBitrateAllocationParameters( + DataRate total_bitrate, + double framerate) + : total_bitrate(total_bitrate), + stable_bitrate(total_bitrate), + framerate(framerate) {} + +VideoBitrateAllocationParameters::VideoBitrateAllocationParameters( + DataRate total_bitrate, + DataRate stable_bitrate, + double framerate) + : total_bitrate(total_bitrate), + stable_bitrate(stable_bitrate), + framerate(framerate) {} + +VideoBitrateAllocationParameters::~VideoBitrateAllocationParameters() = default; + +VideoBitrateAllocation VideoBitrateAllocator::GetAllocation( + uint32_t total_bitrate_bps, + uint32_t framerate) { + return Allocate({DataRate::BitsPerSec(total_bitrate_bps), + DataRate::BitsPerSec(total_bitrate_bps), + static_cast<double>(framerate)}); +} + +VideoBitrateAllocation VideoBitrateAllocator::Allocate( + VideoBitrateAllocationParameters parameters) { + return GetAllocation(parameters.total_bitrate.bps(), parameters.framerate); +} + +void VideoBitrateAllocator::SetLegacyConferenceMode(bool enabled) {} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/video_bitrate_allocator.h b/third_party/libwebrtc/api/video/video_bitrate_allocator.h new file mode 100644 index 0000000000..fdc86dbc57 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_bitrate_allocator.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_BITRATE_ALLOCATOR_H_ +#define API_VIDEO_VIDEO_BITRATE_ALLOCATOR_H_ + +#include "api/units/data_rate.h" +#include "api/video/video_bitrate_allocation.h" + +namespace webrtc { + +struct VideoBitrateAllocationParameters { + VideoBitrateAllocationParameters(uint32_t total_bitrate_bps, + uint32_t framerate); + VideoBitrateAllocationParameters(DataRate total_bitrate, double framerate); + VideoBitrateAllocationParameters(DataRate total_bitrate, + DataRate stable_bitrate, + double framerate); + ~VideoBitrateAllocationParameters(); + + DataRate total_bitrate; + DataRate stable_bitrate; + double framerate; +}; + +class VideoBitrateAllocator { + public: + VideoBitrateAllocator() {} + virtual ~VideoBitrateAllocator() {} + + virtual VideoBitrateAllocation GetAllocation(uint32_t total_bitrate_bps, + uint32_t framerate); + + virtual VideoBitrateAllocation Allocate( + VideoBitrateAllocationParameters parameters); + + // Deprecated: Only used to work around issues with the legacy conference + // screenshare mode and shouldn't be needed by any subclasses. + virtual void SetLegacyConferenceMode(bool enabled); +}; + +class VideoBitrateAllocationObserver { + public: + VideoBitrateAllocationObserver() {} + virtual ~VideoBitrateAllocationObserver() {} + + virtual void OnBitrateAllocationUpdated( + const VideoBitrateAllocation& allocation) = 0; +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_BITRATE_ALLOCATOR_H_ diff --git a/third_party/libwebrtc/api/video/video_bitrate_allocator_factory.h b/third_party/libwebrtc/api/video/video_bitrate_allocator_factory.h new file mode 100644 index 0000000000..cb34ebb5e1 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_bitrate_allocator_factory.h @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_ +#define API_VIDEO_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_ + +#include <memory> + +#include "api/video/video_bitrate_allocator.h" +#include "api/video_codecs/video_codec.h" + +namespace webrtc { + +// A factory that creates VideoBitrateAllocator. +// NOTE: This class is still under development and may change without notice. +class VideoBitrateAllocatorFactory { + public: + virtual ~VideoBitrateAllocatorFactory() = default; + // Creates a VideoBitrateAllocator for a specific video codec. + virtual std::unique_ptr<VideoBitrateAllocator> CreateVideoBitrateAllocator( + const VideoCodec& codec) = 0; +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_ diff --git a/third_party/libwebrtc/api/video/video_bitrate_allocator_factory_gn/moz.build b/third_party/libwebrtc/api/video/video_bitrate_allocator_factory_gn/moz.build new file mode 100644 index 0000000000..a6e2e2c6f5 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_bitrate_allocator_factory_gn/moz.build @@ -0,0 +1,209 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_bitrate_allocator_factory_gn") diff --git a/third_party/libwebrtc/api/video/video_bitrate_allocator_gn/moz.build b/third_party/libwebrtc/api/video/video_bitrate_allocator_gn/moz.build new file mode 100644 index 0000000000..f09476aacb --- /dev/null +++ b/third_party/libwebrtc/api/video/video_bitrate_allocator_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video/video_bitrate_allocator.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_bitrate_allocator_gn") diff --git a/third_party/libwebrtc/api/video/video_codec_constants.h b/third_party/libwebrtc/api/video/video_codec_constants.h new file mode 100644 index 0000000000..5859f9b4cf --- /dev/null +++ b/third_party/libwebrtc/api/video/video_codec_constants.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019 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 API_VIDEO_VIDEO_CODEC_CONSTANTS_H_ +#define API_VIDEO_VIDEO_CODEC_CONSTANTS_H_ + +namespace webrtc { + +enum : int { kMaxEncoderBuffers = 8 }; +enum : int { kMaxSimulcastStreams = 3 }; +enum : int { kMaxSpatialLayers = 5 }; +enum : int { kMaxTemporalStreams = 4 }; +enum : int { kMaxPreferredPixelFormats = 5 }; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_CODEC_CONSTANTS_H_ diff --git a/third_party/libwebrtc/api/video/video_codec_constants_gn/moz.build b/third_party/libwebrtc/api/video/video_codec_constants_gn/moz.build new file mode 100644 index 0000000000..2ac72c5b54 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_codec_constants_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_codec_constants_gn") diff --git a/third_party/libwebrtc/api/video/video_codec_type.h b/third_party/libwebrtc/api/video/video_codec_type.h new file mode 100644 index 0000000000..74a4bc4258 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_codec_type.h @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_CODEC_TYPE_H_ +#define API_VIDEO_VIDEO_CODEC_TYPE_H_ + +namespace webrtc { + +enum VideoCodecType { + // There are various memset(..., 0, ...) calls in the code that rely on + // kVideoCodecGeneric being zero. + kVideoCodecGeneric = 0, + kVideoCodecVP8, + kVideoCodecVP9, + kVideoCodecAV1, + kVideoCodecH264, + kVideoCodecMultiplex, +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_CODEC_TYPE_H_ diff --git a/third_party/libwebrtc/api/video/video_content_type.cc b/third_party/libwebrtc/api/video/video_content_type.cc new file mode 100644 index 0000000000..9ba3ece79b --- /dev/null +++ b/third_party/libwebrtc/api/video/video_content_type.cc @@ -0,0 +1,93 @@ +/* + * 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. + */ + +#include "api/video/video_content_type.h" + +// VideoContentType stored as a single byte, which is sent over the network. +// Structure: +// +// 0 1 2 3 4 5 6 7 +// +---------------+ +// |r r e e e s s c| +// +// where: +// r - reserved bits. +// e - 3-bit number of an experiment group counted from 1. 0 means there's no +// experiment ongoing. +// s - 2-bit simulcast stream id or spatial layer, counted from 1. 0 means that +// no simulcast information is set. +// c - content type. 0 means real-time video, 1 means screenshare. +// + +namespace webrtc { +namespace videocontenttypehelpers { + +namespace { +static constexpr uint8_t kScreenshareBitsSize = 1; +static constexpr uint8_t kScreenshareBitsMask = + (1u << kScreenshareBitsSize) - 1; + +static constexpr uint8_t kSimulcastShift = 1; +static constexpr uint8_t kSimulcastBitsSize = 2; +static constexpr uint8_t kSimulcastBitsMask = ((1u << kSimulcastBitsSize) - 1) + << kSimulcastShift; // 0b00000110 + +static constexpr uint8_t kExperimentShift = 3; +static constexpr uint8_t kExperimentBitsSize = 3; +static constexpr uint8_t kExperimentBitsMask = + ((1u << kExperimentBitsSize) - 1) << kExperimentShift; // 0b00111000 + +static constexpr uint8_t kTotalBitsSize = + kScreenshareBitsSize + kSimulcastBitsSize + kExperimentBitsSize; +} // namespace + +bool SetExperimentId(VideoContentType* content_type, uint8_t experiment_id) { + // Store in bits 2-4. + if (experiment_id >= (1 << kExperimentBitsSize)) + return false; + *content_type = static_cast<VideoContentType>( + (static_cast<uint8_t>(*content_type) & ~kExperimentBitsMask) | + ((experiment_id << kExperimentShift) & kExperimentBitsMask)); + return true; +} + +bool SetSimulcastId(VideoContentType* content_type, uint8_t simulcast_id) { + // Store in bits 5-6. + if (simulcast_id >= (1 << kSimulcastBitsSize)) + return false; + *content_type = static_cast<VideoContentType>( + (static_cast<uint8_t>(*content_type) & ~kSimulcastBitsMask) | + ((simulcast_id << kSimulcastShift) & kSimulcastBitsMask)); + return true; +} + +uint8_t GetExperimentId(const VideoContentType& content_type) { + return (static_cast<uint8_t>(content_type) & kExperimentBitsMask) >> + kExperimentShift; +} +uint8_t GetSimulcastId(const VideoContentType& content_type) { + return (static_cast<uint8_t>(content_type) & kSimulcastBitsMask) >> + kSimulcastShift; +} + +bool IsScreenshare(const VideoContentType& content_type) { + return (static_cast<uint8_t>(content_type) & kScreenshareBitsMask) > 0; +} + +bool IsValidContentType(uint8_t value) { + // Any 6-bit value is allowed. + return value < (1 << kTotalBitsSize); +} + +const char* ToString(const VideoContentType& content_type) { + return IsScreenshare(content_type) ? "screen" : "realtime"; +} +} // namespace videocontenttypehelpers +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/video_content_type.h b/third_party/libwebrtc/api/video/video_content_type.h new file mode 100644 index 0000000000..2d38a62366 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_content_type.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_CONTENT_TYPE_H_ +#define API_VIDEO_VIDEO_CONTENT_TYPE_H_ + +#include <stdint.h> + +namespace webrtc { + +enum class VideoContentType : uint8_t { + UNSPECIFIED = 0, + SCREENSHARE = 1, +}; + +namespace videocontenttypehelpers { +bool SetExperimentId(VideoContentType* content_type, uint8_t experiment_id); +bool SetSimulcastId(VideoContentType* content_type, uint8_t simulcast_id); + +uint8_t GetExperimentId(const VideoContentType& content_type); +uint8_t GetSimulcastId(const VideoContentType& content_type); + +bool IsScreenshare(const VideoContentType& content_type); + +bool IsValidContentType(uint8_t value); + +const char* ToString(const VideoContentType& content_type); +} // namespace videocontenttypehelpers + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_CONTENT_TYPE_H_ diff --git a/third_party/libwebrtc/api/video/video_frame.cc b/third_party/libwebrtc/api/video/video_frame.cc new file mode 100644 index 0000000000..130820a886 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_frame.cc @@ -0,0 +1,317 @@ +/* + * 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 "api/video/video_frame.h" + +#include <algorithm> +#include <utility> + +#include "rtc_base/checks.h" +#include "rtc_base/time_utils.h" + +namespace webrtc { + +void VideoFrame::UpdateRect::Union(const UpdateRect& other) { + if (other.IsEmpty()) + return; + if (IsEmpty()) { + *this = other; + return; + } + int right = std::max(offset_x + width, other.offset_x + other.width); + int bottom = std::max(offset_y + height, other.offset_y + other.height); + offset_x = std::min(offset_x, other.offset_x); + offset_y = std::min(offset_y, other.offset_y); + width = right - offset_x; + height = bottom - offset_y; + RTC_DCHECK_GT(width, 0); + RTC_DCHECK_GT(height, 0); +} + +void VideoFrame::UpdateRect::Intersect(const UpdateRect& other) { + if (other.IsEmpty() || IsEmpty()) { + MakeEmptyUpdate(); + return; + } + + int right = std::min(offset_x + width, other.offset_x + other.width); + int bottom = std::min(offset_y + height, other.offset_y + other.height); + offset_x = std::max(offset_x, other.offset_x); + offset_y = std::max(offset_y, other.offset_y); + width = right - offset_x; + height = bottom - offset_y; + if (width <= 0 || height <= 0) { + MakeEmptyUpdate(); + } +} + +void VideoFrame::UpdateRect::MakeEmptyUpdate() { + width = height = offset_x = offset_y = 0; +} + +bool VideoFrame::UpdateRect::IsEmpty() const { + return width == 0 && height == 0; +} + +VideoFrame::UpdateRect VideoFrame::UpdateRect::ScaleWithFrame( + int frame_width, + int frame_height, + int crop_x, + int crop_y, + int crop_width, + int crop_height, + int scaled_width, + int scaled_height) const { + RTC_DCHECK_GT(frame_width, 0); + RTC_DCHECK_GT(frame_height, 0); + + RTC_DCHECK_GT(crop_width, 0); + RTC_DCHECK_GT(crop_height, 0); + + RTC_DCHECK_LE(crop_width + crop_x, frame_width); + RTC_DCHECK_LE(crop_height + crop_y, frame_height); + + RTC_DCHECK_GT(scaled_width, 0); + RTC_DCHECK_GT(scaled_height, 0); + + // Check if update rect is out of the cropped area. + if (offset_x + width < crop_x || offset_x > crop_x + crop_width || + offset_y + height < crop_y || offset_y > crop_y + crop_width) { + return {0, 0, 0, 0}; + } + + int x = offset_x - crop_x; + int w = width; + if (x < 0) { + w += x; + x = 0; + } + int y = offset_y - crop_y; + int h = height; + if (y < 0) { + h += y; + y = 0; + } + + // Lower corner is rounded down. + x = x * scaled_width / crop_width; + y = y * scaled_height / crop_height; + // Upper corner is rounded up. + w = (w * scaled_width + crop_width - 1) / crop_width; + h = (h * scaled_height + crop_height - 1) / crop_height; + + // Round to full 2x2 blocks due to possible subsampling in the pixel data. + if (x % 2) { + --x; + ++w; + } + if (y % 2) { + --y; + ++h; + } + if (w % 2) { + ++w; + } + if (h % 2) { + ++h; + } + + // Expand the update rect by 2 pixels in each direction to include any + // possible scaling artifacts. + if (scaled_width != crop_width || scaled_height != crop_height) { + if (x > 0) { + x -= 2; + w += 2; + } + if (y > 0) { + y -= 2; + h += 2; + } + w += 2; + h += 2; + } + + // Ensure update rect is inside frame dimensions. + if (x + w > scaled_width) { + w = scaled_width - x; + } + if (y + h > scaled_height) { + h = scaled_height - y; + } + RTC_DCHECK_GE(w, 0); + RTC_DCHECK_GE(h, 0); + if (w == 0 || h == 0) { + w = 0; + h = 0; + x = 0; + y = 0; + } + + return {x, y, w, h}; +} + +VideoFrame::Builder::Builder() = default; + +VideoFrame::Builder::~Builder() = default; + +VideoFrame VideoFrame::Builder::build() { + RTC_CHECK(video_frame_buffer_ != nullptr); + return VideoFrame(id_, video_frame_buffer_, timestamp_us_, timestamp_rtp_, + ntp_time_ms_, rotation_, color_space_, render_parameters_, + update_rect_, packet_infos_); +} + +VideoFrame::Builder& VideoFrame::Builder::set_video_frame_buffer( + const rtc::scoped_refptr<VideoFrameBuffer>& buffer) { + video_frame_buffer_ = buffer; + return *this; +} + +VideoFrame::Builder& VideoFrame::Builder::set_timestamp_ms( + int64_t timestamp_ms) { + timestamp_us_ = timestamp_ms * rtc::kNumMicrosecsPerMillisec; + return *this; +} + +VideoFrame::Builder& VideoFrame::Builder::set_timestamp_us( + int64_t timestamp_us) { + timestamp_us_ = timestamp_us; + return *this; +} + +VideoFrame::Builder& VideoFrame::Builder::set_timestamp_rtp( + uint32_t timestamp_rtp) { + timestamp_rtp_ = timestamp_rtp; + return *this; +} + +VideoFrame::Builder& VideoFrame::Builder::set_ntp_time_ms(int64_t ntp_time_ms) { + ntp_time_ms_ = ntp_time_ms; + return *this; +} + +VideoFrame::Builder& VideoFrame::Builder::set_rotation(VideoRotation rotation) { + rotation_ = rotation; + return *this; +} + +VideoFrame::Builder& VideoFrame::Builder::set_color_space( + const absl::optional<ColorSpace>& color_space) { + color_space_ = color_space; + return *this; +} + +VideoFrame::Builder& VideoFrame::Builder::set_color_space( + const ColorSpace* color_space) { + color_space_ = + color_space ? absl::make_optional(*color_space) : absl::nullopt; + return *this; +} + +VideoFrame::Builder& VideoFrame::Builder::set_id(uint16_t id) { + id_ = id; + return *this; +} + +VideoFrame::Builder& VideoFrame::Builder::set_update_rect( + const absl::optional<VideoFrame::UpdateRect>& update_rect) { + update_rect_ = update_rect; + return *this; +} + +VideoFrame::Builder& VideoFrame::Builder::set_packet_infos( + RtpPacketInfos packet_infos) { + packet_infos_ = std::move(packet_infos); + return *this; +} + +VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer, + webrtc::VideoRotation rotation, + int64_t timestamp_us) + : video_frame_buffer_(buffer), + timestamp_rtp_(0), + ntp_time_ms_(0), + timestamp_us_(timestamp_us), + rotation_(rotation) {} + +VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer, + uint32_t timestamp_rtp, + int64_t render_time_ms, + VideoRotation rotation) + : video_frame_buffer_(buffer), + timestamp_rtp_(timestamp_rtp), + ntp_time_ms_(0), + timestamp_us_(render_time_ms * rtc::kNumMicrosecsPerMillisec), + rotation_(rotation) { + RTC_DCHECK(buffer); +} + +VideoFrame::VideoFrame(uint16_t id, + const rtc::scoped_refptr<VideoFrameBuffer>& buffer, + int64_t timestamp_us, + uint32_t timestamp_rtp, + int64_t ntp_time_ms, + VideoRotation rotation, + const absl::optional<ColorSpace>& color_space, + const RenderParameters& render_parameters, + const absl::optional<UpdateRect>& update_rect, + RtpPacketInfos packet_infos) + : id_(id), + video_frame_buffer_(buffer), + timestamp_rtp_(timestamp_rtp), + ntp_time_ms_(ntp_time_ms), + timestamp_us_(timestamp_us), + rotation_(rotation), + color_space_(color_space), + render_parameters_(render_parameters), + update_rect_(update_rect), + packet_infos_(std::move(packet_infos)) { + if (update_rect_) { + RTC_DCHECK_GE(update_rect_->offset_x, 0); + RTC_DCHECK_GE(update_rect_->offset_y, 0); + RTC_DCHECK_LE(update_rect_->offset_x + update_rect_->width, width()); + RTC_DCHECK_LE(update_rect_->offset_y + update_rect_->height, height()); + } +} + +VideoFrame::~VideoFrame() = default; + +VideoFrame::VideoFrame(const VideoFrame&) = default; +VideoFrame::VideoFrame(VideoFrame&&) = default; +VideoFrame& VideoFrame::operator=(const VideoFrame&) = default; +VideoFrame& VideoFrame::operator=(VideoFrame&&) = default; + +int VideoFrame::width() const { + return video_frame_buffer_ ? video_frame_buffer_->width() : 0; +} + +int VideoFrame::height() const { + return video_frame_buffer_ ? video_frame_buffer_->height() : 0; +} + +uint32_t VideoFrame::size() const { + return width() * height(); +} + +rtc::scoped_refptr<VideoFrameBuffer> VideoFrame::video_frame_buffer() const { + return video_frame_buffer_; +} + +void VideoFrame::set_video_frame_buffer( + const rtc::scoped_refptr<VideoFrameBuffer>& buffer) { + RTC_CHECK(buffer); + video_frame_buffer_ = buffer; +} + +int64_t VideoFrame::render_time_ms() const { + return timestamp_us() / rtc::kNumMicrosecsPerMillisec; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/video_frame.h b/third_party/libwebrtc/api/video/video_frame.h new file mode 100644 index 0000000000..086aad820f --- /dev/null +++ b/third_party/libwebrtc/api/video/video_frame.h @@ -0,0 +1,302 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_FRAME_H_ +#define API_VIDEO_VIDEO_FRAME_H_ + +#include <stdint.h> + +#include <utility> + +#include "absl/types/optional.h" +#include "api/rtp_packet_infos.h" +#include "api/scoped_refptr.h" +#include "api/video/color_space.h" +#include "api/video/hdr_metadata.h" +#include "api/video/video_frame_buffer.h" +#include "api/video/video_rotation.h" +#include "rtc_base/checks.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +class RTC_EXPORT VideoFrame { + public: + // Value used to signal that `VideoFrame::id()` is not set. + static constexpr uint16_t kNotSetId = 0; + + struct RTC_EXPORT UpdateRect { + int offset_x; + int offset_y; + int width; + int height; + + // Makes this UpdateRect a bounding box of this and other rect. + void Union(const UpdateRect& other); + + // Makes this UpdateRect an intersection of this and other rect. + void Intersect(const UpdateRect& other); + + // Sets everything to 0, making this UpdateRect a zero-size (empty) update. + void MakeEmptyUpdate(); + + bool IsEmpty() const; + + // Per-member equality check. Empty rectangles with different offsets would + // be considered different. + bool operator==(const UpdateRect& other) const { + return other.offset_x == offset_x && other.offset_y == offset_y && + other.width == width && other.height == height; + } + + bool operator!=(const UpdateRect& other) const { return !(*this == other); } + + // Scales update_rect given original frame dimensions. + // Cropping is applied first, then rect is scaled down. + // Update rect is snapped to 2x2 grid due to possible UV subsampling and + // then expanded by additional 2 pixels in each direction to accommodate any + // possible scaling artifacts. + // Note, close but not equal update_rects on original frame may result in + // the same scaled update rects. + UpdateRect ScaleWithFrame(int frame_width, + int frame_height, + int crop_x, + int crop_y, + int crop_width, + int crop_height, + int scaled_width, + int scaled_height) const; + }; + + struct RTC_EXPORT ProcessingTime { + TimeDelta Elapsed() const { return finish - start; } + Timestamp start; + Timestamp finish; + }; + + struct RTC_EXPORT RenderParameters { + bool use_low_latency_rendering = false; + absl::optional<int32_t> max_composition_delay_in_frames; + + bool operator==(const RenderParameters& other) const { + return other.use_low_latency_rendering == use_low_latency_rendering && + other.max_composition_delay_in_frames == + max_composition_delay_in_frames; + } + + bool operator!=(const RenderParameters& other) const { + return !(*this == other); + } + }; + + // Preferred way of building VideoFrame objects. + class RTC_EXPORT Builder { + public: + Builder(); + ~Builder(); + + VideoFrame build(); + Builder& set_video_frame_buffer( + const rtc::scoped_refptr<VideoFrameBuffer>& buffer); + Builder& set_timestamp_ms(int64_t timestamp_ms); + Builder& set_timestamp_us(int64_t timestamp_us); + Builder& set_timestamp_rtp(uint32_t timestamp_rtp); + Builder& set_ntp_time_ms(int64_t ntp_time_ms); + Builder& set_rotation(VideoRotation rotation); + Builder& set_color_space(const absl::optional<ColorSpace>& color_space); + Builder& set_color_space(const ColorSpace* color_space); + Builder& set_id(uint16_t id); + Builder& set_update_rect(const absl::optional<UpdateRect>& update_rect); + Builder& set_packet_infos(RtpPacketInfos packet_infos); + + private: + uint16_t id_ = kNotSetId; + rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer_; + int64_t timestamp_us_ = 0; + uint32_t timestamp_rtp_ = 0; + int64_t ntp_time_ms_ = 0; + VideoRotation rotation_ = kVideoRotation_0; + absl::optional<ColorSpace> color_space_; + RenderParameters render_parameters_; + absl::optional<UpdateRect> update_rect_; + RtpPacketInfos packet_infos_; + }; + + // To be deprecated. Migrate all use to Builder. + VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer, + webrtc::VideoRotation rotation, + int64_t timestamp_us); + VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer, + uint32_t timestamp_rtp, + int64_t render_time_ms, + VideoRotation rotation); + + ~VideoFrame(); + + // Support move and copy. + VideoFrame(const VideoFrame&); + VideoFrame(VideoFrame&&); + VideoFrame& operator=(const VideoFrame&); + VideoFrame& operator=(VideoFrame&&); + + // Get frame width. + int width() const; + // Get frame height. + int height() const; + // Get frame size in pixels. + uint32_t size() const; + + // Get frame ID. Returns `kNotSetId` if ID is not set. Not guaranteed to be + // transferred from the sender to the receiver, but preserved on the sender + // side. The id should be propagated between all frame modifications during + // its lifetime from capturing to sending as encoded image. It is intended to + // be unique over a time window of a few minutes for the peer connection to + // which the corresponding video stream belongs to. + uint16_t id() const { return id_; } + void set_id(uint16_t id) { id_ = id; } + + // System monotonic clock, same timebase as rtc::TimeMicros(). + int64_t timestamp_us() const { return timestamp_us_; } + void set_timestamp_us(int64_t timestamp_us) { timestamp_us_ = timestamp_us; } + + // Set frame timestamp (90kHz). + void set_timestamp(uint32_t timestamp) { timestamp_rtp_ = timestamp; } + + // Get frame timestamp (90kHz). + uint32_t timestamp() const { return timestamp_rtp_; } + + // Set capture ntp time in milliseconds. + void set_ntp_time_ms(int64_t ntp_time_ms) { ntp_time_ms_ = ntp_time_ms; } + + // Get capture ntp time in milliseconds. + int64_t ntp_time_ms() const { return ntp_time_ms_; } + + // Naming convention for Coordination of Video Orientation. Please see + // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ts_126114v120700p.pdf + // + // "pending rotation" or "pending" = a frame that has a VideoRotation > 0. + // + // "not pending" = a frame that has a VideoRotation == 0. + // + // "apply rotation" = modify a frame from being "pending" to being "not + // pending" rotation (a no-op for "unrotated"). + // + VideoRotation rotation() const { return rotation_; } + void set_rotation(VideoRotation rotation) { rotation_ = rotation; } + + // Get color space when available. + const absl::optional<ColorSpace>& color_space() const { return color_space_; } + void set_color_space(const absl::optional<ColorSpace>& color_space) { + color_space_ = color_space; + } + + RenderParameters render_parameters() const { return render_parameters_; } + void set_render_parameters(const RenderParameters& render_parameters) { + render_parameters_ = render_parameters; + } + + // Deprecated in favor of render_parameters, will be removed once Chromium is + // updated. max_composition_delay_in_frames() is used in an experiment of a + // low-latency renderer algorithm see crbug.com/1138888. + [[deprecated("Use render_parameters() instead.")]] absl::optional<int32_t> + max_composition_delay_in_frames() const { + return render_parameters_.max_composition_delay_in_frames; + } + + // Get render time in milliseconds. + int64_t render_time_ms() const; + + // Return the underlying buffer. Never nullptr for a properly + // initialized VideoFrame. + rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer() const; + + void set_video_frame_buffer( + const rtc::scoped_refptr<VideoFrameBuffer>& buffer); + + // Return true if the frame is stored in a texture. + bool is_texture() const { + return video_frame_buffer()->type() == VideoFrameBuffer::Type::kNative; + } + + bool has_update_rect() const { return update_rect_.has_value(); } + + // Returns update_rect set by the builder or set_update_rect() or whole frame + // rect if no update rect is available. + UpdateRect update_rect() const { + return update_rect_.value_or(UpdateRect{0, 0, width(), height()}); + } + + // Rectangle must be within the frame dimensions. + void set_update_rect(const VideoFrame::UpdateRect& update_rect) { + RTC_DCHECK_GE(update_rect.offset_x, 0); + RTC_DCHECK_GE(update_rect.offset_y, 0); + RTC_DCHECK_LE(update_rect.offset_x + update_rect.width, width()); + RTC_DCHECK_LE(update_rect.offset_y + update_rect.height, height()); + update_rect_ = update_rect; + } + + void clear_update_rect() { update_rect_ = absl::nullopt; } + + // Get information about packets used to assemble this video frame. Might be + // empty if the information isn't available. + const RtpPacketInfos& packet_infos() const { return packet_infos_; } + void set_packet_infos(RtpPacketInfos value) { + packet_infos_ = std::move(value); + } + + const absl::optional<ProcessingTime> processing_time() const { + return processing_time_; + } + void set_processing_time(const ProcessingTime& processing_time) { + processing_time_ = processing_time; + } + + private: + VideoFrame(uint16_t id, + const rtc::scoped_refptr<VideoFrameBuffer>& buffer, + int64_t timestamp_us, + uint32_t timestamp_rtp, + int64_t ntp_time_ms, + VideoRotation rotation, + const absl::optional<ColorSpace>& color_space, + const RenderParameters& render_parameters, + const absl::optional<UpdateRect>& update_rect, + RtpPacketInfos packet_infos); + + uint16_t id_; + // An opaque reference counted handle that stores the pixel data. + rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer_; + uint32_t timestamp_rtp_; + int64_t ntp_time_ms_; + int64_t timestamp_us_; + VideoRotation rotation_; + absl::optional<ColorSpace> color_space_; + // Contains parameters that affect have the frame should be rendered. + RenderParameters render_parameters_; + // Updated since the last frame area. If present it means that the bounding + // box of all the changes is within the rectangular area and is close to it. + // If absent, it means that there's no information about the change at all and + // update_rect() will return a rectangle corresponding to the entire frame. + absl::optional<UpdateRect> update_rect_; + // Information about packets used to assemble this video frame. This is needed + // by `SourceTracker` when the frame is delivered to the RTCRtpReceiver's + // MediaStreamTrack, in order to implement getContributingSources(). See: + // https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-getcontributingsources + RtpPacketInfos packet_infos_; + // Processing timestamps of the frame. For received video frames these are the + // timestamps when the frame is sent to the decoder and the decoded image + // returned from the decoder. + // Currently, not set for locally captured video frames. + absl::optional<ProcessingTime> processing_time_; +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_FRAME_H_ diff --git a/third_party/libwebrtc/api/video/video_frame_buffer.cc b/third_party/libwebrtc/api/video/video_frame_buffer.cc new file mode 100644 index 0000000000..374b438adc --- /dev/null +++ b/third_party/libwebrtc/api/video/video_frame_buffer.cc @@ -0,0 +1,242 @@ +/* + * 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. + */ + +#include "api/video/video_frame_buffer.h" + +#include "api/video/i420_buffer.h" +#include "api/video/i422_buffer.h" +#include "api/video/i444_buffer.h" +#include "api/video/nv12_buffer.h" +#include "rtc_base/checks.h" + +namespace webrtc { + +rtc::scoped_refptr<VideoFrameBuffer> VideoFrameBuffer::CropAndScale( + int offset_x, + int offset_y, + int crop_width, + int crop_height, + int scaled_width, + int scaled_height) { + rtc::scoped_refptr<I420Buffer> result = + I420Buffer::Create(scaled_width, scaled_height); + result->CropAndScaleFrom(*this->ToI420(), offset_x, offset_y, crop_width, + crop_height); + return result; +} + +const I420BufferInterface* VideoFrameBuffer::GetI420() const { + // Overridden by subclasses that can return an I420 buffer without any + // conversion, in particular, I420BufferInterface. + return nullptr; +} + +const I420ABufferInterface* VideoFrameBuffer::GetI420A() const { + RTC_CHECK(type() == Type::kI420A); + return static_cast<const I420ABufferInterface*>(this); +} + +const I444BufferInterface* VideoFrameBuffer::GetI444() const { + RTC_CHECK(type() == Type::kI444); + return static_cast<const I444BufferInterface*>(this); +} + +const I422BufferInterface* VideoFrameBuffer::GetI422() const { + RTC_CHECK(type() == Type::kI422); + return static_cast<const I422BufferInterface*>(this); +} + +const I010BufferInterface* VideoFrameBuffer::GetI010() const { + RTC_CHECK(type() == Type::kI010); + return static_cast<const I010BufferInterface*>(this); +} + +const I210BufferInterface* VideoFrameBuffer::GetI210() const { + RTC_CHECK(type() == Type::kI210); + return static_cast<const I210BufferInterface*>(this); +} + +const I410BufferInterface* VideoFrameBuffer::GetI410() const { + RTC_CHECK(type() == Type::kI410); + return static_cast<const I410BufferInterface*>(this); +} + +const NV12BufferInterface* VideoFrameBuffer::GetNV12() const { + RTC_CHECK(type() == Type::kNV12); + return static_cast<const NV12BufferInterface*>(this); +} + +rtc::scoped_refptr<VideoFrameBuffer> VideoFrameBuffer::GetMappedFrameBuffer( + rtc::ArrayView<Type> types) { + RTC_CHECK(type() == Type::kNative); + return nullptr; +} + +VideoFrameBuffer::Type I420BufferInterface::type() const { + return Type::kI420; +} + +const char* VideoFrameBufferTypeToString(VideoFrameBuffer::Type type) { + switch (type) { + case VideoFrameBuffer::Type::kNative: + return "kNative"; + case VideoFrameBuffer::Type::kI420: + return "kI420"; + case VideoFrameBuffer::Type::kI420A: + return "kI420A"; + case VideoFrameBuffer::Type::kI444: + return "kI444"; + case VideoFrameBuffer::Type::kI422: + return "kI422"; + case VideoFrameBuffer::Type::kI010: + return "kI010"; + case VideoFrameBuffer::Type::kI210: + return "kI210"; + case VideoFrameBuffer::Type::kI410: + return "kI410"; + case VideoFrameBuffer::Type::kNV12: + return "kNV12"; + default: + RTC_DCHECK_NOTREACHED(); + } +} + +int I420BufferInterface::ChromaWidth() const { + return (width() + 1) / 2; +} + +int I420BufferInterface::ChromaHeight() const { + return (height() + 1) / 2; +} + +rtc::scoped_refptr<I420BufferInterface> I420BufferInterface::ToI420() { + return rtc::scoped_refptr<I420BufferInterface>(this); +} + +const I420BufferInterface* I420BufferInterface::GetI420() const { + return this; +} + +VideoFrameBuffer::Type I420ABufferInterface::type() const { + return Type::kI420A; +} + +VideoFrameBuffer::Type I444BufferInterface::type() const { + return Type::kI444; +} + +int I444BufferInterface::ChromaWidth() const { + return width(); +} + +int I444BufferInterface::ChromaHeight() const { + return height(); +} + +rtc::scoped_refptr<VideoFrameBuffer> I444BufferInterface::CropAndScale( + int offset_x, + int offset_y, + int crop_width, + int crop_height, + int scaled_width, + int scaled_height) { + rtc::scoped_refptr<I444Buffer> result = + I444Buffer::Create(scaled_width, scaled_height); + result->CropAndScaleFrom(*this, offset_x, offset_y, crop_width, crop_height); + return result; +} + +VideoFrameBuffer::Type I422BufferInterface::type() const { + return Type::kI422; +} + +int I422BufferInterface::ChromaWidth() const { + return (width() + 1) / 2; +} + +int I422BufferInterface::ChromaHeight() const { + return height(); +} + +rtc::scoped_refptr<VideoFrameBuffer> I422BufferInterface::CropAndScale( + int offset_x, + int offset_y, + int crop_width, + int crop_height, + int scaled_width, + int scaled_height) { + rtc::scoped_refptr<I422Buffer> result = + I422Buffer::Create(scaled_width, scaled_height); + result->CropAndScaleFrom(*this, offset_x, offset_y, crop_width, crop_height); + return result; +} + +VideoFrameBuffer::Type I010BufferInterface::type() const { + return Type::kI010; +} + +int I010BufferInterface::ChromaWidth() const { + return (width() + 1) / 2; +} + +int I010BufferInterface::ChromaHeight() const { + return (height() + 1) / 2; +} + +VideoFrameBuffer::Type I210BufferInterface::type() const { + return Type::kI210; +} + +int I210BufferInterface::ChromaWidth() const { + return (width() + 1) / 2; +} + +int I210BufferInterface::ChromaHeight() const { + return height(); +} + +VideoFrameBuffer::Type I410BufferInterface::type() const { + return Type::kI410; +} + +int I410BufferInterface::ChromaWidth() const { + return width(); +} + +int I410BufferInterface::ChromaHeight() const { + return height(); +} + +VideoFrameBuffer::Type NV12BufferInterface::type() const { + return Type::kNV12; +} + +int NV12BufferInterface::ChromaWidth() const { + return (width() + 1) / 2; +} + +int NV12BufferInterface::ChromaHeight() const { + return (height() + 1) / 2; +} + +rtc::scoped_refptr<VideoFrameBuffer> NV12BufferInterface::CropAndScale( + int offset_x, + int offset_y, + int crop_width, + int crop_height, + int scaled_width, + int scaled_height) { + rtc::scoped_refptr<NV12Buffer> result = + NV12Buffer::Create(scaled_width, scaled_height); + result->CropAndScaleFrom(*this, offset_x, offset_y, crop_width, crop_height); + return result; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/video_frame_buffer.h b/third_party/libwebrtc/api/video/video_frame_buffer.h new file mode 100644 index 0000000000..aaf786699f --- /dev/null +++ b/third_party/libwebrtc/api/video/video_frame_buffer.h @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2015 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 API_VIDEO_VIDEO_FRAME_BUFFER_H_ +#define API_VIDEO_VIDEO_FRAME_BUFFER_H_ + +#include <stdint.h> + +#include "api/array_view.h" +#include "api/scoped_refptr.h" +#include "rtc_base/ref_count.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +class I420BufferInterface; +class I420ABufferInterface; +class I422BufferInterface; +class I444BufferInterface; +class I010BufferInterface; +class I210BufferInterface; +class I410BufferInterface; +class NV12BufferInterface; + +// Base class for frame buffers of different types of pixel format and storage. +// The tag in type() indicates how the data is represented, and each type is +// implemented as a subclass. To access the pixel data, call the appropriate +// GetXXX() function, where XXX represents the type. There is also a function +// ToI420() that returns a frame buffer in I420 format, converting from the +// underlying representation if necessary. I420 is the most widely accepted +// format and serves as a fallback for video sinks that can only handle I420, +// e.g. the internal WebRTC software encoders. A special enum value 'kNative' is +// provided for external clients to implement their own frame buffer +// representations, e.g. as textures. The external client can produce such +// native frame buffers from custom video sources, and then cast it back to the +// correct subclass in custom video sinks. The purpose of this is to improve +// performance by providing an optimized path without intermediate conversions. +// Frame metadata such as rotation and timestamp are stored in +// webrtc::VideoFrame, and not here. +class RTC_EXPORT VideoFrameBuffer : public rtc::RefCountInterface { + public: + // New frame buffer types will be added conservatively when there is an + // opportunity to optimize the path between some pair of video source and + // video sink. + // GENERATED_JAVA_ENUM_PACKAGE: org.webrtc + // GENERATED_JAVA_CLASS_NAME_OVERRIDE: VideoFrameBufferType + enum class Type { + kNative, + kI420, + kI420A, + kI422, + kI444, + kI010, + kI210, + kI410, + kNV12, + }; + + // This function specifies in what pixel format the data is stored in. + virtual Type type() const = 0; + + // The resolution of the frame in pixels. For formats where some planes are + // subsampled, this is the highest-resolution plane. + virtual int width() const = 0; + virtual int height() const = 0; + + // Returns a memory-backed frame buffer in I420 format. If the pixel data is + // in another format, a conversion will take place. All implementations must + // provide a fallback to I420 for compatibility with e.g. the internal WebRTC + // software encoders. + // Conversion may fail, for example if reading the pixel data from a texture + // fails. If the conversion fails, nullptr is returned. + virtual rtc::scoped_refptr<I420BufferInterface> ToI420() = 0; + + // GetI420() methods should return I420 buffer if conversion is trivial, i.e + // no change for binary data is needed. Otherwise these methods should return + // nullptr. One example of buffer with that property is + // WebrtcVideoFrameAdapter in Chrome - it's I420 buffer backed by a shared + // memory buffer. Therefore it must have type kNative. Yet, ToI420() + // doesn't affect binary data at all. Another example is any I420A buffer. + // TODO(https://crbug.com/webrtc/12021): Make this method non-virtual and + // behave as the other GetXXX methods below. + virtual const I420BufferInterface* GetI420() const; + + // A format specific scale function. Default implementation works by + // converting to I420. But more efficient implementations may override it, + // especially for kNative. + // First, the image is cropped to `crop_width` and `crop_height` and then + // scaled to `scaled_width` and `scaled_height`. + virtual rtc::scoped_refptr<VideoFrameBuffer> CropAndScale(int offset_x, + int offset_y, + int crop_width, + int crop_height, + int scaled_width, + int scaled_height); + + // Alias for common use case. + rtc::scoped_refptr<VideoFrameBuffer> Scale(int scaled_width, + int scaled_height) { + return CropAndScale(0, 0, width(), height(), scaled_width, scaled_height); + } + + // These functions should only be called if type() is of the correct type. + // Calling with a different type will result in a crash. + const I420ABufferInterface* GetI420A() const; + const I422BufferInterface* GetI422() const; + const I444BufferInterface* GetI444() const; + const I010BufferInterface* GetI010() const; + const I210BufferInterface* GetI210() const; + const I410BufferInterface* GetI410() const; + const NV12BufferInterface* GetNV12() const; + + // From a kNative frame, returns a VideoFrameBuffer with a pixel format in + // the list of types that is in the main memory with a pixel perfect + // conversion for encoding with a software encoder. Returns nullptr if the + // frame type is not supported, mapping is not possible, or if the kNative + // frame has not implemented this method. Only callable if type() is kNative. + virtual rtc::scoped_refptr<VideoFrameBuffer> GetMappedFrameBuffer( + rtc::ArrayView<Type> types); + + protected: + ~VideoFrameBuffer() override {} +}; + +// Update when VideoFrameBuffer::Type is updated. +const char* VideoFrameBufferTypeToString(VideoFrameBuffer::Type type); + +// This interface represents planar formats. +class PlanarYuvBuffer : public VideoFrameBuffer { + public: + virtual int ChromaWidth() const = 0; + virtual int ChromaHeight() const = 0; + + // Returns the number of steps(in terms of Data*() return type) between + // successive rows for a given plane. + virtual int StrideY() const = 0; + virtual int StrideU() const = 0; + virtual int StrideV() const = 0; + + protected: + ~PlanarYuvBuffer() override {} +}; + +// This interface represents 8-bit color depth formats: Type::kI420, +// Type::kI420A, Type::kI422 and Type::kI444. +class PlanarYuv8Buffer : public PlanarYuvBuffer { + public: + // Returns pointer to the pixel data for a given plane. The memory is owned by + // the VideoFrameBuffer object and must not be freed by the caller. + virtual const uint8_t* DataY() const = 0; + virtual const uint8_t* DataU() const = 0; + virtual const uint8_t* DataV() const = 0; + + protected: + ~PlanarYuv8Buffer() override {} +}; + +class RTC_EXPORT I420BufferInterface : public PlanarYuv8Buffer { + public: + Type type() const override; + + int ChromaWidth() const final; + int ChromaHeight() const final; + + rtc::scoped_refptr<I420BufferInterface> ToI420() final; + const I420BufferInterface* GetI420() const final; + + protected: + ~I420BufferInterface() override {} +}; + +class RTC_EXPORT I420ABufferInterface : public I420BufferInterface { + public: + Type type() const final; + virtual const uint8_t* DataA() const = 0; + virtual int StrideA() const = 0; + + protected: + ~I420ABufferInterface() override {} +}; + +// Represents Type::kI422, 4:2:2 planar with 8 bits per pixel. +class I422BufferInterface : public PlanarYuv8Buffer { + public: + Type type() const final; + + int ChromaWidth() const final; + int ChromaHeight() const final; + + rtc::scoped_refptr<VideoFrameBuffer> CropAndScale(int offset_x, + int offset_y, + int crop_width, + int crop_height, + int scaled_width, + int scaled_height) override; + + protected: + ~I422BufferInterface() override {} +}; + +// Represents Type::kI444, 4:4:4 planar with 8 bits per pixel. +class I444BufferInterface : public PlanarYuv8Buffer { + public: + Type type() const final; + + int ChromaWidth() const final; + int ChromaHeight() const final; + + rtc::scoped_refptr<VideoFrameBuffer> CropAndScale(int offset_x, + int offset_y, + int crop_width, + int crop_height, + int scaled_width, + int scaled_height) override; + + protected: + ~I444BufferInterface() override {} +}; + +// This interface represents 8-bit to 16-bit color depth formats: Type::kI010 or +// Type::kI210 . +class PlanarYuv16BBuffer : public PlanarYuvBuffer { + public: + // Returns pointer to the pixel data for a given plane. The memory is owned by + // the VideoFrameBuffer object and must not be freed by the caller. + virtual const uint16_t* DataY() const = 0; + virtual const uint16_t* DataU() const = 0; + virtual const uint16_t* DataV() const = 0; + + protected: + ~PlanarYuv16BBuffer() override {} +}; + +// Represents Type::kI010, allocates 16 bits per pixel and fills 10 least +// significant bits with color information. +class I010BufferInterface : public PlanarYuv16BBuffer { + public: + Type type() const override; + + int ChromaWidth() const final; + int ChromaHeight() const final; + + protected: + ~I010BufferInterface() override {} +}; + +// Represents Type::kI210, allocates 16 bits per pixel and fills 10 least +// significant bits with color information. +class I210BufferInterface : public PlanarYuv16BBuffer { + public: + Type type() const override; + + int ChromaWidth() const final; + int ChromaHeight() const final; + + protected: + ~I210BufferInterface() override {} +}; + +// Represents Type::kI410, allocates 16 bits per pixel and fills 10 least +// significant bits with color information. +class I410BufferInterface : public PlanarYuv16BBuffer { + public: + Type type() const override; + + int ChromaWidth() const final; + int ChromaHeight() const final; + + protected: + ~I410BufferInterface() override {} +}; + +class BiplanarYuvBuffer : public VideoFrameBuffer { + public: + virtual int ChromaWidth() const = 0; + virtual int ChromaHeight() const = 0; + + // Returns the number of steps(in terms of Data*() return type) between + // successive rows for a given plane. + virtual int StrideY() const = 0; + virtual int StrideUV() const = 0; + + protected: + ~BiplanarYuvBuffer() override {} +}; + +class BiplanarYuv8Buffer : public BiplanarYuvBuffer { + public: + virtual const uint8_t* DataY() const = 0; + virtual const uint8_t* DataUV() const = 0; + + protected: + ~BiplanarYuv8Buffer() override {} +}; + +// Represents Type::kNV12. NV12 is full resolution Y and half-resolution +// interleved UV. +class RTC_EXPORT NV12BufferInterface : public BiplanarYuv8Buffer { + public: + Type type() const override; + + int ChromaWidth() const final; + int ChromaHeight() const final; + + rtc::scoped_refptr<VideoFrameBuffer> CropAndScale(int offset_x, + int offset_y, + int crop_width, + int crop_height, + int scaled_width, + int scaled_height) override; + + protected: + ~NV12BufferInterface() override {} +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_FRAME_BUFFER_H_ diff --git a/third_party/libwebrtc/api/video/video_frame_gn/moz.build b/third_party/libwebrtc/api/video/video_frame_gn/moz.build new file mode 100644 index 0000000000..7a4e9fdc2c --- /dev/null +++ b/third_party/libwebrtc/api/video/video_frame_gn/moz.build @@ -0,0 +1,236 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/media/libyuv/", + "/media/libyuv/libyuv/include/", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +SOURCES += [ + "/third_party/libwebrtc/api/video/i422_buffer.cc", + "/third_party/libwebrtc/api/video/i444_buffer.cc" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video/i420_buffer.cc", + "/third_party/libwebrtc/api/video/nv12_buffer.cc", + "/third_party/libwebrtc/api/video/video_frame.cc", + "/third_party/libwebrtc/api/video/video_frame_buffer.cc", + "/third_party/libwebrtc/api/video/video_source_interface.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_frame_gn") diff --git a/third_party/libwebrtc/api/video/video_frame_i010_gn/moz.build b/third_party/libwebrtc/api/video/video_frame_i010_gn/moz.build new file mode 100644 index 0000000000..e56d43a299 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_frame_i010_gn/moz.build @@ -0,0 +1,232 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/media/libyuv/", + "/media/libyuv/libyuv/include/", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +SOURCES += [ + "/third_party/libwebrtc/api/video/i210_buffer.cc", + "/third_party/libwebrtc/api/video/i410_buffer.cc" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video/i010_buffer.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_frame_i010_gn") diff --git a/third_party/libwebrtc/api/video/video_frame_metadata.cc b/third_party/libwebrtc/api/video/video_frame_metadata.cc new file mode 100644 index 0000000000..e1863e9c13 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_frame_metadata.cc @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2020 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 "api/video/video_frame_metadata.h" + +#include <utility> + +namespace webrtc { + +VideoFrameMetadata::VideoFrameMetadata() = default; + +VideoFrameType VideoFrameMetadata::GetFrameType() const { + return frame_type_; +} + +void VideoFrameMetadata::SetFrameType(VideoFrameType frame_type) { + frame_type_ = frame_type; +} + +uint16_t VideoFrameMetadata::GetWidth() const { + return width_; +} + +void VideoFrameMetadata::SetWidth(uint16_t width) { + width_ = width; +} + +uint16_t VideoFrameMetadata::GetHeight() const { + return height_; +} + +void VideoFrameMetadata::SetHeight(uint16_t height) { + height_ = height; +} + +VideoRotation VideoFrameMetadata::GetRotation() const { + return rotation_; +} + +void VideoFrameMetadata::SetRotation(VideoRotation rotation) { + rotation_ = rotation; +} + +VideoContentType VideoFrameMetadata::GetContentType() const { + return content_type_; +} + +void VideoFrameMetadata::SetContentType(VideoContentType content_type) { + content_type_ = content_type; +} + +absl::optional<int64_t> VideoFrameMetadata::GetFrameId() const { + return frame_id_; +} + +void VideoFrameMetadata::SetFrameId(absl::optional<int64_t> frame_id) { + frame_id_ = frame_id; +} + +int VideoFrameMetadata::GetSpatialIndex() const { + return spatial_index_; +} + +void VideoFrameMetadata::SetSpatialIndex(int spatial_index) { + spatial_index_ = spatial_index; +} + +int VideoFrameMetadata::GetTemporalIndex() const { + return temporal_index_; +} + +void VideoFrameMetadata::SetTemporalIndex(int temporal_index) { + temporal_index_ = temporal_index; +} + +rtc::ArrayView<const int64_t> VideoFrameMetadata::GetFrameDependencies() const { + return frame_dependencies_; +} + +void VideoFrameMetadata::SetFrameDependencies( + rtc::ArrayView<const int64_t> frame_dependencies) { + frame_dependencies_.assign(frame_dependencies.begin(), + frame_dependencies.end()); +} + +rtc::ArrayView<const DecodeTargetIndication> +VideoFrameMetadata::GetDecodeTargetIndications() const { + return decode_target_indications_; +} + +void VideoFrameMetadata::SetDecodeTargetIndications( + rtc::ArrayView<const DecodeTargetIndication> decode_target_indications) { + decode_target_indications_.assign(decode_target_indications.begin(), + decode_target_indications.end()); +} + +bool VideoFrameMetadata::GetIsLastFrameInPicture() const { + return is_last_frame_in_picture_; +} + +void VideoFrameMetadata::SetIsLastFrameInPicture( + bool is_last_frame_in_picture) { + is_last_frame_in_picture_ = is_last_frame_in_picture; +} + +uint8_t VideoFrameMetadata::GetSimulcastIdx() const { + return simulcast_idx_; +} + +void VideoFrameMetadata::SetSimulcastIdx(uint8_t simulcast_idx) { + simulcast_idx_ = simulcast_idx; +} + +VideoCodecType VideoFrameMetadata::GetCodec() const { + return codec_; +} + +void VideoFrameMetadata::SetCodec(VideoCodecType codec) { + codec_ = codec; +} + +const RTPVideoHeaderCodecSpecifics& +VideoFrameMetadata::GetRTPVideoHeaderCodecSpecifics() const { + return codec_specifics_; +} + +void VideoFrameMetadata::SetRTPVideoHeaderCodecSpecifics( + RTPVideoHeaderCodecSpecifics codec_specifics) { + codec_specifics_ = std::move(codec_specifics); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/video_frame_metadata.h b/third_party/libwebrtc/api/video/video_frame_metadata.h new file mode 100644 index 0000000000..2703f11324 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_frame_metadata.h @@ -0,0 +1,112 @@ +/* + * Copyright 2020 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 API_VIDEO_VIDEO_FRAME_METADATA_H_ +#define API_VIDEO_VIDEO_FRAME_METADATA_H_ + +#include <cstdint> + +#include "absl/container/inlined_vector.h" +#include "absl/types/optional.h" +#include "absl/types/variant.h" +#include "api/array_view.h" +#include "api/transport/rtp/dependency_descriptor.h" +#include "api/video/video_codec_type.h" +#include "api/video/video_content_type.h" +#include "api/video/video_frame_type.h" +#include "api/video/video_rotation.h" +#include "modules/video_coding/codecs/h264/include/h264_globals.h" +#include "modules/video_coding/codecs/vp8/include/vp8_globals.h" +#include "modules/video_coding/codecs/vp9/include/vp9_globals.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +using RTPVideoHeaderCodecSpecifics = absl::variant<absl::monostate, + RTPVideoHeaderVP8, + RTPVideoHeaderVP9, + RTPVideoHeaderH264>; + +// A subset of metadata from the RTP video header, exposed in insertable streams +// API. +class RTC_EXPORT VideoFrameMetadata { + public: + VideoFrameMetadata(); + VideoFrameMetadata(const VideoFrameMetadata&) = default; + VideoFrameMetadata& operator=(const VideoFrameMetadata&) = default; + + VideoFrameType GetFrameType() const; + void SetFrameType(VideoFrameType frame_type); + + uint16_t GetWidth() const; + void SetWidth(uint16_t width); + + uint16_t GetHeight() const; + void SetHeight(uint16_t height); + + VideoRotation GetRotation() const; + void SetRotation(VideoRotation rotation); + + VideoContentType GetContentType() const; + void SetContentType(VideoContentType content_type); + + absl::optional<int64_t> GetFrameId() const; + void SetFrameId(absl::optional<int64_t> frame_id); + + int GetSpatialIndex() const; + void SetSpatialIndex(int spatial_index); + + int GetTemporalIndex() const; + void SetTemporalIndex(int temporal_index); + + rtc::ArrayView<const int64_t> GetFrameDependencies() const; + void SetFrameDependencies(rtc::ArrayView<const int64_t> frame_dependencies); + + rtc::ArrayView<const DecodeTargetIndication> GetDecodeTargetIndications() + const; + void SetDecodeTargetIndications( + rtc::ArrayView<const DecodeTargetIndication> decode_target_indications); + + bool GetIsLastFrameInPicture() const; + void SetIsLastFrameInPicture(bool is_last_frame_in_picture); + + uint8_t GetSimulcastIdx() const; + void SetSimulcastIdx(uint8_t simulcast_idx); + + VideoCodecType GetCodec() const; + void SetCodec(VideoCodecType codec); + + // Which varient is used depends on the VideoCodecType from GetCodecs(). + const RTPVideoHeaderCodecSpecifics& GetRTPVideoHeaderCodecSpecifics() const; + void SetRTPVideoHeaderCodecSpecifics( + RTPVideoHeaderCodecSpecifics codec_specifics); + + private: + VideoFrameType frame_type_ = VideoFrameType::kEmptyFrame; + int16_t width_ = 0; + int16_t height_ = 0; + VideoRotation rotation_ = VideoRotation::kVideoRotation_0; + VideoContentType content_type_ = VideoContentType::UNSPECIFIED; + + // Corresponding to GenericDescriptorInfo. + absl::optional<int64_t> frame_id_; + int spatial_index_ = 0; + int temporal_index_ = 0; + absl::InlinedVector<int64_t, 5> frame_dependencies_; + absl::InlinedVector<DecodeTargetIndication, 10> decode_target_indications_; + + bool is_last_frame_in_picture_ = true; + uint8_t simulcast_idx_ = 0; + VideoCodecType codec_ = VideoCodecType::kVideoCodecGeneric; + RTPVideoHeaderCodecSpecifics codec_specifics_; +}; +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_FRAME_METADATA_H_ diff --git a/third_party/libwebrtc/api/video/video_frame_metadata_gn/moz.build b/third_party/libwebrtc/api/video/video_frame_metadata_gn/moz.build new file mode 100644 index 0000000000..2d2221dbb5 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_frame_metadata_gn/moz.build @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video/video_frame_metadata.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_frame_metadata_gn") diff --git a/third_party/libwebrtc/api/video/video_frame_type.h b/third_party/libwebrtc/api/video/video_frame_type.h new file mode 100644 index 0000000000..4a96f1fe9e --- /dev/null +++ b/third_party/libwebrtc/api/video/video_frame_type.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019 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 API_VIDEO_VIDEO_FRAME_TYPE_H_ +#define API_VIDEO_VIDEO_FRAME_TYPE_H_ + +namespace webrtc { + +enum class VideoFrameType { + kEmptyFrame = 0, + // Wire format for MultiplexEncodedImagePacker seems to depend on numerical + // values of these constants. + kVideoFrameKey = 3, + kVideoFrameDelta = 4, +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_FRAME_TYPE_H_ diff --git a/third_party/libwebrtc/api/video/video_frame_type_gn/moz.build b/third_party/libwebrtc/api/video/video_frame_type_gn/moz.build new file mode 100644 index 0000000000..bc4c46bfbd --- /dev/null +++ b/third_party/libwebrtc/api/video/video_frame_type_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_frame_type_gn") diff --git a/third_party/libwebrtc/api/video/video_layers_allocation.h b/third_party/libwebrtc/api/video/video_layers_allocation.h new file mode 100644 index 0000000000..39734151ae --- /dev/null +++ b/third_party/libwebrtc/api/video/video_layers_allocation.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020 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 API_VIDEO_VIDEO_LAYERS_ALLOCATION_H_ +#define API_VIDEO_VIDEO_LAYERS_ALLOCATION_H_ + +#include <cstdint> + +#include "absl/container/inlined_vector.h" +#include "api/units/data_rate.h" + +namespace webrtc { + +// This struct contains additional stream-level information needed by a +// Selective Forwarding Middlebox to make relay decisions of RTP streams. +struct VideoLayersAllocation { + static constexpr int kMaxSpatialIds = 4; + static constexpr int kMaxTemporalIds = 4; + + friend bool operator==(const VideoLayersAllocation& lhs, + const VideoLayersAllocation& rhs) { + return lhs.rtp_stream_index == rhs.rtp_stream_index && + lhs.resolution_and_frame_rate_is_valid == + rhs.resolution_and_frame_rate_is_valid && + lhs.active_spatial_layers == rhs.active_spatial_layers; + } + + friend bool operator!=(const VideoLayersAllocation& lhs, + const VideoLayersAllocation& rhs) { + return !(lhs == rhs); + } + + struct SpatialLayer { + friend bool operator==(const SpatialLayer& lhs, const SpatialLayer& rhs) { + return lhs.rtp_stream_index == rhs.rtp_stream_index && + lhs.spatial_id == rhs.spatial_id && + lhs.target_bitrate_per_temporal_layer == + rhs.target_bitrate_per_temporal_layer && + lhs.width == rhs.width && lhs.height == rhs.height && + lhs.frame_rate_fps == rhs.frame_rate_fps; + } + + friend bool operator!=(const SpatialLayer& lhs, const SpatialLayer& rhs) { + return !(lhs == rhs); + } + int rtp_stream_index = 0; + // Index of the spatial layer per `rtp_stream_index`. + int spatial_id = 0; + // Target bitrate per decode target. + absl::InlinedVector<DataRate, kMaxTemporalIds> + target_bitrate_per_temporal_layer; + + // These fields are only valid if `resolution_and_frame_rate_is_valid` is + // true + uint16_t width = 0; + uint16_t height = 0; + // Max frame rate used in any temporal layer of this spatial layer. + uint8_t frame_rate_fps = 0; + }; + + // Index of the rtp stream this allocation is sent on. Used for mapping + // a SpatialLayer to a rtp stream. + int rtp_stream_index = 0; + bool resolution_and_frame_rate_is_valid = false; + absl::InlinedVector<SpatialLayer, kMaxSpatialIds> active_spatial_layers; +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_LAYERS_ALLOCATION_H_ diff --git a/third_party/libwebrtc/api/video/video_layers_allocation_gn/moz.build b/third_party/libwebrtc/api/video/video_layers_allocation_gn/moz.build new file mode 100644 index 0000000000..ded4d37ab6 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_layers_allocation_gn/moz.build @@ -0,0 +1,205 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_layers_allocation_gn") diff --git a/third_party/libwebrtc/api/video/video_rotation.h b/third_party/libwebrtc/api/video/video_rotation.h new file mode 100644 index 0000000000..6a29588ee5 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_rotation.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 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 API_VIDEO_VIDEO_ROTATION_H_ +#define API_VIDEO_VIDEO_ROTATION_H_ + +namespace webrtc { + +// enum for clockwise rotation. +enum VideoRotation { + kVideoRotation_0 = 0, + kVideoRotation_90 = 90, + kVideoRotation_180 = 180, + kVideoRotation_270 = 270 +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_ROTATION_H_ diff --git a/third_party/libwebrtc/api/video/video_rtp_headers_gn/moz.build b/third_party/libwebrtc/api/video/video_rtp_headers_gn/moz.build new file mode 100644 index 0000000000..fffe252ebd --- /dev/null +++ b/third_party/libwebrtc/api/video/video_rtp_headers_gn/moz.build @@ -0,0 +1,228 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video/color_space.cc", + "/third_party/libwebrtc/api/video/hdr_metadata.cc", + "/third_party/libwebrtc/api/video/video_content_type.cc", + "/third_party/libwebrtc/api/video/video_timing.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_rtp_headers_gn") diff --git a/third_party/libwebrtc/api/video/video_sink_interface.h b/third_party/libwebrtc/api/video/video_sink_interface.h new file mode 100644 index 0000000000..9c1f5f3214 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_sink_interface.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_SINK_INTERFACE_H_ +#define API_VIDEO_VIDEO_SINK_INTERFACE_H_ + +#include "absl/types/optional.h" +#include "api/video_track_source_constraints.h" +#include "rtc_base/checks.h" + +namespace rtc { + +template <typename VideoFrameT> +class VideoSinkInterface { + public: + virtual ~VideoSinkInterface() = default; + + virtual void OnFrame(const VideoFrameT& frame) = 0; + + // Should be called by the source when it discards the frame due to rate + // limiting. + virtual void OnDiscardedFrame() {} + + // Called on the network thread when video constraints change. + // TODO(crbug/1255737): make pure virtual once downstream project adapts. + virtual void OnConstraintsChanged( + const webrtc::VideoTrackSourceConstraints& constraints) {} +}; + +} // namespace rtc + +#endif // API_VIDEO_VIDEO_SINK_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/video/video_source_interface.cc b/third_party/libwebrtc/api/video/video_source_interface.cc new file mode 100644 index 0000000000..70a86c3d64 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_source_interface.cc @@ -0,0 +1,19 @@ +/* + * 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. + */ + +#include "api/video/video_source_interface.h" + +namespace rtc { + +VideoSinkWants::VideoSinkWants() = default; +VideoSinkWants::VideoSinkWants(const VideoSinkWants&) = default; +VideoSinkWants::~VideoSinkWants() = default; + +} // namespace rtc diff --git a/third_party/libwebrtc/api/video/video_source_interface.h b/third_party/libwebrtc/api/video/video_source_interface.h new file mode 100644 index 0000000000..38d0041718 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_source_interface.h @@ -0,0 +1,130 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_SOURCE_INTERFACE_H_ +#define API_VIDEO_VIDEO_SOURCE_INTERFACE_H_ + +#include <limits> +#include <vector> + +#include "absl/types/optional.h" +#include "api/video/video_sink_interface.h" +#include "rtc_base/system/rtc_export.h" + +namespace rtc { + +// VideoSinkWants is used for notifying the source of properties a video frame +// should have when it is delivered to a certain sink. +struct RTC_EXPORT VideoSinkWants { + struct FrameSize { + FrameSize(int width, int height) : width(width), height(height) {} + FrameSize(const FrameSize&) = default; + ~FrameSize() = default; + + int width; + int height; + }; + + VideoSinkWants(); + VideoSinkWants(const VideoSinkWants&); + ~VideoSinkWants(); + // Tells the source whether the sink wants frames with rotation applied. + // By default, any rotation must be applied by the sink. + bool rotation_applied = false; + + // Tells the source that the sink only wants black frames. + bool black_frames = false; + + // Tells the source the maximum number of pixels the sink wants. + int max_pixel_count = std::numeric_limits<int>::max(); + // Tells the source the desired number of pixels the sinks wants. This will + // typically be used when stepping the resolution up again when conditions + // have improved after an earlier downgrade. The source should select the + // closest resolution to this pixel count, but if max_pixel_count is set, it + // still sets the absolute upper bound. + absl::optional<int> target_pixel_count; + // Tells the source the maximum framerate the sink wants. + int max_framerate_fps = std::numeric_limits<int>::max(); + + // Tells the source that the sink wants width and height of the video frames + // to be divisible by `resolution_alignment`. + // For example: With I420, this value would be a multiple of 2. + // Note that this field is unrelated to any horizontal or vertical stride + // requirements the encoder has on the incoming video frame buffers. + int resolution_alignment = 1; + + // The resolutions that sink is configured to consume. If the sink is an + // encoder this is what the encoder is configured to encode. In singlecast we + // only encode one resolution, but in simulcast and SVC this can mean multiple + // resolutions per frame. + // + // The sink is always configured to consume a subset of the + // webrtc::VideoFrame's resolution. In the case of encoding, we usually encode + // at webrtc::VideoFrame's resolution but this may not always be the case due + // to scaleResolutionDownBy or turning off simulcast or SVC layers. + // + // For example, we may capture at 720p and due to adaptation (e.g. applying + // `max_pixel_count` constraints) create webrtc::VideoFrames of size 480p, but + // if we do scaleResolutionDownBy:2 then the only resolution we end up + // encoding is 240p. In this case we still need to provide webrtc::VideoFrames + // of size 480p but we can optimize internal buffers for 240p, avoiding + // downsampling to 480p if possible. + // + // Note that the `resolutions` can change while frames are in flight and + // should only be used as a hint when constructing the webrtc::VideoFrame. + std::vector<FrameSize> resolutions; + + // This is the resolution requested by the user using RtpEncodingParameters. + absl::optional<FrameSize> requested_resolution; + + // `active` : is (any) of the layers/sink(s) active. + bool is_active = true; + + // This sub-struct contains information computed by VideoBroadcaster + // that aggregates several VideoSinkWants (and sends them to + // AdaptedVideoTrackSource). + struct Aggregates { + // `active_without_requested_resolution` is set by VideoBroadcaster + // when aggregating sink wants if there exists any sink (encoder) that is + // active but has not set the `requested_resolution`, i.e is relying on + // OnOutputFormatRequest to handle encode resolution. + bool any_active_without_requested_resolution = false; + }; + absl::optional<Aggregates> aggregates; +}; + +inline bool operator==(const VideoSinkWants::FrameSize& a, + const VideoSinkWants::FrameSize& b) { + return a.width == b.width && a.height == b.height; +} + +inline bool operator!=(const VideoSinkWants::FrameSize& a, + const VideoSinkWants::FrameSize& b) { + return !(a == b); +} + +template <typename VideoFrameT> +class VideoSourceInterface { + public: + virtual ~VideoSourceInterface() = default; + + virtual void AddOrUpdateSink(VideoSinkInterface<VideoFrameT>* sink, + const VideoSinkWants& wants) = 0; + // RemoveSink must guarantee that at the time the method returns, + // there is no current and no future calls to VideoSinkInterface::OnFrame. + virtual void RemoveSink(VideoSinkInterface<VideoFrameT>* sink) = 0; + + // Request underlying source to capture a new frame. + // TODO(crbug/1255737): make pure virtual once downstream projects adapt. + virtual void RequestRefreshFrame() {} +}; + +} // namespace rtc +#endif // API_VIDEO_VIDEO_SOURCE_INTERFACE_H_ diff --git a/third_party/libwebrtc/api/video/video_stream_decoder.h b/third_party/libwebrtc/api/video/video_stream_decoder.h new file mode 100644 index 0000000000..8d71dd300c --- /dev/null +++ b/third_party/libwebrtc/api/video/video_stream_decoder.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_STREAM_DECODER_H_ +#define API_VIDEO_VIDEO_STREAM_DECODER_H_ + +#include <map> +#include <memory> +#include <utility> + +#include "api/units/time_delta.h" +#include "api/video/encoded_frame.h" +#include "api/video/video_content_type.h" +#include "api/video/video_frame.h" +#include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_decoder_factory.h" + +namespace webrtc { +// NOTE: This class is still under development and may change without notice. +class VideoStreamDecoderInterface { + public: + class Callbacks { + public: + virtual ~Callbacks() = default; + + struct FrameInfo { + absl::optional<int> qp; + VideoContentType content_type; + }; + + // Called when the VideoStreamDecoder enters a non-decodable state. + virtual void OnNonDecodableState() = 0; + + virtual void OnContinuousUntil(int64_t frame_id) {} + + virtual void OnDecodedFrame(VideoFrame frame, + const FrameInfo& frame_info) = 0; + }; + + virtual ~VideoStreamDecoderInterface() = default; + + virtual void OnFrame(std::unique_ptr<EncodedFrame> frame) = 0; + + virtual void SetMinPlayoutDelay(TimeDelta min_delay) = 0; + virtual void SetMaxPlayoutDelay(TimeDelta max_delay) = 0; +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_STREAM_DECODER_H_ diff --git a/third_party/libwebrtc/api/video/video_stream_decoder_create.cc b/third_party/libwebrtc/api/video/video_stream_decoder_create.cc new file mode 100644 index 0000000000..e14c3bc851 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_stream_decoder_create.cc @@ -0,0 +1,32 @@ +/* + * 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 "api/video/video_stream_decoder_create.h" + +#include <memory> + +#include "video/video_stream_decoder_impl.h" + +namespace webrtc { + +std::unique_ptr<VideoStreamDecoderInterface> CreateVideoStreamDecoder( + VideoStreamDecoderInterface::Callbacks* callbacks, + VideoDecoderFactory* decoder_factory, + TaskQueueFactory* task_queue_factory, + std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings, + // TODO(jonaso, webrtc:10335): Consider what to do with factories + // vs. field trials. + const FieldTrialsView* field_trials) { + return std::make_unique<VideoStreamDecoderImpl>( + callbacks, decoder_factory, task_queue_factory, + std::move(decoder_settings), field_trials); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/video_stream_decoder_create.h b/third_party/libwebrtc/api/video/video_stream_decoder_create.h new file mode 100644 index 0000000000..974fd804ce --- /dev/null +++ b/third_party/libwebrtc/api/video/video_stream_decoder_create.h @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_STREAM_DECODER_CREATE_H_ +#define API_VIDEO_VIDEO_STREAM_DECODER_CREATE_H_ + +#include <map> +#include <memory> +#include <utility> + +#include "api/field_trials_view.h" +#include "api/task_queue/task_queue_factory.h" +#include "api/video/video_stream_decoder.h" +#include "api/video_codecs/sdp_video_format.h" + +namespace webrtc { +// The `decoder_settings` parameter is a map between: +// <payload type> --> <<video format>, <number of cores>>. +// The video format is used when instantiating a decoder, and +// the number of cores is used when initializing the decoder. +std::unique_ptr<VideoStreamDecoderInterface> CreateVideoStreamDecoder( + VideoStreamDecoderInterface::Callbacks* callbacks, + VideoDecoderFactory* decoder_factory, + TaskQueueFactory* task_queue_factory, + std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings, + const FieldTrialsView* field_trials = nullptr); + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_STREAM_DECODER_CREATE_H_ diff --git a/third_party/libwebrtc/api/video/video_stream_decoder_create_unittest.cc b/third_party/libwebrtc/api/video/video_stream_decoder_create_unittest.cc new file mode 100644 index 0000000000..849a054a04 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_stream_decoder_create_unittest.cc @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019 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 "api/video/video_stream_decoder_create.h" + +#include "api/task_queue/default_task_queue_factory.h" +#include "api/video_codecs/builtin_video_decoder_factory.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +class NullCallbacks : public VideoStreamDecoderInterface::Callbacks { + public: + ~NullCallbacks() override = default; + void OnNonDecodableState() override {} + void OnDecodedFrame(VideoFrame frame, + const VideoStreamDecoderInterface::Callbacks::FrameInfo& + frame_info) override {} +}; + +TEST(VideoStreamDecoderCreate, CreateVideoStreamDecoder) { + std::map<int, std::pair<SdpVideoFormat, int>> decoder_settings = { + {/*payload_type=*/111, {SdpVideoFormat("VP8"), /*number_of_cores=*/2}}}; + NullCallbacks callbacks; + std::unique_ptr<VideoDecoderFactory> decoder_factory = + CreateBuiltinVideoDecoderFactory(); + + std::unique_ptr<TaskQueueFactory> task_queue_factory = + CreateDefaultTaskQueueFactory(); + + std::unique_ptr<VideoStreamDecoderInterface> decoder = + CreateVideoStreamDecoder(&callbacks, decoder_factory.get(), + task_queue_factory.get(), decoder_settings); + EXPECT_TRUE(decoder); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/video_stream_encoder_gn/moz.build b/third_party/libwebrtc/api/video/video_stream_encoder_gn/moz.build new file mode 100644 index 0000000000..e36bc0df98 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_stream_encoder_gn/moz.build @@ -0,0 +1,209 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_stream_encoder_gn") diff --git a/third_party/libwebrtc/api/video/video_stream_encoder_settings.h b/third_party/libwebrtc/api/video/video_stream_encoder_settings.h new file mode 100644 index 0000000000..3aee5b7050 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_stream_encoder_settings.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_ +#define API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_ + +#include <string> + +#include "api/video/video_bitrate_allocator_factory.h" +#include "api/video_codecs/video_encoder.h" +#include "api/video_codecs/video_encoder_factory.h" + +namespace webrtc { + +class EncoderSwitchRequestCallback { + public: + virtual ~EncoderSwitchRequestCallback() {} + + // Requests switch to next negotiated encoder. + virtual void RequestEncoderFallback() = 0; + + // Requests switch to a specific encoder. If the encoder is not available and + // `allow_default_fallback` is `true` the default fallback is invoked. + virtual void RequestEncoderSwitch(const SdpVideoFormat& format, + bool allow_default_fallback) = 0; +}; + +struct VideoStreamEncoderSettings { + explicit VideoStreamEncoderSettings( + const VideoEncoder::Capabilities& capabilities) + : capabilities(capabilities) {} + + // Enables the new method to estimate the cpu load from encoding, used for + // cpu adaptation. + bool experiment_cpu_load_estimator = false; + + // Ownership stays with WebrtcVideoEngine (delegated from PeerConnection). + VideoEncoderFactory* encoder_factory = nullptr; + + // Requests the WebRtcVideoChannel to perform a codec switch. + EncoderSwitchRequestCallback* encoder_switch_request_callback = nullptr; + + // Ownership stays with WebrtcVideoEngine (delegated from PeerConnection). + VideoBitrateAllocatorFactory* bitrate_allocator_factory = nullptr; + + // Negotiated capabilities which the VideoEncoder may expect the other + // side to use. + VideoEncoder::Capabilities capabilities; +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_ diff --git a/third_party/libwebrtc/api/video/video_timing.cc b/third_party/libwebrtc/api/video/video_timing.cc new file mode 100644 index 0000000000..0483c20e66 --- /dev/null +++ b/third_party/libwebrtc/api/video/video_timing.cc @@ -0,0 +1,101 @@ +/* + * 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. + */ + +#include "api/video/video_timing.h" + +#include "api/array_view.h" +#include "api/units/time_delta.h" +#include "rtc_base/logging.h" +#include "rtc_base/numerics/safe_conversions.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +uint16_t VideoSendTiming::GetDeltaCappedMs(int64_t base_ms, int64_t time_ms) { + if (time_ms < base_ms) { + RTC_DLOG(LS_ERROR) << "Delta " << (time_ms - base_ms) + << "ms expected to be positive"; + } + return rtc::saturated_cast<uint16_t>(time_ms - base_ms); +} + +uint16_t VideoSendTiming::GetDeltaCappedMs(TimeDelta delta) { + if (delta < TimeDelta::Zero()) { + RTC_DLOG(LS_ERROR) << "Delta " << delta.ms() + << "ms expected to be positive"; + } + return rtc::saturated_cast<uint16_t>(delta.ms()); +} + +TimingFrameInfo::TimingFrameInfo() + : rtp_timestamp(0), + capture_time_ms(-1), + encode_start_ms(-1), + encode_finish_ms(-1), + packetization_finish_ms(-1), + pacer_exit_ms(-1), + network_timestamp_ms(-1), + network2_timestamp_ms(-1), + receive_start_ms(-1), + receive_finish_ms(-1), + decode_start_ms(-1), + decode_finish_ms(-1), + render_time_ms(-1), + flags(VideoSendTiming::kNotTriggered) {} + +int64_t TimingFrameInfo::EndToEndDelay() const { + return capture_time_ms >= 0 ? decode_finish_ms - capture_time_ms : -1; +} + +bool TimingFrameInfo::IsLongerThan(const TimingFrameInfo& other) const { + int64_t other_delay = other.EndToEndDelay(); + return other_delay == -1 || EndToEndDelay() > other_delay; +} + +bool TimingFrameInfo::operator<(const TimingFrameInfo& other) const { + return other.IsLongerThan(*this); +} + +bool TimingFrameInfo::operator<=(const TimingFrameInfo& other) const { + return !IsLongerThan(other); +} + +bool TimingFrameInfo::IsOutlier() const { + return !IsInvalid() && (flags & VideoSendTiming::kTriggeredBySize); +} + +bool TimingFrameInfo::IsTimerTriggered() const { + return !IsInvalid() && (flags & VideoSendTiming::kTriggeredByTimer); +} + +bool TimingFrameInfo::IsInvalid() const { + return flags == VideoSendTiming::kInvalid; +} + +std::string TimingFrameInfo::ToString() const { + if (IsInvalid()) { + return ""; + } + + char buf[1024]; + rtc::SimpleStringBuilder sb(buf); + + sb << rtp_timestamp << ',' << capture_time_ms << ',' << encode_start_ms << ',' + << encode_finish_ms << ',' << packetization_finish_ms << ',' + << pacer_exit_ms << ',' << network_timestamp_ms << ',' + << network2_timestamp_ms << ',' << receive_start_ms << ',' + << receive_finish_ms << ',' << decode_start_ms << ',' << decode_finish_ms + << ',' << render_time_ms << ',' << IsOutlier() << ',' + << IsTimerTriggered(); + + return sb.str(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video/video_timing.h b/third_party/libwebrtc/api/video/video_timing.h new file mode 100644 index 0000000000..698477a81a --- /dev/null +++ b/third_party/libwebrtc/api/video/video_timing.h @@ -0,0 +1,132 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_VIDEO_TIMING_H_ +#define API_VIDEO_VIDEO_TIMING_H_ + +#include <stdint.h> + +#include <limits> +#include <string> + +#include "api/units/time_delta.h" + +namespace webrtc { + +// Video timing timestamps in ms counted from capture_time_ms of a frame. +// This structure represents data sent in video-timing RTP header extension. +struct VideoSendTiming { + enum TimingFrameFlags : uint8_t { + kNotTriggered = 0, // Timing info valid, but not to be transmitted. + // Used on send-side only. + kTriggeredByTimer = 1 << 0, // Frame marked for tracing by periodic timer. + kTriggeredBySize = 1 << 1, // Frame marked for tracing due to size. + kInvalid = std::numeric_limits<uint8_t>::max() // Invalid, ignore! + }; + + // Returns |time_ms - base_ms| capped at max 16-bit value. + // Used to fill this data structure as per + // https://webrtc.org/experiments/rtp-hdrext/video-timing/ extension stores + // 16-bit deltas of timestamps from packet capture time. + static uint16_t GetDeltaCappedMs(int64_t base_ms, int64_t time_ms); + static uint16_t GetDeltaCappedMs(TimeDelta delta); + + uint16_t encode_start_delta_ms; + uint16_t encode_finish_delta_ms; + uint16_t packetization_finish_delta_ms; + uint16_t pacer_exit_delta_ms; + uint16_t network_timestamp_delta_ms; + uint16_t network2_timestamp_delta_ms; + uint8_t flags = TimingFrameFlags::kInvalid; +}; + +// Used to report precise timings of a 'timing frames'. Contains all important +// timestamps for a lifetime of that specific frame. Reported as a string via +// GetStats(). Only frame which took the longest between two GetStats calls is +// reported. +struct TimingFrameInfo { + TimingFrameInfo(); + + // Returns end-to-end delay of a frame, if sender and receiver timestamps are + // synchronized, -1 otherwise. + int64_t EndToEndDelay() const; + + // Returns true if current frame took longer to process than `other` frame. + // If other frame's clocks are not synchronized, current frame is always + // preferred. + bool IsLongerThan(const TimingFrameInfo& other) const; + + // Returns true if flags are set to indicate this frame was marked for tracing + // due to the size being outside some limit. + bool IsOutlier() const; + + // Returns true if flags are set to indicate this frame was marked fro tracing + // due to cyclic timer. + bool IsTimerTriggered() const; + + // Returns true if the timing data is marked as invalid, in which case it + // should be ignored. + bool IsInvalid() const; + + std::string ToString() const; + + bool operator<(const TimingFrameInfo& other) const; + + bool operator<=(const TimingFrameInfo& other) const; + + uint32_t rtp_timestamp; // Identifier of a frame. + // All timestamps below are in local monotonous clock of a receiver. + // If sender clock is not yet estimated, sender timestamps + // (capture_time_ms ... pacer_exit_ms) are negative values, still + // relatively correct. + int64_t capture_time_ms; // Captrue time of a frame. + int64_t encode_start_ms; // Encode start time. + int64_t encode_finish_ms; // Encode completion time. + int64_t packetization_finish_ms; // Time when frame was passed to pacer. + int64_t pacer_exit_ms; // Time when last packet was pushed out of pacer. + // Two in-network RTP processor timestamps: meaning is application specific. + int64_t network_timestamp_ms; + int64_t network2_timestamp_ms; + int64_t receive_start_ms; // First received packet time. + int64_t receive_finish_ms; // Last received packet time. + int64_t decode_start_ms; // Decode start time. + int64_t decode_finish_ms; // Decode completion time. + int64_t render_time_ms; // Proposed render time to insure smooth playback. + + uint8_t flags; // Flags indicating validity and/or why tracing was triggered. +}; + +// Minimum and maximum playout delay values from capture to render. +// These are best effort values. +// +// A value < 0 indicates no change from previous valid value. +// +// min = max = 0 indicates that the receiver should try and render +// frame as soon as possible. +// +// min = x, max = y indicates that the receiver is free to adapt +// in the range (x, y) based on network jitter. +struct VideoPlayoutDelay { + VideoPlayoutDelay() = default; + VideoPlayoutDelay(int min_ms, int max_ms) : min_ms(min_ms), max_ms(max_ms) {} + int min_ms = -1; + int max_ms = -1; + + bool operator==(const VideoPlayoutDelay& rhs) const { + return min_ms == rhs.min_ms && max_ms == rhs.max_ms; + } +}; + +// TODO(bugs.webrtc.org/7660): Old name, delete after downstream use is updated. +using PlayoutDelay = VideoPlayoutDelay; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_TIMING_H_ diff --git a/third_party/libwebrtc/api/video_codecs/BUILD.gn b/third_party/libwebrtc/api/video_codecs/BUILD.gn new file mode 100644 index 0000000000..101848a2e4 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/BUILD.gn @@ -0,0 +1,314 @@ +# 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. + +import("../../webrtc.gni") +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +rtc_source_set("scalability_mode") { + visibility = [ "*" ] + sources = [ + "scalability_mode.cc", + "scalability_mode.h", + ] + deps = [ + "../../rtc_base:checks", + "../../rtc_base/system:rtc_export", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/strings" ] +} + +rtc_source_set("scalability_mode_helper") { + visibility = [ "*" ] + sources = [ + "scalability_mode_helper.cc", + "scalability_mode_helper.h", + ] + deps = [ "../../modules/video_coding/svc:scalability_mode_util" ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("video_codecs_api") { + visibility = [ "*" ] + sources = [ + "av1_profile.cc", + "av1_profile.h", + "h264_profile_level_id.cc", + "h264_profile_level_id.h", + "sdp_video_format.cc", + "sdp_video_format.h", + "simulcast_stream.cc", + "simulcast_stream.h", + "spatial_layer.cc", + "spatial_layer.h", + "video_codec.cc", + "video_codec.h", + "video_decoder.cc", + "video_decoder.h", + "video_decoder_factory.h", + "video_encoder.cc", + "video_encoder.h", + "video_encoder_factory.h", + "vp8_frame_buffer_controller.h", + "vp8_frame_config.cc", + "vp8_frame_config.h", + "vp8_temporal_layers.cc", + "vp8_temporal_layers.h", + "vp9_profile.cc", + "vp9_profile.h", + ] + + deps = [ + ":scalability_mode", + "..:fec_controller_api", + "..:scoped_refptr", + "../../api:array_view", + "../../modules/video_coding:codec_globals_headers", + "../../rtc_base:checks", + "../../rtc_base:logging", + "../../rtc_base:macromagic", + "../../rtc_base:refcount", + "../../rtc_base:stringutils", + "../../rtc_base/system:rtc_export", + "../units:data_rate", + "../video:encoded_image", + "../video:render_resolution", + "../video:resolution", + "../video:video_bitrate_allocation", + "../video:video_codec_constants", + "../video:video_frame", + "../video:video_rtp_headers", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/container:inlined_vector", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_source_set("bitstream_parser_api") { + visibility = [ "*" ] + sources = [ "bitstream_parser.h" ] + deps = [ "..:array_view" ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] +} + +rtc_library("builtin_video_decoder_factory") { + visibility = [ "*" ] + allow_poison = [ + "audio_codecs", # TODO(bugs.webrtc.org/8396): Remove. + "software_video_codecs", + ] + sources = [ + "builtin_video_decoder_factory.cc", + "builtin_video_decoder_factory.h", + ] + + deps = [ + ":video_codecs_api", + "../../api:scoped_refptr", + "../../media:rtc_internal_video_codecs", + "../../rtc_base/system:rtc_export", + ] +} + +rtc_library("builtin_video_encoder_factory") { + visibility = [ "*" ] + allow_poison = [ + "audio_codecs", # TODO(bugs.webrtc.org/8396): Remove. + "software_video_codecs", + ] + sources = [ + "builtin_video_encoder_factory.cc", + "builtin_video_encoder_factory.h", + ] + + deps = [ + ":video_codecs_api", + "../../api:scoped_refptr", + "../../media:codec", + "../../media:media_constants", + "../../media:rtc_encoder_simulcast_proxy", + "../../media:rtc_internal_video_codecs", + "../../media:rtc_media_base", + "../../rtc_base:checks", + "../../rtc_base/system:rtc_export", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_source_set("video_encoder_factory_template") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + public = [ "video_encoder_factory_template.h" ] + + deps = [ + ":video_codecs_api", + "../../api:array_view", + "../../modules/video_coding/svc:scalability_mode_util", + ] + + absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container" ] +} + +rtc_source_set("video_encoder_factory_template_libvpx_vp8_adapter") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + public = [ "video_encoder_factory_template_libvpx_vp8_adapter.h" ] + + deps = [ + ":video_codecs_api", + "../../modules/video_coding:webrtc_vp8", + "../../modules/video_coding:webrtc_vp8_scalability", + ] + + absl_deps = [ "//third_party/abseil-cpp/absl/container:inlined_vector" ] +} + +rtc_source_set("video_encoder_factory_template_libvpx_vp9_adapter") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + public = [ "video_encoder_factory_template_libvpx_vp9_adapter.h" ] + + deps = [ "../../modules/video_coding:webrtc_vp9" ] +} + +rtc_source_set("video_encoder_factory_template_open_h264_adapter") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + public = [ "video_encoder_factory_template_open_h264_adapter.h" ] + + deps = [ "../../modules/video_coding:webrtc_h264" ] +} + +rtc_source_set("video_encoder_factory_template_libaom_av1_adapter") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + public = [ "video_encoder_factory_template_libaom_av1_adapter.h" ] + + deps = [ + ":scalability_mode", + ":video_codecs_api", + "../../modules/video_coding/codecs/av1:av1_svc_config", + "../../modules/video_coding/codecs/av1:libaom_av1_encoder", + "../../modules/video_coding/svc:scalability_mode_util", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/container:inlined_vector" ] +} + +rtc_source_set("video_decoder_factory_template") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + public = [ "video_decoder_factory_template.h" ] + + deps = [ + ":video_codecs_api", + "../../api:array_view", + ] + + absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container" ] +} + +rtc_source_set("video_decoder_factory_template_libvpx_vp8_adapter") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + public = [ "video_decoder_factory_template_libvpx_vp8_adapter.h" ] + + deps = [ + ":video_codecs_api", + "../../modules/video_coding:webrtc_vp8", + ] +} + +rtc_source_set("video_decoder_factory_template_libvpx_vp9_adapter") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + public = [ "video_decoder_factory_template_libvpx_vp9_adapter.h" ] + + deps = [ "../../modules/video_coding:webrtc_vp9" ] +} + +rtc_source_set("video_decoder_factory_template_open_h264_adapter") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + public = [ "video_decoder_factory_template_open_h264_adapter.h" ] + + deps = [ "../../modules/video_coding:webrtc_h264" ] +} + +rtc_source_set("video_decoder_factory_template_dav1d_adapter") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + public = [ "video_decoder_factory_template_dav1d_adapter.h" ] + + deps = [ + ":video_codecs_api", + "../../modules/video_coding/codecs/av1:dav1d_decoder", + ] +} + +rtc_library("vp8_temporal_layers_factory") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] + sources = [ + "vp8_temporal_layers_factory.cc", + "vp8_temporal_layers_factory.h", + ] + + deps = [ + ":video_codecs_api", + "../:fec_controller_api", + "../../modules/video_coding:video_coding_utility", + "../../modules/video_coding:webrtc_vp8_temporal_layers", + "../../rtc_base:checks", + ] +} + +rtc_library("rtc_software_fallback_wrappers") { + visibility = [ "*" ] + + sources = [ + "video_decoder_software_fallback_wrapper.cc", + "video_decoder_software_fallback_wrapper.h", + "video_encoder_software_fallback_wrapper.cc", + "video_encoder_software_fallback_wrapper.h", + ] + + deps = [ + ":video_codecs_api", + "..:fec_controller_api", + "../../api/video:video_frame", + "../../media:rtc_media_base", + "../../modules/video_coding:video_codec_interface", + "../../modules/video_coding:video_coding_utility", + "../../rtc_base:checks", + "../../rtc_base:event_tracer", + "../../rtc_base:logging", + "../../rtc_base/system:rtc_export", + "../../system_wrappers:field_trial", + "../../system_wrappers:metrics", + "../video:encoded_image", + "../video:video_bitrate_allocation", + "../video:video_frame", + "../video:video_rtp_headers", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] +} diff --git a/third_party/libwebrtc/api/video_codecs/OWNERS b/third_party/libwebrtc/api/video_codecs/OWNERS new file mode 100644 index 0000000000..f73b04f829 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/OWNERS @@ -0,0 +1,4 @@ +magjed@webrtc.org +sprang@webrtc.org +brandtr@webrtc.org +philipel@webrtc.org diff --git a/third_party/libwebrtc/api/video_codecs/av1_profile.cc b/third_party/libwebrtc/api/video_codecs/av1_profile.cc new file mode 100644 index 0000000000..eefe166d80 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/av1_profile.cc @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2022 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 "api/video_codecs/av1_profile.h" + +#include <map> +#include <utility> + +#include "rtc_base/string_to_number.h" + +namespace webrtc { + +// Parameter name in the format parameter map for AV1 video. +const char kAV1FmtpProfile[] = "profile"; + +absl::string_view AV1ProfileToString(AV1Profile profile) { + switch (profile) { + case AV1Profile::kProfile0: + return "0"; + case AV1Profile::kProfile1: + return "1"; + case AV1Profile::kProfile2: + return "2"; + } + return "0"; +} + +absl::optional<AV1Profile> StringToAV1Profile(absl::string_view str) { + const absl::optional<int> i = rtc::StringToNumber<int>(str); + if (!i.has_value()) + return absl::nullopt; + + switch (i.value()) { + case 0: + return AV1Profile::kProfile0; + case 1: + return AV1Profile::kProfile1; + case 2: + return AV1Profile::kProfile2; + default: + return absl::nullopt; + } +} + +absl::optional<AV1Profile> ParseSdpForAV1Profile( + const SdpVideoFormat::Parameters& params) { + const auto profile_it = params.find(kAV1FmtpProfile); + if (profile_it == params.end()) + return AV1Profile::kProfile0; + const std::string& profile_str = profile_it->second; + return StringToAV1Profile(profile_str); +} + +bool AV1IsSameProfile(const SdpVideoFormat::Parameters& params1, + const SdpVideoFormat::Parameters& params2) { + const absl::optional<AV1Profile> profile = ParseSdpForAV1Profile(params1); + const absl::optional<AV1Profile> other_profile = + ParseSdpForAV1Profile(params2); + return profile && other_profile && profile == other_profile; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/av1_profile.h b/third_party/libwebrtc/api/video_codecs/av1_profile.h new file mode 100644 index 0000000000..2254d5ecd3 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/av1_profile.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_AV1_PROFILE_H_ +#define API_VIDEO_CODECS_AV1_PROFILE_H_ + +#include <string> + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/video_codecs/sdp_video_format.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Profile information for AV1 video. +extern RTC_EXPORT const char kAV1FmtpProfile[]; + +// Profiles can be found at: +// https://aomedia.org/av1/specification/annex-a/#profiles +// The enum values match the number specified in the SDP. +enum class AV1Profile { + kProfile0 = 0, + kProfile1 = 1, + kProfile2 = 2, +}; + +// Helper function which converts an AV1Profile to std::string. Returns "0" if +// an unknown value is passed in. +RTC_EXPORT absl::string_view AV1ProfileToString(AV1Profile profile); + +// Helper function which converts a std::string to AV1Profile. Returns null if +// |profile| is not a valid profile string. +absl::optional<AV1Profile> StringToAV1Profile(absl::string_view profile); + +// Parses an SDP key-value map of format parameters to retrive an AV1 profile. +// Returns an AV1Profile if one has been specified, `kProfile0` if no profile is +// specified and an empty value if the profile key is present but contains an +// invalid value. +RTC_EXPORT absl::optional<AV1Profile> ParseSdpForAV1Profile( + const SdpVideoFormat::Parameters& params); + +// Returns true if the parameters have the same AV1 profile or neither contains +// an AV1 profile, otherwise false. +bool AV1IsSameProfile(const SdpVideoFormat::Parameters& params1, + const SdpVideoFormat::Parameters& params2); + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_AV1_PROFILE_H_ diff --git a/third_party/libwebrtc/api/video_codecs/bitstream_parser.h b/third_party/libwebrtc/api/video_codecs/bitstream_parser.h new file mode 100644 index 0000000000..86ce192e49 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/bitstream_parser.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019 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 API_VIDEO_CODECS_BITSTREAM_PARSER_H_ +#define API_VIDEO_CODECS_BITSTREAM_PARSER_H_ + +#include <stddef.h> +#include <stdint.h> + +#include "absl/types/optional.h" +#include "api/array_view.h" + +namespace webrtc { + +// This class is an interface for bitstream parsers. +class BitstreamParser { + public: + virtual ~BitstreamParser() = default; + + // Parse an additional chunk of the bitstream. + virtual void ParseBitstream(rtc::ArrayView<const uint8_t> bitstream) = 0; + + // Get the last extracted QP value from the parsed bitstream. If no QP + // value could be parsed, returns absl::nullopt. + virtual absl::optional<int> GetLastSliceQp() const = 0; +}; + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_BITSTREAM_PARSER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/bitstream_parser_api_gn/moz.build b/third_party/libwebrtc/api/video_codecs/bitstream_parser_api_gn/moz.build new file mode 100644 index 0000000000..dcf5d2273c --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/bitstream_parser_api_gn/moz.build @@ -0,0 +1,205 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("bitstream_parser_api_gn") diff --git a/third_party/libwebrtc/api/video_codecs/builtin_video_decoder_factory.cc b/third_party/libwebrtc/api/video_codecs/builtin_video_decoder_factory.cc new file mode 100644 index 0000000000..f831905189 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/builtin_video_decoder_factory.cc @@ -0,0 +1,23 @@ +/* + * 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 "api/video_codecs/builtin_video_decoder_factory.h" + +#include <memory> + +#include "media/engine/internal_decoder_factory.h" + +namespace webrtc { + +std::unique_ptr<VideoDecoderFactory> CreateBuiltinVideoDecoderFactory() { + return std::make_unique<InternalDecoderFactory>(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/builtin_video_decoder_factory.h b/third_party/libwebrtc/api/video_codecs/builtin_video_decoder_factory.h new file mode 100644 index 0000000000..d516077d99 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/builtin_video_decoder_factory.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_CODECS_BUILTIN_VIDEO_DECODER_FACTORY_H_ +#define API_VIDEO_CODECS_BUILTIN_VIDEO_DECODER_FACTORY_H_ + +#include <memory> + +#include "api/video_codecs/video_decoder_factory.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Creates a new factory that can create the built-in types of video decoders. +RTC_EXPORT std::unique_ptr<VideoDecoderFactory> +CreateBuiltinVideoDecoderFactory(); + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_BUILTIN_VIDEO_DECODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/video_codecs/builtin_video_encoder_factory.cc b/third_party/libwebrtc/api/video_codecs/builtin_video_encoder_factory.cc new file mode 100644 index 0000000000..7c5f35b216 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/builtin_video_encoder_factory.cc @@ -0,0 +1,71 @@ +/* + * 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 "api/video_codecs/builtin_video_encoder_factory.h" + +#include <memory> +#include <string> +#include <vector> + +#include "absl/strings/match.h" +#include "absl/types/optional.h" +#include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_encoder.h" +#include "media/base/codec.h" +#include "media/base/media_constants.h" +#include "media/engine/encoder_simulcast_proxy.h" +#include "media/engine/internal_encoder_factory.h" +#include "rtc_base/checks.h" + +namespace webrtc { + +namespace { + +// This class wraps the internal factory and adds simulcast. +class BuiltinVideoEncoderFactory : public VideoEncoderFactory { + public: + BuiltinVideoEncoderFactory() + : internal_encoder_factory_(new InternalEncoderFactory()) {} + + std::unique_ptr<VideoEncoder> CreateVideoEncoder( + const SdpVideoFormat& format) override { + // Try creating internal encoder. + std::unique_ptr<VideoEncoder> internal_encoder; + if (format.IsCodecInList( + internal_encoder_factory_->GetSupportedFormats())) { + internal_encoder = std::make_unique<EncoderSimulcastProxy>( + internal_encoder_factory_.get(), format); + } + + return internal_encoder; + } + + std::vector<SdpVideoFormat> GetSupportedFormats() const override { + return internal_encoder_factory_->GetSupportedFormats(); + } + + CodecSupport QueryCodecSupport( + const SdpVideoFormat& format, + absl::optional<std::string> scalability_mode) const override { + return internal_encoder_factory_->QueryCodecSupport(format, + scalability_mode); + } + + private: + const std::unique_ptr<VideoEncoderFactory> internal_encoder_factory_; +}; + +} // namespace + +std::unique_ptr<VideoEncoderFactory> CreateBuiltinVideoEncoderFactory() { + return std::make_unique<BuiltinVideoEncoderFactory>(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/builtin_video_encoder_factory.h b/third_party/libwebrtc/api/video_codecs/builtin_video_encoder_factory.h new file mode 100644 index 0000000000..2c4537205c --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/builtin_video_encoder_factory.h @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_CODECS_BUILTIN_VIDEO_ENCODER_FACTORY_H_ +#define API_VIDEO_CODECS_BUILTIN_VIDEO_ENCODER_FACTORY_H_ + +#include <memory> + +#include "api/video_codecs/video_encoder_factory.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Creates a new factory that can create the built-in types of video encoders. +// The factory has simulcast support for VP8. +RTC_EXPORT std::unique_ptr<VideoEncoderFactory> +CreateBuiltinVideoEncoderFactory(); + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_BUILTIN_VIDEO_ENCODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/video_codecs/h264_profile_level_id.cc b/third_party/libwebrtc/api/video_codecs/h264_profile_level_id.cc new file mode 100644 index 0000000000..02b43ba4f2 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/h264_profile_level_id.cc @@ -0,0 +1,256 @@ +/* + * 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 "api/video_codecs/h264_profile_level_id.h" + +#include <cstdio> +#include <cstdlib> +#include <string> + +#include "rtc_base/arraysize.h" +#include "rtc_base/checks.h" + +namespace webrtc { + +namespace { + +const char kProfileLevelId[] = "profile-level-id"; + +// For level_idc=11 and profile_idc=0x42, 0x4D, or 0x58, the constraint set3 +// flag specifies if level 1b or level 1.1 is used. +const uint8_t kConstraintSet3Flag = 0x10; + +// Convert a string of 8 characters into a byte where the positions containing +// character c will have their bit set. For example, c = 'x', str = "x1xx0000" +// will return 0b10110000. constexpr is used so that the pattern table in +// kProfilePatterns is statically initialized. +constexpr uint8_t ByteMaskString(char c, const char (&str)[9]) { + return (str[0] == c) << 7 | (str[1] == c) << 6 | (str[2] == c) << 5 | + (str[3] == c) << 4 | (str[4] == c) << 3 | (str[5] == c) << 2 | + (str[6] == c) << 1 | (str[7] == c) << 0; +} + +// Class for matching bit patterns such as "x1xx0000" where 'x' is allowed to be +// either 0 or 1. +class BitPattern { + public: + explicit constexpr BitPattern(const char (&str)[9]) + : mask_(~ByteMaskString('x', str)), + masked_value_(ByteMaskString('1', str)) {} + + bool IsMatch(uint8_t value) const { return masked_value_ == (value & mask_); } + + private: + const uint8_t mask_; + const uint8_t masked_value_; +}; + +// Table for converting between profile_idc/profile_iop to H264Profile. +struct ProfilePattern { + const uint8_t profile_idc; + const BitPattern profile_iop; + const H264Profile profile; +}; + +// This is from https://tools.ietf.org/html/rfc6184#section-8.1. +constexpr ProfilePattern kProfilePatterns[] = { + {0x42, BitPattern("x1xx0000"), H264Profile::kProfileConstrainedBaseline}, + {0x4D, BitPattern("1xxx0000"), H264Profile::kProfileConstrainedBaseline}, + {0x58, BitPattern("11xx0000"), H264Profile::kProfileConstrainedBaseline}, + {0x42, BitPattern("x0xx0000"), H264Profile::kProfileBaseline}, + {0x58, BitPattern("10xx0000"), H264Profile::kProfileBaseline}, + {0x4D, BitPattern("0x0x0000"), H264Profile::kProfileMain}, + {0x64, BitPattern("00000000"), H264Profile::kProfileHigh}, + {0x64, BitPattern("00001100"), H264Profile::kProfileConstrainedHigh}, + {0xF4, BitPattern("00000000"), H264Profile::kProfilePredictiveHigh444}}; + +struct LevelConstraint { + const int max_macroblocks_per_second; + const int max_macroblock_frame_size; + const H264Level level; +}; + +// This is from ITU-T H.264 (02/2016) Table A-1 – Level limits. +static constexpr LevelConstraint kLevelConstraints[] = { + {1485, 99, H264Level::kLevel1}, + {1485, 99, H264Level::kLevel1_b}, + {3000, 396, H264Level::kLevel1_1}, + {6000, 396, H264Level::kLevel1_2}, + {11880, 396, H264Level::kLevel1_3}, + {11880, 396, H264Level::kLevel2}, + {19800, 792, H264Level::kLevel2_1}, + {20250, 1620, H264Level::kLevel2_2}, + {40500, 1620, H264Level::kLevel3}, + {108000, 3600, H264Level::kLevel3_1}, + {216000, 5120, H264Level::kLevel3_2}, + {245760, 8192, H264Level::kLevel4}, + {245760, 8192, H264Level::kLevel4_1}, + {522240, 8704, H264Level::kLevel4_2}, + {589824, 22080, H264Level::kLevel5}, + {983040, 36864, H264Level::kLevel5_1}, + {2073600, 36864, H264Level::kLevel5_2}, +}; + +} // anonymous namespace + +absl::optional<H264ProfileLevelId> ParseH264ProfileLevelId(const char* str) { + // The string should consist of 3 bytes in hexadecimal format. + if (strlen(str) != 6u) + return absl::nullopt; + const uint32_t profile_level_id_numeric = strtol(str, nullptr, 16); + if (profile_level_id_numeric == 0) + return absl::nullopt; + + // Separate into three bytes. + const uint8_t level_idc = + static_cast<uint8_t>(profile_level_id_numeric & 0xFF); + const uint8_t profile_iop = + static_cast<uint8_t>((profile_level_id_numeric >> 8) & 0xFF); + const uint8_t profile_idc = + static_cast<uint8_t>((profile_level_id_numeric >> 16) & 0xFF); + + // Parse level based on level_idc and constraint set 3 flag. + H264Level level_casted = static_cast<H264Level>(level_idc); + H264Level level; + + switch (level_casted) { + case H264Level::kLevel1_1: + level = (profile_iop & kConstraintSet3Flag) != 0 ? H264Level::kLevel1_b + : H264Level::kLevel1_1; + break; + case H264Level::kLevel1: + case H264Level::kLevel1_2: + case H264Level::kLevel1_3: + case H264Level::kLevel2: + case H264Level::kLevel2_1: + case H264Level::kLevel2_2: + case H264Level::kLevel3: + case H264Level::kLevel3_1: + case H264Level::kLevel3_2: + case H264Level::kLevel4: + case H264Level::kLevel4_1: + case H264Level::kLevel4_2: + case H264Level::kLevel5: + case H264Level::kLevel5_1: + case H264Level::kLevel5_2: + level = level_casted; + break; + default: + // Unrecognized level_idc. + return absl::nullopt; + } + + // Parse profile_idc/profile_iop into a Profile enum. + for (const ProfilePattern& pattern : kProfilePatterns) { + if (profile_idc == pattern.profile_idc && + pattern.profile_iop.IsMatch(profile_iop)) { + return H264ProfileLevelId(pattern.profile, level); + } + } + + // Unrecognized profile_idc/profile_iop combination. + return absl::nullopt; +} + +absl::optional<H264Level> H264SupportedLevel(int max_frame_pixel_count, + float max_fps) { + static const int kPixelsPerMacroblock = 16 * 16; + + for (int i = arraysize(kLevelConstraints) - 1; i >= 0; --i) { + const LevelConstraint& level_constraint = kLevelConstraints[i]; + if (level_constraint.max_macroblock_frame_size * kPixelsPerMacroblock <= + max_frame_pixel_count && + level_constraint.max_macroblocks_per_second <= + max_fps * level_constraint.max_macroblock_frame_size) { + return level_constraint.level; + } + } + + // No level supported. + return absl::nullopt; +} + +absl::optional<H264ProfileLevelId> ParseSdpForH264ProfileLevelId( + const SdpVideoFormat::Parameters& params) { + // TODO(magjed): The default should really be kProfileBaseline and kLevel1 + // according to the spec: https://tools.ietf.org/html/rfc6184#section-8.1. In + // order to not break backwards compatibility with older versions of WebRTC + // where external codecs don't have any parameters, use + // kProfileConstrainedBaseline kLevel3_1 instead. This workaround will only be + // done in an interim period to allow external clients to update their code. + // http://crbug/webrtc/6337. + static const H264ProfileLevelId kDefaultProfileLevelId( + H264Profile::kProfileConstrainedBaseline, H264Level::kLevel3_1); + + const auto profile_level_id_it = params.find(kProfileLevelId); + return (profile_level_id_it == params.end()) + ? kDefaultProfileLevelId + : ParseH264ProfileLevelId(profile_level_id_it->second.c_str()); +} + +absl::optional<std::string> H264ProfileLevelIdToString( + const H264ProfileLevelId& profile_level_id) { + // Handle special case level == 1b. + if (profile_level_id.level == H264Level::kLevel1_b) { + switch (profile_level_id.profile) { + case H264Profile::kProfileConstrainedBaseline: + return {"42f00b"}; + case H264Profile::kProfileBaseline: + return {"42100b"}; + case H264Profile::kProfileMain: + return {"4d100b"}; + // Level 1b is not allowed for other profiles. + default: + return absl::nullopt; + } + } + + const char* profile_idc_iop_string; + switch (profile_level_id.profile) { + case H264Profile::kProfileConstrainedBaseline: + profile_idc_iop_string = "42e0"; + break; + case H264Profile::kProfileBaseline: + profile_idc_iop_string = "4200"; + break; + case H264Profile::kProfileMain: + profile_idc_iop_string = "4d00"; + break; + case H264Profile::kProfileConstrainedHigh: + profile_idc_iop_string = "640c"; + break; + case H264Profile::kProfileHigh: + profile_idc_iop_string = "6400"; + break; + case H264Profile::kProfilePredictiveHigh444: + profile_idc_iop_string = "f400"; + break; + // Unrecognized profile. + default: + return absl::nullopt; + } + + char str[7]; + snprintf(str, 7u, "%s%02x", profile_idc_iop_string, profile_level_id.level); + return {str}; +} + +bool H264IsSameProfile(const SdpVideoFormat::Parameters& params1, + const SdpVideoFormat::Parameters& params2) { + const absl::optional<H264ProfileLevelId> profile_level_id = + ParseSdpForH264ProfileLevelId(params1); + const absl::optional<H264ProfileLevelId> other_profile_level_id = + ParseSdpForH264ProfileLevelId(params2); + // Compare H264 profiles, but not levels. + return profile_level_id && other_profile_level_id && + profile_level_id->profile == other_profile_level_id->profile; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/h264_profile_level_id.h b/third_party/libwebrtc/api/video_codecs/h264_profile_level_id.h new file mode 100644 index 0000000000..4b46ad329d --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/h264_profile_level_id.h @@ -0,0 +1,92 @@ +/* + * 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 API_VIDEO_CODECS_H264_PROFILE_LEVEL_ID_H_ +#define API_VIDEO_CODECS_H264_PROFILE_LEVEL_ID_H_ + +#include <string> + +#include "absl/types/optional.h" +#include "api/video_codecs/sdp_video_format.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +enum class H264Profile { + kProfileConstrainedBaseline, + kProfileBaseline, + kProfileMain, + kProfileConstrainedHigh, + kProfileHigh, + kProfilePredictiveHigh444, +}; + +// All values are equal to ten times the level number, except level 1b which is +// special. +enum class H264Level { + kLevel1_b = 0, + kLevel1 = 10, + kLevel1_1 = 11, + kLevel1_2 = 12, + kLevel1_3 = 13, + kLevel2 = 20, + kLevel2_1 = 21, + kLevel2_2 = 22, + kLevel3 = 30, + kLevel3_1 = 31, + kLevel3_2 = 32, + kLevel4 = 40, + kLevel4_1 = 41, + kLevel4_2 = 42, + kLevel5 = 50, + kLevel5_1 = 51, + kLevel5_2 = 52 +}; + +struct H264ProfileLevelId { + constexpr H264ProfileLevelId(H264Profile profile, H264Level level) + : profile(profile), level(level) {} + H264Profile profile; + H264Level level; +}; + +// Parse profile level id that is represented as a string of 3 hex bytes. +// Nothing will be returned if the string is not a recognized H264 +// profile level id. +absl::optional<H264ProfileLevelId> ParseH264ProfileLevelId(const char* str); + +// Parse profile level id that is represented as a string of 3 hex bytes +// contained in an SDP key-value map. A default profile level id will be +// returned if the profile-level-id key is missing. Nothing will be returned if +// the key is present but the string is invalid. +RTC_EXPORT absl::optional<H264ProfileLevelId> ParseSdpForH264ProfileLevelId( + const SdpVideoFormat::Parameters& params); + +// Given that a decoder supports up to a given frame size (in pixels) at up to a +// given number of frames per second, return the highest H.264 level where it +// can guarantee that it will be able to support all valid encoded streams that +// are within that level. +RTC_EXPORT absl::optional<H264Level> H264SupportedLevel( + int max_frame_pixel_count, + float max_fps); + +// Returns canonical string representation as three hex bytes of the profile +// level id, or returns nothing for invalid profile level ids. +RTC_EXPORT absl::optional<std::string> H264ProfileLevelIdToString( + const H264ProfileLevelId& profile_level_id); + +// Returns true if the parameters have the same H264 profile (Baseline, High, +// etc). +RTC_EXPORT bool H264IsSameProfile(const SdpVideoFormat::Parameters& params1, + const SdpVideoFormat::Parameters& params2); + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_H264_PROFILE_LEVEL_ID_H_ diff --git a/third_party/libwebrtc/api/video_codecs/rtc_software_fallback_wrappers_gn/moz.build b/third_party/libwebrtc/api/video_codecs/rtc_software_fallback_wrappers_gn/moz.build new file mode 100644 index 0000000000..987a01bd2f --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/rtc_software_fallback_wrappers_gn/moz.build @@ -0,0 +1,234 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc", + "/third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "GLESv2", + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("rtc_software_fallback_wrappers_gn") diff --git a/third_party/libwebrtc/api/video_codecs/scalability_mode.cc b/third_party/libwebrtc/api/video_codecs/scalability_mode.cc new file mode 100644 index 0000000000..c449b4217e --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/scalability_mode.cc @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022 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 "api/video_codecs/scalability_mode.h" + +#include "rtc_base/checks.h" + +namespace webrtc { + +absl::string_view ScalabilityModeToString(ScalabilityMode scalability_mode) { + switch (scalability_mode) { + case ScalabilityMode::kL1T1: + return "L1T1"; + case ScalabilityMode::kL1T2: + return "L1T2"; + case ScalabilityMode::kL1T3: + return "L1T3"; + case ScalabilityMode::kL2T1: + return "L2T1"; + case ScalabilityMode::kL2T1h: + return "L2T1h"; + case ScalabilityMode::kL2T1_KEY: + return "L2T1_KEY"; + case ScalabilityMode::kL2T2: + return "L2T2"; + case ScalabilityMode::kL2T2h: + return "L2T2h"; + case ScalabilityMode::kL2T2_KEY: + return "L2T2_KEY"; + case ScalabilityMode::kL2T2_KEY_SHIFT: + return "L2T2_KEY_SHIFT"; + case ScalabilityMode::kL2T3: + return "L2T3"; + case ScalabilityMode::kL2T3h: + return "L2T3h"; + case ScalabilityMode::kL2T3_KEY: + return "L2T3_KEY"; + case ScalabilityMode::kL3T1: + return "L3T1"; + case ScalabilityMode::kL3T1h: + return "L3T1h"; + case ScalabilityMode::kL3T1_KEY: + return "L3T1_KEY"; + case ScalabilityMode::kL3T2: + return "L3T2"; + case ScalabilityMode::kL3T2h: + return "L3T2h"; + case ScalabilityMode::kL3T2_KEY: + return "L3T2_KEY"; + case ScalabilityMode::kL3T3: + return "L3T3"; + case ScalabilityMode::kL3T3h: + return "L3T3h"; + case ScalabilityMode::kL3T3_KEY: + return "L3T3_KEY"; + case ScalabilityMode::kS2T1: + return "S2T1"; + case ScalabilityMode::kS2T1h: + return "S2T1h"; + case ScalabilityMode::kS2T2: + return "S2T2"; + case ScalabilityMode::kS2T2h: + return "S2T2h"; + case ScalabilityMode::kS2T3: + return "S2T3"; + case ScalabilityMode::kS2T3h: + return "S2T3h"; + case ScalabilityMode::kS3T1: + return "S3T1"; + case ScalabilityMode::kS3T1h: + return "S3T1h"; + case ScalabilityMode::kS3T2: + return "S3T2"; + case ScalabilityMode::kS3T2h: + return "S3T2h"; + case ScalabilityMode::kS3T3: + return "S3T3"; + case ScalabilityMode::kS3T3h: + return "S3T3h"; + } + RTC_CHECK_NOTREACHED(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/scalability_mode.h b/third_party/libwebrtc/api/video_codecs/scalability_mode.h new file mode 100644 index 0000000000..b26f32eb22 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/scalability_mode.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_SCALABILITY_MODE_H_ +#define API_VIDEO_CODECS_SCALABILITY_MODE_H_ + +#include <stddef.h> +#include <stdint.h> + +#include "absl/strings/string_view.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Supported scalability modes. Most applications should use the +// PeerConnection-level apis where scalability mode is represented as a string. +// This list of currently recognized modes is intended for the api boundary +// between webrtc and injected encoders. Any application usage outside of +// injected encoders is strongly discouraged. +enum class ScalabilityMode : uint8_t { + kL1T1, + kL1T2, + kL1T3, + kL2T1, + kL2T1h, + kL2T1_KEY, + kL2T2, + kL2T2h, + kL2T2_KEY, + kL2T2_KEY_SHIFT, + kL2T3, + kL2T3h, + kL2T3_KEY, + kL3T1, + kL3T1h, + kL3T1_KEY, + kL3T2, + kL3T2h, + kL3T2_KEY, + kL3T3, + kL3T3h, + kL3T3_KEY, + kS2T1, + kS2T1h, + kS2T2, + kS2T2h, + kS2T3, + kS2T3h, + kS3T1, + kS3T1h, + kS3T2, + kS3T2h, + kS3T3, + kS3T3h, +}; + +inline constexpr ScalabilityMode kAllScalabilityModes[] = { + // clang-format off + ScalabilityMode::kL1T1, + ScalabilityMode::kL1T2, + ScalabilityMode::kL1T3, + ScalabilityMode::kL2T1, + ScalabilityMode::kL2T1h, + ScalabilityMode::kL2T1_KEY, + ScalabilityMode::kL2T2, + ScalabilityMode::kL2T2h, + ScalabilityMode::kL2T2_KEY, + ScalabilityMode::kL2T2_KEY_SHIFT, + ScalabilityMode::kL2T3, + ScalabilityMode::kL2T3h, + ScalabilityMode::kL2T3_KEY, + ScalabilityMode::kL3T1, + ScalabilityMode::kL3T1h, + ScalabilityMode::kL3T1_KEY, + ScalabilityMode::kL3T2, + ScalabilityMode::kL3T2h, + ScalabilityMode::kL3T2_KEY, + ScalabilityMode::kL3T3, + ScalabilityMode::kL3T3h, + ScalabilityMode::kL3T3_KEY, + ScalabilityMode::kS2T1, + ScalabilityMode::kS2T1h, + ScalabilityMode::kS2T2, + ScalabilityMode::kS2T2h, + ScalabilityMode::kS2T3, + ScalabilityMode::kS2T3h, + ScalabilityMode::kS3T1, + ScalabilityMode::kS3T1h, + ScalabilityMode::kS3T2, + ScalabilityMode::kS3T2h, + ScalabilityMode::kS3T3, + ScalabilityMode::kS3T3h, + // clang-format on +}; + +inline constexpr size_t kScalabilityModeCount = + sizeof(kAllScalabilityModes) / sizeof(ScalabilityMode); + +RTC_EXPORT +absl::string_view ScalabilityModeToString(ScalabilityMode scalability_mode); + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_SCALABILITY_MODE_H_ diff --git a/third_party/libwebrtc/api/video_codecs/scalability_mode_gn/moz.build b/third_party/libwebrtc/api/video_codecs/scalability_mode_gn/moz.build new file mode 100644 index 0000000000..a308bfc58f --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/scalability_mode_gn/moz.build @@ -0,0 +1,221 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video_codecs/scalability_mode.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("scalability_mode_gn") diff --git a/third_party/libwebrtc/api/video_codecs/scalability_mode_helper.cc b/third_party/libwebrtc/api/video_codecs/scalability_mode_helper.cc new file mode 100644 index 0000000000..b4571632d9 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/scalability_mode_helper.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 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 "api/video_codecs/scalability_mode_helper.h" + +#include "modules/video_coding/svc/scalability_mode_util.h" + +namespace webrtc { + +absl::optional<int> ScalabilityModeStringToNumSpatialLayers( + absl::string_view scalability_mode_string) { + absl::optional<ScalabilityMode> scalability_mode = + ScalabilityModeFromString(scalability_mode_string); + if (!scalability_mode.has_value()) { + return absl::nullopt; + } + return ScalabilityModeToNumSpatialLayers(*scalability_mode); +} + +absl::optional<int> ScalabilityModeStringToNumTemporalLayers( + absl::string_view scalability_mode_string) { + absl::optional<ScalabilityMode> scalability_mode = + ScalabilityModeFromString(scalability_mode_string); + if (!scalability_mode.has_value()) { + return absl::nullopt; + } + return ScalabilityModeToNumTemporalLayers(*scalability_mode); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/scalability_mode_helper.h b/third_party/libwebrtc/api/video_codecs/scalability_mode_helper.h new file mode 100644 index 0000000000..a8b060d079 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/scalability_mode_helper.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_SCALABILITY_MODE_HELPER_H_ +#define API_VIDEO_CODECS_SCALABILITY_MODE_HELPER_H_ + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" + +namespace webrtc { + +// Returns the number of spatial layers from the `scalability_mode_string` +// or nullopt if the given mode is unknown. +absl::optional<int> ScalabilityModeStringToNumSpatialLayers( + absl::string_view scalability_mode_string); + +// Returns the number of temporal layers from the `scalability_mode_string` +// or nullopt if the given mode is unknown. +absl::optional<int> ScalabilityModeStringToNumTemporalLayers( + absl::string_view scalability_mode_string); + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_SCALABILITY_MODE_HELPER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/sdp_video_format.cc b/third_party/libwebrtc/api/video_codecs/sdp_video_format.cc new file mode 100644 index 0000000000..cb7e98a682 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/sdp_video_format.cc @@ -0,0 +1,171 @@ +/* + * 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 "api/video_codecs/sdp_video_format.h" + +#include "absl/strings/match.h" +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/video_codecs/av1_profile.h" +#include "api/video_codecs/h264_profile_level_id.h" +#include "api/video_codecs/video_codec.h" +#include "api/video_codecs/vp9_profile.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +namespace { + +std::string H264GetPacketizationModeOrDefault( + const SdpVideoFormat::Parameters& params) { + constexpr char kH264FmtpPacketizationMode[] = "packetization-mode"; + const auto it = params.find(kH264FmtpPacketizationMode); + if (it != params.end()) { + return it->second; + } + // If packetization-mode is not present, default to "0". + // https://tools.ietf.org/html/rfc6184#section-6.2 + return "0"; +} + +bool H264IsSamePacketizationMode(const SdpVideoFormat::Parameters& left, + const SdpVideoFormat::Parameters& right) { + return H264GetPacketizationModeOrDefault(left) == + H264GetPacketizationModeOrDefault(right); +} + +// Some (video) codecs are actually families of codecs and rely on parameters +// to distinguish different incompatible family members. +bool IsSameCodecSpecific(const SdpVideoFormat& format1, + const SdpVideoFormat& format2) { + // The assumption when calling this function is that the two formats have the + // same name. + RTC_DCHECK(absl::EqualsIgnoreCase(format1.name, format2.name)); + + VideoCodecType codec_type = PayloadStringToCodecType(format1.name); + switch (codec_type) { + case kVideoCodecH264: + return H264IsSameProfile(format1.parameters, format2.parameters) && + H264IsSamePacketizationMode(format1.parameters, + format2.parameters); + case kVideoCodecVP9: + return VP9IsSameProfile(format1.parameters, format2.parameters); + case kVideoCodecAV1: + return AV1IsSameProfile(format1.parameters, format2.parameters); + default: + return true; + } +} +} // namespace + +SdpVideoFormat::SdpVideoFormat(const std::string& name) : name(name) {} + +SdpVideoFormat::SdpVideoFormat(const std::string& name, + const Parameters& parameters) + : name(name), parameters(parameters) {} + +SdpVideoFormat::SdpVideoFormat( + const std::string& name, + const Parameters& parameters, + const absl::InlinedVector<ScalabilityMode, kScalabilityModeCount>& + scalability_modes) + : name(name), + parameters(parameters), + scalability_modes(scalability_modes) {} + +SdpVideoFormat::SdpVideoFormat(const SdpVideoFormat&) = default; +SdpVideoFormat::SdpVideoFormat(SdpVideoFormat&&) = default; +SdpVideoFormat& SdpVideoFormat::operator=(const SdpVideoFormat&) = default; +SdpVideoFormat& SdpVideoFormat::operator=(SdpVideoFormat&&) = default; + +SdpVideoFormat::~SdpVideoFormat() = default; + +std::string SdpVideoFormat::ToString() const { + rtc::StringBuilder builder; + builder << "Codec name: " << name << ", parameters: {"; + for (const auto& kv : parameters) { + builder << " " << kv.first << "=" << kv.second; + } + + builder << " }"; + if (!scalability_modes.empty()) { + builder << ", scalability_modes: ["; + bool first = true; + for (const auto scalability_mode : scalability_modes) { + if (first) { + first = false; + } else { + builder << ", "; + } + builder << ScalabilityModeToString(scalability_mode); + } + builder << "]"; + } + + return builder.str(); +} + +bool SdpVideoFormat::IsSameCodec(const SdpVideoFormat& other) const { + // Two codecs are considered the same if the name matches (case insensitive) + // and certain codec-specific parameters match. + return absl::EqualsIgnoreCase(name, other.name) && + IsSameCodecSpecific(*this, other); +} + +bool SdpVideoFormat::IsCodecInList( + rtc::ArrayView<const webrtc::SdpVideoFormat> formats) const { + for (const auto& format : formats) { + if (IsSameCodec(format)) { + return true; + } + } + return false; +} + +bool operator==(const SdpVideoFormat& a, const SdpVideoFormat& b) { + return a.name == b.name && a.parameters == b.parameters && + a.scalability_modes == b.scalability_modes; +} + +absl::optional<SdpVideoFormat> FuzzyMatchSdpVideoFormat( + rtc::ArrayView<const SdpVideoFormat> supported_formats, + const SdpVideoFormat& format) { + absl::optional<SdpVideoFormat> res; + int best_parameter_match = 0; + for (const auto& supported_format : supported_formats) { + if (absl::EqualsIgnoreCase(supported_format.name, format.name)) { + int matching_parameters = 0; + for (const auto& kv : supported_format.parameters) { + auto it = format.parameters.find(kv.first); + if (it != format.parameters.end() && it->second == kv.second) { + matching_parameters += 1; + } + } + + if (!res || matching_parameters > best_parameter_match) { + res = supported_format; + best_parameter_match = matching_parameters; + } + } + } + + if (!res) { + RTC_LOG(LS_INFO) << "Failed to match SdpVideoFormat " << format.ToString(); + } else if (*res != format) { + RTC_LOG(LS_INFO) << "Matched SdpVideoFormat " << format.ToString() + << " with " << res->ToString(); + } + + return res; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/sdp_video_format.h b/third_party/libwebrtc/api/video_codecs/sdp_video_format.h new file mode 100644 index 0000000000..faaa66c241 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/sdp_video_format.h @@ -0,0 +1,75 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_CODECS_SDP_VIDEO_FORMAT_H_ +#define API_VIDEO_CODECS_SDP_VIDEO_FORMAT_H_ + +#include <map> +#include <string> + +#include "absl/container/inlined_vector.h" +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/video_codecs/scalability_mode.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// SDP specification for a single video codec. +// NOTE: This class is still under development and may change without notice. +struct RTC_EXPORT SdpVideoFormat { + using Parameters = std::map<std::string, std::string>; + + explicit SdpVideoFormat(const std::string& name); + SdpVideoFormat(const std::string& name, const Parameters& parameters); + SdpVideoFormat( + const std::string& name, + const Parameters& parameters, + const absl::InlinedVector<ScalabilityMode, kScalabilityModeCount>& + scalability_modes); + SdpVideoFormat(const SdpVideoFormat&); + SdpVideoFormat(SdpVideoFormat&&); + SdpVideoFormat& operator=(const SdpVideoFormat&); + SdpVideoFormat& operator=(SdpVideoFormat&&); + + ~SdpVideoFormat(); + + // Returns true if the SdpVideoFormats have the same names as well as codec + // specific parameters. Please note that two SdpVideoFormats can represent the + // same codec even though not all parameters are the same. + bool IsSameCodec(const SdpVideoFormat& other) const; + bool IsCodecInList( + rtc::ArrayView<const webrtc::SdpVideoFormat> formats) const; + + std::string ToString() const; + + friend RTC_EXPORT bool operator==(const SdpVideoFormat& a, + const SdpVideoFormat& b); + friend RTC_EXPORT bool operator!=(const SdpVideoFormat& a, + const SdpVideoFormat& b) { + return !(a == b); + } + + std::string name; + Parameters parameters; + absl::InlinedVector<ScalabilityMode, kScalabilityModeCount> scalability_modes; +}; + +// For not so good reasons sometimes additional parameters are added to an +// SdpVideoFormat, which makes instances that should compare equal to not match +// anymore. Until we stop misusing SdpVideoFormats provide this convenience +// function to perform fuzzy matching. +absl::optional<SdpVideoFormat> FuzzyMatchSdpVideoFormat( + rtc::ArrayView<const SdpVideoFormat> supported_formats, + const SdpVideoFormat& format); + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_SDP_VIDEO_FORMAT_H_ diff --git a/third_party/libwebrtc/api/video_codecs/simulcast_stream.cc b/third_party/libwebrtc/api/video_codecs/simulcast_stream.cc new file mode 100644 index 0000000000..312429ef9f --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/simulcast_stream.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 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 "api/video_codecs/simulcast_stream.h" + +#include "rtc_base/checks.h" + +namespace webrtc { + +unsigned char SimulcastStream::GetNumberOfTemporalLayers() const { + return numberOfTemporalLayers; +} +void SimulcastStream::SetNumberOfTemporalLayers(unsigned char n) { + RTC_DCHECK_GE(n, 1); + RTC_DCHECK_LE(n, 3); + numberOfTemporalLayers = n; +} + +ScalabilityMode SimulcastStream::GetScalabilityMode() const { + RTC_CHECK_GE(numberOfTemporalLayers, 1); + RTC_CHECK_LE(numberOfTemporalLayers, 3); + static const ScalabilityMode scalability_modes[3] = { + ScalabilityMode::kL1T1, + ScalabilityMode::kL1T2, + ScalabilityMode::kL1T3, + }; + return scalability_modes[numberOfTemporalLayers - 1]; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/simulcast_stream.h b/third_party/libwebrtc/api/video_codecs/simulcast_stream.h new file mode 100644 index 0000000000..7c0dd5d786 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/simulcast_stream.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_SIMULCAST_STREAM_H_ +#define API_VIDEO_CODECS_SIMULCAST_STREAM_H_ + +#include "api/video_codecs/scalability_mode.h" + +namespace webrtc { + +// TODO(bugs.webrtc.org/6883): Unify with struct VideoStream, part of +// VideoEncoderConfig. +struct SimulcastStream { + // Temporary utility methods for transition from numberOfTemporalLayers + // setting to ScalabilityMode. + unsigned char GetNumberOfTemporalLayers() const; + ScalabilityMode GetScalabilityMode() const; + void SetNumberOfTemporalLayers(unsigned char n); + + int width = 0; + int height = 0; + float maxFramerate = 0; // fps. + unsigned char numberOfTemporalLayers = 1; + unsigned int maxBitrate = 0; // kilobits/sec. + unsigned int targetBitrate = 0; // kilobits/sec. + unsigned int minBitrate = 0; // kilobits/sec. + unsigned int qpMax = 0; // minimum quality + bool active = false; // encoded and sent. +}; + +} // namespace webrtc +#endif // API_VIDEO_CODECS_SIMULCAST_STREAM_H_ diff --git a/third_party/libwebrtc/api/video_codecs/spatial_layer.cc b/third_party/libwebrtc/api/video_codecs/spatial_layer.cc new file mode 100644 index 0000000000..25ccdfeb48 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/spatial_layer.cc @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020 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 "api/video_codecs/spatial_layer.h" + +namespace webrtc { + +bool SpatialLayer::operator==(const SpatialLayer& other) const { + return (width == other.width && height == other.height && + maxFramerate == other.maxFramerate && + numberOfTemporalLayers == other.numberOfTemporalLayers && + maxBitrate == other.maxBitrate && + targetBitrate == other.targetBitrate && + minBitrate == other.minBitrate && qpMax == other.qpMax && + active == other.active); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/spatial_layer.h b/third_party/libwebrtc/api/video_codecs/spatial_layer.h new file mode 100644 index 0000000000..5a1b425427 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/spatial_layer.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 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 API_VIDEO_CODECS_SPATIAL_LAYER_H_ +#define API_VIDEO_CODECS_SPATIAL_LAYER_H_ + +namespace webrtc { + +struct SpatialLayer { + bool operator==(const SpatialLayer& other) const; + bool operator!=(const SpatialLayer& other) const { return !(*this == other); } + + unsigned short width; // NOLINT(runtime/int) + unsigned short height; // NOLINT(runtime/int) + float maxFramerate; // fps. + unsigned char numberOfTemporalLayers; + unsigned int maxBitrate; // kilobits/sec. + unsigned int targetBitrate; // kilobits/sec. + unsigned int minBitrate; // kilobits/sec. + unsigned int qpMax; // minimum quality + bool active; // encoded and sent. +}; + +} // namespace webrtc +#endif // API_VIDEO_CODECS_SPATIAL_LAYER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/test/BUILD.gn b/third_party/libwebrtc/api/video_codecs/test/BUILD.gn new file mode 100644 index 0000000000..47d5ff9aa3 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/test/BUILD.gn @@ -0,0 +1,81 @@ +# 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. + +import("../../../webrtc.gni") + +if (rtc_include_tests) { + rtc_library("video_codecs_api_unittests") { + testonly = true + sources = [ + "builtin_video_encoder_factory_unittest.cc", + "h264_profile_level_id_unittest.cc", + "sdp_video_format_unittest.cc", + "video_decoder_software_fallback_wrapper_unittest.cc", + "video_encoder_software_fallback_wrapper_unittest.cc", + ] + + deps = [ + ":video_decoder_factory_template_tests", + ":video_encoder_factory_template_tests", + "..:builtin_video_encoder_factory", + "..:rtc_software_fallback_wrappers", + "..:video_codecs_api", + "../..:fec_controller_api", + "../..:mock_video_encoder", + "../../../api:scoped_refptr", + "../../../media:media_constants", + "../../../media:rtc_media_base", + "../../../modules/video_coding:video_codec_interface", + "../../../modules/video_coding:video_coding_utility", + "../../../modules/video_coding:webrtc_vp8", + "../../../rtc_base:checks", + "../../../rtc_base:rtc_base_tests_utils", + "../../../test:field_trial", + "../../../test:test_support", + "../../../test:video_test_common", + "../../video:encoded_image", + "../../video:video_bitrate_allocation", + "../../video:video_frame", + "../../video:video_rtp_headers", + "//testing/gtest", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + } + + rtc_library("video_encoder_factory_template_tests") { + testonly = true + sources = [ "video_encoder_factory_template_tests.cc" ] + + deps = [ + "..:video_encoder_factory_template", + "..:video_encoder_factory_template_libaom_av1_adapter", + "..:video_encoder_factory_template_libvpx_vp8_adapter", + "..:video_encoder_factory_template_libvpx_vp9_adapter", + "..:video_encoder_factory_template_open_h264_adapter", + "../../:mock_video_encoder", + "../../../test:test_support", + "//testing/gtest", + ] + } + + rtc_library("video_decoder_factory_template_tests") { + testonly = true + sources = [ "video_decoder_factory_template_tests.cc" ] + + deps = [ + "..:video_decoder_factory_template", + "..:video_decoder_factory_template_dav1d_adapter", + "..:video_decoder_factory_template_libvpx_vp8_adapter", + "..:video_decoder_factory_template_libvpx_vp9_adapter", + "..:video_decoder_factory_template_open_h264_adapter", + "../../:mock_video_decoder", + "../../../test:test_support", + "//testing/gtest", + ] + } +} diff --git a/third_party/libwebrtc/api/video_codecs/test/builtin_video_encoder_factory_unittest.cc b/third_party/libwebrtc/api/video_codecs/test/builtin_video_encoder_factory_unittest.cc new file mode 100644 index 0000000000..84fd594b4c --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/test/builtin_video_encoder_factory_unittest.cc @@ -0,0 +1,39 @@ +/* + * 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 "api/video_codecs/builtin_video_encoder_factory.h" + +#include <memory> +#include <string> +#include <vector> + +#include "api/video_codecs/sdp_video_format.h" +#include "test/gtest.h" + +namespace webrtc { + +TEST(BuiltinVideoEncoderFactoryTest, AnnouncesVp9AccordingToBuildFlags) { + std::unique_ptr<VideoEncoderFactory> factory = + CreateBuiltinVideoEncoderFactory(); + bool claims_vp9_support = false; + for (const SdpVideoFormat& format : factory->GetSupportedFormats()) { + if (format.name == "VP9") { + claims_vp9_support = true; + break; + } + } +#if defined(RTC_ENABLE_VP9) + EXPECT_TRUE(claims_vp9_support); +#else + EXPECT_FALSE(claims_vp9_support); +#endif // defined(RTC_ENABLE_VP9) +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/test/h264_profile_level_id_unittest.cc b/third_party/libwebrtc/api/video_codecs/test/h264_profile_level_id_unittest.cc new file mode 100644 index 0000000000..47098d2682 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/test/h264_profile_level_id_unittest.cc @@ -0,0 +1,171 @@ +/* + * 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 "api/video_codecs/h264_profile_level_id.h" + +#include <map> +#include <string> + +#include "absl/types/optional.h" +#include "test/gtest.h" + +namespace webrtc { + +TEST(H264ProfileLevelId, TestParsingInvalid) { + // Malformed strings. + EXPECT_FALSE(ParseH264ProfileLevelId("")); + EXPECT_FALSE(ParseH264ProfileLevelId(" 42e01f")); + EXPECT_FALSE(ParseH264ProfileLevelId("4242e01f")); + EXPECT_FALSE(ParseH264ProfileLevelId("e01f")); + EXPECT_FALSE(ParseH264ProfileLevelId("gggggg")); + + // Invalid level. + EXPECT_FALSE(ParseH264ProfileLevelId("42e000")); + EXPECT_FALSE(ParseH264ProfileLevelId("42e00f")); + EXPECT_FALSE(ParseH264ProfileLevelId("42e0ff")); + + // Invalid profile. + EXPECT_FALSE(ParseH264ProfileLevelId("42e11f")); + EXPECT_FALSE(ParseH264ProfileLevelId("58601f")); + EXPECT_FALSE(ParseH264ProfileLevelId("64e01f")); +} + +TEST(H264ProfileLevelId, TestParsingLevel) { + EXPECT_EQ(H264Level::kLevel3_1, ParseH264ProfileLevelId("42e01f")->level); + EXPECT_EQ(H264Level::kLevel1_1, ParseH264ProfileLevelId("42e00b")->level); + EXPECT_EQ(H264Level::kLevel1_b, ParseH264ProfileLevelId("42f00b")->level); + EXPECT_EQ(H264Level::kLevel4_2, ParseH264ProfileLevelId("42C02A")->level); + EXPECT_EQ(H264Level::kLevel5_2, ParseH264ProfileLevelId("640c34")->level); +} + +TEST(H264ProfileLevelId, TestParsingConstrainedBaseline) { + EXPECT_EQ(H264Profile::kProfileConstrainedBaseline, + ParseH264ProfileLevelId("42e01f")->profile); + EXPECT_EQ(H264Profile::kProfileConstrainedBaseline, + ParseH264ProfileLevelId("42C02A")->profile); + EXPECT_EQ(H264Profile::kProfileConstrainedBaseline, + ParseH264ProfileLevelId("4de01f")->profile); + EXPECT_EQ(H264Profile::kProfileConstrainedBaseline, + ParseH264ProfileLevelId("58f01f")->profile); +} + +TEST(H264ProfileLevelId, TestParsingBaseline) { + EXPECT_EQ(H264Profile::kProfileBaseline, + ParseH264ProfileLevelId("42a01f")->profile); + EXPECT_EQ(H264Profile::kProfileBaseline, + ParseH264ProfileLevelId("58A01F")->profile); +} + +TEST(H264ProfileLevelId, TestParsingMain) { + EXPECT_EQ(H264Profile::kProfileMain, + ParseH264ProfileLevelId("4D401f")->profile); +} + +TEST(H264ProfileLevelId, TestParsingHigh) { + EXPECT_EQ(H264Profile::kProfileHigh, + ParseH264ProfileLevelId("64001f")->profile); +} + +TEST(H264ProfileLevelId, TestParsingConstrainedHigh) { + EXPECT_EQ(H264Profile::kProfileConstrainedHigh, + ParseH264ProfileLevelId("640c1f")->profile); +} + +TEST(H264ProfileLevelId, TestSupportedLevel) { + EXPECT_EQ(H264Level::kLevel2_1, *H264SupportedLevel(640 * 480, 25)); + EXPECT_EQ(H264Level::kLevel3_1, *H264SupportedLevel(1280 * 720, 30)); + EXPECT_EQ(H264Level::kLevel4_2, *H264SupportedLevel(1920 * 1280, 60)); +} + +// Test supported level below level 1 requirements. +TEST(H264ProfileLevelId, TestSupportedLevelInvalid) { + EXPECT_FALSE(H264SupportedLevel(0, 0)); + // All levels support fps > 5. + EXPECT_FALSE(H264SupportedLevel(1280 * 720, 5)); + // All levels support frame sizes > 183 * 137. + EXPECT_FALSE(H264SupportedLevel(183 * 137, 30)); +} + +TEST(H264ProfileLevelId, TestToString) { + EXPECT_EQ("42e01f", *H264ProfileLevelIdToString(H264ProfileLevelId( + H264Profile::kProfileConstrainedBaseline, + H264Level::kLevel3_1))); + EXPECT_EQ("42000a", *H264ProfileLevelIdToString(H264ProfileLevelId( + H264Profile::kProfileBaseline, H264Level::kLevel1))); + EXPECT_EQ("4d001f", H264ProfileLevelIdToString(H264ProfileLevelId( + H264Profile::kProfileMain, H264Level::kLevel3_1))); + EXPECT_EQ("640c2a", + *H264ProfileLevelIdToString(H264ProfileLevelId( + H264Profile::kProfileConstrainedHigh, H264Level::kLevel4_2))); + EXPECT_EQ("64002a", *H264ProfileLevelIdToString(H264ProfileLevelId( + H264Profile::kProfileHigh, H264Level::kLevel4_2))); +} + +TEST(H264ProfileLevelId, TestToStringLevel1b) { + EXPECT_EQ("42f00b", *H264ProfileLevelIdToString(H264ProfileLevelId( + H264Profile::kProfileConstrainedBaseline, + H264Level::kLevel1_b))); + EXPECT_EQ("42100b", + *H264ProfileLevelIdToString(H264ProfileLevelId( + H264Profile::kProfileBaseline, H264Level::kLevel1_b))); + EXPECT_EQ("4d100b", *H264ProfileLevelIdToString(H264ProfileLevelId( + H264Profile::kProfileMain, H264Level::kLevel1_b))); +} + +TEST(H264ProfileLevelId, TestToStringRoundTrip) { + EXPECT_EQ("42e01f", + *H264ProfileLevelIdToString(*ParseH264ProfileLevelId("42e01f"))); + EXPECT_EQ("42e01f", + *H264ProfileLevelIdToString(*ParseH264ProfileLevelId("42E01F"))); + EXPECT_EQ("4d100b", + *H264ProfileLevelIdToString(*ParseH264ProfileLevelId("4d100b"))); + EXPECT_EQ("4d100b", + *H264ProfileLevelIdToString(*ParseH264ProfileLevelId("4D100B"))); + EXPECT_EQ("640c2a", + *H264ProfileLevelIdToString(*ParseH264ProfileLevelId("640c2a"))); + EXPECT_EQ("640c2a", + *H264ProfileLevelIdToString(*ParseH264ProfileLevelId("640C2A"))); +} + +TEST(H264ProfileLevelId, TestToStringInvalid) { + EXPECT_FALSE(H264ProfileLevelIdToString( + H264ProfileLevelId(H264Profile::kProfileHigh, H264Level::kLevel1_b))); + EXPECT_FALSE(H264ProfileLevelIdToString(H264ProfileLevelId( + H264Profile::kProfileConstrainedHigh, H264Level::kLevel1_b))); + EXPECT_FALSE(H264ProfileLevelIdToString( + H264ProfileLevelId(static_cast<H264Profile>(255), H264Level::kLevel3_1))); +} + +TEST(H264ProfileLevelId, TestParseSdpProfileLevelIdEmpty) { + const absl::optional<H264ProfileLevelId> profile_level_id = + ParseSdpForH264ProfileLevelId(SdpVideoFormat::Parameters()); + EXPECT_TRUE(profile_level_id); + EXPECT_EQ(H264Profile::kProfileConstrainedBaseline, + profile_level_id->profile); + EXPECT_EQ(H264Level::kLevel3_1, profile_level_id->level); +} + +TEST(H264ProfileLevelId, TestParseSdpProfileLevelIdConstrainedHigh) { + SdpVideoFormat::Parameters params; + params["profile-level-id"] = "640c2a"; + const absl::optional<H264ProfileLevelId> profile_level_id = + ParseSdpForH264ProfileLevelId(params); + EXPECT_TRUE(profile_level_id); + EXPECT_EQ(H264Profile::kProfileConstrainedHigh, profile_level_id->profile); + EXPECT_EQ(H264Level::kLevel4_2, profile_level_id->level); +} + +TEST(H264ProfileLevelId, TestParseSdpProfileLevelIdInvalid) { + SdpVideoFormat::Parameters params; + params["profile-level-id"] = "foobar"; + EXPECT_FALSE(ParseSdpForH264ProfileLevelId(params)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/test/sdp_video_format_unittest.cc b/third_party/libwebrtc/api/video_codecs/test/sdp_video_format_unittest.cc new file mode 100644 index 0000000000..bb158aeb95 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/test/sdp_video_format_unittest.cc @@ -0,0 +1,103 @@ +/* + * 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 "api/video_codecs/sdp_video_format.h" + +#include <stdint.h> + +#include "media/base/media_constants.h" +#include "test/gtest.h" + +namespace webrtc { + +typedef SdpVideoFormat Sdp; +typedef SdpVideoFormat::Parameters Params; + +TEST(SdpVideoFormatTest, SameCodecNameNoParameters) { + EXPECT_TRUE(Sdp("H264").IsSameCodec(Sdp("h264"))); + EXPECT_TRUE(Sdp("VP8").IsSameCodec(Sdp("vp8"))); + EXPECT_TRUE(Sdp("VP9").IsSameCodec(Sdp("vp9"))); + EXPECT_TRUE(Sdp("AV1").IsSameCodec(Sdp("Av1"))); +} + +TEST(SdpVideoFormatTest, DifferentCodecNameNoParameters) { + EXPECT_FALSE(Sdp("H264").IsSameCodec(Sdp("VP8"))); + EXPECT_FALSE(Sdp("VP8").IsSameCodec(Sdp("VP9"))); + EXPECT_FALSE(Sdp("AV1").IsSameCodec(Sdp("VP8"))); +} + +TEST(SdpVideoFormatTest, SameCodecNameSameParameters) { + EXPECT_TRUE(Sdp("VP9").IsSameCodec(Sdp("VP9", Params{{"profile-id", "0"}}))); + EXPECT_TRUE(Sdp("VP9", Params{{"profile-id", "0"}}) + .IsSameCodec(Sdp("VP9", Params{{"profile-id", "0"}}))); + EXPECT_TRUE(Sdp("VP9", Params{{"profile-id", "2"}}) + .IsSameCodec(Sdp("VP9", Params{{"profile-id", "2"}}))); + EXPECT_TRUE( + Sdp("H264", Params{{"profile-level-id", "42e01f"}}) + .IsSameCodec(Sdp("H264", Params{{"profile-level-id", "42e01f"}}))); + EXPECT_TRUE( + Sdp("H264", Params{{"profile-level-id", "640c34"}}) + .IsSameCodec(Sdp("H264", Params{{"profile-level-id", "640c34"}}))); + EXPECT_TRUE(Sdp("AV1").IsSameCodec(Sdp("AV1", Params{{"profile", "0"}}))); + EXPECT_TRUE(Sdp("AV1", Params{{"profile", "0"}}) + .IsSameCodec(Sdp("AV1", Params{{"profile", "0"}}))); + EXPECT_TRUE(Sdp("AV1", Params{{"profile", "2"}}) + .IsSameCodec(Sdp("AV1", Params{{"profile", "2"}}))); +} + +TEST(SdpVideoFormatTest, SameCodecNameDifferentParameters) { + EXPECT_FALSE(Sdp("VP9").IsSameCodec(Sdp("VP9", Params{{"profile-id", "2"}}))); + EXPECT_FALSE(Sdp("VP9", Params{{"profile-id", "0"}}) + .IsSameCodec(Sdp("VP9", Params{{"profile-id", "1"}}))); + EXPECT_FALSE(Sdp("VP9", Params{{"profile-id", "2"}}) + .IsSameCodec(Sdp("VP9", Params{{"profile-id", "0"}}))); + EXPECT_FALSE( + Sdp("H264", Params{{"profile-level-id", "42e01f"}}) + .IsSameCodec(Sdp("H264", Params{{"profile-level-id", "640c34"}}))); + EXPECT_FALSE( + Sdp("H264", Params{{"profile-level-id", "640c34"}}) + .IsSameCodec(Sdp("H264", Params{{"profile-level-id", "42f00b"}}))); + EXPECT_FALSE(Sdp("AV1").IsSameCodec(Sdp("AV1", Params{{"profile", "1"}}))); + EXPECT_FALSE(Sdp("AV1", Params{{"profile", "0"}}) + .IsSameCodec(Sdp("AV1", Params{{"profile", "1"}}))); + EXPECT_FALSE(Sdp("AV1", Params{{"profile", "1"}}) + .IsSameCodec(Sdp("AV1", Params{{"profile", "2"}}))); +} + +TEST(SdpVideoFormatTest, DifferentCodecNameSameParameters) { + EXPECT_FALSE(Sdp("VP9", Params{{"profile-id", "0"}}) + .IsSameCodec(Sdp("H264", Params{{"profile-id", "0"}}))); + EXPECT_FALSE(Sdp("VP9", Params{{"profile-id", "2"}}) + .IsSameCodec(Sdp("VP8", Params{{"profile-id", "2"}}))); + EXPECT_FALSE( + Sdp("H264", Params{{"profile-level-id", "42e01f"}}) + .IsSameCodec(Sdp("VP9", Params{{"profile-level-id", "42e01f"}}))); + EXPECT_FALSE( + Sdp("H264", Params{{"profile-level-id", "640c34"}}) + .IsSameCodec(Sdp("VP8", Params{{"profile-level-id", "640c34"}}))); + EXPECT_FALSE(Sdp("AV1", Params{{"profile", "0"}}) + .IsSameCodec(Sdp("H264", Params{{"profile", "0"}}))); + EXPECT_FALSE(Sdp("AV1", Params{{"profile", "2"}}) + .IsSameCodec(Sdp("VP9", Params{{"profile", "2"}}))); +} + +TEST(SdpVideoFormatTest, H264PacketizationMode) { + // The default packetization mode is 0. + EXPECT_TRUE(Sdp("H264", Params{{cricket::kH264FmtpPacketizationMode, "0"}}) + .IsSameCodec(Sdp("H264"))); + EXPECT_FALSE(Sdp("H264", Params{{cricket::kH264FmtpPacketizationMode, "1"}}) + .IsSameCodec(Sdp("H264"))); + + EXPECT_TRUE( + Sdp("H264", Params{{cricket::kH264FmtpPacketizationMode, "1"}}) + .IsSameCodec( + Sdp("H264", Params{{cricket::kH264FmtpPacketizationMode, "1"}}))); +} +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/test/video_decoder_factory_template_tests.cc b/third_party/libwebrtc/api/video_codecs/test/video_decoder_factory_template_tests.cc new file mode 100644 index 0000000000..e9d7052501 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/test/video_decoder_factory_template_tests.cc @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2022 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 "api/test/mock_video_decoder.h" +#include "api/video_codecs/video_decoder_factory_template.h" +#include "api/video_codecs/video_decoder_factory_template_dav1d_adapter.h" +#include "api/video_codecs/video_decoder_factory_template_libvpx_vp8_adapter.h" +#include "api/video_codecs/video_decoder_factory_template_libvpx_vp9_adapter.h" +#include "api/video_codecs/video_decoder_factory_template_open_h264_adapter.h" +#include "test/gmock.h" +#include "test/gtest.h" + +using ::testing::Contains; +using ::testing::Each; +using ::testing::Eq; +using ::testing::Field; +using ::testing::IsEmpty; +using ::testing::Ne; +using ::testing::Not; +using ::testing::UnorderedElementsAre; + +namespace webrtc { +namespace { +const SdpVideoFormat kFooSdp("Foo"); +const SdpVideoFormat kBarLowSdp("Bar", {{"profile", "low"}}); +const SdpVideoFormat kBarHighSdp("Bar", {{"profile", "high"}}); + +struct FooDecoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { return {kFooSdp}; } + + static std::unique_ptr<VideoDecoder> CreateDecoder( + const SdpVideoFormat& format) { + auto decoder = std::make_unique<testing::StrictMock<MockVideoDecoder>>(); + EXPECT_CALL(*decoder, Destruct); + return decoder; + } +}; + +struct BarDecoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { + return {kBarLowSdp, kBarHighSdp}; + } + + static std::unique_ptr<VideoDecoder> CreateDecoder( + const SdpVideoFormat& format) { + auto decoder = std::make_unique<testing::StrictMock<MockVideoDecoder>>(); + EXPECT_CALL(*decoder, Destruct); + return decoder; + } +}; + +TEST(VideoDecoderFactoryTemplate, OneTemplateAdapterCreateDecoder) { + VideoDecoderFactoryTemplate<FooDecoderTemplateAdapter> factory; + EXPECT_THAT(factory.GetSupportedFormats(), UnorderedElementsAre(kFooSdp)); + EXPECT_THAT(factory.CreateVideoDecoder(kFooSdp), Ne(nullptr)); + EXPECT_THAT(factory.CreateVideoDecoder(SdpVideoFormat("FooX")), Eq(nullptr)); +} + +TEST(VideoDecoderFactoryTemplate, TwoTemplateAdaptersNoDuplicates) { + VideoDecoderFactoryTemplate<FooDecoderTemplateAdapter, + FooDecoderTemplateAdapter> + factory; + EXPECT_THAT(factory.GetSupportedFormats(), UnorderedElementsAre(kFooSdp)); +} + +TEST(VideoDecoderFactoryTemplate, TwoTemplateAdaptersCreateDecoders) { + VideoDecoderFactoryTemplate<FooDecoderTemplateAdapter, + BarDecoderTemplateAdapter> + factory; + EXPECT_THAT(factory.GetSupportedFormats(), + UnorderedElementsAre(kFooSdp, kBarLowSdp, kBarHighSdp)); + EXPECT_THAT(factory.CreateVideoDecoder(kFooSdp), Ne(nullptr)); + EXPECT_THAT(factory.CreateVideoDecoder(kBarLowSdp), Ne(nullptr)); + EXPECT_THAT(factory.CreateVideoDecoder(kBarHighSdp), Ne(nullptr)); + EXPECT_THAT(factory.CreateVideoDecoder(SdpVideoFormat("FooX")), Eq(nullptr)); + EXPECT_THAT(factory.CreateVideoDecoder(SdpVideoFormat("Bar")), Eq(nullptr)); +} + +TEST(VideoDecoderFactoryTemplate, LibvpxVp8) { + VideoDecoderFactoryTemplate<LibvpxVp8DecoderTemplateAdapter> factory; + auto formats = factory.GetSupportedFormats(); + EXPECT_THAT(formats.size(), 1); + EXPECT_THAT(formats[0], Field(&SdpVideoFormat::name, "VP8")); + EXPECT_THAT(factory.CreateVideoDecoder(formats[0]), Ne(nullptr)); +} + +TEST(VideoDecoderFactoryTemplate, LibvpxVp9) { + VideoDecoderFactoryTemplate<LibvpxVp9DecoderTemplateAdapter> factory; + auto formats = factory.GetSupportedFormats(); + EXPECT_THAT(formats, Not(IsEmpty())); + EXPECT_THAT(formats, Each(Field(&SdpVideoFormat::name, "VP9"))); + EXPECT_THAT(factory.CreateVideoDecoder(formats[0]), Ne(nullptr)); +} + +// TODO(bugs.webrtc.org/13573): When OpenH264 is no longer a conditional build +// target remove this #ifdef. +#if defined(WEBRTC_USE_H264) +TEST(VideoDecoderFactoryTemplate, OpenH264) { + VideoDecoderFactoryTemplate<OpenH264DecoderTemplateAdapter> factory; + auto formats = factory.GetSupportedFormats(); + EXPECT_THAT(formats, Not(IsEmpty())); + EXPECT_THAT(formats, Each(Field(&SdpVideoFormat::name, "H264"))); + EXPECT_THAT(factory.CreateVideoDecoder(formats[0]), Ne(nullptr)); +} +#endif // defined(WEBRTC_USE_H264) + +TEST(VideoDecoderFactoryTemplate, Dav1d) { + VideoDecoderFactoryTemplate<Dav1dDecoderTemplateAdapter> factory; + auto formats = factory.GetSupportedFormats(); + EXPECT_THAT(formats.size(), 1); + EXPECT_THAT(formats[0], Field(&SdpVideoFormat::name, "AV1")); + EXPECT_THAT(factory.CreateVideoDecoder(formats[0]), Ne(nullptr)); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/test/video_decoder_software_fallback_wrapper_unittest.cc b/third_party/libwebrtc/api/video_codecs/test/video_decoder_software_fallback_wrapper_unittest.cc new file mode 100644 index 0000000000..73dedc8395 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/test/video_decoder_software_fallback_wrapper_unittest.cc @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2015 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 "api/video_codecs/video_decoder_software_fallback_wrapper.h" + +#include <stdint.h> + +#include "absl/types/optional.h" +#include "api/video/encoded_image.h" +#include "api/video/video_frame.h" +#include "api/video_codecs/video_decoder.h" +#include "modules/video_coding/codecs/vp8/include/vp8.h" +#include "modules/video_coding/include/video_codec_interface.h" +#include "modules/video_coding/include/video_error_codes.h" +#include "rtc_base/checks.h" +#include "test/field_trial.h" +#include "test/gtest.h" + +namespace webrtc { + +class VideoDecoderSoftwareFallbackWrapperTest : public ::testing::Test { + protected: + VideoDecoderSoftwareFallbackWrapperTest() + : VideoDecoderSoftwareFallbackWrapperTest("") {} + explicit VideoDecoderSoftwareFallbackWrapperTest( + const std::string& field_trials) + : override_field_trials_(field_trials), + fake_decoder_(new CountingFakeDecoder()), + fallback_wrapper_(CreateVideoDecoderSoftwareFallbackWrapper( + std::unique_ptr<VideoDecoder>(VP8Decoder::Create()), + std::unique_ptr<VideoDecoder>(fake_decoder_))) {} + + class CountingFakeDecoder : public VideoDecoder { + public: + bool Configure(const Settings& settings) override { + ++configure_count_; + return configure_return_value_; + } + + int32_t Decode(const EncodedImage& input_image, + bool missing_frames, + int64_t render_time_ms) override { + ++decode_count_; + return decode_return_code_; + } + + int32_t RegisterDecodeCompleteCallback( + DecodedImageCallback* callback) override { + decode_complete_callback_ = callback; + return WEBRTC_VIDEO_CODEC_OK; + } + + int32_t Release() override { + ++release_count_; + return WEBRTC_VIDEO_CODEC_OK; + } + + const char* ImplementationName() const override { return "fake-decoder"; } + + int configure_count_ = 0; + int decode_count_ = 0; + bool configure_return_value_ = true; + int32_t decode_return_code_ = WEBRTC_VIDEO_CODEC_OK; + DecodedImageCallback* decode_complete_callback_ = nullptr; + int release_count_ = 0; + int reset_count_ = 0; + }; + test::ScopedFieldTrials override_field_trials_; + // `fake_decoder_` is owned and released by `fallback_wrapper_`. + CountingFakeDecoder* fake_decoder_; + std::unique_ptr<VideoDecoder> fallback_wrapper_; +}; + +TEST_F(VideoDecoderSoftwareFallbackWrapperTest, InitializesDecoder) { + fallback_wrapper_->Configure({}); + EXPECT_EQ(1, fake_decoder_->configure_count_); + + EncodedImage encoded_image; + encoded_image._frameType = VideoFrameType::kVideoFrameKey; + fallback_wrapper_->Decode(encoded_image, false, -1); + EXPECT_EQ(1, fake_decoder_->configure_count_) + << "Initialized decoder should not be reinitialized."; + EXPECT_EQ(1, fake_decoder_->decode_count_); +} + +TEST_F(VideoDecoderSoftwareFallbackWrapperTest, + UsesFallbackDecoderAfterAnyInitDecodeFailure) { + fake_decoder_->configure_return_value_ = false; + fallback_wrapper_->Configure({}); + EXPECT_EQ(1, fake_decoder_->configure_count_); + + EncodedImage encoded_image; + encoded_image._frameType = VideoFrameType::kVideoFrameKey; + fallback_wrapper_->Decode(encoded_image, false, -1); + EXPECT_EQ(1, fake_decoder_->configure_count_) + << "Should not have attempted reinitializing the fallback decoder on " + "keyframe."; + // Unfortunately faking a VP8 frame is hard. Rely on no Decode -> using SW + // decoder. + EXPECT_EQ(0, fake_decoder_->decode_count_) + << "Decoder used even though no InitDecode had succeeded."; +} + +TEST_F(VideoDecoderSoftwareFallbackWrapperTest, IsSoftwareFallbackSticky) { + fallback_wrapper_->Configure({}); + + fake_decoder_->decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; + EncodedImage encoded_image; + fallback_wrapper_->Decode(encoded_image, false, -1); + EXPECT_EQ(1, fake_decoder_->decode_count_); + + // Software fallback should be sticky, fake_decoder_ shouldn't be used. + encoded_image._frameType = VideoFrameType::kVideoFrameKey; + fallback_wrapper_->Decode(encoded_image, false, -1); + EXPECT_EQ(1, fake_decoder_->decode_count_) + << "Decoder shouldn't be used after failure."; + + // fake_decoder_ should have only been initialized once during the test. + EXPECT_EQ(1, fake_decoder_->configure_count_); +} + +TEST_F(VideoDecoderSoftwareFallbackWrapperTest, DoesNotFallbackOnEveryError) { + fallback_wrapper_->Configure({}); + fake_decoder_->decode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR; + EncodedImage encoded_image; + EXPECT_EQ(fake_decoder_->decode_return_code_, + fallback_wrapper_->Decode(encoded_image, false, -1)); + EXPECT_EQ(1, fake_decoder_->decode_count_); + + fallback_wrapper_->Decode(encoded_image, false, -1); + EXPECT_EQ(2, fake_decoder_->decode_count_) + << "Decoder should be active even though previous decode failed."; +} + +TEST_F(VideoDecoderSoftwareFallbackWrapperTest, UsesHwDecoderAfterReinit) { + fallback_wrapper_->Configure({}); + + fake_decoder_->decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; + EncodedImage encoded_image; + fallback_wrapper_->Decode(encoded_image, false, -1); + EXPECT_EQ(1, fake_decoder_->decode_count_); + + fallback_wrapper_->Release(); + fallback_wrapper_->Configure({}); + + fake_decoder_->decode_return_code_ = WEBRTC_VIDEO_CODEC_OK; + fallback_wrapper_->Decode(encoded_image, false, -1); + EXPECT_EQ(2, fake_decoder_->decode_count_) + << "Should not be using fallback after reinit."; +} + +TEST_F(VideoDecoderSoftwareFallbackWrapperTest, ForwardsReleaseCall) { + fallback_wrapper_->Configure({}); + fallback_wrapper_->Release(); + EXPECT_EQ(1, fake_decoder_->release_count_); + + fallback_wrapper_->Configure({}); + fake_decoder_->decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; + EncodedImage encoded_image; + fallback_wrapper_->Decode(encoded_image, false, -1); + EXPECT_EQ(2, fake_decoder_->release_count_) + << "Decoder should be released during fallback."; + fallback_wrapper_->Release(); + EXPECT_EQ(2, fake_decoder_->release_count_); +} + +// TODO(pbos): Fake a VP8 frame well enough to actually receive a callback from +// the software decoder. +TEST_F(VideoDecoderSoftwareFallbackWrapperTest, + ForwardsRegisterDecodeCompleteCallback) { + class FakeDecodedImageCallback : public DecodedImageCallback { + int32_t Decoded(VideoFrame& decodedImage) override { return 0; } + int32_t Decoded(webrtc::VideoFrame& decodedImage, + int64_t decode_time_ms) override { + RTC_DCHECK_NOTREACHED(); + return -1; + } + void Decoded(webrtc::VideoFrame& decodedImage, + absl::optional<int32_t> decode_time_ms, + absl::optional<uint8_t> qp) override { + RTC_DCHECK_NOTREACHED(); + } + } callback; + + fallback_wrapper_->Configure({}); + fallback_wrapper_->RegisterDecodeCompleteCallback(&callback); + EXPECT_EQ(&callback, fake_decoder_->decode_complete_callback_); +} + +TEST_F(VideoDecoderSoftwareFallbackWrapperTest, + ReportsFallbackImplementationName) { + fallback_wrapper_->Configure({}); + + fake_decoder_->decode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; + EncodedImage encoded_image; + fallback_wrapper_->Decode(encoded_image, false, -1); + // Hard coded expected value since libvpx is the software implementation name + // for VP8. Change accordingly if the underlying implementation does. + EXPECT_STREQ("libvpx (fallback from: fake-decoder)", + fallback_wrapper_->ImplementationName()); + fallback_wrapper_->Release(); +} + +TEST_F(VideoDecoderSoftwareFallbackWrapperTest, FallbacksOnTooManyErrors) { + fallback_wrapper_->Configure({}); + + fake_decoder_->decode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR; + EncodedImage encoded_image; + encoded_image._frameType = VideoFrameType::kVideoFrameKey; + // Doesn't fallback from a single error. + fallback_wrapper_->Decode(encoded_image, false, -1); + EXPECT_STREQ("fake-decoder", fallback_wrapper_->ImplementationName()); + + // However, many frames with the same error, fallback should happen. + const int kNumFramesToEncode = 10; + for (int i = 0; i < kNumFramesToEncode; ++i) { + fallback_wrapper_->Decode(encoded_image, false, -1); + } + // Hard coded expected value since libvpx is the software implementation name + // for VP8. Change accordingly if the underlying implementation does. + EXPECT_STREQ("libvpx (fallback from: fake-decoder)", + fallback_wrapper_->ImplementationName()); + fallback_wrapper_->Release(); +} + +TEST_F(VideoDecoderSoftwareFallbackWrapperTest, + DoesNotFallbackOnDeltaFramesErrors) { + fallback_wrapper_->Configure({}); + + fake_decoder_->decode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR; + EncodedImage encoded_image; + encoded_image._frameType = VideoFrameType::kVideoFrameDelta; + + // Many decoded frames with the same error + const int kNumFramesToEncode = 10; + for (int i = 0; i < kNumFramesToEncode; ++i) { + fallback_wrapper_->Decode(encoded_image, false, -1); + } + EXPECT_STREQ("fake-decoder", fallback_wrapper_->ImplementationName()); + + fallback_wrapper_->Release(); +} + +TEST_F(VideoDecoderSoftwareFallbackWrapperTest, + DoesNotFallbacksOnNonConsequtiveErrors) { + fallback_wrapper_->Configure({}); + + EncodedImage encoded_image; + encoded_image._frameType = VideoFrameType::kVideoFrameKey; + + const int kNumFramesToEncode = 10; + for (int i = 0; i < kNumFramesToEncode; ++i) { + // Interleaved errors and successful decodes. + fake_decoder_->decode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR; + fallback_wrapper_->Decode(encoded_image, false, -1); + fake_decoder_->decode_return_code_ = WEBRTC_VIDEO_CODEC_OK; + fallback_wrapper_->Decode(encoded_image, false, -1); + } + EXPECT_STREQ("fake-decoder", fallback_wrapper_->ImplementationName()); + fallback_wrapper_->Release(); +} + +class ForcedSoftwareDecoderFallbackTest + : public VideoDecoderSoftwareFallbackWrapperTest { + public: + ForcedSoftwareDecoderFallbackTest() + : VideoDecoderSoftwareFallbackWrapperTest( + "WebRTC-Video-ForcedSwDecoderFallback/Enabled/") { + fake_decoder_ = new CountingFakeDecoder(); + sw_fallback_decoder_ = new CountingFakeDecoder(); + fallback_wrapper_ = CreateVideoDecoderSoftwareFallbackWrapper( + std::unique_ptr<VideoDecoder>(sw_fallback_decoder_), + std::unique_ptr<VideoDecoder>(fake_decoder_)); + } + + CountingFakeDecoder* sw_fallback_decoder_; +}; + +TEST_F(ForcedSoftwareDecoderFallbackTest, UsesForcedFallback) { + fallback_wrapper_->Configure({}); + EXPECT_EQ(1, sw_fallback_decoder_->configure_count_); + + EncodedImage encoded_image; + encoded_image._frameType = VideoFrameType::kVideoFrameKey; + fallback_wrapper_->Decode(encoded_image, false, -1); + EXPECT_EQ(1, sw_fallback_decoder_->configure_count_); + EXPECT_EQ(1, sw_fallback_decoder_->decode_count_); + + fallback_wrapper_->Release(); + EXPECT_EQ(1, sw_fallback_decoder_->release_count_); + + // Only fallback decoder should have been used. + EXPECT_EQ(0, fake_decoder_->configure_count_); + EXPECT_EQ(0, fake_decoder_->decode_count_); + EXPECT_EQ(0, fake_decoder_->release_count_); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/test/video_encoder_factory_template_tests.cc b/third_party/libwebrtc/api/video_codecs/test/video_encoder_factory_template_tests.cc new file mode 100644 index 0000000000..4c3d0cd24e --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/test/video_encoder_factory_template_tests.cc @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2022 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 "api/test/mock_video_encoder.h" +#include "api/video_codecs/video_encoder_factory_template.h" +#include "api/video_codecs/video_encoder_factory_template_libaom_av1_adapter.h" +#include "api/video_codecs/video_encoder_factory_template_libvpx_vp8_adapter.h" +#include "api/video_codecs/video_encoder_factory_template_libvpx_vp9_adapter.h" +#include "api/video_codecs/video_encoder_factory_template_open_h264_adapter.h" +#include "test/gmock.h" +#include "test/gtest.h" + +using ::testing::Contains; +using ::testing::Each; +using ::testing::Eq; +using ::testing::Field; +using ::testing::IsEmpty; +using ::testing::Ne; +using ::testing::Not; +using ::testing::UnorderedElementsAre; + +namespace webrtc { +namespace { +using CodecSupport = VideoEncoderFactory::CodecSupport; +const SdpVideoFormat kFooSdp("Foo"); +const SdpVideoFormat kBarLowSdp("Bar", {{"profile", "low"}}); +const SdpVideoFormat kBarHighSdp("Bar", {{"profile", "high"}}); + +struct FooEncoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { return {kFooSdp}; } + + static std::unique_ptr<VideoEncoder> CreateEncoder( + const SdpVideoFormat& format) { + return std::make_unique<testing::StrictMock<MockVideoEncoder>>(); + } + + static bool IsScalabilityModeSupported(ScalabilityMode scalability_mode) { + return scalability_mode == ScalabilityMode::kL1T2 || + scalability_mode == ScalabilityMode::kL1T3; + } +}; + +struct BarEncoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { + return {kBarLowSdp, kBarHighSdp}; + } + + static std::unique_ptr<VideoEncoder> CreateEncoder( + const SdpVideoFormat& format) { + return std::make_unique<testing::StrictMock<MockVideoEncoder>>(); + } + + static bool IsScalabilityModeSupported(ScalabilityMode scalability_mode) { + return scalability_mode == ScalabilityMode::kL1T2 || + scalability_mode == ScalabilityMode::kL1T3 || + scalability_mode == ScalabilityMode::kS2T1 || + scalability_mode == ScalabilityMode::kS3T3; + } +}; + +TEST(VideoEncoderFactoryTemplate, OneTemplateAdapterCreateEncoder) { + VideoEncoderFactoryTemplate<FooEncoderTemplateAdapter> factory; + EXPECT_THAT(factory.GetSupportedFormats(), UnorderedElementsAre(kFooSdp)); + EXPECT_THAT(factory.CreateVideoEncoder(kFooSdp), Ne(nullptr)); + EXPECT_THAT(factory.CreateVideoEncoder(SdpVideoFormat("FooX")), Eq(nullptr)); +} + +TEST(VideoEncoderFactoryTemplate, OneTemplateAdapterCodecSupport) { + VideoEncoderFactoryTemplate<FooEncoderTemplateAdapter> factory; + EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, absl::nullopt), + Field(&CodecSupport::is_supported, true)); + EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "L1T2"), + Field(&CodecSupport::is_supported, true)); + EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "S3T3"), + Field(&CodecSupport::is_supported, false)); + EXPECT_THAT(factory.QueryCodecSupport(SdpVideoFormat("FooX"), absl::nullopt), + Field(&CodecSupport::is_supported, false)); +} + +TEST(VideoEncoderFactoryTemplate, TwoTemplateAdaptersNoDuplicates) { + VideoEncoderFactoryTemplate<FooEncoderTemplateAdapter, + FooEncoderTemplateAdapter> + factory; + EXPECT_THAT(factory.GetSupportedFormats(), UnorderedElementsAre(kFooSdp)); +} + +TEST(VideoEncoderFactoryTemplate, TwoTemplateAdaptersCreateEncoders) { + VideoEncoderFactoryTemplate<FooEncoderTemplateAdapter, + BarEncoderTemplateAdapter> + factory; + EXPECT_THAT(factory.GetSupportedFormats(), + UnorderedElementsAre(kFooSdp, kBarLowSdp, kBarHighSdp)); + EXPECT_THAT(factory.CreateVideoEncoder(kFooSdp), Ne(nullptr)); + EXPECT_THAT(factory.CreateVideoEncoder(kBarLowSdp), Ne(nullptr)); + EXPECT_THAT(factory.CreateVideoEncoder(kBarHighSdp), Ne(nullptr)); + EXPECT_THAT(factory.CreateVideoEncoder(SdpVideoFormat("FooX")), Eq(nullptr)); + EXPECT_THAT(factory.CreateVideoEncoder(SdpVideoFormat("Bar")), Eq(nullptr)); +} + +TEST(VideoEncoderFactoryTemplate, TwoTemplateAdaptersCodecSupport) { + VideoEncoderFactoryTemplate<FooEncoderTemplateAdapter, + BarEncoderTemplateAdapter> + factory; + EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, absl::nullopt), + Field(&CodecSupport::is_supported, true)); + EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "L1T2"), + Field(&CodecSupport::is_supported, true)); + EXPECT_THAT(factory.QueryCodecSupport(kFooSdp, "S3T3"), + Field(&CodecSupport::is_supported, false)); + EXPECT_THAT(factory.QueryCodecSupport(kBarLowSdp, absl::nullopt), + Field(&CodecSupport::is_supported, true)); + EXPECT_THAT(factory.QueryCodecSupport(kBarHighSdp, absl::nullopt), + Field(&CodecSupport::is_supported, true)); + EXPECT_THAT(factory.QueryCodecSupport(kBarLowSdp, "S2T1"), + Field(&CodecSupport::is_supported, true)); + EXPECT_THAT(factory.QueryCodecSupport(kBarHighSdp, "S3T2"), + Field(&CodecSupport::is_supported, false)); +} + +TEST(VideoEncoderFactoryTemplate, LibvpxVp8) { + VideoEncoderFactoryTemplate<LibvpxVp8EncoderTemplateAdapter> factory; + auto formats = factory.GetSupportedFormats(); + EXPECT_THAT(formats.size(), 1); + EXPECT_THAT(formats[0], Field(&SdpVideoFormat::name, "VP8")); + EXPECT_THAT(formats[0], Field(&SdpVideoFormat::scalability_modes, + Contains(ScalabilityMode::kL1T3))); + EXPECT_THAT(factory.CreateVideoEncoder(formats[0]), Ne(nullptr)); +} + +TEST(VideoEncoderFactoryTemplate, LibvpxVp9) { + VideoEncoderFactoryTemplate<LibvpxVp9EncoderTemplateAdapter> factory; + auto formats = factory.GetSupportedFormats(); + EXPECT_THAT(formats, Not(IsEmpty())); + EXPECT_THAT(formats, Each(Field(&SdpVideoFormat::name, "VP9"))); + EXPECT_THAT(formats, Each(Field(&SdpVideoFormat::scalability_modes, + Contains(ScalabilityMode::kL3T3_KEY)))); + EXPECT_THAT(factory.CreateVideoEncoder(formats[0]), Ne(nullptr)); +} + +// TODO(bugs.webrtc.org/13573): When OpenH264 is no longer a conditional build +// target remove this #ifdef. +#if defined(WEBRTC_USE_H264) +TEST(VideoEncoderFactoryTemplate, OpenH264) { + VideoEncoderFactoryTemplate<OpenH264EncoderTemplateAdapter> factory; + auto formats = factory.GetSupportedFormats(); + EXPECT_THAT(formats, Not(IsEmpty())); + EXPECT_THAT(formats, Each(Field(&SdpVideoFormat::name, "H264"))); + EXPECT_THAT(formats, Each(Field(&SdpVideoFormat::scalability_modes, + Contains(ScalabilityMode::kL1T3)))); + EXPECT_THAT(factory.CreateVideoEncoder(formats[0]), Ne(nullptr)); +} +#endif // defined(WEBRTC_USE_H264) + +TEST(VideoEncoderFactoryTemplate, LibaomAv1) { + VideoEncoderFactoryTemplate<LibaomAv1EncoderTemplateAdapter> factory; + auto formats = factory.GetSupportedFormats(); + EXPECT_THAT(formats.size(), 1); + EXPECT_THAT(formats[0], Field(&SdpVideoFormat::name, "AV1")); + EXPECT_THAT(formats[0], Field(&SdpVideoFormat::scalability_modes, + Contains(ScalabilityMode::kL3T3_KEY))); + EXPECT_THAT(factory.CreateVideoEncoder(formats[0]), Ne(nullptr)); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/test/video_encoder_software_fallback_wrapper_unittest.cc b/third_party/libwebrtc/api/video_codecs/test/video_encoder_software_fallback_wrapper_unittest.cc new file mode 100644 index 0000000000..b213356e7b --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/test/video_encoder_software_fallback_wrapper_unittest.cc @@ -0,0 +1,1055 @@ +/* + * Copyright (c) 2015 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 "api/video_codecs/video_encoder_software_fallback_wrapper.h" + +#include <stddef.h> +#include <stdint.h> + +#include <memory> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/fec_controller_override.h" +#include "api/scoped_refptr.h" +#include "api/test/mock_video_encoder.h" +#include "api/video/encoded_image.h" +#include "api/video/i420_buffer.h" +#include "api/video/video_bitrate_allocation.h" +#include "api/video/video_frame.h" +#include "api/video/video_frame_buffer.h" +#include "api/video/video_rotation.h" +#include "api/video_codecs/video_codec.h" +#include "api/video_codecs/video_encoder.h" +#include "modules/video_coding/codecs/vp8/include/vp8.h" +#include "modules/video_coding/include/video_codec_interface.h" +#include "modules/video_coding/include/video_error_codes.h" +#include "modules/video_coding/utility/simulcast_rate_allocator.h" +#include "rtc_base/fake_clock.h" +#include "test/fake_texture_frame.h" +#include "test/field_trial.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { +using ::testing::_; +using ::testing::Return; + +namespace { +const int kWidth = 320; +const int kHeight = 240; +const int kNumCores = 2; +const uint32_t kFramerate = 30; +const size_t kMaxPayloadSize = 800; +const int kLowThreshold = 10; +const int kHighThreshold = 20; + +const VideoEncoder::Capabilities kCapabilities(false); +const VideoEncoder::Settings kSettings(kCapabilities, + kNumCores, + kMaxPayloadSize); + +VideoEncoder::EncoderInfo GetEncoderInfoWithTrustedRateController( + bool trusted_rate_controller) { + VideoEncoder::EncoderInfo info; + info.has_trusted_rate_controller = trusted_rate_controller; + return info; +} + +VideoEncoder::EncoderInfo GetEncoderInfoWithHardwareAccelerated( + bool hardware_accelerated) { + VideoEncoder::EncoderInfo info; + info.is_hardware_accelerated = hardware_accelerated; + return info; +} + +class FakeEncodedImageCallback : public EncodedImageCallback { + public: + Result OnEncodedImage(const EncodedImage& encoded_image, + const CodecSpecificInfo* codec_specific_info) override { + ++callback_count_; + return Result(Result::OK, callback_count_); + } + int callback_count_ = 0; +}; +} // namespace + +class VideoEncoderSoftwareFallbackWrapperTestBase : public ::testing::Test { + protected: + VideoEncoderSoftwareFallbackWrapperTestBase( + const std::string& field_trials, + std::unique_ptr<VideoEncoder> sw_encoder) + : override_field_trials_(field_trials), + fake_encoder_(new CountingFakeEncoder()), + wrapper_initialized_(false), + fallback_wrapper_(CreateVideoEncoderSoftwareFallbackWrapper( + std::move(sw_encoder), + std::unique_ptr<VideoEncoder>(fake_encoder_), + false)) {} + + class CountingFakeEncoder : public VideoEncoder { + public: + void SetFecControllerOverride( + FecControllerOverride* fec_controller_override) override { + // Ignored. + } + + int32_t InitEncode(const VideoCodec* codec_settings, + const VideoEncoder::Settings& settings) override { + ++init_encode_count_; + return init_encode_return_code_; + } + + int32_t Encode(const VideoFrame& frame, + const std::vector<VideoFrameType>* frame_types) override { + ++encode_count_; + last_video_frame_ = frame; + if (encode_complete_callback_ && + encode_return_code_ == WEBRTC_VIDEO_CODEC_OK) { + encode_complete_callback_->OnEncodedImage(EncodedImage(), nullptr); + } + return encode_return_code_; + } + + int32_t RegisterEncodeCompleteCallback( + EncodedImageCallback* callback) override { + encode_complete_callback_ = callback; + return WEBRTC_VIDEO_CODEC_OK; + } + + int32_t Release() override { + ++release_count_; + return WEBRTC_VIDEO_CODEC_OK; + } + + void SetRates(const RateControlParameters& parameters) override {} + + EncoderInfo GetEncoderInfo() const override { + ++supports_native_handle_count_; + EncoderInfo info; + info.scaling_settings = ScalingSettings(kLowThreshold, kHighThreshold); + info.supports_native_handle = supports_native_handle_; + info.implementation_name = implementation_name_; + if (is_qp_trusted_) + info.is_qp_trusted = is_qp_trusted_; + return info; + } + + int init_encode_count_ = 0; + int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK; + int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK; + int encode_count_ = 0; + EncodedImageCallback* encode_complete_callback_ = nullptr; + int release_count_ = 0; + mutable int supports_native_handle_count_ = 0; + bool supports_native_handle_ = false; + bool is_qp_trusted_ = false; + std::string implementation_name_ = "fake-encoder"; + absl::optional<VideoFrame> last_video_frame_; + }; + + void InitEncode(); + void UtilizeFallbackEncoder(); + void FallbackFromEncodeRequest(); + void EncodeFrame(); + void EncodeFrame(int expected_ret); + void CheckLastEncoderName(const char* expected_name) { + EXPECT_EQ(expected_name, + fallback_wrapper_->GetEncoderInfo().implementation_name); + } + + test::ScopedFieldTrials override_field_trials_; + FakeEncodedImageCallback callback_; + // `fake_encoder_` is owned and released by `fallback_wrapper_`. + CountingFakeEncoder* fake_encoder_; + CountingFakeEncoder* fake_sw_encoder_; + bool wrapper_initialized_; + std::unique_ptr<VideoEncoder> fallback_wrapper_; + VideoCodec codec_ = {}; + std::unique_ptr<VideoFrame> frame_; + std::unique_ptr<SimulcastRateAllocator> rate_allocator_; +}; + +class VideoEncoderSoftwareFallbackWrapperTest + : public VideoEncoderSoftwareFallbackWrapperTestBase { + protected: + VideoEncoderSoftwareFallbackWrapperTest() + : VideoEncoderSoftwareFallbackWrapperTest(new CountingFakeEncoder()) {} + explicit VideoEncoderSoftwareFallbackWrapperTest( + CountingFakeEncoder* fake_sw_encoder) + : VideoEncoderSoftwareFallbackWrapperTestBase( + "", + std::unique_ptr<VideoEncoder>(fake_sw_encoder)), + fake_sw_encoder_(fake_sw_encoder) { + fake_sw_encoder_->implementation_name_ = "fake_sw_encoder"; + } + + CountingFakeEncoder* fake_sw_encoder_; +}; + +void VideoEncoderSoftwareFallbackWrapperTestBase::EncodeFrame() { + EncodeFrame(WEBRTC_VIDEO_CODEC_OK); +} + +void VideoEncoderSoftwareFallbackWrapperTestBase::EncodeFrame( + int expected_ret) { + rtc::scoped_refptr<I420Buffer> buffer = + I420Buffer::Create(codec_.width, codec_.height); + I420Buffer::SetBlack(buffer.get()); + std::vector<VideoFrameType> types(1, VideoFrameType::kVideoFrameKey); + + frame_ = + std::make_unique<VideoFrame>(VideoFrame::Builder() + .set_video_frame_buffer(buffer) + .set_rotation(webrtc::kVideoRotation_0) + .set_timestamp_us(0) + .build()); + EXPECT_EQ(expected_ret, fallback_wrapper_->Encode(*frame_, &types)); +} + +void VideoEncoderSoftwareFallbackWrapperTestBase::InitEncode() { + if (!wrapper_initialized_) { + fallback_wrapper_->RegisterEncodeCompleteCallback(&callback_); + EXPECT_EQ(&callback_, fake_encoder_->encode_complete_callback_); + } + + // Register fake encoder as main. + codec_.codecType = kVideoCodecVP8; + codec_.maxFramerate = kFramerate; + codec_.width = kWidth; + codec_.height = kHeight; + codec_.VP8()->numberOfTemporalLayers = 1; + rate_allocator_.reset(new SimulcastRateAllocator(codec_)); + + if (wrapper_initialized_) { + fallback_wrapper_->Release(); + } + + fake_encoder_->init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK; + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + fallback_wrapper_->InitEncode(&codec_, kSettings)); + + if (!wrapper_initialized_) { + fallback_wrapper_->SetRates(VideoEncoder::RateControlParameters( + rate_allocator_->Allocate( + VideoBitrateAllocationParameters(300000, kFramerate)), + kFramerate)); + } + wrapper_initialized_ = true; +} + +void VideoEncoderSoftwareFallbackWrapperTestBase::UtilizeFallbackEncoder() { + if (!wrapper_initialized_) { + fallback_wrapper_->RegisterEncodeCompleteCallback(&callback_); + EXPECT_EQ(&callback_, fake_encoder_->encode_complete_callback_); + } + + // Register with failing fake encoder. Should succeed with VP8 fallback. + codec_.codecType = kVideoCodecVP8; + codec_.maxFramerate = kFramerate; + codec_.width = kWidth; + codec_.height = kHeight; + codec_.VP8()->numberOfTemporalLayers = 1; + rate_allocator_.reset(new SimulcastRateAllocator(codec_)); + + if (wrapper_initialized_) { + fallback_wrapper_->Release(); + } + + fake_encoder_->init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR; + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + fallback_wrapper_->InitEncode(&codec_, kSettings)); + fallback_wrapper_->SetRates(VideoEncoder::RateControlParameters( + rate_allocator_->Allocate( + VideoBitrateAllocationParameters(300000, kFramerate)), + kFramerate)); + + int callback_count = callback_.callback_count_; + int encode_count = fake_encoder_->encode_count_; + EncodeFrame(); + EXPECT_EQ(encode_count, fake_encoder_->encode_count_); + EXPECT_EQ(callback_count + 1, callback_.callback_count_); +} + +void VideoEncoderSoftwareFallbackWrapperTestBase::FallbackFromEncodeRequest() { + fallback_wrapper_->RegisterEncodeCompleteCallback(&callback_); + codec_.codecType = kVideoCodecVP8; + codec_.maxFramerate = kFramerate; + codec_.width = kWidth; + codec_.height = kHeight; + codec_.VP8()->numberOfTemporalLayers = 1; + rate_allocator_.reset(new SimulcastRateAllocator(codec_)); + if (wrapper_initialized_) { + fallback_wrapper_->Release(); + } + fallback_wrapper_->InitEncode(&codec_, kSettings); + fallback_wrapper_->SetRates(VideoEncoder::RateControlParameters( + rate_allocator_->Allocate( + VideoBitrateAllocationParameters(300000, kFramerate)), + kFramerate)); + EXPECT_EQ(1, fake_encoder_->init_encode_count_); + + // Have the non-fallback encoder request a software fallback. + fake_encoder_->encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; + int callback_count = callback_.callback_count_; + int encode_count = fake_encoder_->encode_count_; + EncodeFrame(); + // Single encode request, which returned failure. + EXPECT_EQ(encode_count + 1, fake_encoder_->encode_count_); + EXPECT_EQ(callback_count + 1, callback_.callback_count_); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) { + VideoCodec codec = {}; + fallback_wrapper_->InitEncode(&codec, kSettings); + EXPECT_EQ(1, fake_encoder_->init_encode_count_); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) { + FallbackFromEncodeRequest(); + // After fallback, further encodes shouldn't hit the fake encoder. + int encode_count = fake_encoder_->encode_count_; + EncodeFrame(); + EXPECT_EQ(encode_count, fake_encoder_->encode_count_); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) { + UtilizeFallbackEncoder(); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, + InternalEncoderReleasedDuringFallback) { + EXPECT_EQ(0, fake_encoder_->init_encode_count_); + EXPECT_EQ(0, fake_encoder_->release_count_); + + InitEncode(); + + EXPECT_EQ(1, fake_encoder_->init_encode_count_); + EXPECT_EQ(0, fake_encoder_->release_count_); + + UtilizeFallbackEncoder(); + + // One successful InitEncode(), one failed. + EXPECT_EQ(2, fake_encoder_->init_encode_count_); + EXPECT_EQ(1, fake_encoder_->release_count_); + + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); + + // No extra release when the fallback is released. + EXPECT_EQ(2, fake_encoder_->init_encode_count_); + EXPECT_EQ(1, fake_encoder_->release_count_); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, + InternalEncoderNotEncodingDuringFallback) { + UtilizeFallbackEncoder(); + int encode_count = fake_encoder_->encode_count_; + EncodeFrame(); + EXPECT_EQ(encode_count, fake_encoder_->encode_count_); + + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, + CanRegisterCallbackWhileUsingFallbackEncoder) { + InitEncode(); + EXPECT_EQ(&callback_, fake_encoder_->encode_complete_callback_); + + UtilizeFallbackEncoder(); + + // Registering an encode-complete callback will now pass to the fallback + // instead of the main encoder. + FakeEncodedImageCallback callback2; + fallback_wrapper_->RegisterEncodeCompleteCallback(&callback2); + EXPECT_EQ(&callback_, fake_encoder_->encode_complete_callback_); + + // Encoding a frame using the fallback should arrive at the new callback. + std::vector<VideoFrameType> types(1, VideoFrameType::kVideoFrameKey); + frame_->set_timestamp(frame_->timestamp() + 1000); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Encode(*frame_, &types)); + EXPECT_EQ(callback2.callback_count_, 1); + + // Re-initialize to use the main encoder, the new callback should be in use. + InitEncode(); + EXPECT_EQ(&callback2, fake_encoder_->encode_complete_callback_); + + frame_->set_timestamp(frame_->timestamp() + 2000); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Encode(*frame_, &types)); + EXPECT_EQ(callback2.callback_count_, 2); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, + SupportsNativeHandleForwardedWithoutFallback) { + fallback_wrapper_->GetEncoderInfo(); + EXPECT_EQ(1, fake_encoder_->supports_native_handle_count_); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, + SupportsNativeHandleNotForwardedDuringFallback) { + // Fake encoder signals support for native handle, default (libvpx) does not. + fake_encoder_->supports_native_handle_ = true; + EXPECT_TRUE(fallback_wrapper_->GetEncoderInfo().supports_native_handle); + UtilizeFallbackEncoder(); + EXPECT_FALSE(fallback_wrapper_->GetEncoderInfo().supports_native_handle); + // Both times, both encoders are queried. + EXPECT_EQ(2, fake_encoder_->supports_native_handle_count_); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) { + codec_.width = kWidth; + codec_.height = kHeight; + fallback_wrapper_->RegisterEncodeCompleteCallback(&callback_); + fallback_wrapper_->InitEncode(&codec_, kSettings); + EncodeFrame(); + CheckLastEncoderName("fake-encoder"); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, + IsQpTrustedNotForwardedDuringFallback) { + // Fake encoder signals trusted QP, default (libvpx) does not. + fake_encoder_->is_qp_trusted_ = true; + EXPECT_TRUE(fake_encoder_->GetEncoderInfo().is_qp_trusted.value_or(false)); + UtilizeFallbackEncoder(); + EXPECT_FALSE(fallback_wrapper_->GetEncoderInfo().is_qp_trusted.has_value()); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, + ReportsFallbackImplementationName) { + UtilizeFallbackEncoder(); + CheckLastEncoderName(fake_sw_encoder_->implementation_name_.c_str()); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, + OnEncodeFallbackNativeFrameScaledIfFallbackDoesNotSupportNativeFrames) { + fake_encoder_->supports_native_handle_ = true; + fake_sw_encoder_->supports_native_handle_ = false; + InitEncode(); + int width = codec_.width * 2; + int height = codec_.height * 2; + VideoFrame native_frame = test::FakeNativeBuffer::CreateFrame( + width, height, 0, 0, VideoRotation::kVideoRotation_0); + std::vector<VideoFrameType> types(1, VideoFrameType::kVideoFrameKey); + fake_encoder_->encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; + + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + fallback_wrapper_->Encode(native_frame, &types)); + EXPECT_EQ(1, fake_sw_encoder_->encode_count_); + ASSERT_TRUE(fake_sw_encoder_->last_video_frame_.has_value()); + EXPECT_NE(VideoFrameBuffer::Type::kNative, + fake_sw_encoder_->last_video_frame_->video_frame_buffer()->type()); + EXPECT_EQ(codec_.width, fake_sw_encoder_->last_video_frame_->width()); + EXPECT_EQ(codec_.height, fake_sw_encoder_->last_video_frame_->height()); +} + +TEST_F(VideoEncoderSoftwareFallbackWrapperTest, + OnEncodeFallbackNativeFrameForwardedToFallbackIfItSupportsNativeFrames) { + fake_encoder_->supports_native_handle_ = true; + fake_sw_encoder_->supports_native_handle_ = true; + InitEncode(); + int width = codec_.width * 2; + int height = codec_.height * 2; + VideoFrame native_frame = test::FakeNativeBuffer::CreateFrame( + width, height, 0, 0, VideoRotation::kVideoRotation_0); + std::vector<VideoFrameType> types(1, VideoFrameType::kVideoFrameKey); + fake_encoder_->encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; + + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + fallback_wrapper_->Encode(native_frame, &types)); + EXPECT_EQ(1, fake_sw_encoder_->encode_count_); + ASSERT_TRUE(fake_sw_encoder_->last_video_frame_.has_value()); + EXPECT_EQ(VideoFrameBuffer::Type::kNative, + fake_sw_encoder_->last_video_frame_->video_frame_buffer()->type()); + EXPECT_EQ(native_frame.width(), fake_sw_encoder_->last_video_frame_->width()); + EXPECT_EQ(native_frame.height(), + fake_sw_encoder_->last_video_frame_->height()); +} + +namespace { +const int kBitrateKbps = 200; +const int kMinPixelsPerFrame = 1; +const char kFieldTrial[] = "WebRTC-VP8-Forced-Fallback-Encoder-v2"; +} // namespace + +class ForcedFallbackTest : public VideoEncoderSoftwareFallbackWrapperTestBase { + public: + explicit ForcedFallbackTest(const std::string& field_trials) + : VideoEncoderSoftwareFallbackWrapperTestBase(field_trials, + VP8Encoder::Create()) {} + + ~ForcedFallbackTest() override {} + + protected: + void SetUp() override { + clock_.SetTime(Timestamp::Micros(1234)); + ConfigureVp8Codec(); + } + + void TearDown() override { + if (wrapper_initialized_) { + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); + } + } + + void ConfigureVp8Codec() { + codec_.codecType = kVideoCodecVP8; + codec_.maxFramerate = kFramerate; + codec_.width = kWidth; + codec_.height = kHeight; + codec_.VP8()->numberOfTemporalLayers = 1; + codec_.VP8()->automaticResizeOn = true; + codec_.SetFrameDropEnabled(true); + rate_allocator_.reset(new SimulcastRateAllocator(codec_)); + } + + void InitEncode(int width, int height) { + codec_.width = width; + codec_.height = height; + if (wrapper_initialized_) { + fallback_wrapper_->Release(); + } + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + fallback_wrapper_->InitEncode(&codec_, kSettings)); + fallback_wrapper_->RegisterEncodeCompleteCallback(&callback_); + wrapper_initialized_ = true; + SetRateAllocation(kBitrateKbps); + } + + void SetRateAllocation(uint32_t bitrate_kbps) { + fallback_wrapper_->SetRates(VideoEncoder::RateControlParameters( + rate_allocator_->Allocate( + VideoBitrateAllocationParameters(bitrate_kbps * 1000, kFramerate)), + kFramerate)); + } + + void EncodeFrameAndVerifyLastName(const char* expected_name) { + EncodeFrameAndVerifyLastName(expected_name, WEBRTC_VIDEO_CODEC_OK); + } + + void EncodeFrameAndVerifyLastName(const char* expected_name, + int expected_ret) { + EncodeFrame(expected_ret); + CheckLastEncoderName(expected_name); + } + + rtc::ScopedFakeClock clock_; +}; + +class ForcedFallbackTestEnabled : public ForcedFallbackTest { + public: + ForcedFallbackTestEnabled() + : ForcedFallbackTest(std::string(kFieldTrial) + "/Enabled-" + + std::to_string(kMinPixelsPerFrame) + "," + + std::to_string(kWidth * kHeight) + ",30000/") {} +}; + +class ForcedFallbackTestDisabled : public ForcedFallbackTest { + public: + ForcedFallbackTestDisabled() + : ForcedFallbackTest(std::string(kFieldTrial) + "/Disabled/") {} +}; + +TEST_F(ForcedFallbackTestDisabled, NoFallbackWithoutFieldTrial) { + // Resolution above max threshold. + InitEncode(kWidth + 1, kHeight); + EXPECT_EQ(1, fake_encoder_->init_encode_count_); + EncodeFrameAndVerifyLastName("fake-encoder"); + + // Resolution at max threshold. + InitEncode(kWidth, kHeight); + EncodeFrameAndVerifyLastName("fake-encoder"); +} + +TEST_F(ForcedFallbackTestEnabled, FallbackIfAtMaxResolutionLimit) { + // Resolution above max threshold. + InitEncode(kWidth + 1, kHeight); + EXPECT_EQ(1, fake_encoder_->init_encode_count_); + EncodeFrameAndVerifyLastName("fake-encoder"); + + // Resolution at max threshold. + InitEncode(kWidth, kHeight); + EncodeFrameAndVerifyLastName("libvpx"); +} + +TEST_F(ForcedFallbackTestEnabled, FallbackIsKeptWhenInitEncodeIsCalled) { + // Resolution above max threshold. + InitEncode(kWidth + 1, kHeight); + EXPECT_EQ(1, fake_encoder_->init_encode_count_); + EncodeFrameAndVerifyLastName("fake-encoder"); + + // Resolution at max threshold. + InitEncode(kWidth, kHeight); + EncodeFrameAndVerifyLastName("libvpx"); + + // Re-initialize encoder, still expect fallback. + InitEncode(kWidth / 2, kHeight / 2); + EXPECT_EQ(1, fake_encoder_->init_encode_count_); // No change. + EncodeFrameAndVerifyLastName("libvpx"); +} + +TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedWhenResolutionIsTooLarge) { + // Resolution above max threshold. + InitEncode(kWidth + 1, kHeight); + EXPECT_EQ(1, fake_encoder_->init_encode_count_); + EncodeFrameAndVerifyLastName("fake-encoder"); + + // Resolution at max threshold. + InitEncode(kWidth, kHeight); + EncodeFrameAndVerifyLastName("libvpx"); + + // Re-initialize encoder with a larger resolution, expect no fallback. + InitEncode(kWidth + 1, kHeight); + EXPECT_EQ(2, fake_encoder_->init_encode_count_); + EncodeFrameAndVerifyLastName("fake-encoder"); +} + +TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedForNonValidSettings) { + // Resolution at max threshold. + InitEncode(kWidth, kHeight); + EncodeFrameAndVerifyLastName("libvpx"); + + // Re-initialize encoder with invalid setting, expect no fallback. + codec_.numberOfSimulcastStreams = 2; + InitEncode(kWidth, kHeight); + EXPECT_EQ(1, fake_encoder_->init_encode_count_); + EncodeFrameAndVerifyLastName("fake-encoder"); + + // Re-initialize encoder with valid setting. + codec_.numberOfSimulcastStreams = 1; + InitEncode(kWidth, kHeight); + EXPECT_EQ(1, fake_encoder_->init_encode_count_); + EncodeFrameAndVerifyLastName("libvpx"); +} + +TEST_F(ForcedFallbackTestEnabled, MultipleStartEndFallback) { + const int kNumRuns = 5; + for (int i = 1; i <= kNumRuns; ++i) { + // Resolution at max threshold. + InitEncode(kWidth, kHeight); + EncodeFrameAndVerifyLastName("libvpx"); + // Resolution above max threshold. + InitEncode(kWidth + 1, kHeight); + EXPECT_EQ(i, fake_encoder_->init_encode_count_); + EncodeFrameAndVerifyLastName("fake-encoder"); + } +} + +TEST_F(ForcedFallbackTestDisabled, GetScaleSettings) { + // Resolution above max threshold. + InitEncode(kWidth + 1, kHeight); + EXPECT_EQ(1, fake_encoder_->init_encode_count_); + EncodeFrameAndVerifyLastName("fake-encoder"); + + // Default min pixels per frame should be used. + const auto settings = fallback_wrapper_->GetEncoderInfo().scaling_settings; + EXPECT_TRUE(settings.thresholds.has_value()); + EXPECT_EQ(kDefaultMinPixelsPerFrame, settings.min_pixels_per_frame); +} + +TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithNoFallback) { + // Resolution above max threshold. + InitEncode(kWidth + 1, kHeight); + EncodeFrameAndVerifyLastName("fake-encoder"); + + // Configured min pixels per frame should be used. + const auto settings = fallback_wrapper_->GetEncoderInfo().scaling_settings; + EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame); + ASSERT_TRUE(settings.thresholds); + EXPECT_EQ(kLowThreshold, settings.thresholds->low); + EXPECT_EQ(kHighThreshold, settings.thresholds->high); +} + +TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithFallback) { + // Resolution at max threshold. + InitEncode(kWidth, kHeight); + EncodeFrameAndVerifyLastName("libvpx"); + + // Configured min pixels per frame should be used. + const auto settings = fallback_wrapper_->GetEncoderInfo().scaling_settings; + EXPECT_TRUE(settings.thresholds.has_value()); + EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame); +} + +TEST_F(ForcedFallbackTestEnabled, ScalingDisabledIfResizeOff) { + // Resolution at max threshold. + codec_.VP8()->automaticResizeOn = false; + InitEncode(kWidth, kHeight); + EncodeFrameAndVerifyLastName("libvpx"); + + // Should be disabled for automatic resize off. + const auto settings = fallback_wrapper_->GetEncoderInfo().scaling_settings; + EXPECT_FALSE(settings.thresholds.has_value()); +} + +TEST(SoftwareFallbackEncoderTest, BothRateControllersNotTrusted) { + auto* sw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); + auto* hw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); + + EXPECT_CALL(*sw_encoder, GetEncoderInfo()) + .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(false))); + EXPECT_CALL(*hw_encoder, GetEncoderInfo()) + .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(false))); + + std::unique_ptr<VideoEncoder> wrapper = + CreateVideoEncoderSoftwareFallbackWrapper( + std::unique_ptr<VideoEncoder>(sw_encoder), + std::unique_ptr<VideoEncoder>(hw_encoder)); + EXPECT_FALSE(wrapper->GetEncoderInfo().has_trusted_rate_controller); +} + +TEST(SoftwareFallbackEncoderTest, SwRateControllerTrusted) { + auto* sw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); + auto* hw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); + EXPECT_CALL(*sw_encoder, GetEncoderInfo()) + .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(true))); + EXPECT_CALL(*hw_encoder, GetEncoderInfo()) + .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(false))); + + std::unique_ptr<VideoEncoder> wrapper = + CreateVideoEncoderSoftwareFallbackWrapper( + std::unique_ptr<VideoEncoder>(sw_encoder), + std::unique_ptr<VideoEncoder>(hw_encoder)); + EXPECT_FALSE(wrapper->GetEncoderInfo().has_trusted_rate_controller); +} + +TEST(SoftwareFallbackEncoderTest, HwRateControllerTrusted) { + auto* sw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); + auto* hw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); + EXPECT_CALL(*sw_encoder, GetEncoderInfo()) + .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(false))); + EXPECT_CALL(*hw_encoder, GetEncoderInfo()) + .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(true))); + + std::unique_ptr<VideoEncoder> wrapper = + CreateVideoEncoderSoftwareFallbackWrapper( + std::unique_ptr<VideoEncoder>(sw_encoder), + std::unique_ptr<VideoEncoder>(hw_encoder)); + EXPECT_TRUE(wrapper->GetEncoderInfo().has_trusted_rate_controller); + + VideoCodec codec_ = {}; + codec_.width = 100; + codec_.height = 100; + wrapper->InitEncode(&codec_, kSettings); + + // Trigger fallback to software. + EXPECT_CALL(*hw_encoder, Encode) + .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE)); + VideoFrame frame = VideoFrame::Builder() + .set_video_frame_buffer(I420Buffer::Create(100, 100)) + .build(); + wrapper->Encode(frame, nullptr); + + EXPECT_FALSE(wrapper->GetEncoderInfo().has_trusted_rate_controller); +} + +TEST(SoftwareFallbackEncoderTest, BothRateControllersTrusted) { + auto* sw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); + auto* hw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); + EXPECT_CALL(*sw_encoder, GetEncoderInfo()) + .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(true))); + EXPECT_CALL(*hw_encoder, GetEncoderInfo()) + .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(true))); + + std::unique_ptr<VideoEncoder> wrapper = + CreateVideoEncoderSoftwareFallbackWrapper( + std::unique_ptr<VideoEncoder>(sw_encoder), + std::unique_ptr<VideoEncoder>(hw_encoder)); + EXPECT_TRUE(wrapper->GetEncoderInfo().has_trusted_rate_controller); +} + +TEST(SoftwareFallbackEncoderTest, ReportsHardwareAccelerated) { + auto* sw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); + auto* hw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); + EXPECT_CALL(*sw_encoder, GetEncoderInfo()) + .WillRepeatedly(Return(GetEncoderInfoWithHardwareAccelerated(false))); + EXPECT_CALL(*hw_encoder, GetEncoderInfo()) + .WillRepeatedly(Return(GetEncoderInfoWithHardwareAccelerated(true))); + + std::unique_ptr<VideoEncoder> wrapper = + CreateVideoEncoderSoftwareFallbackWrapper( + std::unique_ptr<VideoEncoder>(sw_encoder), + std::unique_ptr<VideoEncoder>(hw_encoder)); + EXPECT_TRUE(wrapper->GetEncoderInfo().is_hardware_accelerated); + + VideoCodec codec_ = {}; + codec_.width = 100; + codec_.height = 100; + wrapper->InitEncode(&codec_, kSettings); + + // Trigger fallback to software. + EXPECT_CALL(*hw_encoder, Encode) + .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE)); + VideoFrame frame = VideoFrame::Builder() + .set_video_frame_buffer(I420Buffer::Create(100, 100)) + .build(); + wrapper->Encode(frame, nullptr); + EXPECT_FALSE(wrapper->GetEncoderInfo().is_hardware_accelerated); +} + +class PreferTemporalLayersFallbackTest : public ::testing::Test { + public: + PreferTemporalLayersFallbackTest() {} + void SetUp() override { + sw_ = new ::testing::NiceMock<MockVideoEncoder>(); + sw_info_.implementation_name = "sw"; + EXPECT_CALL(*sw_, GetEncoderInfo).WillRepeatedly([&]() { + return sw_info_; + }); + EXPECT_CALL(*sw_, InitEncode(_, _, _)) + .WillRepeatedly(Return(WEBRTC_VIDEO_CODEC_OK)); + + hw_ = new ::testing::NiceMock<MockVideoEncoder>(); + hw_info_.implementation_name = "hw"; + EXPECT_CALL(*hw_, GetEncoderInfo()).WillRepeatedly([&]() { + return hw_info_; + }); + EXPECT_CALL(*hw_, InitEncode(_, _, _)) + .WillRepeatedly(Return(WEBRTC_VIDEO_CODEC_OK)); + + wrapper_ = CreateVideoEncoderSoftwareFallbackWrapper( + std::unique_ptr<VideoEncoder>(sw_), std::unique_ptr<VideoEncoder>(hw_), + /*prefer_temporal_support=*/true); + + codec_settings.codecType = kVideoCodecVP8; + codec_settings.maxFramerate = kFramerate; + codec_settings.width = kWidth; + codec_settings.height = kHeight; + codec_settings.numberOfSimulcastStreams = 1; + codec_settings.VP8()->numberOfTemporalLayers = 1; + } + + protected: + void SetSupportsLayers(VideoEncoder::EncoderInfo* info, bool tl_enabled) { + int num_layers = 1; + if (tl_enabled) { + num_layers = codec_settings.VP8()->numberOfTemporalLayers; + } + SetNumLayers(info, num_layers); + } + + void SetNumLayers(VideoEncoder::EncoderInfo* info, int num_layers) { + info->fps_allocation[0].clear(); + for (int i = 0; i < num_layers; ++i) { + info->fps_allocation[0].push_back( + VideoEncoder::EncoderInfo::kMaxFramerateFraction >> + (num_layers - i - 1)); + } + } + + VideoCodec codec_settings; + ::testing::NiceMock<MockVideoEncoder>* sw_; + ::testing::NiceMock<MockVideoEncoder>* hw_; + VideoEncoder::EncoderInfo sw_info_; + VideoEncoder::EncoderInfo hw_info_; + std::unique_ptr<VideoEncoder> wrapper_; +}; + +TEST_F(PreferTemporalLayersFallbackTest, UsesMainWhenLayersNotUsed) { + codec_settings.VP8()->numberOfTemporalLayers = 1; + SetSupportsLayers(&hw_info_, true); + SetSupportsLayers(&sw_info_, true); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + wrapper_->InitEncode(&codec_settings, kSettings)); + EXPECT_EQ(wrapper_->GetEncoderInfo().implementation_name, "hw"); +} + +TEST_F(PreferTemporalLayersFallbackTest, UsesMainWhenLayersSupported) { + codec_settings.VP8()->numberOfTemporalLayers = 2; + SetSupportsLayers(&hw_info_, true); + SetSupportsLayers(&sw_info_, true); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + wrapper_->InitEncode(&codec_settings, kSettings)); + EXPECT_EQ(wrapper_->GetEncoderInfo().implementation_name, "hw"); +} + +TEST_F(PreferTemporalLayersFallbackTest, + UsesFallbackWhenLayersNotSupportedOnMain) { + codec_settings.VP8()->numberOfTemporalLayers = 2; + SetSupportsLayers(&hw_info_, false); + SetSupportsLayers(&sw_info_, true); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + wrapper_->InitEncode(&codec_settings, kSettings)); + EXPECT_EQ(wrapper_->GetEncoderInfo().implementation_name, "sw"); +} + +TEST_F(PreferTemporalLayersFallbackTest, UsesMainWhenNeitherSupportsTemporal) { + codec_settings.VP8()->numberOfTemporalLayers = 2; + SetSupportsLayers(&hw_info_, false); + SetSupportsLayers(&sw_info_, false); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + wrapper_->InitEncode(&codec_settings, kSettings)); + EXPECT_EQ(wrapper_->GetEncoderInfo().implementation_name, "hw"); +} + +TEST_F(PreferTemporalLayersFallbackTest, UsesFallbackWhenLayersAreUndefined) { + codec_settings.VP8()->numberOfTemporalLayers = 2; + SetNumLayers(&hw_info_, 1); + SetNumLayers(&sw_info_, 0); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + wrapper_->InitEncode(&codec_settings, kSettings)); + EXPECT_EQ(wrapper_->GetEncoderInfo().implementation_name, "sw"); +} + +TEST_F(PreferTemporalLayersFallbackTest, PrimesEncoderOnSwitch) { + codec_settings.VP8()->numberOfTemporalLayers = 2; + // Both support temporal layers, will use main one. + SetSupportsLayers(&hw_info_, true); + SetSupportsLayers(&sw_info_, true); + + // On first InitEncode most params have no state and will not be + // called to update. + EXPECT_CALL(*hw_, RegisterEncodeCompleteCallback).Times(0); + EXPECT_CALL(*sw_, RegisterEncodeCompleteCallback).Times(0); + + EXPECT_CALL(*hw_, SetFecControllerOverride).Times(0); + EXPECT_CALL(*sw_, SetFecControllerOverride).Times(0); + + EXPECT_CALL(*hw_, SetRates).Times(0); + EXPECT_CALL(*hw_, SetRates).Times(0); + + EXPECT_CALL(*hw_, OnPacketLossRateUpdate).Times(0); + EXPECT_CALL(*sw_, OnPacketLossRateUpdate).Times(0); + + EXPECT_CALL(*hw_, OnRttUpdate).Times(0); + EXPECT_CALL(*sw_, OnRttUpdate).Times(0); + + EXPECT_CALL(*hw_, OnLossNotification).Times(0); + EXPECT_CALL(*sw_, OnLossNotification).Times(0); + + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + wrapper_->InitEncode(&codec_settings, kSettings)); + EXPECT_EQ(wrapper_->GetEncoderInfo().implementation_name, "hw"); + + FakeEncodedImageCallback callback1; + class DummyFecControllerOverride : public FecControllerOverride { + public: + void SetFecAllowed(bool fec_allowed) override {} + }; + DummyFecControllerOverride fec_controller_override1; + VideoEncoder::RateControlParameters rate_params1; + float packet_loss1 = 0.1; + int64_t rtt1 = 1; + VideoEncoder::LossNotification lntf1; + + EXPECT_CALL(*hw_, RegisterEncodeCompleteCallback(&callback1)); + EXPECT_CALL(*sw_, RegisterEncodeCompleteCallback).Times(0); + wrapper_->RegisterEncodeCompleteCallback(&callback1); + + EXPECT_CALL(*hw_, SetFecControllerOverride(&fec_controller_override1)); + EXPECT_CALL(*sw_, SetFecControllerOverride).Times(1); + wrapper_->SetFecControllerOverride(&fec_controller_override1); + + EXPECT_CALL(*hw_, SetRates(rate_params1)); + EXPECT_CALL(*sw_, SetRates).Times(0); + wrapper_->SetRates(rate_params1); + + EXPECT_CALL(*hw_, OnPacketLossRateUpdate(packet_loss1)); + EXPECT_CALL(*sw_, OnPacketLossRateUpdate).Times(0); + wrapper_->OnPacketLossRateUpdate(packet_loss1); + + EXPECT_CALL(*hw_, OnRttUpdate(rtt1)); + EXPECT_CALL(*sw_, OnRttUpdate).Times(0); + wrapper_->OnRttUpdate(rtt1); + + EXPECT_CALL(*hw_, OnLossNotification).Times(1); + EXPECT_CALL(*sw_, OnLossNotification).Times(0); + wrapper_->OnLossNotification(lntf1); + + // Release and re-init, with fallback to software. This should trigger + // the software encoder to be primed with the current state. + wrapper_->Release(); + EXPECT_CALL(*sw_, RegisterEncodeCompleteCallback(&callback1)); + EXPECT_CALL(*hw_, RegisterEncodeCompleteCallback).Times(0); + + EXPECT_CALL(*sw_, SetFecControllerOverride).Times(0); + EXPECT_CALL(*hw_, SetFecControllerOverride).Times(0); + + // Rate control parameters are cleared on InitEncode. + EXPECT_CALL(*sw_, SetRates).Times(0); + EXPECT_CALL(*hw_, SetRates).Times(0); + + EXPECT_CALL(*sw_, OnPacketLossRateUpdate(packet_loss1)); + EXPECT_CALL(*hw_, OnPacketLossRateUpdate).Times(0); + + EXPECT_CALL(*sw_, OnRttUpdate(rtt1)); + EXPECT_CALL(*hw_, OnRttUpdate).Times(0); + + EXPECT_CALL(*sw_, OnLossNotification).Times(1); + EXPECT_CALL(*hw_, OnLossNotification).Times(0); + + SetSupportsLayers(&hw_info_, false); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + wrapper_->InitEncode(&codec_settings, kSettings)); + EXPECT_EQ(wrapper_->GetEncoderInfo().implementation_name, "sw"); + + // Update with all-new params for the software encoder. + FakeEncodedImageCallback callback2; + DummyFecControllerOverride fec_controller_override2; + VideoEncoder::RateControlParameters rate_params2; + float packet_loss2 = 0.2; + int64_t rtt2 = 2; + VideoEncoder::LossNotification lntf2; + + EXPECT_CALL(*sw_, RegisterEncodeCompleteCallback(&callback2)); + EXPECT_CALL(*hw_, RegisterEncodeCompleteCallback).Times(0); + wrapper_->RegisterEncodeCompleteCallback(&callback2); + + EXPECT_CALL(*sw_, SetFecControllerOverride(&fec_controller_override2)); + EXPECT_CALL(*hw_, SetFecControllerOverride).Times(1); + wrapper_->SetFecControllerOverride(&fec_controller_override2); + + EXPECT_CALL(*sw_, SetRates(rate_params2)); + EXPECT_CALL(*hw_, SetRates).Times(0); + wrapper_->SetRates(rate_params2); + + EXPECT_CALL(*sw_, OnPacketLossRateUpdate(packet_loss2)); + EXPECT_CALL(*hw_, OnPacketLossRateUpdate).Times(0); + wrapper_->OnPacketLossRateUpdate(packet_loss2); + + EXPECT_CALL(*sw_, OnRttUpdate(rtt2)); + EXPECT_CALL(*hw_, OnRttUpdate).Times(0); + wrapper_->OnRttUpdate(rtt2); + + EXPECT_CALL(*sw_, OnLossNotification).Times(1); + EXPECT_CALL(*hw_, OnLossNotification).Times(0); + wrapper_->OnLossNotification(lntf2); + + // Release and re-init, back to main encoder. This should trigger + // the main encoder to be primed with the current state. + wrapper_->Release(); + EXPECT_CALL(*hw_, RegisterEncodeCompleteCallback(&callback2)); + EXPECT_CALL(*sw_, RegisterEncodeCompleteCallback).Times(0); + + EXPECT_CALL(*hw_, SetFecControllerOverride).Times(0); + EXPECT_CALL(*sw_, SetFecControllerOverride).Times(0); + + // Rate control parameters are cleared on InitEncode. + EXPECT_CALL(*sw_, SetRates).Times(0); + EXPECT_CALL(*hw_, SetRates).Times(0); + + EXPECT_CALL(*hw_, OnPacketLossRateUpdate(packet_loss2)); + EXPECT_CALL(*sw_, OnPacketLossRateUpdate).Times(0); + + EXPECT_CALL(*hw_, OnRttUpdate(rtt2)); + EXPECT_CALL(*sw_, OnRttUpdate).Times(0); + + EXPECT_CALL(*hw_, OnLossNotification).Times(1); + EXPECT_CALL(*sw_, OnLossNotification).Times(0); + + SetSupportsLayers(&hw_info_, true); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + wrapper_->InitEncode(&codec_settings, kSettings)); + EXPECT_EQ(wrapper_->GetEncoderInfo().implementation_name, "hw"); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/video_codec.cc b/third_party/libwebrtc/api/video_codecs/video_codec.cc new file mode 100644 index 0000000000..c6122d3f6a --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_codec.cc @@ -0,0 +1,155 @@ +/* + * 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 "api/video_codecs/video_codec.h" + +#include <string.h> + +#include <string> + +#include "absl/strings/match.h" +#include "rtc_base/checks.h" + +namespace webrtc { +namespace { +constexpr char kPayloadNameVp8[] = "VP8"; +constexpr char kPayloadNameVp9[] = "VP9"; +constexpr char kPayloadNameAv1[] = "AV1"; +// TODO(bugs.webrtc.org/13166): Remove AV1X when backwards compatibility is not +// needed. +constexpr char kPayloadNameAv1x[] = "AV1X"; +constexpr char kPayloadNameH264[] = "H264"; +constexpr char kPayloadNameGeneric[] = "Generic"; +constexpr char kPayloadNameMultiplex[] = "Multiplex"; +} // namespace + +bool VideoCodecVP8::operator==(const VideoCodecVP8& other) const { + return (numberOfTemporalLayers == other.numberOfTemporalLayers && + denoisingOn == other.denoisingOn && + automaticResizeOn == other.automaticResizeOn && + keyFrameInterval == other.keyFrameInterval); +} + +bool VideoCodecVP9::operator==(const VideoCodecVP9& other) const { + return (numberOfTemporalLayers == other.numberOfTemporalLayers && + denoisingOn == other.denoisingOn && + keyFrameInterval == other.keyFrameInterval && + adaptiveQpMode == other.adaptiveQpMode && + automaticResizeOn == other.automaticResizeOn && + numberOfSpatialLayers == other.numberOfSpatialLayers && + flexibleMode == other.flexibleMode); +} + +bool VideoCodecH264::operator==(const VideoCodecH264& other) const { + return (keyFrameInterval == other.keyFrameInterval && + numberOfTemporalLayers == other.numberOfTemporalLayers); +} + +VideoCodec::VideoCodec() + : codecType(kVideoCodecGeneric), + width(0), + height(0), + startBitrate(0), + maxBitrate(0), + minBitrate(0), + maxFramerate(0), + active(true), + qpMax(0), + numberOfSimulcastStreams(0), + simulcastStream(), + spatialLayers(), + mode(VideoCodecMode::kRealtimeVideo), + expect_encode_from_texture(false), + timing_frame_thresholds({0, 0}), + legacy_conference_mode(false), + codec_specific_(), + complexity_(VideoCodecComplexity::kComplexityNormal) {} + +VideoCodecVP8* VideoCodec::VP8() { + RTC_DCHECK_EQ(codecType, kVideoCodecVP8); + return &codec_specific_.VP8; +} + +const VideoCodecVP8& VideoCodec::VP8() const { + RTC_DCHECK_EQ(codecType, kVideoCodecVP8); + return codec_specific_.VP8; +} + +VideoCodecVP9* VideoCodec::VP9() { + RTC_DCHECK_EQ(codecType, kVideoCodecVP9); + return &codec_specific_.VP9; +} + +const VideoCodecVP9& VideoCodec::VP9() const { + RTC_DCHECK_EQ(codecType, kVideoCodecVP9); + return codec_specific_.VP9; +} + +VideoCodecH264* VideoCodec::H264() { + RTC_DCHECK_EQ(codecType, kVideoCodecH264); + return &codec_specific_.H264; +} + +const VideoCodecH264& VideoCodec::H264() const { + RTC_DCHECK_EQ(codecType, kVideoCodecH264); + return codec_specific_.H264; +} + +const char* CodecTypeToPayloadString(VideoCodecType type) { + switch (type) { + case kVideoCodecVP8: + return kPayloadNameVp8; + case kVideoCodecVP9: + return kPayloadNameVp9; + case kVideoCodecAV1: + return kPayloadNameAv1; + case kVideoCodecH264: + return kPayloadNameH264; + case kVideoCodecMultiplex: + return kPayloadNameMultiplex; + case kVideoCodecGeneric: + return kPayloadNameGeneric; + } + RTC_CHECK_NOTREACHED(); +} + +VideoCodecType PayloadStringToCodecType(const std::string& name) { + if (absl::EqualsIgnoreCase(name, kPayloadNameVp8)) + return kVideoCodecVP8; + if (absl::EqualsIgnoreCase(name, kPayloadNameVp9)) + return kVideoCodecVP9; + if (absl::EqualsIgnoreCase(name, kPayloadNameAv1) || + absl::EqualsIgnoreCase(name, kPayloadNameAv1x)) + return kVideoCodecAV1; + if (absl::EqualsIgnoreCase(name, kPayloadNameH264)) + return kVideoCodecH264; + if (absl::EqualsIgnoreCase(name, kPayloadNameMultiplex)) + return kVideoCodecMultiplex; + return kVideoCodecGeneric; +} + +VideoCodecComplexity VideoCodec::GetVideoEncoderComplexity() const { + return complexity_; +} + +void VideoCodec::SetVideoEncoderComplexity( + VideoCodecComplexity complexity_setting) { + complexity_ = complexity_setting; +} + +bool VideoCodec::GetFrameDropEnabled() const { + return frame_drop_enabled_; +} + +void VideoCodec::SetFrameDropEnabled(bool enabled) { + frame_drop_enabled_ = enabled; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/video_codec.h b/third_party/libwebrtc/api/video_codecs/video_codec.h new file mode 100644 index 0000000000..10bceda0d2 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_codec.h @@ -0,0 +1,200 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_CODECS_VIDEO_CODEC_H_ +#define API_VIDEO_CODECS_VIDEO_CODEC_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <string> + +#include "absl/strings/string_view.h" +#include "api/video/video_bitrate_allocation.h" +#include "api/video/video_codec_type.h" +#include "api/video_codecs/scalability_mode.h" +#include "api/video_codecs/simulcast_stream.h" +#include "api/video_codecs/spatial_layer.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// The VideoCodec class represents an old defacto-apis, which we're migrating +// away from slowly. + +// Video codec +enum class VideoCodecComplexity { + kComplexityLow = -1, + kComplexityNormal = 0, + kComplexityHigh = 1, + kComplexityHigher = 2, + kComplexityMax = 3 +}; + +// VP8 specific +struct VideoCodecVP8 { + bool operator==(const VideoCodecVP8& other) const; + bool operator!=(const VideoCodecVP8& other) const { + return !(*this == other); + } + // Temporary utility method for transition deleting numberOfTemporalLayers + // setting (replaced by ScalabilityMode). + void SetNumberOfTemporalLayers(unsigned char n) { + numberOfTemporalLayers = n; + } + unsigned char numberOfTemporalLayers; + bool denoisingOn; + bool automaticResizeOn; + int keyFrameInterval; +}; + +enum class InterLayerPredMode : int { + kOff = 0, // Inter-layer prediction is disabled. + kOn = 1, // Inter-layer prediction is enabled. + kOnKeyPic = 2 // Inter-layer prediction is enabled but limited to key frames. +}; + +// VP9 specific. +struct VideoCodecVP9 { + bool operator==(const VideoCodecVP9& other) const; + bool operator!=(const VideoCodecVP9& other) const { + return !(*this == other); + } + // Temporary utility method for transition deleting numberOfTemporalLayers + // setting (replaced by ScalabilityMode). + void SetNumberOfTemporalLayers(unsigned char n) { + numberOfTemporalLayers = n; + } + unsigned char numberOfTemporalLayers; + bool denoisingOn; + int keyFrameInterval; + bool adaptiveQpMode; + bool automaticResizeOn; + unsigned char numberOfSpatialLayers; + bool flexibleMode; + InterLayerPredMode interLayerPred; +}; + +// H264 specific. +struct VideoCodecH264 { + bool operator==(const VideoCodecH264& other) const; + bool operator!=(const VideoCodecH264& other) const { + return !(*this == other); + } + // Temporary utility method for transition deleting numberOfTemporalLayers + // setting (replaced by ScalabilityMode). + void SetNumberOfTemporalLayers(unsigned char n) { + numberOfTemporalLayers = n; + } + int keyFrameInterval; + uint8_t numberOfTemporalLayers; +}; + +// Translates from name of codec to codec type and vice versa. +RTC_EXPORT const char* CodecTypeToPayloadString(VideoCodecType type); +RTC_EXPORT VideoCodecType PayloadStringToCodecType(const std::string& name); + +union VideoCodecUnion { + VideoCodecVP8 VP8; + VideoCodecVP9 VP9; + VideoCodecH264 H264; +}; + +enum class VideoCodecMode { kRealtimeVideo, kScreensharing }; + +// Common video codec properties +class RTC_EXPORT VideoCodec { + public: + VideoCodec(); + + // Scalability mode as described in + // https://www.w3.org/TR/webrtc-svc/#scalabilitymodes* + absl::optional<ScalabilityMode> GetScalabilityMode() const { + return scalability_mode_; + } + void SetScalabilityMode(ScalabilityMode scalability_mode) { + scalability_mode_ = scalability_mode; + } + void UnsetScalabilityMode() { scalability_mode_ = absl::nullopt; } + + VideoCodecComplexity GetVideoEncoderComplexity() const; + void SetVideoEncoderComplexity(VideoCodecComplexity complexity_setting); + + bool GetFrameDropEnabled() const; + void SetFrameDropEnabled(bool enabled); + + // Public variables. TODO(hta): Make them private with accessors. + VideoCodecType codecType; + + // TODO(nisse): Change to int, for consistency. + uint16_t width; + uint16_t height; + + unsigned int startBitrate; // kilobits/sec. + unsigned int maxBitrate; // kilobits/sec. + unsigned int minBitrate; // kilobits/sec. + + uint32_t maxFramerate; + + // This enables/disables encoding and sending when there aren't multiple + // simulcast streams,by allocating 0 bitrate if inactive. + bool active; + + unsigned int qpMax; + unsigned char numberOfSimulcastStreams; + SimulcastStream simulcastStream[kMaxSimulcastStreams]; + SpatialLayer spatialLayers[kMaxSpatialLayers]; + + VideoCodecMode mode; + bool expect_encode_from_texture; + + // Timing frames configuration. There is delay of delay_ms between two + // consequent timing frames, excluding outliers. Frame is always made a + // timing frame if it's at least outlier_ratio in percent of "ideal" average + // frame given bitrate and framerate, i.e. if it's bigger than + // |outlier_ratio / 100.0 * bitrate_bps / fps| in bits. This way, timing + // frames will not be sent too often usually. Yet large frames will always + // have timing information for debug purposes because they are more likely to + // cause extra delays. + struct TimingFrameTriggerThresholds { + int64_t delay_ms; + uint16_t outlier_ratio_percent; + } timing_frame_thresholds; + + // Legacy Google conference mode flag for simulcast screenshare + bool legacy_conference_mode; + + bool operator==(const VideoCodec& other) const = delete; + bool operator!=(const VideoCodec& other) const = delete; + + // Accessors for codec specific information. + // There is a const version of each that returns a reference, + // and a non-const version that returns a pointer, in order + // to allow modification of the parameters. + VideoCodecVP8* VP8(); + const VideoCodecVP8& VP8() const; + VideoCodecVP9* VP9(); + const VideoCodecVP9& VP9() const; + VideoCodecH264* H264(); + const VideoCodecH264& H264() const; + + private: + // TODO(hta): Consider replacing the union with a pointer type. + // This will allow removing the VideoCodec* types from this file. + VideoCodecUnion codec_specific_; + absl::optional<ScalabilityMode> scalability_mode_; + // 'complexity_' indicates the CPU capability of the client. It's used to + // determine encoder CPU complexity (e.g., cpu_used for VP8, VP9. and AV1). + VideoCodecComplexity complexity_; + bool frame_drop_enabled_ = false; +}; + +} // namespace webrtc +#endif // API_VIDEO_CODECS_VIDEO_CODEC_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_codecs_api_gn/moz.build b/third_party/libwebrtc/api/video_codecs/video_codecs_api_gn/moz.build new file mode 100644 index 0000000000..eccdc6cfc7 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_codecs_api_gn/moz.build @@ -0,0 +1,235 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video_codecs/av1_profile.cc", + "/third_party/libwebrtc/api/video_codecs/h264_profile_level_id.cc", + "/third_party/libwebrtc/api/video_codecs/sdp_video_format.cc", + "/third_party/libwebrtc/api/video_codecs/simulcast_stream.cc", + "/third_party/libwebrtc/api/video_codecs/spatial_layer.cc", + "/third_party/libwebrtc/api/video_codecs/video_codec.cc", + "/third_party/libwebrtc/api/video_codecs/video_decoder.cc", + "/third_party/libwebrtc/api/video_codecs/video_encoder.cc", + "/third_party/libwebrtc/api/video_codecs/vp8_frame_config.cc", + "/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers.cc", + "/third_party/libwebrtc/api/video_codecs/vp9_profile.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_codecs_api_gn") diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder.cc b/third_party/libwebrtc/api/video_codecs/video_decoder.cc new file mode 100644 index 0000000000..c8f40cee7f --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_decoder.cc @@ -0,0 +1,65 @@ +/* + * 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 "api/video_codecs/video_decoder.h" + +#include "absl/types/optional.h" +#include "api/video/render_resolution.h" +#include "api/video/video_codec_type.h" +#include "rtc_base/checks.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +int32_t DecodedImageCallback::Decoded(VideoFrame& decodedImage, + int64_t decode_time_ms) { + // The default implementation ignores custom decode time value. + return Decoded(decodedImage); +} + +void DecodedImageCallback::Decoded(VideoFrame& decodedImage, + absl::optional<int32_t> decode_time_ms, + absl::optional<uint8_t> qp) { + Decoded(decodedImage, decode_time_ms.value_or(-1)); +} + +VideoDecoder::DecoderInfo VideoDecoder::GetDecoderInfo() const { + DecoderInfo info; + info.implementation_name = ImplementationName(); + return info; +} + +const char* VideoDecoder::ImplementationName() const { + return "unknown"; +} + +std::string VideoDecoder::DecoderInfo::ToString() const { + char string_buf[2048]; + rtc::SimpleStringBuilder oss(string_buf); + + oss << "DecoderInfo { " + << "prefers_late_decoding = " + << "implementation_name = '" << implementation_name << "', " + << "is_hardware_accelerated = " + << (is_hardware_accelerated ? "true" : "false") << " }"; + return oss.str(); +} + +bool VideoDecoder::DecoderInfo::operator==(const DecoderInfo& rhs) const { + return is_hardware_accelerated == rhs.is_hardware_accelerated && + implementation_name == rhs.implementation_name; +} + +void VideoDecoder::Settings::set_number_of_cores(int value) { + RTC_DCHECK_GT(value, 0); + number_of_cores_ = value; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder.h b/third_party/libwebrtc/api/video_codecs/video_decoder.h new file mode 100644 index 0000000000..aa7ee24307 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_decoder.h @@ -0,0 +1,136 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_CODECS_VIDEO_DECODER_H_ +#define API_VIDEO_CODECS_VIDEO_DECODER_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/video/encoded_image.h" +#include "api/video/render_resolution.h" +#include "api/video/video_codec_type.h" +#include "api/video/video_frame.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +class RTC_EXPORT DecodedImageCallback { + public: + virtual ~DecodedImageCallback() {} + + virtual int32_t Decoded(VideoFrame& decodedImage) = 0; + // Provides an alternative interface that allows the decoder to specify the + // decode time excluding waiting time for any previous pending frame to + // return. This is necessary for breaking positive feedback in the delay + // estimation when the decoder has a single output buffer. + virtual int32_t Decoded(VideoFrame& decodedImage, int64_t decode_time_ms); + + // TODO(sakal): Remove other implementations when upstream projects have been + // updated. + virtual void Decoded(VideoFrame& decodedImage, + absl::optional<int32_t> decode_time_ms, + absl::optional<uint8_t> qp); +}; + +class RTC_EXPORT VideoDecoder { + public: + struct DecoderInfo { + // Descriptive name of the decoder implementation. + std::string implementation_name; + + // True if the decoder is backed by hardware acceleration. + bool is_hardware_accelerated = false; + + std::string ToString() const; + bool operator==(const DecoderInfo& rhs) const; + bool operator!=(const DecoderInfo& rhs) const { return !(*this == rhs); } + }; + + class Settings { + public: + Settings() = default; + Settings(const Settings&) = default; + Settings& operator=(const Settings&) = default; + ~Settings() = default; + + // The size of pool which is used to store video frame buffers inside + // decoder. If value isn't present some codec-default value will be used. If + // value is present and decoder doesn't have buffer pool the value will be + // ignored. + absl::optional<int> buffer_pool_size() const; + void set_buffer_pool_size(absl::optional<int> value); + + // When valid, user of the VideoDecoder interface shouldn't `Decode` + // encoded images with render resolution larger than width and height + // specified here. + RenderResolution max_render_resolution() const; + void set_max_render_resolution(RenderResolution value); + + // Maximum number of cpu cores the decoder is allowed to use in parallel. + // Must be positive. + int number_of_cores() const { return number_of_cores_; } + void set_number_of_cores(int value); + + // Codec of encoded images user of the VideoDecoder interface will `Decode`. + VideoCodecType codec_type() const { return codec_type_; } + void set_codec_type(VideoCodecType value) { codec_type_ = value; } + + private: + absl::optional<int> buffer_pool_size_; + RenderResolution max_resolution_; + int number_of_cores_ = 1; + VideoCodecType codec_type_ = kVideoCodecGeneric; + }; + + virtual ~VideoDecoder() = default; + + // Prepares decoder to handle incoming encoded frames. Can be called multiple + // times, in such case only latest `settings` are in effect. + virtual bool Configure(const Settings& settings) = 0; + + virtual int32_t Decode(const EncodedImage& input_image, + bool missing_frames, + int64_t render_time_ms) = 0; + + virtual int32_t RegisterDecodeCompleteCallback( + DecodedImageCallback* callback) = 0; + + virtual int32_t Release() = 0; + + virtual DecoderInfo GetDecoderInfo() const; + + // Deprecated, use GetDecoderInfo().implementation_name instead. + virtual const char* ImplementationName() const; +}; + +inline absl::optional<int> VideoDecoder::Settings::buffer_pool_size() const { + return buffer_pool_size_; +} + +inline void VideoDecoder::Settings::set_buffer_pool_size( + absl::optional<int> value) { + buffer_pool_size_ = value; +} + +inline RenderResolution VideoDecoder::Settings::max_render_resolution() const { + return max_resolution_; +} + +inline void VideoDecoder::Settings::set_max_render_resolution( + RenderResolution value) { + max_resolution_ = value; +} + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_DECODER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_factory.h b/third_party/libwebrtc/api/video_codecs/video_decoder_factory.h new file mode 100644 index 0000000000..7e1d2ee883 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_decoder_factory.h @@ -0,0 +1,69 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_H_ +#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/video_codecs/sdp_video_format.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +class VideoDecoder; + +// A factory that creates VideoDecoders. +// NOTE: This class is still under development and may change without notice. +class RTC_EXPORT VideoDecoderFactory { + public: + struct CodecSupport { + bool is_supported = false; + bool is_power_efficient = false; + }; + + // Returns a list of supported video formats in order of preference, to use + // for signaling etc. + virtual std::vector<SdpVideoFormat> GetSupportedFormats() const = 0; + + // Query whether the specifed format is supported or not and if it will be + // power efficient, which is currently interpreted as if there is support for + // hardware acceleration. + // The parameter `reference_scaling` is used to query support for prediction + // across spatial layers. An example where support for reference scaling is + // needed is if the video stream is produced with a scalability mode that has + // a dependency between the spatial layers. See + // https://w3c.github.io/webrtc-svc/#scalabilitymodes* for a specification of + // different scalabilty modes. NOTE: QueryCodecSupport is currently an + // experimental feature that is subject to change without notice. + virtual CodecSupport QueryCodecSupport(const SdpVideoFormat& format, + bool reference_scaling) const { + // Default implementation, query for supported formats and check if the + // specified format is supported. Returns false if `reference_scaling` is + // true. + CodecSupport codec_support; + codec_support.is_supported = + !reference_scaling && format.IsCodecInList(GetSupportedFormats()); + return codec_support; + } + + // Creates a VideoDecoder for the specified format. + virtual std::unique_ptr<VideoDecoder> CreateVideoDecoder( + const SdpVideoFormat& format) = 0; + + virtual ~VideoDecoderFactory() {} +}; + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template.h b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template.h new file mode 100644 index 0000000000..703ae11664 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_H_ +#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_H_ + +#include <memory> +#include <vector> + +#include "absl/algorithm/container.h" +#include "api/array_view.h" +#include "api/video_codecs/video_decoder.h" +#include "api/video_codecs/video_decoder_factory.h" + +namespace webrtc { +// The VideoDecoderFactoryTemplate supports decoder implementations given as +// template arguments. +// +// To include a decoder in the factory it requires two static members +// functions to be defined: +// +// // Returns the supported SdpVideoFormats this decoder can decode. +// static std::vector<SdpVideoFormat> SupportedFormats(); +// +// // Creates a decoder instance for the given format. +// static std::unique_ptr<VideoDecoder> +// CreateDecoder(const SdpVideoFormat& format); +// +// Note that the order of the template arguments matter as the factory will +// return the first decoder implementation supporting the given SdpVideoFormat. +template <typename... Ts> +class VideoDecoderFactoryTemplate : public VideoDecoderFactory { + public: + std::vector<SdpVideoFormat> GetSupportedFormats() const override { + return GetSupportedFormatsInternal<Ts...>(); + } + + std::unique_ptr<VideoDecoder> CreateVideoDecoder( + const SdpVideoFormat& format) override { + return CreateVideoDecoderInternal<Ts...>(format); + } + + private: + bool IsFormatInList( + const SdpVideoFormat& format, + rtc::ArrayView<const SdpVideoFormat> supported_formats) const { + return absl::c_any_of( + supported_formats, [&](const SdpVideoFormat& supported_format) { + return supported_format.name == format.name && + supported_format.parameters == format.parameters; + }); + } + + template <typename V, typename... Vs> + std::vector<SdpVideoFormat> GetSupportedFormatsInternal() const { + auto supported_formats = V::SupportedFormats(); + + if constexpr (sizeof...(Vs) > 0) { + // Supported formats may overlap between implementations, so duplicates + // should be filtered out. + for (const auto& other_format : GetSupportedFormatsInternal<Vs...>()) { + if (!IsFormatInList(other_format, supported_formats)) { + supported_formats.push_back(other_format); + } + } + } + + return supported_formats; + } + + template <typename V, typename... Vs> + std::unique_ptr<VideoDecoder> CreateVideoDecoderInternal( + const SdpVideoFormat& format) { + if (IsFormatInList(format, V::SupportedFormats())) { + return V::CreateDecoder(format); + } + + if constexpr (sizeof...(Vs) > 0) { + return CreateVideoDecoderInternal<Vs...>(format); + } + + return nullptr; + } +}; + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_dav1d_adapter.h b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_dav1d_adapter.h new file mode 100644 index 0000000000..6d80cadf83 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_dav1d_adapter.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_DAV1D_ADAPTER_H_ +#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_DAV1D_ADAPTER_H_ + +#include <memory> +#include <vector> + +#include "api/video_codecs/sdp_video_format.h" +#include "modules/video_coding/codecs/av1/dav1d_decoder.h" + +namespace webrtc { +struct Dav1dDecoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { + return {SdpVideoFormat("AV1")}; + } + + static std::unique_ptr<VideoDecoder> CreateDecoder( + const SdpVideoFormat& format) { + return CreateDav1dDecoder(); + } +}; + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_DAV1D_ADAPTER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_libvpx_vp8_adapter.h b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_libvpx_vp8_adapter.h new file mode 100644 index 0000000000..0c45a4b622 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_libvpx_vp8_adapter.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP8_ADAPTER_H_ +#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP8_ADAPTER_H_ + +#include <memory> +#include <vector> + +#include "api/video_codecs/sdp_video_format.h" +#include "modules/video_coding/codecs/vp8/include/vp8.h" + +namespace webrtc { +struct LibvpxVp8DecoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { + return {SdpVideoFormat("VP8")}; + } + + static std::unique_ptr<VideoDecoder> CreateDecoder( + const SdpVideoFormat& format) { + return VP8Decoder::Create(); + } +}; +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP8_ADAPTER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_libvpx_vp9_adapter.h b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_libvpx_vp9_adapter.h new file mode 100644 index 0000000000..e0ec0010be --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_libvpx_vp9_adapter.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP9_ADAPTER_H_ +#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP9_ADAPTER_H_ + +#include <memory> +#include <vector> + +#include "modules/video_coding/codecs/vp9/include/vp9.h" + +namespace webrtc { +struct LibvpxVp9DecoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { + return SupportedVP9DecoderCodecs(); + } + + static std::unique_ptr<VideoDecoder> CreateDecoder( + const SdpVideoFormat& format) { + return VP9Decoder::Create(); + } +}; +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP9_ADAPTER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_open_h264_adapter.h b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_open_h264_adapter.h new file mode 100644 index 0000000000..2746bde132 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_decoder_factory_template_open_h264_adapter.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_OPEN_H264_ADAPTER_H_ +#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_OPEN_H264_ADAPTER_H_ + +#include <memory> +#include <vector> + +#include "modules/video_coding/codecs/h264/include/h264.h" + +namespace webrtc { +// TODO(bugs.webrtc.org/13573): When OpenH264 is no longer a conditional build +// target remove #ifdefs. +struct OpenH264DecoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { +#if defined(WEBRTC_USE_H264) + + return SupportedH264DecoderCodecs(); +#else + return {}; +#endif + } + + static std::unique_ptr<VideoDecoder> CreateDecoder( + const SdpVideoFormat& format) { +#if defined(WEBRTC_USE_H264) + + return H264Decoder::Create(); +#else + return nullptr; +#endif + } +}; +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_OPEN_H264_ADAPTER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc b/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc new file mode 100644 index 0000000000..cf6f823b92 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.cc @@ -0,0 +1,284 @@ +/* + * 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. + */ + +#include "api/video_codecs/video_decoder_software_fallback_wrapper.h" + +#include <stdint.h> + +#include <memory> +#include <string> +#include <utility> + +#include "api/video/encoded_image.h" +#include "api/video_codecs/video_decoder.h" +#include "modules/video_coding/include/video_error_codes.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" +#include "rtc_base/trace_event.h" +#include "system_wrappers/include/field_trial.h" +#include "system_wrappers/include/metrics.h" + +namespace webrtc { + +namespace { + +constexpr size_t kMaxConsequtiveHwErrors = 4; + +class VideoDecoderSoftwareFallbackWrapper final : public VideoDecoder { + public: + VideoDecoderSoftwareFallbackWrapper( + std::unique_ptr<VideoDecoder> sw_fallback_decoder, + std::unique_ptr<VideoDecoder> hw_decoder); + ~VideoDecoderSoftwareFallbackWrapper() override; + + bool Configure(const Settings& settings) override; + + int32_t Decode(const EncodedImage& input_image, + bool missing_frames, + int64_t render_time_ms) override; + + int32_t RegisterDecodeCompleteCallback( + DecodedImageCallback* callback) override; + + int32_t Release() override; + + DecoderInfo GetDecoderInfo() const override; + const char* ImplementationName() const override; + + private: + bool InitFallbackDecoder(); + void UpdateFallbackDecoderHistograms(); + + bool InitHwDecoder(); + + VideoDecoder& active_decoder() const; + + // Determines if we are trying to use the HW or SW decoder. + enum class DecoderType { + kNone, + kHardware, + kFallback, + } decoder_type_; + std::unique_ptr<VideoDecoder> hw_decoder_; + + Settings decoder_settings_; + const std::unique_ptr<VideoDecoder> fallback_decoder_; + const std::string fallback_implementation_name_; + DecodedImageCallback* callback_; + int32_t hw_decoded_frames_since_last_fallback_; + size_t hw_consequtive_generic_errors_; +}; + +VideoDecoderSoftwareFallbackWrapper::VideoDecoderSoftwareFallbackWrapper( + std::unique_ptr<VideoDecoder> sw_fallback_decoder, + std::unique_ptr<VideoDecoder> hw_decoder) + : decoder_type_(DecoderType::kNone), + hw_decoder_(std::move(hw_decoder)), + fallback_decoder_(std::move(sw_fallback_decoder)), + fallback_implementation_name_( + fallback_decoder_->GetDecoderInfo().implementation_name + + " (fallback from: " + + hw_decoder_->GetDecoderInfo().implementation_name + ")"), + callback_(nullptr), + hw_decoded_frames_since_last_fallback_(0), + hw_consequtive_generic_errors_(0) {} +VideoDecoderSoftwareFallbackWrapper::~VideoDecoderSoftwareFallbackWrapper() = + default; + +bool VideoDecoderSoftwareFallbackWrapper::Configure(const Settings& settings) { + decoder_settings_ = settings; + + if (webrtc::field_trial::IsEnabled("WebRTC-Video-ForcedSwDecoderFallback")) { + RTC_LOG(LS_INFO) << "Forced software decoder fallback enabled."; + RTC_DCHECK(decoder_type_ == DecoderType::kNone); + return InitFallbackDecoder(); + } + if (InitHwDecoder()) { + return true; + } + + RTC_DCHECK(decoder_type_ == DecoderType::kNone); + return InitFallbackDecoder(); +} + +bool VideoDecoderSoftwareFallbackWrapper::InitHwDecoder() { + RTC_DCHECK(decoder_type_ == DecoderType::kNone); + if (!hw_decoder_->Configure(decoder_settings_)) { + return false; + } + + decoder_type_ = DecoderType::kHardware; + if (callback_) + hw_decoder_->RegisterDecodeCompleteCallback(callback_); + return true; +} + +bool VideoDecoderSoftwareFallbackWrapper::InitFallbackDecoder() { + RTC_DCHECK(decoder_type_ == DecoderType::kNone || + decoder_type_ == DecoderType::kHardware); + RTC_LOG(LS_WARNING) << "Decoder falling back to software decoding."; + if (!fallback_decoder_->Configure(decoder_settings_)) { + RTC_LOG(LS_ERROR) << "Failed to initialize software-decoder fallback."; + return false; + } + + UpdateFallbackDecoderHistograms(); + + if (decoder_type_ == DecoderType::kHardware) { + hw_decoder_->Release(); + } + decoder_type_ = DecoderType::kFallback; + + if (callback_) + fallback_decoder_->RegisterDecodeCompleteCallback(callback_); + return true; +} + +void VideoDecoderSoftwareFallbackWrapper::UpdateFallbackDecoderHistograms() { + const std::string kFallbackHistogramsUmaPrefix = + "WebRTC.Video.HardwareDecodedFramesBetweenSoftwareFallbacks."; + // Each histogram needs its own code path for this to work otherwise the + // histogram names will be mixed up by the optimization that takes place. + switch (decoder_settings_.codec_type()) { + case kVideoCodecGeneric: + RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Generic", + hw_decoded_frames_since_last_fallback_); + break; + case kVideoCodecVP8: + RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Vp8", + hw_decoded_frames_since_last_fallback_); + break; + case kVideoCodecVP9: + RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Vp9", + hw_decoded_frames_since_last_fallback_); + break; + case kVideoCodecAV1: + RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Av1", + hw_decoded_frames_since_last_fallback_); + break; + case kVideoCodecH264: + RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "H264", + hw_decoded_frames_since_last_fallback_); + break; + case kVideoCodecMultiplex: + RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Multiplex", + hw_decoded_frames_since_last_fallback_); + break; + } +} + +int32_t VideoDecoderSoftwareFallbackWrapper::Decode( + const EncodedImage& input_image, + bool missing_frames, + int64_t render_time_ms) { + TRACE_EVENT0("webrtc", "VideoDecoderSoftwareFallbackWrapper::Decode"); + switch (decoder_type_) { + case DecoderType::kNone: + return WEBRTC_VIDEO_CODEC_UNINITIALIZED; + case DecoderType::kHardware: { + int32_t ret = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; + ret = hw_decoder_->Decode(input_image, missing_frames, render_time_ms); + if (ret != WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE) { + if (ret != WEBRTC_VIDEO_CODEC_ERROR) { + ++hw_decoded_frames_since_last_fallback_; + hw_consequtive_generic_errors_ = 0; + return ret; + } + if (input_image._frameType == VideoFrameType::kVideoFrameKey) { + // Only count errors on key-frames, since generic errors can happen + // with hw decoder due to many arbitrary reasons. + // However, requesting a key-frame is supposed to fix the issue. + ++hw_consequtive_generic_errors_; + } + if (hw_consequtive_generic_errors_ < kMaxConsequtiveHwErrors) { + return ret; + } + } + + // HW decoder returned WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE or + // too many generic errors on key-frames encountered. + if (!InitFallbackDecoder()) { + return ret; + } + + // Fallback decoder initialized, fall-through. + [[fallthrough]]; + } + case DecoderType::kFallback: + return fallback_decoder_->Decode(input_image, missing_frames, + render_time_ms); + default: + RTC_DCHECK_NOTREACHED(); + return WEBRTC_VIDEO_CODEC_ERROR; + } +} + +int32_t VideoDecoderSoftwareFallbackWrapper::RegisterDecodeCompleteCallback( + DecodedImageCallback* callback) { + callback_ = callback; + return active_decoder().RegisterDecodeCompleteCallback(callback); +} + +int32_t VideoDecoderSoftwareFallbackWrapper::Release() { + int32_t status; + switch (decoder_type_) { + case DecoderType::kHardware: + status = hw_decoder_->Release(); + break; + case DecoderType::kFallback: + RTC_LOG(LS_INFO) << "Releasing software fallback decoder."; + status = fallback_decoder_->Release(); + break; + case DecoderType::kNone: + status = WEBRTC_VIDEO_CODEC_OK; + break; + default: + RTC_DCHECK_NOTREACHED(); + status = WEBRTC_VIDEO_CODEC_ERROR; + } + + decoder_type_ = DecoderType::kNone; + return status; +} + +VideoDecoder::DecoderInfo VideoDecoderSoftwareFallbackWrapper::GetDecoderInfo() + const { + DecoderInfo info = active_decoder().GetDecoderInfo(); + if (decoder_type_ == DecoderType::kFallback) { + // Cached "A (fallback from B)" string. + info.implementation_name = fallback_implementation_name_; + } + return info; +} + +const char* VideoDecoderSoftwareFallbackWrapper::ImplementationName() const { + if (decoder_type_ == DecoderType::kFallback) { + // Cached "A (fallback from B)" string. + return fallback_implementation_name_.c_str(); + } else { + return hw_decoder_->ImplementationName(); + } +} + +VideoDecoder& VideoDecoderSoftwareFallbackWrapper::active_decoder() const { + return decoder_type_ == DecoderType::kFallback ? *fallback_decoder_ + : *hw_decoder_; +} + +} // namespace + +std::unique_ptr<VideoDecoder> CreateVideoDecoderSoftwareFallbackWrapper( + std::unique_ptr<VideoDecoder> sw_fallback_decoder, + std::unique_ptr<VideoDecoder> hw_decoder) { + return std::make_unique<VideoDecoderSoftwareFallbackWrapper>( + std::move(sw_fallback_decoder), std::move(hw_decoder)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h b/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h new file mode 100644 index 0000000000..3f44e02b26 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_CODECS_VIDEO_DECODER_SOFTWARE_FALLBACK_WRAPPER_H_ +#define API_VIDEO_CODECS_VIDEO_DECODER_SOFTWARE_FALLBACK_WRAPPER_H_ + +#include <memory> + +#include "api/video_codecs/video_decoder.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Used to wrap external VideoDecoders to provide a fallback option on +// software decoding when a hardware decoder fails to decode a stream due to +// hardware restrictions, such as max resolution. +RTC_EXPORT std::unique_ptr<VideoDecoder> +CreateVideoDecoderSoftwareFallbackWrapper( + std::unique_ptr<VideoDecoder> sw_fallback_decoder, + std::unique_ptr<VideoDecoder> hw_decoder); + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_DECODER_SOFTWARE_FALLBACK_WRAPPER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder.cc b/third_party/libwebrtc/api/video_codecs/video_encoder.cc new file mode 100644 index 0000000000..deb4fdc637 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_encoder.cc @@ -0,0 +1,345 @@ +/* + * 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. + */ + +#include "api/video_codecs/video_encoder.h" + +#include <string.h> +#include <algorithm> + +#include "rtc_base/checks.h" +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +// TODO(mflodman): Add default complexity for VP9 and VP9. +VideoCodecVP8 VideoEncoder::GetDefaultVp8Settings() { + VideoCodecVP8 vp8_settings; + memset(&vp8_settings, 0, sizeof(vp8_settings)); + + vp8_settings.numberOfTemporalLayers = 1; + vp8_settings.denoisingOn = true; + vp8_settings.automaticResizeOn = false; + vp8_settings.keyFrameInterval = 3000; + + return vp8_settings; +} + +VideoCodecVP9 VideoEncoder::GetDefaultVp9Settings() { + VideoCodecVP9 vp9_settings; + memset(&vp9_settings, 0, sizeof(vp9_settings)); + + vp9_settings.numberOfTemporalLayers = 1; + vp9_settings.denoisingOn = true; + vp9_settings.keyFrameInterval = 3000; + vp9_settings.adaptiveQpMode = true; + vp9_settings.automaticResizeOn = true; + vp9_settings.numberOfSpatialLayers = 1; + vp9_settings.flexibleMode = false; + vp9_settings.interLayerPred = InterLayerPredMode::kOn; + + return vp9_settings; +} + +VideoCodecH264 VideoEncoder::GetDefaultH264Settings() { + VideoCodecH264 h264_settings; + memset(&h264_settings, 0, sizeof(h264_settings)); + + h264_settings.keyFrameInterval = 3000; + h264_settings.numberOfTemporalLayers = 1; + + return h264_settings; +} + +VideoEncoder::ScalingSettings::ScalingSettings() = default; + +VideoEncoder::ScalingSettings::ScalingSettings(KOff) : ScalingSettings() {} + +VideoEncoder::ScalingSettings::ScalingSettings(int low, int high) + : thresholds(QpThresholds(low, high)) {} + +VideoEncoder::ScalingSettings::ScalingSettings(int low, + int high, + int min_pixels) + : thresholds(QpThresholds(low, high)), min_pixels_per_frame(min_pixels) {} + +VideoEncoder::ScalingSettings::ScalingSettings(const ScalingSettings&) = + default; + +VideoEncoder::ScalingSettings::~ScalingSettings() {} + +// static +constexpr VideoEncoder::ScalingSettings::KOff + VideoEncoder::ScalingSettings::kOff; +// static +constexpr uint8_t VideoEncoder::EncoderInfo::kMaxFramerateFraction; + +bool VideoEncoder::ResolutionBitrateLimits::operator==( + const ResolutionBitrateLimits& rhs) const { + return frame_size_pixels == rhs.frame_size_pixels && + min_start_bitrate_bps == rhs.min_start_bitrate_bps && + min_bitrate_bps == rhs.min_bitrate_bps && + max_bitrate_bps == rhs.max_bitrate_bps; +} + +VideoEncoder::EncoderInfo::EncoderInfo() + : scaling_settings(VideoEncoder::ScalingSettings::kOff), + requested_resolution_alignment(1), + apply_alignment_to_all_simulcast_layers(false), + supports_native_handle(false), + implementation_name("unknown"), + has_trusted_rate_controller(false), + is_hardware_accelerated(true), + fps_allocation{absl::InlinedVector<uint8_t, kMaxTemporalStreams>( + 1, + kMaxFramerateFraction)}, + supports_simulcast(false), + preferred_pixel_formats{VideoFrameBuffer::Type::kI420} {} + +VideoEncoder::EncoderInfo::EncoderInfo(const EncoderInfo&) = default; + +VideoEncoder::EncoderInfo::~EncoderInfo() = default; + +std::string VideoEncoder::EncoderInfo::ToString() const { + char string_buf[2048]; + rtc::SimpleStringBuilder oss(string_buf); + + oss << "EncoderInfo { " + "ScalingSettings { "; + if (scaling_settings.thresholds) { + oss << "Thresholds { " + "low = " + << scaling_settings.thresholds->low + << ", high = " << scaling_settings.thresholds->high << "}, "; + } + oss << "min_pixels_per_frame = " << scaling_settings.min_pixels_per_frame + << " }"; + oss << ", requested_resolution_alignment = " << requested_resolution_alignment + << ", apply_alignment_to_all_simulcast_layers = " + << apply_alignment_to_all_simulcast_layers + << ", supports_native_handle = " << supports_native_handle + << ", implementation_name = '" << implementation_name + << "'" + ", has_trusted_rate_controller = " + << has_trusted_rate_controller + << ", is_hardware_accelerated = " << is_hardware_accelerated + << ", fps_allocation = ["; + size_t num_spatial_layer_with_fps_allocation = 0; + for (size_t i = 0; i < kMaxSpatialLayers; ++i) { + if (!fps_allocation[i].empty()) { + num_spatial_layer_with_fps_allocation = i + 1; + } + } + bool first = true; + for (size_t i = 0; i < num_spatial_layer_with_fps_allocation; ++i) { + if (fps_allocation[i].empty()) { + break; + } + if (!first) { + oss << ", "; + } + const absl::InlinedVector<uint8_t, kMaxTemporalStreams>& fractions = + fps_allocation[i]; + if (!fractions.empty()) { + first = false; + oss << "[ "; + for (size_t i = 0; i < fractions.size(); ++i) { + if (i > 0) { + oss << ", "; + } + oss << (static_cast<double>(fractions[i]) / kMaxFramerateFraction); + } + oss << "] "; + } + } + oss << "]"; + oss << ", resolution_bitrate_limits = ["; + for (size_t i = 0; i < resolution_bitrate_limits.size(); ++i) { + if (i > 0) { + oss << ", "; + } + ResolutionBitrateLimits l = resolution_bitrate_limits[i]; + oss << "Limits { " + "frame_size_pixels = " + << l.frame_size_pixels + << ", min_start_bitrate_bps = " << l.min_start_bitrate_bps + << ", min_bitrate_bps = " << l.min_bitrate_bps + << ", max_bitrate_bps = " << l.max_bitrate_bps << "} "; + } + oss << "] " + ", supports_simulcast = " + << supports_simulcast; + oss << ", preferred_pixel_formats = ["; + for (size_t i = 0; i < preferred_pixel_formats.size(); ++i) { + if (i > 0) + oss << ", "; +#if defined(WEBRTC_MOZILLA_BUILD) + // This could assert, as opposed to throw using the form in the + // else, but since we're in a for loop that uses .size() we can + // be fairly sure that this is safe without doing a further + // check to make sure 'i' is in-range. + oss << VideoFrameBufferTypeToString(preferred_pixel_formats[i]); +#else + oss << VideoFrameBufferTypeToString(preferred_pixel_formats.at(i)); +#endif + } + oss << "]"; + if (is_qp_trusted.has_value()) { + oss << ", is_qp_trusted = " << is_qp_trusted.value(); + } + oss << "}"; + return oss.str(); +} + +bool VideoEncoder::EncoderInfo::operator==(const EncoderInfo& rhs) const { + if (scaling_settings.thresholds.has_value() != + rhs.scaling_settings.thresholds.has_value()) { + return false; + } + if (scaling_settings.thresholds.has_value()) { + QpThresholds l = *scaling_settings.thresholds; + QpThresholds r = *rhs.scaling_settings.thresholds; + if (l.low != r.low || l.high != r.high) { + return false; + } + } + if (scaling_settings.min_pixels_per_frame != + rhs.scaling_settings.min_pixels_per_frame) { + return false; + } + + if (supports_native_handle != rhs.supports_native_handle || + implementation_name != rhs.implementation_name || + has_trusted_rate_controller != rhs.has_trusted_rate_controller || + is_hardware_accelerated != rhs.is_hardware_accelerated) { + return false; + } + + for (size_t i = 0; i < kMaxSpatialLayers; ++i) { + if (fps_allocation[i] != rhs.fps_allocation[i]) { + return false; + } + } + + if (resolution_bitrate_limits != rhs.resolution_bitrate_limits || + supports_simulcast != rhs.supports_simulcast) { + return false; + } + + return true; +} + +absl::optional<VideoEncoder::ResolutionBitrateLimits> +VideoEncoder::EncoderInfo::GetEncoderBitrateLimitsForResolution( + int frame_size_pixels) const { + std::vector<ResolutionBitrateLimits> bitrate_limits = + resolution_bitrate_limits; + + // Sort the list of bitrate limits by resolution. + sort(bitrate_limits.begin(), bitrate_limits.end(), + [](const ResolutionBitrateLimits& lhs, + const ResolutionBitrateLimits& rhs) { + return lhs.frame_size_pixels < rhs.frame_size_pixels; + }); + + for (size_t i = 0; i < bitrate_limits.size(); ++i) { + RTC_DCHECK_GE(bitrate_limits[i].min_bitrate_bps, 0); + RTC_DCHECK_GE(bitrate_limits[i].min_start_bitrate_bps, 0); + RTC_DCHECK_GE(bitrate_limits[i].max_bitrate_bps, + bitrate_limits[i].min_bitrate_bps); + if (i > 0) { + // The bitrate limits aren't expected to decrease with resolution. + RTC_DCHECK_GE(bitrate_limits[i].min_bitrate_bps, + bitrate_limits[i - 1].min_bitrate_bps); + RTC_DCHECK_GE(bitrate_limits[i].min_start_bitrate_bps, + bitrate_limits[i - 1].min_start_bitrate_bps); + RTC_DCHECK_GE(bitrate_limits[i].max_bitrate_bps, + bitrate_limits[i - 1].max_bitrate_bps); + } + + if (bitrate_limits[i].frame_size_pixels >= frame_size_pixels) { + return absl::optional<ResolutionBitrateLimits>(bitrate_limits[i]); + } + } + + return absl::nullopt; +} + +VideoEncoder::RateControlParameters::RateControlParameters() + : bitrate(VideoBitrateAllocation()), + framerate_fps(0.0), + bandwidth_allocation(DataRate::Zero()) {} + +VideoEncoder::RateControlParameters::RateControlParameters( + const VideoBitrateAllocation& bitrate, + double framerate_fps) + : bitrate(bitrate), + framerate_fps(framerate_fps), + bandwidth_allocation(DataRate::BitsPerSec(bitrate.get_sum_bps())) {} + +VideoEncoder::RateControlParameters::RateControlParameters( + const VideoBitrateAllocation& bitrate, + double framerate_fps, + DataRate bandwidth_allocation) + : bitrate(bitrate), + framerate_fps(framerate_fps), + bandwidth_allocation(bandwidth_allocation) {} + +bool VideoEncoder::RateControlParameters::operator==( + const VideoEncoder::RateControlParameters& rhs) const { + return std::tie(bitrate, framerate_fps, bandwidth_allocation) == + std::tie(rhs.bitrate, rhs.framerate_fps, rhs.bandwidth_allocation); +} + +bool VideoEncoder::RateControlParameters::operator!=( + const VideoEncoder::RateControlParameters& rhs) const { + return !(rhs == *this); +} + +VideoEncoder::RateControlParameters::~RateControlParameters() = default; + +void VideoEncoder::SetFecControllerOverride( + FecControllerOverride* fec_controller_override) {} + +int32_t VideoEncoder::InitEncode(const VideoCodec* codec_settings, + int32_t number_of_cores, + size_t max_payload_size) { + const VideoEncoder::Capabilities capabilities(/* loss_notification= */ false); + const VideoEncoder::Settings settings(capabilities, number_of_cores, + max_payload_size); + // In theory, this and the other version of InitEncode() could end up calling + // each other in a loop until we get a stack overflow. + // In practice, any subclass of VideoEncoder would overload at least one + // of these, and we have a TODO in the header file to make this pure virtual. + return InitEncode(codec_settings, settings); +} + +int VideoEncoder::InitEncode(const VideoCodec* codec_settings, + const VideoEncoder::Settings& settings) { + // In theory, this and the other version of InitEncode() could end up calling + // each other in a loop until we get a stack overflow. + // In practice, any subclass of VideoEncoder would overload at least one + // of these, and we have a TODO in the header file to make this pure virtual. + return InitEncode(codec_settings, settings.number_of_cores, + settings.max_payload_size); +} + +void VideoEncoder::OnPacketLossRateUpdate(float packet_loss_rate) {} + +void VideoEncoder::OnRttUpdate(int64_t rtt_ms) {} + +void VideoEncoder::OnLossNotification( + const LossNotification& loss_notification) {} + +// TODO(webrtc:9722): Remove and make pure virtual. +VideoEncoder::EncoderInfo VideoEncoder::GetEncoderInfo() const { + return EncoderInfo(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder.h b/third_party/libwebrtc/api/video_codecs/video_encoder.h new file mode 100644 index 0000000000..395a87e089 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_encoder.h @@ -0,0 +1,426 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_CODECS_VIDEO_ENCODER_H_ +#define API_VIDEO_CODECS_VIDEO_ENCODER_H_ + +#include <limits> +#include <memory> +#include <string> +#include <vector> + +#include "absl/container/inlined_vector.h" +#include "absl/types/optional.h" +#include "api/fec_controller_override.h" +#include "api/units/data_rate.h" +#include "api/video/encoded_image.h" +#include "api/video/video_bitrate_allocation.h" +#include "api/video/video_codec_constants.h" +#include "api/video/video_frame.h" +#include "api/video_codecs/video_codec.h" +#include "rtc_base/checks.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// TODO(pbos): Expose these through a public (root) header or change these APIs. +struct CodecSpecificInfo; + +constexpr int kDefaultMinPixelsPerFrame = 320 * 180; + +class RTC_EXPORT EncodedImageCallback { + public: + virtual ~EncodedImageCallback() {} + + struct Result { + enum Error { + OK, + + // Failed to send the packet. + ERROR_SEND_FAILED, + }; + + explicit Result(Error error) : error(error) {} + Result(Error error, uint32_t frame_id) : error(error), frame_id(frame_id) {} + + Error error; + + // Frame ID assigned to the frame. The frame ID should be the same as the ID + // seen by the receiver for this frame. RTP timestamp of the frame is used + // as frame ID when RTP is used to send video. Must be used only when + // error=OK. + uint32_t frame_id = 0; + + // Tells the encoder that the next frame is should be dropped. + bool drop_next_frame = false; + }; + + // Used to signal the encoder about reason a frame is dropped. + // kDroppedByMediaOptimizations - dropped by MediaOptimizations (for rate + // limiting purposes). + // kDroppedByEncoder - dropped by encoder's internal rate limiter. + // TODO(bugs.webrtc.org/10164): Delete this enum? It duplicates the more + // general VideoStreamEncoderObserver::DropReason. Also, + // kDroppedByMediaOptimizations is not produced by any encoder, but by + // VideoStreamEncoder. + enum class DropReason : uint8_t { + kDroppedByMediaOptimizations, + kDroppedByEncoder + }; + + // Callback function which is called when an image has been encoded. + virtual Result OnEncodedImage( + const EncodedImage& encoded_image, + const CodecSpecificInfo* codec_specific_info) = 0; + + virtual void OnDroppedFrame(DropReason reason) {} +}; + +class RTC_EXPORT VideoEncoder { + public: + struct QpThresholds { + QpThresholds(int l, int h) : low(l), high(h) {} + QpThresholds() : low(-1), high(-1) {} + int low; + int high; + }; + + // Quality scaling is enabled if thresholds are provided. + struct RTC_EXPORT ScalingSettings { + private: + // Private magic type for kOff, implicitly convertible to + // ScalingSettings. + struct KOff {}; + + public: + // TODO(bugs.webrtc.org/9078): Since absl::optional should be trivially copy + // constructible, this magic value can likely be replaced by a constexpr + // ScalingSettings value. + static constexpr KOff kOff = {}; + + ScalingSettings(int low, int high); + ScalingSettings(int low, int high, int min_pixels); + ScalingSettings(const ScalingSettings&); + ScalingSettings(KOff); // NOLINT(runtime/explicit) + ~ScalingSettings(); + + absl::optional<QpThresholds> thresholds; + + // We will never ask for a resolution lower than this. + // TODO(kthelgason): Lower this limit when better testing + // on MediaCodec and fallback implementations are in place. + // See https://bugs.chromium.org/p/webrtc/issues/detail?id=7206 + int min_pixels_per_frame = kDefaultMinPixelsPerFrame; + + private: + // Private constructor; to get an object without thresholds, use + // the magic constant ScalingSettings::kOff. + ScalingSettings(); + }; + + // Bitrate limits for resolution. + struct ResolutionBitrateLimits { + ResolutionBitrateLimits(int frame_size_pixels, + int min_start_bitrate_bps, + int min_bitrate_bps, + int max_bitrate_bps) + : frame_size_pixels(frame_size_pixels), + min_start_bitrate_bps(min_start_bitrate_bps), + min_bitrate_bps(min_bitrate_bps), + max_bitrate_bps(max_bitrate_bps) {} + // Size of video frame, in pixels, the bitrate thresholds are intended for. + int frame_size_pixels = 0; + // Recommended minimum bitrate to start encoding. + int min_start_bitrate_bps = 0; + // Recommended minimum bitrate. + int min_bitrate_bps = 0; + // Recommended maximum bitrate. + int max_bitrate_bps = 0; + + bool operator==(const ResolutionBitrateLimits& rhs) const; + bool operator!=(const ResolutionBitrateLimits& rhs) const { + return !(*this == rhs); + } + }; + + // Struct containing metadata about the encoder implementing this interface. + struct RTC_EXPORT EncoderInfo { + static constexpr uint8_t kMaxFramerateFraction = + std::numeric_limits<uint8_t>::max(); + + EncoderInfo(); + EncoderInfo(const EncoderInfo&); + + ~EncoderInfo(); + + std::string ToString() const; + bool operator==(const EncoderInfo& rhs) const; + bool operator!=(const EncoderInfo& rhs) const { return !(*this == rhs); } + + // Any encoder implementation wishing to use the WebRTC provided + // quality scaler must populate this field. + ScalingSettings scaling_settings; + + // The width and height of the incoming video frames should be divisible + // by `requested_resolution_alignment`. If they are not, the encoder may + // drop the incoming frame. + // For example: With I420, this value would be a multiple of 2. + // Note that this field is unrelated to any horizontal or vertical stride + // requirements the encoder has on the incoming video frame buffers. + uint32_t requested_resolution_alignment; + + // Same as above but if true, each simulcast layer should also be divisible + // by `requested_resolution_alignment`. + // Note that scale factors `scale_resolution_down_by` may be adjusted so a + // common multiple is not too large to avoid largely cropped frames and + // possibly with an aspect ratio far from the original. + // Warning: large values of scale_resolution_down_by could be changed + // considerably, especially if `requested_resolution_alignment` is large. + bool apply_alignment_to_all_simulcast_layers; + + // If true, encoder supports working with a native handle (e.g. texture + // handle for hw codecs) rather than requiring a raw I420 buffer. + bool supports_native_handle; + + // The name of this particular encoder implementation, e.g. "libvpx". + std::string implementation_name; + + // If this field is true, the encoder rate controller must perform + // well even in difficult situations, and produce close to the specified + // target bitrate seen over a reasonable time window, drop frames if + // necessary in order to keep the rate correct, and react quickly to + // changing bitrate targets. If this method returns true, we disable the + // frame dropper in the media optimization module and rely entirely on the + // encoder to produce media at a bitrate that closely matches the target. + // Any overshooting may result in delay buildup. If this method returns + // false (default behavior), the media opt frame dropper will drop input + // frames if it suspect encoder misbehavior. Misbehavior is common, + // especially in hardware codecs. Disable media opt at your own risk. + bool has_trusted_rate_controller; + + // If this field is true, the encoder uses hardware support and different + // thresholds will be used in CPU adaptation. + bool is_hardware_accelerated; + + // For each spatial layer (simulcast stream or SVC layer), represented as an + // element in `fps_allocation` a vector indicates how many temporal layers + // the encoder is using for that spatial layer. + // For each spatial/temporal layer pair, the frame rate fraction is given as + // an 8bit unsigned integer where 0 = 0% and 255 = 100%. + // + // If the vector is empty for a given spatial layer, it indicates that frame + // rates are not defined and we can't count on any specific frame rate to be + // generated. Likely this indicates Vp8TemporalLayersType::kBitrateDynamic. + // + // The encoder may update this on a per-frame basis in response to both + // internal and external signals. + // + // Spatial layers are treated independently, but temporal layers are + // cumulative. For instance, if: + // fps_allocation[0][0] = kFullFramerate / 2; + // fps_allocation[0][1] = kFullFramerate; + // Then half of the frames are in the base layer and half is in TL1, but + // since TL1 is assumed to depend on the base layer, the frame rate is + // indicated as the full 100% for the top layer. + // + // Defaults to a single spatial layer containing a single temporal layer + // with a 100% frame rate fraction. + absl::InlinedVector<uint8_t, kMaxTemporalStreams> + fps_allocation[kMaxSpatialLayers]; + + // Recommended bitrate limits for different resolutions. + std::vector<ResolutionBitrateLimits> resolution_bitrate_limits; + + // Obtains the limits from `resolution_bitrate_limits` that best matches the + // `frame_size_pixels`. + absl::optional<ResolutionBitrateLimits> + GetEncoderBitrateLimitsForResolution(int frame_size_pixels) const; + + // If true, this encoder has internal support for generating simulcast + // streams. Otherwise, an adapter class will be needed. + // Even if true, the config provided to InitEncode() might not be supported, + // in such case the encoder should return + // WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED. + bool supports_simulcast; + + // The list of pixel formats preferred by the encoder. It is assumed that if + // the list is empty and supports_native_handle is false, then {I420} is the + // preferred pixel format. The order of the formats does not matter. + absl::InlinedVector<VideoFrameBuffer::Type, kMaxPreferredPixelFormats> + preferred_pixel_formats; + + // Indicates whether or not QP value encoder writes into frame/slice/tile + // header can be interpreted as average frame/slice/tile QP. + absl::optional<bool> is_qp_trusted; + }; + + struct RTC_EXPORT RateControlParameters { + RateControlParameters(); + RateControlParameters(const VideoBitrateAllocation& bitrate, + double framerate_fps); + RateControlParameters(const VideoBitrateAllocation& bitrate, + double framerate_fps, + DataRate bandwidth_allocation); + virtual ~RateControlParameters(); + + // Target bitrate, per spatial/temporal layer. + // A target bitrate of 0bps indicates a layer should not be encoded at all. + VideoBitrateAllocation target_bitrate; + // Adjusted target bitrate, per spatial/temporal layer. May be lower or + // higher than the target depending on encoder behaviour. + VideoBitrateAllocation bitrate; + // Target framerate, in fps. A value <= 0.0 is invalid and should be + // interpreted as framerate target not available. In this case the encoder + // should fall back to the max framerate specified in `codec_settings` of + // the last InitEncode() call. + double framerate_fps; + // The network bandwidth available for video. This is at least + // `bitrate.get_sum_bps()`, but may be higher if the application is not + // network constrained. + DataRate bandwidth_allocation; + + bool operator==(const RateControlParameters& rhs) const; + bool operator!=(const RateControlParameters& rhs) const; + }; + + struct LossNotification { + // The timestamp of the last decodable frame *prior* to the last received. + // (The last received - described below - might itself be decodable or not.) + uint32_t timestamp_of_last_decodable; + // The timestamp of the last received frame. + uint32_t timestamp_of_last_received; + // Describes whether the dependencies of the last received frame were + // all decodable. + // `false` if some dependencies were undecodable, `true` if all dependencies + // were decodable, and `nullopt` if the dependencies are unknown. + absl::optional<bool> dependencies_of_last_received_decodable; + // Describes whether the received frame was decodable. + // `false` if some dependency was undecodable or if some packet belonging + // to the last received frame was missed. + // `true` if all dependencies were decodable and all packets belonging + // to the last received frame were received. + // `nullopt` if no packet belonging to the last frame was missed, but the + // last packet in the frame was not yet received. + absl::optional<bool> last_received_decodable; + }; + + // Negotiated capabilities which the VideoEncoder may expect the other + // side to use. + struct Capabilities { + explicit Capabilities(bool loss_notification) + : loss_notification(loss_notification) {} + bool loss_notification; + }; + + struct Settings { + Settings(const Capabilities& capabilities, + int number_of_cores, + size_t max_payload_size) + : capabilities(capabilities), + number_of_cores(number_of_cores), + max_payload_size(max_payload_size) {} + + Capabilities capabilities; + int number_of_cores; + size_t max_payload_size; + }; + + static VideoCodecVP8 GetDefaultVp8Settings(); + static VideoCodecVP9 GetDefaultVp9Settings(); + static VideoCodecH264 GetDefaultH264Settings(); + + virtual ~VideoEncoder() {} + + // Set a FecControllerOverride, through which the encoder may override + // decisions made by FecController. + // TODO(bugs.webrtc.org/10769): Update downstream, then make pure-virtual. + virtual void SetFecControllerOverride( + FecControllerOverride* fec_controller_override); + + // Initialize the encoder with the information from the codecSettings + // + // Input: + // - codec_settings : Codec settings + // - settings : Settings affecting the encoding itself. + // Input for deprecated version: + // - number_of_cores : Number of cores available for the encoder + // - max_payload_size : The maximum size each payload is allowed + // to have. Usually MTU - overhead. + // + // Return value : Set bit rate if OK + // <0 - Errors: + // WEBRTC_VIDEO_CODEC_ERR_PARAMETER + // WEBRTC_VIDEO_CODEC_ERR_SIZE + // WEBRTC_VIDEO_CODEC_MEMORY + // WEBRTC_VIDEO_CODEC_ERROR + // TODO(bugs.webrtc.org/10720): After updating downstream projects and posting + // an announcement to discuss-webrtc, remove the three-parameters variant + // and make the two-parameters variant pure-virtual. + /* ABSL_DEPRECATED("bugs.webrtc.org/10720") */ virtual int32_t InitEncode( + const VideoCodec* codec_settings, + int32_t number_of_cores, + size_t max_payload_size); + virtual int InitEncode(const VideoCodec* codec_settings, + const VideoEncoder::Settings& settings); + + // Register an encode complete callback object. + // + // Input: + // - callback : Callback object which handles encoded images. + // + // Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise. + virtual int32_t RegisterEncodeCompleteCallback( + EncodedImageCallback* callback) = 0; + + // Free encoder memory. + // Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise. + virtual int32_t Release() = 0; + + // Encode an image (as a part of a video stream). The encoded image + // will be returned to the user through the encode complete callback. + // + // Input: + // - frame : Image to be encoded + // - frame_types : Frame type to be generated by the encoder. + // + // Return value : WEBRTC_VIDEO_CODEC_OK if OK + // <0 - Errors: + // WEBRTC_VIDEO_CODEC_ERR_PARAMETER + // WEBRTC_VIDEO_CODEC_MEMORY + // WEBRTC_VIDEO_CODEC_ERROR + virtual int32_t Encode(const VideoFrame& frame, + const std::vector<VideoFrameType>* frame_types) = 0; + + // Sets rate control parameters: bitrate, framerate, etc. These settings are + // instantaneous (i.e. not moving averages) and should apply from now until + // the next call to SetRates(). + virtual void SetRates(const RateControlParameters& parameters) = 0; + + // Inform the encoder when the packet loss rate changes. + // + // Input: - packet_loss_rate : The packet loss rate (0.0 to 1.0). + virtual void OnPacketLossRateUpdate(float packet_loss_rate); + + // Inform the encoder when the round trip time changes. + // + // Input: - rtt_ms : The new RTT, in milliseconds. + virtual void OnRttUpdate(int64_t rtt_ms); + + // Called when a loss notification is received. + virtual void OnLossNotification(const LossNotification& loss_notification); + + // Returns meta-data about the encoder, such as implementation name. + // The output of this method may change during runtime. For instance if a + // hardware encoder fails, it may fall back to doing software encoding using + // an implementation with different characteristics. + virtual EncoderInfo GetEncoderInfo() const; +}; +} // namespace webrtc +#endif // API_VIDEO_CODECS_VIDEO_ENCODER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder_factory.h b/third_party/libwebrtc/api/video_codecs/video_encoder_factory.h new file mode 100644 index 0000000000..d28a2a4035 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_encoder_factory.h @@ -0,0 +1,127 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_H_ +#define API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "absl/types/optional.h" +#include "api/units/data_rate.h" +#include "api/video/render_resolution.h" +#include "api/video_codecs/sdp_video_format.h" + +namespace webrtc { + +class VideoEncoder; + +// A factory that creates VideoEncoders. +// NOTE: This class is still under development and may change without notice. +class VideoEncoderFactory { + public: + struct CodecSupport { + bool is_supported = false; + bool is_power_efficient = false; + }; + + // An injectable class that is continuously updated with encoding conditions + // and selects the best encoder given those conditions. An implementation is + // typically stateful to avoid toggling between different encoders, which is + // costly due to recreation of objects, a new codec will always start with a + // key-frame. + class EncoderSelectorInterface { + public: + virtual ~EncoderSelectorInterface() {} + + // Informs the encoder selector about which encoder that is currently being + // used. + virtual void OnCurrentEncoder(const SdpVideoFormat& format) = 0; + + // Called every time the available bitrate is updated. Should return a + // non-empty if an encoder switch should be performed. + virtual absl::optional<SdpVideoFormat> OnAvailableBitrate( + const DataRate& rate) = 0; + + // Called every time the encoder input resolution change. Should return a + // non-empty if an encoder switch should be performed. + virtual absl::optional<SdpVideoFormat> OnResolutionChange( + const RenderResolution& resolution) { + return absl::nullopt; + } + + // Called if the currently used encoder reports itself as broken. Should + // return a non-empty if an encoder switch should be performed. + virtual absl::optional<SdpVideoFormat> OnEncoderBroken() = 0; + }; + + // Returns a list of supported video formats in order of preference, to use + // for signaling etc. + virtual std::vector<SdpVideoFormat> GetSupportedFormats() const = 0; + + // Returns a list of supported video formats in order of preference, that can + // also be tagged with additional information to allow the VideoEncoderFactory + // to separate between different implementations when CreateVideoEncoder is + // called. + virtual std::vector<SdpVideoFormat> GetImplementations() const { + return GetSupportedFormats(); + } + + // Query whether the specifed format is supported or not and if it will be + // power efficient, which is currently interpreted as if there is support for + // hardware acceleration. + // See https://w3c.github.io/webrtc-svc/#scalabilitymodes* for a specification + // of valid values for `scalability_mode`. + // NOTE: QueryCodecSupport is currently an experimental feature that is + // subject to change without notice. + virtual CodecSupport QueryCodecSupport( + const SdpVideoFormat& format, + absl::optional<std::string> scalability_mode) const { + // Default implementation, query for supported formats and check if the + // specified format is supported. Returns false if scalability_mode is + // specified. + CodecSupport codec_support; + if (!scalability_mode) { + codec_support.is_supported = format.IsCodecInList(GetSupportedFormats()); + } + return codec_support; + } + + // Creates a VideoEncoder for the specified format. + virtual std::unique_ptr<VideoEncoder> CreateVideoEncoder( + const SdpVideoFormat& format) = 0; + + // This method creates a EncoderSelector to use for a VideoSendStream. + // (and hence should probably been called CreateEncoderSelector()). + // + // Note: This method is unsuitable if encoding several streams that + // are using same VideoEncoderFactory (either by several streams in one + // PeerConnection or streams with different PeerConnection but same + // PeerConnectionFactory). This is due to the fact that the method is not + // given any stream identifier, nor is the EncoderSelectorInterface given any + // stream identifiers, i.e one does not know which stream is being encoded + // with help of the selector. + // + // In such scenario, the `RtpSenderInterface::SetEncoderSelector` is + // recommended. + // + // TODO(bugs.webrtc.org:14122): Deprecate and remove in favor of + // `RtpSenderInterface::SetEncoderSelector`. + virtual std::unique_ptr<EncoderSelectorInterface> GetEncoderSelector() const { + return nullptr; + } + + virtual ~VideoEncoderFactory() {} +}; + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template.h b/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template.h new file mode 100644 index 0000000000..643096dbbb --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_H_ +#define API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "absl/algorithm/container.h" +#include "api/array_view.h" +#include "api/video_codecs/video_encoder.h" +#include "api/video_codecs/video_encoder_factory.h" +#include "modules/video_coding/svc/scalability_mode_util.h" + +namespace webrtc { +// The VideoEncoderFactoryTemplate supports encoders implementations given as +// template arguments. +// +// To include an encoder in the factory it requires three static members +// functions to be defined: +// +// // Returns the supported SdpVideoFormats this encoder can produce. +// static std::vector<SdpVideoFormat> SupportedFormats(); +// +// // Creates an encoder instance for the given format. +// static std::unique_ptr<VideoEncoder> +// CreateEncoder(const SdpVideoFormat& format); +// +// // Returns true if the encoder supports the given scalability mode. +// static bool +// IsScalabilityModeSupported(ScalabilityMode scalability_mode); +// +// Note that the order of the template arguments matter as the factory will +// query/return the first encoder implementation supporting the given +// SdpVideoFormat. +template <typename... Ts> +class VideoEncoderFactoryTemplate : public VideoEncoderFactory { + public: + std::vector<SdpVideoFormat> GetSupportedFormats() const override { + return GetSupportedFormatsInternal<Ts...>(); + } + + std::unique_ptr<VideoEncoder> CreateVideoEncoder( + const SdpVideoFormat& format) override { + return CreateVideoEncoderInternal<Ts...>(format); + } + + CodecSupport QueryCodecSupport( + const SdpVideoFormat& format, + absl::optional<std::string> scalability_mode) const override { + return QueryCodecSupportInternal<Ts...>(format, scalability_mode); + } + + private: + bool IsFormatInList( + const SdpVideoFormat& format, + rtc::ArrayView<const SdpVideoFormat> supported_formats) const { + return absl::c_any_of( + supported_formats, [&](const SdpVideoFormat& supported_format) { + return supported_format.name == format.name && + supported_format.parameters == format.parameters; + }); + } + + template <typename V> + bool IsScalabilityModeSupported( + const absl::optional<std::string>& scalability_mode_string) const { + if (!scalability_mode_string.has_value()) { + return true; + } + absl::optional<ScalabilityMode> scalability_mode = + ScalabilityModeFromString(*scalability_mode_string); + return scalability_mode.has_value() && + V::IsScalabilityModeSupported(*scalability_mode); + } + + template <typename V, typename... Vs> + std::vector<SdpVideoFormat> GetSupportedFormatsInternal() const { + auto supported_formats = V::SupportedFormats(); + + if constexpr (sizeof...(Vs) > 0) { + // Supported formats may overlap between implementations, so duplicates + // should be filtered out. + for (const auto& other_format : GetSupportedFormatsInternal<Vs...>()) { + if (!IsFormatInList(other_format, supported_formats)) { + supported_formats.push_back(other_format); + } + } + } + + return supported_formats; + } + + template <typename V, typename... Vs> + std::unique_ptr<VideoEncoder> CreateVideoEncoderInternal( + const SdpVideoFormat& format) { + if (IsFormatInList(format, V::SupportedFormats())) { + return V::CreateEncoder(format); + } + + if constexpr (sizeof...(Vs) > 0) { + return CreateVideoEncoderInternal<Vs...>(format); + } + + return nullptr; + } + + template <typename V, typename... Vs> + CodecSupport QueryCodecSupportInternal( + const SdpVideoFormat& format, + const absl::optional<std::string>& scalability_mode) const { + if (IsFormatInList(format, V::SupportedFormats())) { + return {.is_supported = IsScalabilityModeSupported<V>(scalability_mode)}; + } + + if constexpr (sizeof...(Vs) > 0) { + return QueryCodecSupportInternal<Vs...>(format, scalability_mode); + } + + return {.is_supported = false}; + } +}; + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_libaom_av1_adapter.h b/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_libaom_av1_adapter.h new file mode 100644 index 0000000000..417df1e192 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_libaom_av1_adapter.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_LIBAOM_AV1_ADAPTER_H_ +#define API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_LIBAOM_AV1_ADAPTER_H_ + +#include <memory> +#include <vector> + +#include "absl/container/inlined_vector.h" +#include "api/video_codecs/sdp_video_format.h" +#include "modules/video_coding/codecs/av1/av1_svc_config.h" +#include "modules/video_coding/codecs/av1/libaom_av1_encoder.h" + +namespace webrtc { +struct LibaomAv1EncoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { + absl::InlinedVector<ScalabilityMode, kScalabilityModeCount> + scalability_modes = LibaomAv1EncoderSupportedScalabilityModes(); + return { + SdpVideoFormat("AV1", SdpVideoFormat::Parameters(), scalability_modes)}; + } + + static std::unique_ptr<VideoEncoder> CreateEncoder( + const SdpVideoFormat& format) { + return CreateLibaomAv1Encoder(); + } + + static bool IsScalabilityModeSupported(ScalabilityMode scalability_mode) { + return LibaomAv1EncoderSupportsScalabilityMode(scalability_mode); + } +}; + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_LIBAOM_AV1_ADAPTER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_libvpx_vp8_adapter.h b/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_libvpx_vp8_adapter.h new file mode 100644 index 0000000000..0f0a9bacd5 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_libvpx_vp8_adapter.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_LIBVPX_VP8_ADAPTER_H_ +#define API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_LIBVPX_VP8_ADAPTER_H_ + +#include <memory> +#include <vector> + +#include "absl/container/inlined_vector.h" +#include "api/video_codecs/sdp_video_format.h" +#include "modules/video_coding/codecs/vp8/include/vp8.h" +#include "modules/video_coding/codecs/vp8/vp8_scalability.h" + +namespace webrtc { +struct LibvpxVp8EncoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { + absl::InlinedVector<ScalabilityMode, kScalabilityModeCount> + scalability_modes; + for (const auto scalability_mode : kVP8SupportedScalabilityModes) { + scalability_modes.push_back(scalability_mode); + } + + return { + SdpVideoFormat("VP8", SdpVideoFormat::Parameters(), scalability_modes)}; + } + + static std::unique_ptr<VideoEncoder> CreateEncoder( + const SdpVideoFormat& format) { + return VP8Encoder::Create(); + } + + static bool IsScalabilityModeSupported(ScalabilityMode scalability_mode) { + return VP8SupportsScalabilityMode(scalability_mode); + } +}; +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_LIBVPX_VP8_ADAPTER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_libvpx_vp9_adapter.h b/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_libvpx_vp9_adapter.h new file mode 100644 index 0000000000..c10fda4dc2 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_libvpx_vp9_adapter.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_LIBVPX_VP9_ADAPTER_H_ +#define API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_LIBVPX_VP9_ADAPTER_H_ + +#include <memory> +#include <vector> + +#include "modules/video_coding/codecs/vp9/include/vp9.h" + +namespace webrtc { +struct LibvpxVp9EncoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { + return SupportedVP9Codecs(/*add_scalability_modes=*/true); + } + + static std::unique_ptr<VideoEncoder> CreateEncoder( + const SdpVideoFormat& format) { + return VP9Encoder::Create(cricket::VideoCodec(format)); + } + + static bool IsScalabilityModeSupported(ScalabilityMode scalability_mode) { + return VP9Encoder::SupportsScalabilityMode(scalability_mode); + } +}; +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_LIBVPX_VP9_ADAPTER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_open_h264_adapter.h b/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_open_h264_adapter.h new file mode 100644 index 0000000000..0830460cdb --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_encoder_factory_template_open_h264_adapter.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_OPEN_H264_ADAPTER_H_ +#define API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_OPEN_H264_ADAPTER_H_ + +#include <memory> +#include <vector> + +#include "modules/video_coding/codecs/h264/include/h264.h" + +namespace webrtc { +// TODO(bugs.webrtc.org/13573): When OpenH264 is no longer a conditional build +// target remove #ifdefs. +struct OpenH264EncoderTemplateAdapter { + static std::vector<SdpVideoFormat> SupportedFormats() { +#if defined(WEBRTC_USE_H264) + return SupportedH264Codecs(/*add_scalability_modes=*/true); +#else + return {}; +#endif + } + + static std::unique_ptr<VideoEncoder> CreateEncoder( + const SdpVideoFormat& format) { +#if defined(WEBRTC_USE_H264) + return H264Encoder::Create(cricket::VideoCodec(format)); +#else + return nullptr; +#endif + } + + static bool IsScalabilityModeSupported(ScalabilityMode scalability_mode) { +#if defined(WEBRTC_USE_H264) + return H264Encoder::SupportsScalabilityMode(scalability_mode); +#else + return false; +#endif + } +}; +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_ENCODER_FACTORY_TEMPLATE_OPEN_H264_ADAPTER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.cc b/third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.cc new file mode 100644 index 0000000000..39c52a0081 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.cc @@ -0,0 +1,519 @@ +/* + * 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. + */ + +#include "api/video_codecs/video_encoder_software_fallback_wrapper.h" + +#include <stdint.h> + +#include <cstdio> +#include <memory> +#include <string> +#include <vector> + +#include "absl/strings/match.h" +#include "absl/types/optional.h" +#include "api/fec_controller_override.h" +#include "api/video/i420_buffer.h" +#include "api/video/video_bitrate_allocation.h" +#include "api/video/video_frame.h" +#include "api/video_codecs/video_codec.h" +#include "api/video_codecs/video_encoder.h" +#include "media/base/video_common.h" +#include "modules/video_coding/include/video_error_codes.h" +#include "modules/video_coding/utility/simulcast_utility.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" +#include "system_wrappers/include/field_trial.h" + +namespace webrtc { + +namespace { + +// If forced fallback is allowed, either: +// +// 1) The forced fallback is requested if the resolution is less than or equal +// to `max_pixels_`. The resolution is allowed to be scaled down to +// `min_pixels_`. +// +// 2) The forced fallback is requested if temporal support is preferred and the +// SW fallback supports temporal layers while the HW encoder does not. + +struct ForcedFallbackParams { + public: + bool SupportsResolutionBasedSwitch(const VideoCodec& codec) const { + return enable_resolution_based_switch && + codec.codecType == kVideoCodecVP8 && + codec.numberOfSimulcastStreams <= 1 && + codec.width * codec.height <= max_pixels; + } + + bool SupportsTemporalBasedSwitch(const VideoCodec& codec) const { + return enable_temporal_based_switch && + SimulcastUtility::NumberOfTemporalLayers(codec, 0) != 1; + } + + bool enable_temporal_based_switch = false; + bool enable_resolution_based_switch = false; + int min_pixels = 320 * 180; + int max_pixels = 320 * 240; +}; + +const char kVp8ForceFallbackEncoderFieldTrial[] = + "WebRTC-VP8-Forced-Fallback-Encoder-v2"; + +absl::optional<ForcedFallbackParams> ParseFallbackParamsFromFieldTrials( + const VideoEncoder& main_encoder) { + const std::string field_trial = + webrtc::field_trial::FindFullName(kVp8ForceFallbackEncoderFieldTrial); + if (!absl::StartsWith(field_trial, "Enabled")) { + return absl::nullopt; + } + + int max_pixels_lower_bound = + main_encoder.GetEncoderInfo().scaling_settings.min_pixels_per_frame - 1; + + ForcedFallbackParams params; + params.enable_resolution_based_switch = true; + + int min_bps = 0; + if (sscanf(field_trial.c_str(), "Enabled-%d,%d,%d", ¶ms.min_pixels, + ¶ms.max_pixels, &min_bps) != 3) { + RTC_LOG(LS_WARNING) + << "Invalid number of forced fallback parameters provided."; + return absl::nullopt; + } else if (params.min_pixels <= 0 || + params.max_pixels < max_pixels_lower_bound || + params.max_pixels < params.min_pixels || min_bps <= 0) { + RTC_LOG(LS_WARNING) << "Invalid forced fallback parameter value provided."; + return absl::nullopt; + } + + return params; +} + +absl::optional<ForcedFallbackParams> GetForcedFallbackParams( + bool prefer_temporal_support, + const VideoEncoder& main_encoder) { + absl::optional<ForcedFallbackParams> params = + ParseFallbackParamsFromFieldTrials(main_encoder); + if (prefer_temporal_support) { + if (!params.has_value()) { + params.emplace(); + } + params->enable_temporal_based_switch = prefer_temporal_support; + } + return params; +} + +class VideoEncoderSoftwareFallbackWrapper final : public VideoEncoder { + public: + VideoEncoderSoftwareFallbackWrapper( + std::unique_ptr<webrtc::VideoEncoder> sw_encoder, + std::unique_ptr<webrtc::VideoEncoder> hw_encoder, + bool prefer_temporal_support); + ~VideoEncoderSoftwareFallbackWrapper() override; + + void SetFecControllerOverride( + FecControllerOverride* fec_controller_override) override; + + int32_t InitEncode(const VideoCodec* codec_settings, + const VideoEncoder::Settings& settings) override; + + int32_t RegisterEncodeCompleteCallback( + EncodedImageCallback* callback) override; + + int32_t Release() override; + + int32_t Encode(const VideoFrame& frame, + const std::vector<VideoFrameType>* frame_types) override; + + void OnPacketLossRateUpdate(float packet_loss_rate) override; + + void OnRttUpdate(int64_t rtt_ms) override; + + void OnLossNotification(const LossNotification& loss_notification) override; + + void SetRates(const RateControlParameters& parameters) override; + + EncoderInfo GetEncoderInfo() const override; + + private: + bool InitFallbackEncoder(bool is_forced); + bool TryInitForcedFallbackEncoder(); + bool IsFallbackActive() const; + + VideoEncoder* current_encoder() { + switch (encoder_state_) { + case EncoderState::kUninitialized: + RTC_LOG(LS_WARNING) + << "Trying to access encoder in uninitialized fallback wrapper."; + // Return main encoder to preserve previous behavior. + [[fallthrough]]; + case EncoderState::kMainEncoderUsed: + return encoder_.get(); + case EncoderState::kFallbackDueToFailure: + case EncoderState::kForcedFallback: + return fallback_encoder_.get(); + } + RTC_CHECK_NOTREACHED(); + } + + // Updates encoder with last observed parameters, such as callbacks, rates, + // etc. + void PrimeEncoder(VideoEncoder* encoder) const; + + // Settings used in the last InitEncode call and used if a dynamic fallback to + // software is required. + VideoCodec codec_settings_; + absl::optional<VideoEncoder::Settings> encoder_settings_; + + // The last rate control settings, if set. + absl::optional<RateControlParameters> rate_control_parameters_; + + // The last channel parameters set. + absl::optional<float> packet_loss_; + absl::optional<int64_t> rtt_; + absl::optional<LossNotification> loss_notification_; + + enum class EncoderState { + kUninitialized, + kMainEncoderUsed, + kFallbackDueToFailure, + kForcedFallback + }; + + EncoderState encoder_state_; + const std::unique_ptr<webrtc::VideoEncoder> encoder_; + const std::unique_ptr<webrtc::VideoEncoder> fallback_encoder_; + + EncodedImageCallback* callback_; + + const absl::optional<ForcedFallbackParams> fallback_params_; + int32_t EncodeWithMainEncoder(const VideoFrame& frame, + const std::vector<VideoFrameType>* frame_types); +}; + +VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper( + std::unique_ptr<webrtc::VideoEncoder> sw_encoder, + std::unique_ptr<webrtc::VideoEncoder> hw_encoder, + bool prefer_temporal_support) + : encoder_state_(EncoderState::kUninitialized), + encoder_(std::move(hw_encoder)), + fallback_encoder_(std::move(sw_encoder)), + callback_(nullptr), + fallback_params_( + GetForcedFallbackParams(prefer_temporal_support, *encoder_)) { + RTC_DCHECK(fallback_encoder_); +} + +VideoEncoderSoftwareFallbackWrapper::~VideoEncoderSoftwareFallbackWrapper() = + default; + +void VideoEncoderSoftwareFallbackWrapper::PrimeEncoder( + VideoEncoder* encoder) const { + RTC_DCHECK(encoder); + // Replay callback, rates, and channel parameters. + if (callback_) { + encoder->RegisterEncodeCompleteCallback(callback_); + } + if (rate_control_parameters_) { + encoder->SetRates(*rate_control_parameters_); + } + if (rtt_.has_value()) { + encoder->OnRttUpdate(rtt_.value()); + } + if (packet_loss_.has_value()) { + encoder->OnPacketLossRateUpdate(packet_loss_.value()); + } + + if (loss_notification_.has_value()) { + encoder->OnLossNotification(loss_notification_.value()); + } +} + +bool VideoEncoderSoftwareFallbackWrapper::InitFallbackEncoder(bool is_forced) { + RTC_LOG(LS_WARNING) << "Encoder falling back to software encoding."; + + RTC_DCHECK(encoder_settings_.has_value()); + const int ret = fallback_encoder_->InitEncode(&codec_settings_, + encoder_settings_.value()); + + if (ret != WEBRTC_VIDEO_CODEC_OK) { + RTC_LOG(LS_ERROR) << "Failed to initialize software-encoder fallback."; + fallback_encoder_->Release(); + return false; + } + + if (encoder_state_ == EncoderState::kMainEncoderUsed) { + // Since we're switching to the fallback encoder, Release the real encoder. + // It may be re-initialized via InitEncode later, and it will continue to + // get Set calls for rates and channel parameters in the meantime. + encoder_->Release(); + } + + if (is_forced) { + encoder_state_ = EncoderState::kForcedFallback; + } else { + encoder_state_ = EncoderState::kFallbackDueToFailure; + } + + return true; +} + +void VideoEncoderSoftwareFallbackWrapper::SetFecControllerOverride( + FecControllerOverride* fec_controller_override) { + // It is important that only one of those would ever interact with the + // `fec_controller_override` at a given time. This is the responsibility + // of `this` to maintain. + + encoder_->SetFecControllerOverride(fec_controller_override); + fallback_encoder_->SetFecControllerOverride(fec_controller_override); +} + +int32_t VideoEncoderSoftwareFallbackWrapper::InitEncode( + const VideoCodec* codec_settings, + const VideoEncoder::Settings& settings) { + // Store settings, in case we need to dynamically switch to the fallback + // encoder after a failed Encode call. + codec_settings_ = *codec_settings; + encoder_settings_ = settings; + // Clear stored rate/channel parameters. + rate_control_parameters_ = absl::nullopt; + + RTC_DCHECK_EQ(encoder_state_, EncoderState::kUninitialized) + << "InitEncode() should never be called on an active instance!"; + + // Try to init forced software codec if it should be used. + if (TryInitForcedFallbackEncoder()) { + PrimeEncoder(current_encoder()); + return WEBRTC_VIDEO_CODEC_OK; + } + + int32_t ret = encoder_->InitEncode(codec_settings, settings); + if (ret == WEBRTC_VIDEO_CODEC_OK) { + encoder_state_ = EncoderState::kMainEncoderUsed; + PrimeEncoder(current_encoder()); + return ret; + } + + // Try to instantiate software codec. + if (InitFallbackEncoder(/*is_forced=*/false)) { + PrimeEncoder(current_encoder()); + return WEBRTC_VIDEO_CODEC_OK; + } + + // Software encoder failed too, use original return code. + encoder_state_ = EncoderState::kUninitialized; + return ret; +} + +int32_t VideoEncoderSoftwareFallbackWrapper::RegisterEncodeCompleteCallback( + EncodedImageCallback* callback) { + callback_ = callback; + return current_encoder()->RegisterEncodeCompleteCallback(callback); +} + +int32_t VideoEncoderSoftwareFallbackWrapper::Release() { + if (encoder_state_ == EncoderState::kUninitialized) { + return WEBRTC_VIDEO_CODEC_OK; + } + int32_t ret = current_encoder()->Release(); + encoder_state_ = EncoderState::kUninitialized; + return ret; +} + +int32_t VideoEncoderSoftwareFallbackWrapper::Encode( + const VideoFrame& frame, + const std::vector<VideoFrameType>* frame_types) { + switch (encoder_state_) { + case EncoderState::kUninitialized: + return WEBRTC_VIDEO_CODEC_ERROR; + case EncoderState::kMainEncoderUsed: { + return EncodeWithMainEncoder(frame, frame_types); + } + case EncoderState::kFallbackDueToFailure: + case EncoderState::kForcedFallback: + return fallback_encoder_->Encode(frame, frame_types); + } + RTC_CHECK_NOTREACHED(); +} + +int32_t VideoEncoderSoftwareFallbackWrapper::EncodeWithMainEncoder( + const VideoFrame& frame, + const std::vector<VideoFrameType>* frame_types) { + int32_t ret = encoder_->Encode(frame, frame_types); + // If requested, try a software fallback. + bool fallback_requested = (ret == WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE); + if (fallback_requested && InitFallbackEncoder(/*is_forced=*/false)) { + // Start using the fallback with this frame. + PrimeEncoder(current_encoder()); + if (frame.video_frame_buffer()->type() == VideoFrameBuffer::Type::kNative && + fallback_encoder_->GetEncoderInfo().supports_native_handle) { + return fallback_encoder_->Encode(frame, frame_types); + } else { + RTC_LOG(LS_INFO) << "Fallback encoder does not support native handle - " + "converting frame to I420"; + rtc::scoped_refptr<I420BufferInterface> src_buffer = + frame.video_frame_buffer()->ToI420(); + if (!src_buffer) { + RTC_LOG(LS_ERROR) << "Failed to convert from to I420"; + return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE; + } + rtc::scoped_refptr<VideoFrameBuffer> dst_buffer = + src_buffer->Scale(codec_settings_.width, codec_settings_.height); + if (!dst_buffer) { + RTC_LOG(LS_ERROR) << "Failed to scale video frame."; + return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE; + } + VideoFrame scaled_frame = frame; + scaled_frame.set_video_frame_buffer(dst_buffer); + scaled_frame.set_update_rect(VideoFrame::UpdateRect{ + 0, 0, scaled_frame.width(), scaled_frame.height()}); + return fallback_encoder_->Encode(scaled_frame, frame_types); + } + } + // Fallback encoder failed too, return original error code. + return ret; +} + +void VideoEncoderSoftwareFallbackWrapper::SetRates( + const RateControlParameters& parameters) { + rate_control_parameters_ = parameters; + return current_encoder()->SetRates(parameters); +} + +void VideoEncoderSoftwareFallbackWrapper::OnPacketLossRateUpdate( + float packet_loss_rate) { + packet_loss_ = packet_loss_rate; + current_encoder()->OnPacketLossRateUpdate(packet_loss_rate); +} + +void VideoEncoderSoftwareFallbackWrapper::OnRttUpdate(int64_t rtt_ms) { + rtt_ = rtt_ms; + current_encoder()->OnRttUpdate(rtt_ms); +} + +void VideoEncoderSoftwareFallbackWrapper::OnLossNotification( + const LossNotification& loss_notification) { + loss_notification_ = loss_notification; + current_encoder()->OnLossNotification(loss_notification); +} + +VideoEncoder::EncoderInfo VideoEncoderSoftwareFallbackWrapper::GetEncoderInfo() + const { + EncoderInfo fallback_encoder_info = fallback_encoder_->GetEncoderInfo(); + EncoderInfo default_encoder_info = encoder_->GetEncoderInfo(); + + EncoderInfo info = + IsFallbackActive() ? fallback_encoder_info : default_encoder_info; + + info.requested_resolution_alignment = cricket::LeastCommonMultiple( + fallback_encoder_info.requested_resolution_alignment, + default_encoder_info.requested_resolution_alignment); + info.apply_alignment_to_all_simulcast_layers = + fallback_encoder_info.apply_alignment_to_all_simulcast_layers || + default_encoder_info.apply_alignment_to_all_simulcast_layers; + + if (fallback_params_.has_value()) { + const auto settings = (encoder_state_ == EncoderState::kForcedFallback) + ? fallback_encoder_info.scaling_settings + : default_encoder_info.scaling_settings; + info.scaling_settings = + settings.thresholds + ? VideoEncoder::ScalingSettings(settings.thresholds->low, + settings.thresholds->high, + fallback_params_->min_pixels) + : VideoEncoder::ScalingSettings::kOff; + } else { + info.scaling_settings = default_encoder_info.scaling_settings; + } + + return info; +} + +bool VideoEncoderSoftwareFallbackWrapper::IsFallbackActive() const { + return encoder_state_ == EncoderState::kForcedFallback || + encoder_state_ == EncoderState::kFallbackDueToFailure; +} + +bool VideoEncoderSoftwareFallbackWrapper::TryInitForcedFallbackEncoder() { + if (!fallback_params_) { + return false; + } + + RTC_DCHECK_EQ(encoder_state_, EncoderState::kUninitialized); + + if (fallback_params_->SupportsResolutionBasedSwitch(codec_settings_)) { + // Settings valid, try to instantiate software codec. + RTC_LOG(LS_INFO) << "Request forced SW encoder fallback: " + << codec_settings_.width << "x" << codec_settings_.height; + return InitFallbackEncoder(/*is_forced=*/true); + } + + if (fallback_params_->SupportsTemporalBasedSwitch(codec_settings_)) { + // First init main encoder to see if that supports temporal layers. + if (encoder_->InitEncode(&codec_settings_, encoder_settings_.value()) == + WEBRTC_VIDEO_CODEC_OK) { + encoder_state_ = EncoderState::kMainEncoderUsed; + } + + if (encoder_state_ == EncoderState::kMainEncoderUsed && + encoder_->GetEncoderInfo().fps_allocation[0].size() != 1) { + // Primary encoder already supports temporal layers, use that instead. + return true; + } + + // Try to initialize fallback and check if it supports temporal layers. + if (fallback_encoder_->InitEncode(&codec_settings_, + encoder_settings_.value()) == + WEBRTC_VIDEO_CODEC_OK) { + if (fallback_encoder_->GetEncoderInfo().fps_allocation[0].size() != 1) { + // Fallback encoder available and supports temporal layers, use it! + if (encoder_state_ == EncoderState::kMainEncoderUsed) { + // Main encoder initialized but does not support temporal layers, + // release it again. + encoder_->Release(); + } + encoder_state_ = EncoderState::kForcedFallback; + RTC_LOG(LS_INFO) + << "Forced switch to SW encoder due to temporal support."; + return true; + } else { + // Fallback encoder intialization succeeded, but it does not support + // temporal layers either - release it. + fallback_encoder_->Release(); + } + } + + if (encoder_state_ == EncoderState::kMainEncoderUsed) { + // Main encoder already initialized - make use of it. + RTC_LOG(LS_INFO) + << "Cannot fall back for temporal support since fallback that " + "supports is not available. Using main encoder instead."; + return true; + } + } + + // Neither forced fallback mode supported. + return false; +} + +} // namespace + +std::unique_ptr<VideoEncoder> CreateVideoEncoderSoftwareFallbackWrapper( + std::unique_ptr<VideoEncoder> sw_fallback_encoder, + std::unique_ptr<VideoEncoder> hw_encoder, + bool prefer_temporal_support) { + return std::make_unique<VideoEncoderSoftwareFallbackWrapper>( + std::move(sw_fallback_encoder), std::move(hw_encoder), + prefer_temporal_support); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.h b/third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.h new file mode 100644 index 0000000000..6e6902eb3f --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/video_encoder_software_fallback_wrapper.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_CODECS_VIDEO_ENCODER_SOFTWARE_FALLBACK_WRAPPER_H_ +#define API_VIDEO_CODECS_VIDEO_ENCODER_SOFTWARE_FALLBACK_WRAPPER_H_ + +#include <memory> +#include <utility> + +#include "api/video_codecs/video_encoder.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Used to wrap external VideoEncoders to provide a fallback option on +// software encoding when a hardware encoder fails to encode a stream due to +// hardware restrictions, such as max resolution. +// |bool prefer_temporal_support| indicates that if the software fallback +// encoder supports temporal layers but the hardware encoder does not, a +// fallback should be forced even if the encoder otherwise works. +RTC_EXPORT std::unique_ptr<VideoEncoder> +CreateVideoEncoderSoftwareFallbackWrapper( + std::unique_ptr<VideoEncoder> sw_fallback_encoder, + std::unique_ptr<VideoEncoder> hw_encoder, + bool prefer_temporal_support); + +// Default fallback for call-sites not yet updated with +// `prefer_temporal_support`. +// TODO(sprang): Remove when usage is gone. +RTC_EXPORT inline std::unique_ptr<VideoEncoder> +CreateVideoEncoderSoftwareFallbackWrapper( + std::unique_ptr<VideoEncoder> sw_fallback_encoder, + std::unique_ptr<VideoEncoder> hw_encoder) { + return CreateVideoEncoderSoftwareFallbackWrapper( + std::move(sw_fallback_encoder), std::move(hw_encoder), false); +} + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VIDEO_ENCODER_SOFTWARE_FALLBACK_WRAPPER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/vp8_frame_buffer_controller.h b/third_party/libwebrtc/api/video_codecs/vp8_frame_buffer_controller.h new file mode 100644 index 0000000000..fc494f7293 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/vp8_frame_buffer_controller.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2019 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 API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_ +#define API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_ + +#include <array> +#include <memory> +#include <vector> + +#include "absl/types/optional.h" +#include "api/fec_controller_override.h" +#include "api/video_codecs/video_codec.h" +#include "api/video_codecs/video_encoder.h" +#include "api/video_codecs/vp8_frame_config.h" + +namespace webrtc { + +// Some notes on the prerequisites of the TemporalLayers interface. +// * Vp8FrameBufferController is not thread safe, synchronization is the +// caller's responsibility. +// * The encoder is assumed to encode all frames in order, and callbacks to +// PopulateCodecSpecific() / OnEncodeDone() must happen in the same order. +// +// This means that in the case of pipelining encoders, it is OK to have a chain +// of calls such as this: +// - NextFrameConfig(timestampA) +// - NextFrameConfig(timestampB) +// - PopulateCodecSpecific(timestampA, ...) +// - NextFrameConfig(timestampC) +// - OnEncodeDone(timestampA, 1234, ...) +// - NextFrameConfig(timestampC) +// - OnEncodeDone(timestampB, 0, ...) +// - OnEncodeDone(timestampC, 1234, ...) +// Note that NextFrameConfig() for a new frame can happen before +// OnEncodeDone() for a previous one, but calls themselves must be both +// synchronized (e.g. run on a task queue) and in order (per type). +// +// TODO(eladalon): Revise comment (referring to PopulateCodecSpecific in this +// context is not very meaningful). + +struct CodecSpecificInfo; + +// Each member represents an override of the VPX configuration if the optional +// value is set. +struct Vp8EncoderConfig { + struct TemporalLayerConfig { + bool operator!=(const TemporalLayerConfig& other) const { + return ts_number_layers != other.ts_number_layers || + ts_target_bitrate != other.ts_target_bitrate || + ts_rate_decimator != other.ts_rate_decimator || + ts_periodicity != other.ts_periodicity || + ts_layer_id != other.ts_layer_id; + } + + static constexpr size_t kMaxPeriodicity = 16; + static constexpr size_t kMaxLayers = 5; + + // Number of active temporal layers. Set to 0 if not used. + uint32_t ts_number_layers; + + // Arrays of length `ts_number_layers`, indicating (cumulative) target + // bitrate and rate decimator (e.g. 4 if every 4th frame is in the given + // layer) for each active temporal layer, starting with temporal id 0. + std::array<uint32_t, kMaxLayers> ts_target_bitrate; + std::array<uint32_t, kMaxLayers> ts_rate_decimator; + + // The periodicity of the temporal pattern. Set to 0 if not used. + uint32_t ts_periodicity; + + // Array of length `ts_periodicity` indicating the sequence of temporal id's + // to assign to incoming frames. + std::array<uint32_t, kMaxPeriodicity> ts_layer_id; + }; + + absl::optional<TemporalLayerConfig> temporal_layer_config; + + // Target bitrate, in bps. + absl::optional<uint32_t> rc_target_bitrate; + + // Clamp QP to max. Use 0 to disable clamping. + absl::optional<uint32_t> rc_max_quantizer; + + // Error resilience mode. + absl::optional<uint32_t> g_error_resilient; + + // If set to true, all previous configuration overrides should be reset. + bool reset_previous_configuration_overrides = false; +}; + +// This interface defines a way of delegating the logic of buffer management. +// Multiple streams may be controlled by a single controller, demuxing between +// them using stream_index. +class Vp8FrameBufferController { + public: + virtual ~Vp8FrameBufferController() = default; + + // Set limits on QP. + // The limits are suggestion-only; the controller is allowed to exceed them. + virtual void SetQpLimits(size_t stream_index, int min_qp, int max_qp) = 0; + + // Number of streamed controlled by `this`. + virtual size_t StreamCount() const = 0; + + // If this method returns true, the encoder is free to drop frames for + // instance in an effort to uphold encoding bitrate. + // If this return false, the encoder must not drop any frames unless: + // 1. Requested to do so via Vp8FrameConfig.drop_frame + // 2. The frame to be encoded is requested to be a keyframe + // 3. The encoder detected a large overshoot and decided to drop and then + // re-encode the image at a low bitrate. In this case the encoder should + // call OnFrameDropped() once to indicate drop, and then call + // OnEncodeDone() again when the frame has actually been encoded. + virtual bool SupportsEncoderFrameDropping(size_t stream_index) const = 0; + + // New target bitrate for a stream (each entry in + // `bitrates_bps` is for another temporal layer). + virtual void OnRatesUpdated(size_t stream_index, + const std::vector<uint32_t>& bitrates_bps, + int framerate_fps) = 0; + + // Called by the encoder before encoding a frame. Returns a set of overrides + // the controller wishes to enact in the encoder's configuration. + // If a value is not overridden, previous overrides are still in effect. + // However, if `Vp8EncoderConfig::reset_previous_configuration_overrides` + // is set to `true`, all previous overrides are reset. + virtual Vp8EncoderConfig UpdateConfiguration(size_t stream_index) = 0; + + // Returns the recommended VP8 encode flags needed. + // The timestamp may be used as both a time and a unique identifier, and so + // the caller must make sure no two frames use the same timestamp. + // The timestamp uses a 90kHz RTP clock. + // After calling this method, first call the actual encoder with the provided + // frame configuration, and then OnEncodeDone() below. + virtual Vp8FrameConfig NextFrameConfig(size_t stream_index, + uint32_t rtp_timestamp) = 0; + + // Called after the encode step is done. `rtp_timestamp` must match the + // parameter use in the NextFrameConfig() call. + // `is_keyframe` must be true iff the encoder decided to encode this frame as + // a keyframe. + // If `info` is not null, the encoder may update `info` with codec specific + // data such as temporal id. `qp` should indicate the frame-level QP this + // frame was encoded at. If the encoder does not support extracting this, `qp` + // should be set to 0. + virtual void OnEncodeDone(size_t stream_index, + uint32_t rtp_timestamp, + size_t size_bytes, + bool is_keyframe, + int qp, + CodecSpecificInfo* info) = 0; + + // Called when a frame is dropped by the encoder. + virtual void OnFrameDropped(size_t stream_index, uint32_t rtp_timestamp) = 0; + + // Called by the encoder when the packet loss rate changes. + // `packet_loss_rate` runs between 0.0 (no loss) and 1.0 (everything lost). + virtual void OnPacketLossRateUpdate(float packet_loss_rate) = 0; + + // Called by the encoder when the round trip time changes. + virtual void OnRttUpdate(int64_t rtt_ms) = 0; + + // Called when a loss notification is received. + virtual void OnLossNotification( + const VideoEncoder::LossNotification& loss_notification) = 0; +}; + +// Interface for a factory of Vp8FrameBufferController instances. +class Vp8FrameBufferControllerFactory { + public: + virtual ~Vp8FrameBufferControllerFactory() = default; + + // Clones oneself. (Avoids Vp8FrameBufferControllerFactoryFactory.) + virtual std::unique_ptr<Vp8FrameBufferControllerFactory> Clone() const = 0; + + // Create a Vp8FrameBufferController instance. + virtual std::unique_ptr<Vp8FrameBufferController> Create( + const VideoCodec& codec, + const VideoEncoder::Settings& settings, + FecControllerOverride* fec_controller_override) = 0; +}; + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_ diff --git a/third_party/libwebrtc/api/video_codecs/vp8_frame_config.cc b/third_party/libwebrtc/api/video_codecs/vp8_frame_config.cc new file mode 100644 index 0000000000..05e1911bb7 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/vp8_frame_config.cc @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019 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 "api/video_codecs/vp8_frame_config.h" + +#include "modules/video_coding/codecs/interface/common_constants.h" +#include "rtc_base/checks.h" + +namespace webrtc { + +Vp8FrameConfig::Vp8FrameConfig() : Vp8FrameConfig(kNone, kNone, kNone, false) {} + +Vp8FrameConfig::Vp8FrameConfig(BufferFlags last, + BufferFlags golden, + BufferFlags arf) + : Vp8FrameConfig(last, golden, arf, false) {} + +Vp8FrameConfig::Vp8FrameConfig(BufferFlags last, + BufferFlags golden, + BufferFlags arf, + FreezeEntropy) + : Vp8FrameConfig(last, golden, arf, true) {} + +Vp8FrameConfig::Vp8FrameConfig(BufferFlags last, + BufferFlags golden, + BufferFlags arf, + bool freeze_entropy) + : drop_frame(last == BufferFlags::kNone && golden == BufferFlags::kNone && + arf == BufferFlags::kNone), + last_buffer_flags(last), + golden_buffer_flags(golden), + arf_buffer_flags(arf), + encoder_layer_id(0), + packetizer_temporal_idx(kNoTemporalIdx), + layer_sync(false), + freeze_entropy(freeze_entropy), + first_reference(Vp8BufferReference::kNone), + second_reference(Vp8BufferReference::kNone), + retransmission_allowed(true) {} + +bool Vp8FrameConfig::References(Buffer buffer) const { + switch (buffer) { + case Buffer::kLast: + return (last_buffer_flags & kReference) != 0; + case Buffer::kGolden: + return (golden_buffer_flags & kReference) != 0; + case Buffer::kArf: + return (arf_buffer_flags & kReference) != 0; + case Buffer::kCount: + break; + } + RTC_DCHECK_NOTREACHED(); + return false; +} + +bool Vp8FrameConfig::Updates(Buffer buffer) const { + switch (buffer) { + case Buffer::kLast: + return (last_buffer_flags & kUpdate) != 0; + case Buffer::kGolden: + return (golden_buffer_flags & kUpdate) != 0; + case Buffer::kArf: + return (arf_buffer_flags & kUpdate) != 0; + case Buffer::kCount: + break; + } + RTC_DCHECK_NOTREACHED(); + return false; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/vp8_frame_config.h b/third_party/libwebrtc/api/video_codecs/vp8_frame_config.h new file mode 100644 index 0000000000..5369bf58bc --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/vp8_frame_config.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2019 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 API_VIDEO_CODECS_VP8_FRAME_CONFIG_H_ +#define API_VIDEO_CODECS_VP8_FRAME_CONFIG_H_ + +#include <stdint.h> + +namespace webrtc { + +// Configuration of a VP8 frame - which buffers are to be referenced +// by it, which buffers should be updated, etc. +struct Vp8FrameConfig { + static Vp8FrameConfig GetIntraFrameConfig() { + Vp8FrameConfig frame_config = Vp8FrameConfig( + BufferFlags::kUpdate, BufferFlags::kUpdate, BufferFlags::kUpdate); + frame_config.packetizer_temporal_idx = 0; + return frame_config; + } + + enum BufferFlags : int { + kNone = 0, + kReference = 1, + kUpdate = 2, + kReferenceAndUpdate = kReference | kUpdate, + }; + + enum FreezeEntropy { kFreezeEntropy }; + + // Defined bit-maskable reference to the three buffers available in VP8. + enum class Vp8BufferReference : uint8_t { + kNone = 0, + kLast = 1, + kGolden = 2, + kAltref = 4 + }; + + Vp8FrameConfig(); + + Vp8FrameConfig(BufferFlags last, BufferFlags golden, BufferFlags arf); + Vp8FrameConfig(BufferFlags last, + BufferFlags golden, + BufferFlags arf, + FreezeEntropy); + + enum class Buffer : int { kLast = 0, kGolden = 1, kArf = 2, kCount }; + + bool References(Buffer buffer) const; + + bool Updates(Buffer buffer) const; + + bool IntraFrame() const { + // Intra frames do not reference any buffers, and update all buffers. + return last_buffer_flags == kUpdate && golden_buffer_flags == kUpdate && + arf_buffer_flags == kUpdate; + } + + bool drop_frame; + BufferFlags last_buffer_flags; + BufferFlags golden_buffer_flags; + BufferFlags arf_buffer_flags; + + // The encoder layer ID is used to utilize the correct bitrate allocator + // inside the encoder. It does not control references nor determine which + // "actual" temporal layer this is. The packetizer temporal index determines + // which layer the encoded frame should be packetized into. + // Normally these are the same, but current temporal-layer strategies for + // screenshare use one bitrate allocator for all layers, but attempt to + // packetize / utilize references to split a stream into multiple layers, + // with different quantizer settings, to hit target bitrate. + // TODO(sprang): Screenshare layers are being reconsidered at the time of + // writing, we might be able to remove this distinction, and have a temporal + // layer imply both (the normal case). + int encoder_layer_id; + // TODO(eladalon/sprang): Move out of this class. + int packetizer_temporal_idx; + + // TODO(eladalon/sprang): Move out of this class. + bool layer_sync; + + bool freeze_entropy; + + // Indicates in which order the encoder should search the reference buffers + // when doing motion prediction. Set to kNone to use unspecified order. Any + // buffer indicated here must not have the corresponding no_ref bit set. + // If all three buffers can be reference, the one not listed here should be + // searched last. + Vp8BufferReference first_reference; + Vp8BufferReference second_reference; + + // Whether this frame is eligible for retransmission. + bool retransmission_allowed; + + private: + Vp8FrameConfig(BufferFlags last, + BufferFlags golden, + BufferFlags arf, + bool freeze_entropy); +}; + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VP8_FRAME_CONFIG_H_ diff --git a/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers.cc b/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers.cc new file mode 100644 index 0000000000..dd75c616d8 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers.cc @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2019 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 "api/video_codecs/vp8_temporal_layers.h" + +#include <utility> + +#include "absl/algorithm/container.h" +#include "rtc_base/checks.h" + +namespace webrtc { + +Vp8TemporalLayers::Vp8TemporalLayers( + std::vector<std::unique_ptr<Vp8FrameBufferController>>&& controllers, + FecControllerOverride* fec_controller_override) + : controllers_(std::move(controllers)) { + RTC_DCHECK(!controllers_.empty()); + RTC_DCHECK(absl::c_none_of( + controllers_, + [](const std::unique_ptr<Vp8FrameBufferController>& controller) { + return controller.get() == nullptr; + })); + if (fec_controller_override) { + fec_controller_override->SetFecAllowed(true); + } +} + +void Vp8TemporalLayers::SetQpLimits(size_t stream_index, + int min_qp, + int max_qp) { + RTC_DCHECK_LT(stream_index, controllers_.size()); + return controllers_[stream_index]->SetQpLimits(0, min_qp, max_qp); +} + +size_t Vp8TemporalLayers::StreamCount() const { + return controllers_.size(); +} + +bool Vp8TemporalLayers::SupportsEncoderFrameDropping( + size_t stream_index) const { + RTC_DCHECK_LT(stream_index, controllers_.size()); + return controllers_[stream_index]->SupportsEncoderFrameDropping(0); +} + +void Vp8TemporalLayers::OnRatesUpdated( + size_t stream_index, + const std::vector<uint32_t>& bitrates_bps, + int framerate_fps) { + RTC_DCHECK_LT(stream_index, controllers_.size()); + return controllers_[stream_index]->OnRatesUpdated(0, bitrates_bps, + framerate_fps); +} + +Vp8EncoderConfig Vp8TemporalLayers::UpdateConfiguration(size_t stream_index) { + RTC_DCHECK_LT(stream_index, controllers_.size()); + return controllers_[stream_index]->UpdateConfiguration(0); +} + +Vp8FrameConfig Vp8TemporalLayers::NextFrameConfig(size_t stream_index, + uint32_t rtp_timestamp) { + RTC_DCHECK_LT(stream_index, controllers_.size()); + return controllers_[stream_index]->NextFrameConfig(0, rtp_timestamp); +} + +void Vp8TemporalLayers::OnEncodeDone(size_t stream_index, + uint32_t rtp_timestamp, + size_t size_bytes, + bool is_keyframe, + int qp, + CodecSpecificInfo* info) { + RTC_DCHECK_LT(stream_index, controllers_.size()); + return controllers_[stream_index]->OnEncodeDone(0, rtp_timestamp, size_bytes, + is_keyframe, qp, info); +} + +void Vp8TemporalLayers::OnFrameDropped(size_t stream_index, + uint32_t rtp_timestamp) { + RTC_DCHECK_LT(stream_index, controllers_.size()); + controllers_[stream_index]->OnFrameDropped(stream_index, rtp_timestamp); +} + +void Vp8TemporalLayers::OnPacketLossRateUpdate(float packet_loss_rate) { + for (auto& controller : controllers_) { + controller->OnPacketLossRateUpdate(packet_loss_rate); + } +} + +void Vp8TemporalLayers::OnRttUpdate(int64_t rtt_ms) { + for (auto& controller : controllers_) { + controller->OnRttUpdate(rtt_ms); + } +} + +void Vp8TemporalLayers::OnLossNotification( + const VideoEncoder::LossNotification& loss_notification) { + for (auto& controller : controllers_) { + controller->OnLossNotification(loss_notification); + } +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers.h b/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers.h new file mode 100644 index 0000000000..2ffe6eacdf --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers.h @@ -0,0 +1,77 @@ +/* + * 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. + */ + +#ifndef API_VIDEO_CODECS_VP8_TEMPORAL_LAYERS_H_ +#define API_VIDEO_CODECS_VP8_TEMPORAL_LAYERS_H_ + +#include <memory> +#include <vector> + +#include "api/fec_controller_override.h" +#include "api/video_codecs/video_codec.h" +#include "api/video_codecs/vp8_frame_buffer_controller.h" +#include "api/video_codecs/vp8_frame_config.h" + +namespace webrtc { + +// Two different flavors of temporal layers are currently available: +// kFixedPattern uses a fixed repeating pattern of 1-4 layers. +// kBitrateDynamic can allocate frames dynamically to 1 or 2 layers, based on +// the bitrate produced. +// TODO(eladalon): Remove this enum. +enum class Vp8TemporalLayersType { kFixedPattern, kBitrateDynamic }; + +// This interface defines a way of getting the encoder settings needed to +// realize a temporal layer structure. +class Vp8TemporalLayers final : public Vp8FrameBufferController { + public: + Vp8TemporalLayers( + std::vector<std::unique_ptr<Vp8FrameBufferController>>&& controllers, + FecControllerOverride* fec_controller_override); + ~Vp8TemporalLayers() override = default; + + void SetQpLimits(size_t stream_index, int min_qp, int max_qp) override; + + size_t StreamCount() const override; + + bool SupportsEncoderFrameDropping(size_t stream_index) const override; + + void OnRatesUpdated(size_t stream_index, + const std::vector<uint32_t>& bitrates_bps, + int framerate_fps) override; + + Vp8EncoderConfig UpdateConfiguration(size_t stream_index) override; + + Vp8FrameConfig NextFrameConfig(size_t stream_index, + uint32_t rtp_timestamp) override; + + void OnEncodeDone(size_t stream_index, + uint32_t rtp_timestamp, + size_t size_bytes, + bool is_keyframe, + int qp, + CodecSpecificInfo* info) override; + + void OnFrameDropped(size_t stream_index, uint32_t rtp_timestamp) override; + + void OnPacketLossRateUpdate(float packet_loss_rate) override; + + void OnRttUpdate(int64_t rtt_ms) override; + + void OnLossNotification( + const VideoEncoder::LossNotification& loss_notification) override; + + private: + std::vector<std::unique_ptr<Vp8FrameBufferController>> controllers_; +}; + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VP8_TEMPORAL_LAYERS_H_ diff --git a/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers_factory.cc b/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers_factory.cc new file mode 100644 index 0000000000..193494d71d --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers_factory.cc @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019 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 "api/video_codecs/vp8_temporal_layers_factory.h" + +#include <algorithm> +#include <memory> +#include <utility> +#include <vector> + +#include "api/fec_controller_override.h" +#include "modules/video_coding/codecs/vp8/default_temporal_layers.h" +#include "modules/video_coding/codecs/vp8/screenshare_layers.h" +#include "modules/video_coding/utility/simulcast_utility.h" +#include "rtc_base/checks.h" + +namespace webrtc { + +std::unique_ptr<Vp8FrameBufferController> Vp8TemporalLayersFactory::Create( + const VideoCodec& codec, + const VideoEncoder::Settings& settings, + FecControllerOverride* fec_controller_override) { + std::vector<std::unique_ptr<Vp8FrameBufferController>> controllers; + const int num_streams = SimulcastUtility::NumberOfSimulcastStreams(codec); + RTC_DCHECK_GE(num_streams, 1); + controllers.reserve(num_streams); + + for (int i = 0; i < num_streams; ++i) { + int num_temporal_layers = + SimulcastUtility::NumberOfTemporalLayers(codec, i); + RTC_DCHECK_GE(num_temporal_layers, 1); + if (SimulcastUtility::IsConferenceModeScreenshare(codec) && i == 0) { + // Legacy screenshare layers supports max 2 layers. + num_temporal_layers = std::max(2, num_temporal_layers); + controllers.push_back( + std::make_unique<ScreenshareLayers>(num_temporal_layers)); + } else { + controllers.push_back( + std::make_unique<DefaultTemporalLayers>(num_temporal_layers)); + } + } + + return std::make_unique<Vp8TemporalLayers>(std::move(controllers), + fec_controller_override); +} + +std::unique_ptr<Vp8FrameBufferControllerFactory> +Vp8TemporalLayersFactory::Clone() const { + return std::make_unique<Vp8TemporalLayersFactory>(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers_factory.h b/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers_factory.h new file mode 100644 index 0000000000..7a146f1d4f --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers_factory.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 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 API_VIDEO_CODECS_VP8_TEMPORAL_LAYERS_FACTORY_H_ +#define API_VIDEO_CODECS_VP8_TEMPORAL_LAYERS_FACTORY_H_ + +#include <memory> + +#include "api/video_codecs/vp8_temporal_layers.h" + +namespace webrtc { + +class Vp8TemporalLayersFactory : public Vp8FrameBufferControllerFactory { + public: + ~Vp8TemporalLayersFactory() override = default; + + std::unique_ptr<Vp8FrameBufferControllerFactory> Clone() const override; + + std::unique_ptr<Vp8FrameBufferController> Create( + const VideoCodec& codec, + const VideoEncoder::Settings& settings, + FecControllerOverride* fec_controller_override) override; +}; + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VP8_TEMPORAL_LAYERS_FACTORY_H_ diff --git a/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers_factory_gn/moz.build b/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers_factory_gn/moz.build new file mode 100644 index 0000000000..2769bef0eb --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers_factory_gn/moz.build @@ -0,0 +1,232 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +UNIFIED_SOURCES += [ + "/third_party/libwebrtc/api/video_codecs/vp8_temporal_layers_factory.cc" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "log" + ] + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + + OS_LIBS += [ + "rt" + ] + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + + OS_LIBS += [ + "crypt32", + "iphlpapi", + "secur32", + "winmm" + ] + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + CXXFLAGS += [ + "-mfpu=neon" + ] + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + CXXFLAGS += [ + "-msse2" + ] + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + CXXFLAGS += [ + "-msse2" + ] + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("vp8_temporal_layers_factory_gn") diff --git a/third_party/libwebrtc/api/video_codecs/vp9_profile.cc b/third_party/libwebrtc/api/video_codecs/vp9_profile.cc new file mode 100644 index 0000000000..7e627cc080 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/vp9_profile.cc @@ -0,0 +1,73 @@ +/* + * 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 "api/video_codecs/vp9_profile.h" + +#include <map> +#include <utility> + +#include "rtc_base/string_to_number.h" + +namespace webrtc { + +// Profile information for VP9 video. +const char kVP9FmtpProfileId[] = "profile-id"; + +std::string VP9ProfileToString(VP9Profile profile) { + switch (profile) { + case VP9Profile::kProfile0: + return "0"; + case VP9Profile::kProfile1: + return "1"; + case VP9Profile::kProfile2: + return "2"; + case VP9Profile::kProfile3: + return "3"; + } + return "0"; +} + +absl::optional<VP9Profile> StringToVP9Profile(const std::string& str) { + const absl::optional<int> i = rtc::StringToNumber<int>(str); + if (!i.has_value()) + return absl::nullopt; + + switch (i.value()) { + case 0: + return VP9Profile::kProfile0; + case 1: + return VP9Profile::kProfile1; + case 2: + return VP9Profile::kProfile2; + case 3: + return VP9Profile::kProfile3; + default: + return absl::nullopt; + } +} + +absl::optional<VP9Profile> ParseSdpForVP9Profile( + const SdpVideoFormat::Parameters& params) { + const auto profile_it = params.find(kVP9FmtpProfileId); + if (profile_it == params.end()) + return VP9Profile::kProfile0; + const std::string& profile_str = profile_it->second; + return StringToVP9Profile(profile_str); +} + +bool VP9IsSameProfile(const SdpVideoFormat::Parameters& params1, + const SdpVideoFormat::Parameters& params2) { + const absl::optional<VP9Profile> profile = ParseSdpForVP9Profile(params1); + const absl::optional<VP9Profile> other_profile = + ParseSdpForVP9Profile(params2); + return profile && other_profile && profile == other_profile; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/video_codecs/vp9_profile.h b/third_party/libwebrtc/api/video_codecs/vp9_profile.h new file mode 100644 index 0000000000..b570bc3bb6 --- /dev/null +++ b/third_party/libwebrtc/api/video_codecs/vp9_profile.h @@ -0,0 +1,54 @@ +/* + * 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 API_VIDEO_CODECS_VP9_PROFILE_H_ +#define API_VIDEO_CODECS_VP9_PROFILE_H_ + +#include <string> + +#include "absl/types/optional.h" +#include "api/video_codecs/sdp_video_format.h" +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Profile information for VP9 video. +extern RTC_EXPORT const char kVP9FmtpProfileId[]; + +enum class VP9Profile { + kProfile0, + kProfile1, + kProfile2, + kProfile3, +}; + +// Helper functions to convert VP9Profile to std::string. Returns "0" by +// default. +RTC_EXPORT std::string VP9ProfileToString(VP9Profile profile); + +// Helper functions to convert std::string to VP9Profile. Returns null if given +// an invalid profile string. +absl::optional<VP9Profile> StringToVP9Profile(const std::string& str); + +// Parse profile that is represented as a string of single digit contained in an +// SDP key-value map. A default profile(kProfile0) will be returned if the +// profile key is missing. Nothing will be returned if the key is present but +// the string is invalid. +RTC_EXPORT absl::optional<VP9Profile> ParseSdpForVP9Profile( + const SdpVideoFormat::Parameters& params); + +// Returns true if the parameters have the same VP9 profile, or neither contains +// VP9 profile. +bool VP9IsSameProfile(const SdpVideoFormat::Parameters& params1, + const SdpVideoFormat::Parameters& params2); + +} // namespace webrtc + +#endif // API_VIDEO_CODECS_VP9_PROFILE_H_ diff --git a/third_party/libwebrtc/api/video_track_source_constraints.h b/third_party/libwebrtc/api/video_track_source_constraints.h new file mode 100644 index 0000000000..55e5396d62 --- /dev/null +++ b/third_party/libwebrtc/api/video_track_source_constraints.h @@ -0,0 +1,32 @@ +/* + * Copyright 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. + */ + +// This file contains interfaces for MediaStream, MediaTrack and MediaSource. +// These interfaces are used for implementing MediaStream and MediaTrack as +// defined in http://dev.w3.org/2011/webrtc/editor/webrtc.html#stream-api. These +// interfaces must be used only with PeerConnection. + +#ifndef API_VIDEO_TRACK_SOURCE_CONSTRAINTS_H_ +#define API_VIDEO_TRACK_SOURCE_CONSTRAINTS_H_ + +#include "absl/types/optional.h" + +namespace webrtc { + +// This struct definition describes constraints on the video source that may be +// set with VideoTrackSourceInterface::ProcessConstraints. +struct VideoTrackSourceConstraints { + absl::optional<double> min_fps; + absl::optional<double> max_fps; +}; + +} // namespace webrtc + +#endif // API_VIDEO_TRACK_SOURCE_CONSTRAINTS_H_ diff --git a/third_party/libwebrtc/api/video_track_source_constraints_gn/moz.build b/third_party/libwebrtc/api/video_track_source_constraints_gn/moz.build new file mode 100644 index 0000000000..77f7ba4d70 --- /dev/null +++ b/third_party/libwebrtc/api/video_track_source_constraints_gn/moz.build @@ -0,0 +1,201 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ### + ### DO NOT edit it by hand. ### + +COMPILE_FLAGS["OS_INCLUDES"] = [] +AllowCompilerWarnings() + +DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1" +DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True +DEFINES["RTC_ENABLE_VP9"] = True +DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0" +DEFINES["WEBRTC_LIBRARY_IMPL"] = True +DEFINES["WEBRTC_MOZILLA_BUILD"] = True +DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0" +DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0" + +FINAL_LIBRARY = "webrtc" + + +LOCAL_INCLUDES += [ + "!/ipc/ipdl/_ipdlheaders", + "!/third_party/libwebrtc/gen", + "/ipc/chromium/src", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/tools/profiler/public" +] + +if not CONFIG["MOZ_DEBUG"]: + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0" + DEFINES["NDEBUG"] = True + DEFINES["NVALGRIND"] = True + +if CONFIG["MOZ_DEBUG"] == "1": + + DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1" + +if CONFIG["OS_TARGET"] == "Android": + + DEFINES["ANDROID"] = True + DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1" + DEFINES["HAVE_SYS_UIO_H"] = True + DEFINES["WEBRTC_ANDROID"] = True + DEFINES["WEBRTC_ANDROID_OPENSLES"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_GNU_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["WEBRTC_MAC"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True + DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0" + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_AURA"] = "1" + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_NSS_CERTS"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_UDEV"] = True + DEFINES["WEBRTC_LINUX"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["USE_GLIB"] = "1" + DEFINES["USE_OZONE"] = "1" + DEFINES["USE_X11"] = "1" + DEFINES["WEBRTC_BSD"] = True + DEFINES["WEBRTC_POSIX"] = True + DEFINES["_FILE_OFFSET_BITS"] = "64" + DEFINES["_LARGEFILE64_SOURCE"] = True + DEFINES["_LARGEFILE_SOURCE"] = True + DEFINES["__STDC_CONSTANT_MACROS"] = True + DEFINES["__STDC_FORMAT_MACROS"] = True + +if CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True + DEFINES["NOMINMAX"] = True + DEFINES["NTDDI_VERSION"] = "0x0A000000" + DEFINES["PSAPI_VERSION"] = "2" + DEFINES["UNICODE"] = True + DEFINES["USE_AURA"] = "1" + DEFINES["WEBRTC_WIN"] = True + DEFINES["WIN32"] = True + DEFINES["WIN32_LEAN_AND_MEAN"] = True + DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP" + DEFINES["WINVER"] = "0x0A00" + DEFINES["_ATL_NO_OPENGL"] = True + DEFINES["_CRT_RAND_S"] = True + DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True + DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True + DEFINES["_HAS_EXCEPTIONS"] = "0" + DEFINES["_HAS_NODISCARD"] = True + DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True + DEFINES["_SECURE_ATL"] = True + DEFINES["_UNICODE"] = True + DEFINES["_WIN32_WINNT"] = "0x0A00" + DEFINES["_WINDOWS"] = True + DEFINES["__STD_C"] = True + +if CONFIG["CPU_ARCH"] == "aarch64": + + DEFINES["WEBRTC_ARCH_ARM64"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "arm": + + DEFINES["WEBRTC_ARCH_ARM"] = True + DEFINES["WEBRTC_ARCH_ARM_V7"] = True + DEFINES["WEBRTC_HAS_NEON"] = True + +if CONFIG["CPU_ARCH"] == "mips32": + + DEFINES["MIPS32_LE"] = True + DEFINES["MIPS_FPU_LE"] = True + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "mips64": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["CPU_ARCH"] == "x86_64": + + DEFINES["WEBRTC_ENABLE_AVX2"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD": + + DEFINES["_DEBUG"] = True + +if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT": + + DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0" + +if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["USE_X11"] = "1" + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support", + "unwind" + ] + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android": + + OS_LIBS += [ + "android_support" + ] + +if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": + + DEFINES["_GNU_SOURCE"] = True + +Library("video_track_source_constraints_gn") diff --git a/third_party/libwebrtc/api/video_track_source_proxy_factory.h b/third_party/libwebrtc/api/video_track_source_proxy_factory.h new file mode 100644 index 0000000000..eb6e96429a --- /dev/null +++ b/third_party/libwebrtc/api/video_track_source_proxy_factory.h @@ -0,0 +1,29 @@ +/* + * Copyright 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 API_VIDEO_TRACK_SOURCE_PROXY_FACTORY_H_ +#define API_VIDEO_TRACK_SOURCE_PROXY_FACTORY_H_ + +#include "api/media_stream_interface.h" +#include "rtc_base/thread.h" + +namespace webrtc { + +// Creates a proxy source for `source` which makes sure the real +// VideoTrackSourceInterface implementation is destroyed on the signaling thread +// and marshals calls to `worker_thread` and `signaling_thread`. +rtc::scoped_refptr<VideoTrackSourceInterface> RTC_EXPORT +CreateVideoTrackSourceProxy(rtc::Thread* signaling_thread, + rtc::Thread* worker_thread, + VideoTrackSourceInterface* source); + +} // namespace webrtc + +#endif // API_VIDEO_TRACK_SOURCE_PROXY_FACTORY_H_ diff --git a/third_party/libwebrtc/api/voip/BUILD.gn b/third_party/libwebrtc/api/voip/BUILD.gn new file mode 100644 index 0000000000..714490a526 --- /dev/null +++ b/third_party/libwebrtc/api/voip/BUILD.gn @@ -0,0 +1,85 @@ +# Copyright(c) 2020 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") + +rtc_source_set("voip_api") { + visibility = [ "*" ] + sources = [ + "voip_base.h", + "voip_codec.h", + "voip_dtmf.h", + "voip_engine.h", + "voip_network.h", + "voip_statistics.h", + "voip_volume_control.h", + ] + deps = [ + "..:array_view", + "../audio_codecs:audio_codecs_api", + "../neteq:neteq_api", + ] + absl_deps = [ + "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_library("voip_engine_factory") { + visibility = [ "*" ] + sources = [ + "voip_engine_factory.cc", + "voip_engine_factory.h", + ] + deps = [ + ":voip_api", + "..:scoped_refptr", + "../../audio/voip:voip_core", + "../../modules/audio_device:audio_device_api", + "../../modules/audio_processing:api", + "../../rtc_base:logging", + "../audio_codecs:audio_codecs_api", + "../task_queue", + ] +} + +if (rtc_include_tests) { + rtc_source_set("mock_voip_engine") { + testonly = true + visibility = [ "*" ] + sources = [ "test/mock_voip_engine.h" ] + deps = [ + ":voip_api", + "..:array_view", + "../../test:test_support", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] + } + + rtc_library("voip_engine_factory_unittests") { + testonly = true + sources = [ "test/voip_engine_factory_unittest.cc" ] + deps = [ + ":voip_engine_factory", + "../../modules/audio_device:mock_audio_device", + "../../modules/audio_processing:mocks", + "../../test:audio_codec_mocks", + "../../test:test_support", + "../task_queue:default_task_queue_factory", + ] + } + + rtc_library("compile_all_headers") { + testonly = true + sources = [ "test/compile_all_headers.cc" ] + deps = [ + ":mock_voip_engine", + "../../test:test_support", + ] + } +} diff --git a/third_party/libwebrtc/api/voip/DEPS b/third_party/libwebrtc/api/voip/DEPS new file mode 100644 index 0000000000..3845dffab0 --- /dev/null +++ b/third_party/libwebrtc/api/voip/DEPS @@ -0,0 +1,10 @@ +specific_include_rules = { + ".*\.h": [ + "+third_party/absl/types/optional.h", + ], + + "voip_engine_factory.h": [ + "+modules/audio_device/include/audio_device.h", + "+modules/audio_processing/include/audio_processing.h", + ], +} diff --git a/third_party/libwebrtc/api/voip/test/compile_all_headers.cc b/third_party/libwebrtc/api/voip/test/compile_all_headers.cc new file mode 100644 index 0000000000..73a0f0d1c4 --- /dev/null +++ b/third_party/libwebrtc/api/voip/test/compile_all_headers.cc @@ -0,0 +1,14 @@ +/* + * 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. + */ + +// This file verifies that all include files in this directory can be +// compiled without errors or other required includes. + +#include "api/voip/test/mock_voip_engine.h" diff --git a/third_party/libwebrtc/api/voip/test/mock_voip_engine.h b/third_party/libwebrtc/api/voip/test/mock_voip_engine.h new file mode 100644 index 0000000000..74b880d652 --- /dev/null +++ b/third_party/libwebrtc/api/voip/test/mock_voip_engine.h @@ -0,0 +1,124 @@ +/* + * 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 API_VOIP_TEST_MOCK_VOIP_ENGINE_H_ +#define API_VOIP_TEST_MOCK_VOIP_ENGINE_H_ + +#include <map> + +#include "absl/types/optional.h" +#include "api/array_view.h" +#include "api/voip/voip_base.h" +#include "api/voip/voip_codec.h" +#include "api/voip/voip_dtmf.h" +#include "api/voip/voip_engine.h" +#include "api/voip/voip_network.h" +#include "api/voip/voip_statistics.h" +#include "api/voip/voip_volume_control.h" +#include "test/gmock.h" + +namespace webrtc { + +class MockVoipBase : public VoipBase { + public: + MOCK_METHOD(ChannelId, + CreateChannel, + (Transport*, absl::optional<uint32_t>), + (override)); + MOCK_METHOD(VoipResult, ReleaseChannel, (ChannelId), (override)); + MOCK_METHOD(VoipResult, StartSend, (ChannelId), (override)); + MOCK_METHOD(VoipResult, StopSend, (ChannelId), (override)); + MOCK_METHOD(VoipResult, StartPlayout, (ChannelId), (override)); + MOCK_METHOD(VoipResult, StopPlayout, (ChannelId), (override)); +}; + +class MockVoipCodec : public VoipCodec { + public: + MOCK_METHOD(VoipResult, + SetSendCodec, + (ChannelId, int, const SdpAudioFormat&), + (override)); + MOCK_METHOD(VoipResult, + SetReceiveCodecs, + (ChannelId, (const std::map<int, SdpAudioFormat>&)), + (override)); +}; + +class MockVoipDtmf : public VoipDtmf { + public: + MOCK_METHOD(VoipResult, + RegisterTelephoneEventType, + (ChannelId, int, int), + (override)); + MOCK_METHOD(VoipResult, + SendDtmfEvent, + (ChannelId, DtmfEvent, int), + (override)); +}; + +class MockVoipNetwork : public VoipNetwork { + public: + MOCK_METHOD(VoipResult, + ReceivedRTPPacket, + (ChannelId channel_id, rtc::ArrayView<const uint8_t> rtp_packet), + (override)); + MOCK_METHOD(VoipResult, + ReceivedRTCPPacket, + (ChannelId channel_id, rtc::ArrayView<const uint8_t> rtcp_packet), + (override)); +}; + +class MockVoipStatistics : public VoipStatistics { + public: + MOCK_METHOD(VoipResult, + GetIngressStatistics, + (ChannelId, IngressStatistics&), + (override)); + MOCK_METHOD(VoipResult, + GetChannelStatistics, + (ChannelId channel_id, ChannelStatistics&), + (override)); +}; + +class MockVoipVolumeControl : public VoipVolumeControl { + public: + MOCK_METHOD(VoipResult, SetInputMuted, (ChannelId, bool), (override)); + + MOCK_METHOD(VoipResult, + GetInputVolumeInfo, + (ChannelId, VolumeInfo&), + (override)); + MOCK_METHOD(VoipResult, + GetOutputVolumeInfo, + (ChannelId, VolumeInfo&), + (override)); +}; + +class MockVoipEngine : public VoipEngine { + public: + VoipBase& Base() override { return base_; } + VoipNetwork& Network() override { return network_; } + VoipCodec& Codec() override { return codec_; } + VoipDtmf& Dtmf() override { return dtmf_; } + VoipStatistics& Statistics() override { return statistics_; } + VoipVolumeControl& VolumeControl() override { return volume_; } + + // Direct access to underlying members are required for testing. + MockVoipBase base_; + MockVoipNetwork network_; + MockVoipCodec codec_; + MockVoipDtmf dtmf_; + MockVoipStatistics statistics_; + MockVoipVolumeControl volume_; +}; + +} // namespace webrtc + +#endif // API_VOIP_TEST_MOCK_VOIP_ENGINE_H_ diff --git a/third_party/libwebrtc/api/voip/test/voip_engine_factory_unittest.cc b/third_party/libwebrtc/api/voip/test/voip_engine_factory_unittest.cc new file mode 100644 index 0000000000..f967a0ba8f --- /dev/null +++ b/third_party/libwebrtc/api/voip/test/voip_engine_factory_unittest.cc @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020 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 <utility> + +#include "api/task_queue/default_task_queue_factory.h" +#include "api/voip/voip_engine_factory.h" +#include "modules/audio_device/include/mock_audio_device.h" +#include "modules/audio_processing/include/mock_audio_processing.h" +#include "test/gtest.h" +#include "test/mock_audio_decoder_factory.h" +#include "test/mock_audio_encoder_factory.h" + +namespace webrtc { +namespace { + +// Create voip engine with mock modules as normal use case. +TEST(VoipEngineFactoryTest, CreateEngineWithMockModules) { + VoipEngineConfig config; + config.encoder_factory = rtc::make_ref_counted<MockAudioEncoderFactory>(); + config.decoder_factory = rtc::make_ref_counted<MockAudioDecoderFactory>(); + config.task_queue_factory = CreateDefaultTaskQueueFactory(); + config.audio_processing = + rtc::make_ref_counted<testing::NiceMock<test::MockAudioProcessing>>(); + config.audio_device_module = test::MockAudioDeviceModule::CreateNice(); + + auto voip_engine = CreateVoipEngine(std::move(config)); + EXPECT_NE(voip_engine, nullptr); +} + +// Create voip engine without setting audio processing as optional component. +TEST(VoipEngineFactoryTest, UseNoAudioProcessing) { + VoipEngineConfig config; + config.encoder_factory = rtc::make_ref_counted<MockAudioEncoderFactory>(); + config.decoder_factory = rtc::make_ref_counted<MockAudioDecoderFactory>(); + config.task_queue_factory = CreateDefaultTaskQueueFactory(); + config.audio_device_module = test::MockAudioDeviceModule::CreateNice(); + + auto voip_engine = CreateVoipEngine(std::move(config)); + EXPECT_NE(voip_engine, nullptr); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/api/voip/voip_base.h b/third_party/libwebrtc/api/voip/voip_base.h new file mode 100644 index 0000000000..8df7bd0571 --- /dev/null +++ b/third_party/libwebrtc/api/voip/voip_base.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2020 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 API_VOIP_VOIP_BASE_H_ +#define API_VOIP_VOIP_BASE_H_ + +#include "absl/base/attributes.h" +#include "absl/types/optional.h" + +namespace webrtc { + +class Transport; + +// VoipBase interface +// +// VoipBase provides a management interface on a media session using a +// concept called 'channel'. A channel represents an interface handle +// for application to request various media session operations. This +// notion of channel is used throughout other interfaces as well. +// +// Underneath the interface, a channel id is mapped into an audio session +// object that is capable of sending and receiving a single RTP stream with +// another media endpoint. It's possible to create and use multiple active +// channels simultaneously which would mean that particular application +// session has RTP streams with multiple remote endpoints. +// +// A typical example for the usage context is outlined in VoipEngine +// header file. + +enum class ChannelId : int {}; + +enum class ABSL_MUST_USE_RESULT VoipResult { + // kOk indicates the function was successfully invoked with no error. + kOk, + // kInvalidArgument indicates the caller specified an invalid argument, such + // as an invalid ChannelId. + kInvalidArgument, + // kFailedPrecondition indicates that the operation was failed due to not + // satisfying prerequisite such as not setting codec type before sending. + kFailedPrecondition, + // kInternal is used to indicate various internal failures that are not the + // caller's fault. Further detail is commented on each function that uses this + // return value. + kInternal, +}; + +class VoipBase { + public: + // Creates a channel. + // Each channel handle maps into one audio media session where each has + // its own separate module for send/receive rtp packet with one peer. + // Caller must set `transport`, webrtc::Transport callback pointer to + // receive rtp/rtcp packets from corresponding media session in VoIP engine. + // VoipEngine framework expects applications to handle network I/O directly + // and injection for incoming RTP from remote endpoint is handled via + // VoipNetwork interface. `local_ssrc` is optional and when local_ssrc is not + // set, some random value will be used by voip engine. + // Returns a ChannelId created for caller to handle subsequent Channel + // operations. + virtual ChannelId CreateChannel(Transport* transport, + absl::optional<uint32_t> local_ssrc) = 0; + + // Releases `channel_id` that no longer has any use. + // Returns following VoipResult; + // kOk - `channel_id` is released. + // kInvalidArgument - `channel_id` is invalid. + // kInternal - Fails to stop audio output device. + virtual VoipResult ReleaseChannel(ChannelId channel_id) = 0; + + // Starts sending on `channel_id`. This starts microphone if not started yet. + // Returns following VoipResult; + // kOk - Channel successfully started to send. + // kInvalidArgument - `channel_id` is invalid. + // kFailedPrecondition - Missing prerequisite on VoipCodec::SetSendCodec. + // kInternal - initialization has failed on selected microphone. + virtual VoipResult StartSend(ChannelId channel_id) = 0; + + // Stops sending on `channel_id`. If this is the last active channel, it will + // stop microphone input from underlying audio platform layer. + // Returns following VoipResult; + // kOk - Channel successfully stopped to send. + // kInvalidArgument - `channel_id` is invalid. + // kInternal - Failed to stop the active microphone device. + virtual VoipResult StopSend(ChannelId channel_id) = 0; + + // Starts playing on speaker device for `channel_id`. + // This will start underlying platform speaker device if not started. + // Returns following VoipResult; + // kOk - Channel successfully started to play out. + // kInvalidArgument - `channel_id` is invalid. + // kFailedPrecondition - Missing prerequisite on VoipCodec::SetReceiveCodecs. + // kInternal - Failed to initializate the selected speaker device. + virtual VoipResult StartPlayout(ChannelId channel_id) = 0; + + // Stops playing on speaker device for `channel_id`. + // Returns following VoipResult; + // kOk - Channel successfully stopped t play out. + // kInvalidArgument - `channel_id` is invalid. + virtual VoipResult StopPlayout(ChannelId channel_id) = 0; + + protected: + virtual ~VoipBase() = default; +}; + +} // namespace webrtc + +#endif // API_VOIP_VOIP_BASE_H_ diff --git a/third_party/libwebrtc/api/voip/voip_codec.h b/third_party/libwebrtc/api/voip/voip_codec.h new file mode 100644 index 0000000000..46cddfad6c --- /dev/null +++ b/third_party/libwebrtc/api/voip/voip_codec.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020 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 API_VOIP_VOIP_CODEC_H_ +#define API_VOIP_VOIP_CODEC_H_ + +#include <map> + +#include "api/audio_codecs/audio_format.h" +#include "api/voip/voip_base.h" + +namespace webrtc { + +// VoipCodec interface currently provides any codec related interface +// such as setting encoder and decoder types that are negotiated with +// remote endpoint. Typically after SDP offer and answer exchange, +// the local endpoint understands what are the codec payload types that +// are used with negotiated codecs. This interface is subject to expand +// as needed in future. +// +// This interface requires a channel id created via VoipBase interface. +class VoipCodec { + public: + // Set encoder type here along with its payload type to use. + // Returns following VoipResult; + // kOk - sending codec is set as provided. + // kInvalidArgument - `channel_id` is invalid. + virtual VoipResult SetSendCodec(ChannelId channel_id, + int payload_type, + const SdpAudioFormat& encoder_spec) = 0; + + // Set decoder payload type here. In typical offer and answer model, + // this should be called after payload type has been agreed in media + // session. Note that payload type can differ with same codec in each + // direction. + // Returns following VoipResult; + // kOk - receiving codecs are set as provided. + // kInvalidArgument - `channel_id` is invalid. + virtual VoipResult SetReceiveCodecs( + ChannelId channel_id, + const std::map<int, SdpAudioFormat>& decoder_specs) = 0; + + protected: + virtual ~VoipCodec() = default; +}; + +} // namespace webrtc + +#endif // API_VOIP_VOIP_CODEC_H_ diff --git a/third_party/libwebrtc/api/voip/voip_dtmf.h b/third_party/libwebrtc/api/voip/voip_dtmf.h new file mode 100644 index 0000000000..ef7ea28c94 --- /dev/null +++ b/third_party/libwebrtc/api/voip/voip_dtmf.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020 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 API_VOIP_VOIP_DTMF_H_ +#define API_VOIP_VOIP_DTMF_H_ + +#include "api/voip/voip_base.h" + +namespace webrtc { + +// DTMF events and their event codes as defined in +// https://tools.ietf.org/html/rfc4733#section-7 +enum class DtmfEvent : uint8_t { + kDigitZero = 0, + kDigitOne, + kDigitTwo, + kDigitThree, + kDigitFour, + kDigitFive, + kDigitSix, + kDigitSeven, + kDigitEight, + kDigitNine, + kAsterisk, + kHash, + kLetterA, + kLetterB, + kLetterC, + kLetterD +}; + +// VoipDtmf interface provides DTMF related interfaces such +// as sending DTMF events to the remote endpoint. +class VoipDtmf { + public: + // Register the payload type and sample rate for DTMF (RFC 4733) payload. + // Must be called exactly once prior to calling SendDtmfEvent after payload + // type has been negotiated with remote. + // Returns following VoipResult; + // kOk - telephone event type is registered as provided. + // kInvalidArgument - `channel_id` is invalid. + virtual VoipResult RegisterTelephoneEventType(ChannelId channel_id, + int rtp_payload_type, + int sample_rate_hz) = 0; + + // Send DTMF named event as specified by + // https://tools.ietf.org/html/rfc4733#section-3.2 + // `duration_ms` specifies the duration of DTMF packets that will be emitted + // in place of real RTP packets instead. + // Must be called after RegisterTelephoneEventType and VoipBase::StartSend + // have been called. + // Returns following VoipResult; + // kOk - requested DTMF event is successfully scheduled. + // kInvalidArgument - `channel_id` is invalid. + // kFailedPrecondition - Missing prerequisite on RegisterTelephoneEventType + // or sending state. + virtual VoipResult SendDtmfEvent(ChannelId channel_id, + DtmfEvent dtmf_event, + int duration_ms) = 0; + + protected: + virtual ~VoipDtmf() = default; +}; + +} // namespace webrtc + +#endif // API_VOIP_VOIP_DTMF_H_ diff --git a/third_party/libwebrtc/api/voip/voip_engine.h b/third_party/libwebrtc/api/voip/voip_engine.h new file mode 100644 index 0000000000..d223f6ad6c --- /dev/null +++ b/third_party/libwebrtc/api/voip/voip_engine.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020 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 API_VOIP_VOIP_ENGINE_H_ +#define API_VOIP_VOIP_ENGINE_H_ + +namespace webrtc { + +class VoipBase; +class VoipCodec; +class VoipNetwork; +class VoipDtmf; +class VoipStatistics; +class VoipVolumeControl; + +// VoipEngine is the main interface serving as the entry point for all VoIP +// APIs. A single instance of VoipEngine should suffice the most of the need for +// typical VoIP applications as it handles multiple media sessions including a +// specialized session type like ad-hoc conference. Below example code +// describes the typical sequence of API usage. Each API header contains more +// description on what the methods are used for. +// +// // Caller is responsible of setting desired audio components. +// VoipEngineConfig config; +// config.encoder_factory = CreateBuiltinAudioEncoderFactory(); +// config.decoder_factory = CreateBuiltinAudioDecoderFactory(); +// config.task_queue_factory = CreateDefaultTaskQueueFactory(); +// config.audio_device = +// AudioDeviceModule::Create(AudioDeviceModule::kPlatformDefaultAudio, +// config.task_queue_factory.get()); +// config.audio_processing = AudioProcessingBuilder().Create(); +// +// auto voip_engine = CreateVoipEngine(std::move(config)); +// +// auto& voip_base = voip_engine->Base(); +// auto& voip_codec = voip_engine->Codec(); +// auto& voip_network = voip_engine->Network(); +// +// ChannelId channel = voip_base.CreateChannel(&app_transport_); +// +// // After SDP offer/answer, set payload type and codecs that have been +// // decided through SDP negotiation. +// // VoipResult handling omitted here. +// voip_codec.SetSendCodec(channel, ...); +// voip_codec.SetReceiveCodecs(channel, ...); +// +// // Start sending and playing RTP on voip channel. +// // VoipResult handling omitted here. +// voip_base.StartSend(channel); +// voip_base.StartPlayout(channel); +// +// // Inject received RTP/RTCP through VoipNetwork interface. +// // VoipResult handling omitted here. +// voip_network.ReceivedRTPPacket(channel, ...); +// voip_network.ReceivedRTCPPacket(channel, ...); +// +// // Stop and release voip channel. +// // VoipResult handling omitted here. +// voip_base.StopSend(channel); +// voip_base.StopPlayout(channel); +// voip_base.ReleaseChannel(channel); +// +class VoipEngine { + public: + virtual ~VoipEngine() = default; + + // VoipBase is the audio session management interface that + // creates/releases/starts/stops an one-to-one audio media session. + virtual VoipBase& Base() = 0; + + // VoipNetwork provides injection APIs that would enable application + // to send and receive RTP/RTCP packets. There is no default network module + // that provides RTP transmission and reception. + virtual VoipNetwork& Network() = 0; + + // VoipCodec provides codec configuration APIs for encoder and decoders. + virtual VoipCodec& Codec() = 0; + + // VoipDtmf provides DTMF event APIs to register and send DTMF events. + virtual VoipDtmf& Dtmf() = 0; + + // VoipStatistics provides performance metrics around audio decoding module + // and jitter buffer (NetEq). + virtual VoipStatistics& Statistics() = 0; + + // VoipVolumeControl provides various input/output volume control. + virtual VoipVolumeControl& VolumeControl() = 0; +}; + +} // namespace webrtc + +#endif // API_VOIP_VOIP_ENGINE_H_ diff --git a/third_party/libwebrtc/api/voip/voip_engine_factory.cc b/third_party/libwebrtc/api/voip/voip_engine_factory.cc new file mode 100644 index 0000000000..8da53cef74 --- /dev/null +++ b/third_party/libwebrtc/api/voip/voip_engine_factory.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 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 "api/voip/voip_engine_factory.h" + +#include <utility> + +#include "audio/voip/voip_core.h" +#include "rtc_base/logging.h" + +namespace webrtc { + +std::unique_ptr<VoipEngine> CreateVoipEngine(VoipEngineConfig config) { + RTC_CHECK(config.encoder_factory); + RTC_CHECK(config.decoder_factory); + RTC_CHECK(config.task_queue_factory); + RTC_CHECK(config.audio_device_module); + + if (!config.audio_processing) { + RTC_DLOG(LS_INFO) << "No audio processing functionality provided."; + } + + return std::make_unique<VoipCore>(std::move(config.encoder_factory), + std::move(config.decoder_factory), + std::move(config.task_queue_factory), + std::move(config.audio_device_module), + std::move(config.audio_processing)); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/voip/voip_engine_factory.h b/third_party/libwebrtc/api/voip/voip_engine_factory.h new file mode 100644 index 0000000000..62fe8011a6 --- /dev/null +++ b/third_party/libwebrtc/api/voip/voip_engine_factory.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2020 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 API_VOIP_VOIP_ENGINE_FACTORY_H_ +#define API_VOIP_VOIP_ENGINE_FACTORY_H_ + +#include <memory> + +#include "api/audio_codecs/audio_decoder_factory.h" +#include "api/audio_codecs/audio_encoder_factory.h" +#include "api/scoped_refptr.h" +#include "api/task_queue/task_queue_factory.h" +#include "api/voip/voip_engine.h" +#include "modules/audio_device/include/audio_device.h" +#include "modules/audio_processing/include/audio_processing.h" + +namespace webrtc { + +// VoipEngineConfig is a struct that defines parameters to instantiate a +// VoipEngine instance through CreateVoipEngine factory method. Each member is +// marked with comments as either mandatory or optional and default +// implementations that applications can use. +struct VoipEngineConfig { + // Mandatory (e.g. api/audio_codec/builtin_audio_encoder_factory). + // AudioEncoderFactory provides a set of audio codecs for VoipEngine to encode + // the audio input sample. Application can choose to limit the set to reduce + // application footprint. + rtc::scoped_refptr<AudioEncoderFactory> encoder_factory; + + // Mandatory (e.g. api/audio_codec/builtin_audio_decoder_factory). + // AudioDecoderFactory provides a set of audio codecs for VoipEngine to decode + // the received RTP packets from remote media endpoint. Application can choose + // to limit the set to reduce application footprint. + rtc::scoped_refptr<AudioDecoderFactory> decoder_factory; + + // Mandatory (e.g. api/task_queue/default_task_queue_factory). + // TaskQeueuFactory provided for VoipEngine to work asynchronously on its + // encoding flow. + std::unique_ptr<TaskQueueFactory> task_queue_factory; + + // Mandatory (e.g. modules/audio_device/include). + // AudioDeviceModule that periocally provides audio input samples from + // recording device (e.g. microphone) and requests audio output samples to + // play through its output device (e.g. speaker). + rtc::scoped_refptr<AudioDeviceModule> audio_device_module; + + // Optional (e.g. modules/audio_processing/include). + // AudioProcessing provides audio procesing functionalities (e.g. acoustic + // echo cancellation, noise suppression, gain control, etc) on audio input + // samples for VoipEngine. When optionally not set, VoipEngine will not have + // such functionalities to perform on audio input samples received from + // AudioDeviceModule. + rtc::scoped_refptr<AudioProcessing> audio_processing; +}; + +// Creates a VoipEngine instance with provided VoipEngineConfig. +std::unique_ptr<VoipEngine> CreateVoipEngine(VoipEngineConfig config); + +} // namespace webrtc + +#endif // API_VOIP_VOIP_ENGINE_FACTORY_H_ diff --git a/third_party/libwebrtc/api/voip/voip_network.h b/third_party/libwebrtc/api/voip/voip_network.h new file mode 100644 index 0000000000..0ea16b68de --- /dev/null +++ b/third_party/libwebrtc/api/voip/voip_network.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020 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 API_VOIP_VOIP_NETWORK_H_ +#define API_VOIP_VOIP_NETWORK_H_ + +#include "api/array_view.h" +#include "api/voip/voip_base.h" + +namespace webrtc { + +// VoipNetwork interface provides any network related interfaces such as +// processing received RTP/RTCP packet from remote endpoint. This interface +// requires a ChannelId created via VoipBase interface. +class VoipNetwork { + public: + // The data received from the network including RTP header is passed here. + // Returns following VoipResult; + // kOk - received RTP packet is processed. + // kInvalidArgument - `channel_id` is invalid. + virtual VoipResult ReceivedRTPPacket( + ChannelId channel_id, + rtc::ArrayView<const uint8_t> rtp_packet) = 0; + + // The data received from the network including RTCP header is passed here. + // Returns following VoipResult; + // kOk - received RTCP packet is processed. + // kInvalidArgument - `channel_id` is invalid. + virtual VoipResult ReceivedRTCPPacket( + ChannelId channel_id, + rtc::ArrayView<const uint8_t> rtcp_packet) = 0; + + protected: + virtual ~VoipNetwork() = default; +}; + +} // namespace webrtc + +#endif // API_VOIP_VOIP_NETWORK_H_ diff --git a/third_party/libwebrtc/api/voip/voip_statistics.h b/third_party/libwebrtc/api/voip/voip_statistics.h new file mode 100644 index 0000000000..2d1ab8d5e8 --- /dev/null +++ b/third_party/libwebrtc/api/voip/voip_statistics.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020 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 API_VOIP_VOIP_STATISTICS_H_ +#define API_VOIP_VOIP_STATISTICS_H_ + +#include "api/neteq/neteq.h" +#include "api/voip/voip_base.h" + +namespace webrtc { + +struct IngressStatistics { + // Stats included from api/neteq/neteq.h. + NetEqLifetimeStatistics neteq_stats; + + // Represents the total duration in seconds of all samples that have been + // received. + // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-totalsamplesduration + double total_duration = 0.0; +}; + +// Remote statistics obtained via remote RTCP SR/RR report received. +struct RemoteRtcpStatistics { + // Jitter as defined in RFC 3550 [6.4.1] expressed in seconds. + double jitter = 0.0; + + // Cumulative packets lost as defined in RFC 3550 [6.4.1] + int64_t packets_lost = 0; + + // Fraction lost as defined in RFC 3550 [6.4.1] expressed as a floating + // pointer number. + double fraction_lost = 0.0; + + // https://w3c.github.io/webrtc-stats/#dom-rtcremoteinboundrtpstreamstats-roundtriptime + absl::optional<double> round_trip_time; + + // Last time (not RTP timestamp) when RTCP report received in milliseconds. + int64_t last_report_received_timestamp_ms; +}; + +struct ChannelStatistics { + // https://w3c.github.io/webrtc-stats/#dom-rtcsentrtpstreamstats-packetssent + uint64_t packets_sent = 0; + + // https://w3c.github.io/webrtc-stats/#dom-rtcsentrtpstreamstats-bytessent + uint64_t bytes_sent = 0; + + // https://w3c.github.io/webrtc-stats/#dom-rtcreceivedrtpstreamstats-packetsreceived + uint64_t packets_received = 0; + + // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-bytesreceived + uint64_t bytes_received = 0; + + // https://w3c.github.io/webrtc-stats/#dom-rtcreceivedrtpstreamstats-jitter + double jitter = 0.0; + + // https://w3c.github.io/webrtc-stats/#dom-rtcreceivedrtpstreamstats-packetslost + int64_t packets_lost = 0; + + // SSRC from remote media endpoint as indicated either by RTP header in RFC + // 3550 [5.1] or RTCP SSRC of sender in RFC 3550 [6.4.1]. + absl::optional<uint32_t> remote_ssrc; + + absl::optional<RemoteRtcpStatistics> remote_rtcp; +}; + +// VoipStatistics interface provides the interfaces for querying metrics around +// the jitter buffer (NetEq) performance. +class VoipStatistics { + public: + // Gets the audio ingress statistics by `ingress_stats` reference. + // Returns following VoipResult; + // kOk - successfully set provided IngressStatistics reference. + // kInvalidArgument - `channel_id` is invalid. + virtual VoipResult GetIngressStatistics(ChannelId channel_id, + IngressStatistics& ingress_stats) = 0; + + // Gets the channel statistics by `channel_stats` reference. + // Returns following VoipResult; + // kOk - successfully set provided ChannelStatistics reference. + // kInvalidArgument - `channel_id` is invalid. + virtual VoipResult GetChannelStatistics(ChannelId channel_id, + ChannelStatistics& channel_stats) = 0; + + protected: + virtual ~VoipStatistics() = default; +}; + +} // namespace webrtc + +#endif // API_VOIP_VOIP_STATISTICS_H_ diff --git a/third_party/libwebrtc/api/voip/voip_volume_control.h b/third_party/libwebrtc/api/voip/voip_volume_control.h new file mode 100644 index 0000000000..aab14180df --- /dev/null +++ b/third_party/libwebrtc/api/voip/voip_volume_control.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020 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 API_VOIP_VOIP_VOLUME_CONTROL_H_ +#define API_VOIP_VOIP_VOLUME_CONTROL_H_ + +#include "api/voip/voip_base.h" + +namespace webrtc { + +struct VolumeInfo { + // https://w3c.github.io/webrtc-stats/#dom-rtcaudiosourcestats-audiolevel + double audio_level = 0; + // https://w3c.github.io/webrtc-stats/#dom-rtcaudiosourcestats-totalaudioenergy + double total_energy = 0.0; + // https://w3c.github.io/webrtc-stats/#dom-rtcaudiosourcestats-totalsamplesduration + double total_duration = 0.0; +}; + +// VoipVolumeControl interface. +// +// This sub-API supports functions related to the input (microphone) and output +// (speaker) device. +// +// Caller must ensure that ChannelId is valid otherwise it will result in no-op +// with error logging. +class VoipVolumeControl { + public: + // Mute/unmutes the microphone input sample before encoding process. Note that + // mute doesn't affect audio input level and energy values as input sample is + // silenced after the measurement. + // Returns following VoipResult; + // kOk - input source muted or unmuted as provided by `enable`. + // kInvalidArgument - `channel_id` is invalid. + virtual VoipResult SetInputMuted(ChannelId channel_id, bool enable) = 0; + + // Gets the microphone volume info via `volume_info` reference. + // Returns following VoipResult; + // kOk - successfully set provided input volume info. + // kInvalidArgument - `channel_id` is invalid. + virtual VoipResult GetInputVolumeInfo(ChannelId channel_id, + VolumeInfo& volume_info) = 0; + + // Gets the speaker volume info via `volume_info` reference. + // Returns following VoipResult; + // kOk - successfully set provided output volume info. + // kInvalidArgument - `channel_id` is invalid. + virtual VoipResult GetOutputVolumeInfo(ChannelId channel_id, + VolumeInfo& volume_info) = 0; + + protected: + virtual ~VoipVolumeControl() = default; +}; + +} // namespace webrtc + +#endif // API_VOIP_VOIP_VOLUME_CONTROL_H_ diff --git a/third_party/libwebrtc/api/webrtc_key_value_config.h b/third_party/libwebrtc/api/webrtc_key_value_config.h new file mode 100644 index 0000000000..e3cac59698 --- /dev/null +++ b/third_party/libwebrtc/api/webrtc_key_value_config.h @@ -0,0 +1,17 @@ +/* + * Copyright 2019 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 API_WEBRTC_KEY_VALUE_CONFIG_H_ +#define API_WEBRTC_KEY_VALUE_CONFIG_H_ + +// TODO(bugs.webrtc.org/10335): Remove once all migrated to +// api/field_trials_view.h +#include "api/field_trials_view.h" + +#endif // API_WEBRTC_KEY_VALUE_CONFIG_H_ diff --git a/third_party/libwebrtc/api/wrapping_async_dns_resolver.cc b/third_party/libwebrtc/api/wrapping_async_dns_resolver.cc new file mode 100644 index 0000000000..866cb0076d --- /dev/null +++ b/third_party/libwebrtc/api/wrapping_async_dns_resolver.cc @@ -0,0 +1,31 @@ +/* + * Copyright 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 "api/wrapping_async_dns_resolver.h" + +namespace webrtc { + +bool WrappingAsyncDnsResolverResult::GetResolvedAddress( + int family, + rtc::SocketAddress* addr) const { + if (!owner_->wrapped()) { + return false; + } + return owner_->wrapped()->GetResolvedAddress(family, addr); +} + +int WrappingAsyncDnsResolverResult::GetError() const { + if (!owner_->wrapped()) { + return -1; // FIXME: Find a code that makes sense. + } + return owner_->wrapped()->GetError(); +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/wrapping_async_dns_resolver.h b/third_party/libwebrtc/api/wrapping_async_dns_resolver.h new file mode 100644 index 0000000000..5155b0f528 --- /dev/null +++ b/third_party/libwebrtc/api/wrapping_async_dns_resolver.h @@ -0,0 +1,131 @@ +/* + * Copyright 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 API_WRAPPING_ASYNC_DNS_RESOLVER_H_ +#define API_WRAPPING_ASYNC_DNS_RESOLVER_H_ + +#include <functional> +#include <memory> +#include <utility> + +#include "absl/memory/memory.h" +#include "api/async_dns_resolver.h" +#include "api/sequence_checker.h" +#include "rtc_base/async_resolver.h" +#include "rtc_base/async_resolver_interface.h" +#include "rtc_base/checks.h" +#include "rtc_base/socket_address.h" +#include "rtc_base/third_party/sigslot/sigslot.h" +#include "rtc_base/thread_annotations.h" + +// This file defines a DNS resolver that wraps an old-style +// AsyncResolver. +// It is part of the conversion to the newer interface, and will go away +// once conversion is finished. +// TODO(bugs.webrtc.org/12598): Delete this API. + +namespace webrtc { + +class WrappingAsyncDnsResolver; + +class RTC_EXPORT WrappingAsyncDnsResolverResult + : public AsyncDnsResolverResult { + public: + explicit WrappingAsyncDnsResolverResult(WrappingAsyncDnsResolver* owner) + : owner_(owner) {} + ~WrappingAsyncDnsResolverResult() {} + + // Note: Inline declaration not possible, since it refers to + // WrappingAsyncDnsResolver. + bool GetResolvedAddress(int family, rtc::SocketAddress* addr) const override; + int GetError() const override; + + private: + WrappingAsyncDnsResolver* const owner_; +}; + +class RTC_EXPORT WrappingAsyncDnsResolver : public AsyncDnsResolverInterface, + public sigslot::has_slots<> { + public: + explicit WrappingAsyncDnsResolver(rtc::AsyncResolverInterface* wrapped) + : wrapped_(absl::WrapUnique(wrapped)), result_(this) {} + + ~WrappingAsyncDnsResolver() override { + // Workaround to get around the fact that sigslot-using objects can't be + // destroyed from within their callback: Alert class users early. + // TODO(bugs.webrtc.org/12651): Delete this class once the sigslot users are + // gone. + RTC_CHECK(!within_resolve_result_); + wrapped_.release()->Destroy(false); + } + + void Start(const rtc::SocketAddress& addr, + std::function<void()> callback) override { + RTC_DCHECK_RUN_ON(&sequence_checker_); + PrepareToResolve(std::move(callback)); + wrapped_->Start(addr); + } + + void Start(const rtc::SocketAddress& addr, + int family, + std::function<void()> callback) override { + RTC_DCHECK_RUN_ON(&sequence_checker_); + PrepareToResolve(std::move(callback)); + wrapped_->Start(addr, family); + } + + const AsyncDnsResolverResult& result() const override { + RTC_DCHECK_RUN_ON(&sequence_checker_); + RTC_DCHECK_EQ(State::kResolved, state_); + return result_; + } + + private: + enum class State { kNotStarted, kStarted, kResolved }; + + friend class WrappingAsyncDnsResolverResult; + // For use by WrappingAsyncDnsResolverResult + rtc::AsyncResolverInterface* wrapped() const { + RTC_DCHECK_RUN_ON(&sequence_checker_); + return wrapped_.get(); + } + + void PrepareToResolve(std::function<void()> callback) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + RTC_DCHECK_EQ(State::kNotStarted, state_); + state_ = State::kStarted; + callback_ = std::move(callback); + wrapped_->SignalDone.connect(this, + &WrappingAsyncDnsResolver::OnResolveResult); + } + + void OnResolveResult(rtc::AsyncResolverInterface* ref) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + RTC_DCHECK(state_ == State::kStarted); + RTC_DCHECK_EQ(ref, wrapped_.get()); + state_ = State::kResolved; + within_resolve_result_ = true; + callback_(); + within_resolve_result_ = false; + } + + // The class variables need to be accessed on a single thread. + SequenceChecker sequence_checker_; + std::function<void()> callback_ RTC_GUARDED_BY(sequence_checker_); + std::unique_ptr<rtc::AsyncResolverInterface> wrapped_ + RTC_GUARDED_BY(sequence_checker_); + State state_ RTC_GUARDED_BY(sequence_checker_) = State::kNotStarted; + WrappingAsyncDnsResolverResult result_ RTC_GUARDED_BY(sequence_checker_); + bool within_resolve_result_ RTC_GUARDED_BY(sequence_checker_) = false; +}; + +} // namespace webrtc + +#endif // API_WRAPPING_ASYNC_DNS_RESOLVER_H_ |