Compare commits

..

3 Commits

Author SHA1 Message Date
Adel Lahlou
2631ea6c2a Revert "Try the non mac option"
This reverts commit b3a7810f2b.
2025-12-05 01:52:38 -08:00
Adel Lahlou
b3a7810f2b Try the non mac option 2025-12-05 01:26:20 -08:00
Adel Lahlou
856ed7ef95 Attempt this patch: https://gist.github.com/kota-yata/3dcde1eac5ac266a40648ac78a248198 2025-12-04 22:38:54 -08:00
2814 changed files with 63099 additions and 97001 deletions

View File

@ -1,72 +0,0 @@
---
name: gn-check-autofix
description: Automatically fix GN check errors in WebRTC BUILD.gn files. Use when encountering "Include not allowed", "rtc_source_set shall not contain cc files", or when needing to clean up non-absolute dependencies.
---
# GN Check Autofix
This skill provides instructions for using `tools_webrtc/gn_check_autofix.py` to
automatically resolve common GN build configuration errors in WebRTC.
## Core Workflows
### Fix Missing Dependencies
When you see "Include not allowed" errors from `gn gen --check`, use this
workflow:
1. Run the autofix tool on your output directory:
```bash
tools_webrtc/gn_check_autofix.py -C <dir>
```
2. The tool will:
- Identify targets missing dependencies.
- Add the missing `deps` to the appropriate `BUILD.gn` files.
- Automatically run `gn format` on modified files.
### Fix rtc_source_set Violations
If you see "rtc_source_set shall not contain cc files", the tool will
automatically convert them to `rtc_library`:
1. Run the tool:
```bash
tools_webrtc/gn_check_autofix.py -C <dir>
```
### Clean Up Dependencies
To remove all non-absolute dependencies (those not starting with `//`) from
specific `BUILD.gn` files:
```bash
tools_webrtc/gn_check_autofix.py -r path/to/BUILD.gn
```
*Note: This preserves absolute dependencies (starting with `//`) and targets
ending in `_test`, `_tests`, `_unittest`, or `_unittests`.*
## Integration with Include Cleaner
This tool is the recommended second step after running `webrtc-include-cleaner`.
While the include cleaner updates your C++ source files, `gn-check-autofix`
synchronizes your `BUILD.gn` files to match.
## Parameters
- `-C <dir>`: Path to a local build directory (e.g., `out/Default`). The tool
internally runs `gn gen --check --error-limit=20000`.
- `-r <files>`: Remove all non-absolute dependencies from the specified files.
- `--error-limit`: Can be used to override the default error cap.
## Post-Fix Steps
After the tool runs, always verify the changes:
1. **Deduplicate**: The tool may occasionally add a dependency that is already
present. Check the `deps` list for duplicates.
2. **Regenerate GN**: Run `gn gen <dir>` to confirm errors are resolved.
3. **Format**: The tool runs `gn format`, but a final `git cl format` is
recommended for consistency.
4. **Review**: Check the diff to ensure dependencies were added to the correct
targets.

View File

@ -1,60 +0,0 @@
---
name: gtest-parallel
description: Run Google Test binaries in parallel using the gtest-parallel script. Use when needing to speed up test execution, run flaky tests with repeat, or filter specific tests.
---
# gtest-parallel
`gtest-parallel` is a script that executes Google Test binaries in parallel,
providing speedup for single-threaded tests and tests that do not run at 100%
CPU.
## Location
The script is located at `third_party/gtest-parallel/gtest-parallel`.
## Core Flags
### Filtering Tests
Use `--gtest_filter` to run a select set of tests. It supports the same syntax
as Google Test (including exclusion with `-`).
```bash
third_party/gtest-parallel/gtest-parallel path/to/binary --gtest_filter=Foo.*:Bar.*
```
### Timeouts
- `--timeout=TIMEOUT`: Interrupt all remaining processes after the given time
(in seconds).
- `--timeout_per_test=TIMEOUT_PER_TEST`: Interrupt single processes after the
given time (in seconds).
### Output and Logging
- `-d OUTPUT_DIR`, `--output_dir=OUTPUT_DIR`: Output directory for test logs.
Logs will be available under `gtest-parallel-logs/` inside the specified
directory.
- `--dump_json_test_results=DUMP_JSON_TEST_RESULTS`: Saves the results of the
tests as a JSON machine-readable file.
## Advanced Usage
### Repeating Tests (Flakiness Testing)
Use `--repeat=N` to run tests multiple times.
```bash
third_party/gtest-parallel/gtest-parallel path/to/binary --repeat=1000
```
### Workers
Use `-w WORKERS` or `--workers=WORKERS` to specify the number of parallel
workers (defaults to the number of cores).
### Serializing Test Cases
Use `--serialize_test_cases` to run tests within the same test case sequentially
(useful if they share resources).

View File

@ -1,67 +0,0 @@
---
name: webrtc-include-cleaner
description: Runs the WebRTC include-cleaner tool (IWYU replacement) to fix headers in C++ files. Use when preparing a CL for upload, after modifying .cc or .h files, or when instructed to fix include regressions.
---
# WebRTC Include Cleaner
This skill provides instructions for using
`tools_webrtc/iwyu/apply-include-cleaner`, a tool that automatically manages C++
`#include` directives in the WebRTC codebase. It ensures that every header used
is explicitly included and that unused headers are removed.
## When to Use
- **Pre-upload**: Run this tool before uploading a CL to ensure clean includes.
- **After refactoring**: When moving code or changing dependencies, use this to
update `#include` blocks.
- **Fixing regressions**: Use this if a presubmit or bot identifies
include-related issues.
## Basic Usage
To run the include cleaner on specific files:
```bash
tools_webrtc/iwyu/apply-include-cleaner path/to/file.cc path/to/file.h
```
To run it on all modified files relative to the upstream branch (ideal for CL
preparation):
```bash
tools_webrtc/iwyu/apply-include-cleaner
```
Note: This is as expensive as a build for each file, so use it sparingly.
## Options
- `-p`, `--print`: Don't modify the files, just print the proposed changes.
- `-w WORK_DIR`, `--work-dir WORK_DIR`: Specify the GN work directory (default:
`out/Default`).
## Post-Execution Steps
After running the include cleaner, it is recommended to perform the following
steps to ensure build and style consistency:
1. **Check for build errors**: The tool might occasionally make mistakes. Run a
build to verify.
1. **Fix GN dependencies**: Use `tools_webrtc/gn_check_autofix.py` to fix any
`deps` issues caused by include changes.
```bash
tools_webrtc/gn_check_autofix.py -C out/Default
```
1. **Format code**: Run `git cl format` to fix any formatting issues in the
`#include` blocks.
```bash
git cl format
```
## Prerequisites
- The tool automatically generates `compile_commands.json` in the output
directory if `out/Default` exists.
- `clangd` must be checked out in your `.gclient` file
(`"checkout_clangd": True`).

View File

@ -1,7 +1,7 @@
---
---
Checks: '-*,
bugprone-argument-comment,
bugprone-argument-comment
llvm-namespace-comment,
modernize-use-designated-initializers,
modernize-use-override,

View File

@ -32,5 +32,3 @@ c018bae80743596694db91478b879815f19dfb74
bceec84aeedcb9f5992d30dae0b477fb5e227fee
# Format the rest
7220ee97aafaa33a914f578e0f04184a94d17974
# Run clang-tidy on the repo
97b46e12582606a238d4f0c8524365cf5bdcb411

2
.gitignore vendored
View File

@ -34,13 +34,11 @@
.cproject
.gdb_history
.gdbinit
.gemini
.landmines
.metadata
.project
.pydevproject
.settings
.siso_failed_targets
.sw?
/Makefile
/base

9
.gn
View File

@ -12,8 +12,8 @@ import("//build/dotfile_settings.gni")
buildconfig = "//build/config/BUILDCONFIG.gn"
# The python interpreter to use by default. On Windows, this will look
# for python3.exe and python3.bat.
script_executable = "python3"
# for vpython3.exe and vpython3.bat.
script_executable = "vpython3"
# The secondary source root is a parallel directory tree where
# GN build files are placed when they can not be placed directly
@ -96,9 +96,4 @@ default_args = {
# Use Siso instead of Ninja.
use_siso = true
clang_unsafe_buffers_paths = "//unsafe_buffers_paths.txt"
# WebRTC must stay in C++20 for longer compared to Chromium.
use_cxx23 = false
}

View File

@ -31,13 +31,6 @@ wheel: <
version: "version:5.8.0.chromium.3"
>
# Used by:
# third_party/catapult
wheel: <
name: "infra/python/wheels/packaging-py2_py3"
version: "version:16.8"
>
# Used by tools_webrtc/perf/process_perf_results.py.
wheel: <
name: "infra/python/wheels/httplib2-py3"
@ -87,7 +80,7 @@ wheel: <
>
wheel: <
name: "infra/python/wheels/protobuf-py3"
version: "version:6.33.0"
version: "version:6.32.0"
>
wheel: <
name: "infra/python/wheels/requests-py3"

10
AUTHORS
View File

@ -17,7 +17,6 @@ Akshay Shah <meetakshay99@gmail.com>
Alexander Brauckmann <a.brauckmann@gmail.com>
Alexandre Gouaillard <agouaillard@gmail.com>
Alex Henrie <alexhenrie24@gmail.com>
Ambareesh Balaji <ambareeshbalaji@gmail.com>
Andrei Volykhin <andrei.volykhin@gmail.com>
Andrew MacDonald <andrew@webrtc.org>
Andrey Efremov <yoklmnprst@ya.ru>
@ -59,7 +58,6 @@ Frederik Riedel, Frogg GmbH <frederik.riedel@frogg.io>
Gao Chun <gaochun.dev@gmail.com>
Giji Gangadharan <giji.g@samsung.com>
Graham Yoakum <gyoakum@skobalt.com>
Gregory Bolshakov <gubidonius@gmail.com>
Guillaume Petit <guillaume.petit@shadow.tech>
Gustavo Garcia <gustavogb@gmail.com>
Hans Knoechel <hans@hans-knoechel.de>
@ -83,7 +81,6 @@ Karim Hammache <karim@karhm.com>
Keiichi Enomoto <enm10k@gmail.com>
Kiran Thind <kiran.thind@gmail.com>
Korniltsev Anatoly <korniltsev.anatoly@gmail.com>
Kun Wu <kunwu1987@gmail.com>
Kyutae Lee <gorisanson@gmail.com>
lauren n. liberda <lauren@selfisekai.rocks>
Lennart Grahl <lennart.grahl@gmail.com>
@ -106,7 +103,6 @@ Min Wang <mingewang@gmail.com>
Mike Woodworth <mike@divergentmedia.com>
Mo Zanaty <mzanaty@cisco.com>
Mohamed Risaldar UT <mohamed.ut@travancoreanalytics.com>
Moonki Choi <moonki1107@gmail.com>
Nico Schlumprecht <me@github.nico.onl>
Niek van der Maas <mail@niekvandermaas.nl>
Olivier Crête <olivier.crete@ocrete.ca>
@ -166,9 +162,6 @@ Pengfei Han <hanpfei@gmail.com>
Yingying Ma <yingying.ma@intel.com>
Hailin Zhao <lynnworld7@gmail.com>
Fizz Fang <fangkb555@gmail.com>
Sai Xu <saixu@qti.qualcomm.com>
Shunyang Zhang <zsy1522943066@gmail.com>
Suresh Jain <jainudr1982@gmail.com>
# END individuals section.
# BEGIN organizations section.
@ -181,7 +174,6 @@ BroadSoft Inc. <*@broadsoft.com>
Canonical Ltd <*@canonical.com>
CoSMo Software Consulting, Pte Ltd <*@cosmosoftware.io>
Discord Inc. <*@discordapp.com>
Eyevinn Technology AB <*@eyevinn.se>
Facebook Inc. <*@fb.com>
Google Inc. <*@google.com>
Highfive, Inc. <*@highfive.com>
@ -189,7 +181,6 @@ Hopin Ltd. <*@hopin.to>
HyperConnect Inc. <*@hpcnt.com>
Igalia S.L. <*@igalia.com>
Intel Corporation <*@intel.com>
Island Technology, Inc. <*@island.io>
LG Electronics, Inc. <*@lge.com>
Life On Air Inc. <*@lifeonair.com>
LiveKit <*@livekit.io>
@ -225,5 +216,4 @@ Vonage Holdings Corp. <*@vonage.com>
Wang Qing <wangqing-hf@loongson.cn>
Wire Swiss GmbH <*@wire.com>
&yet LLC <*@andyet.com>
Ahmad Yar <ahmaddurranitrg@gmail.com>
# END organizations section.

View File

@ -47,7 +47,6 @@ if (!build_with_chromium) {
}
if (rtc_include_tests) {
deps += [
":audio_engine_tests",
":rtc_p2p_unittests",
":rtc_unittests",
":video_engine_tests",
@ -67,7 +66,6 @@ if (!build_with_chromium) {
"modules/video_capture:video_capture_internal_impl",
"modules/video_coding:video_codec_perf_tests",
"net/dcsctp:dcsctp_unittests",
"p2p:dtls_ice_integration_bench",
"pc:peerconnection_unittests",
"pc:rtc_pc_unittests",
"pc:slow_peer_connection_unittests",
@ -80,7 +78,6 @@ if (!build_with_chromium) {
"video:screenshare_loopback",
"video:sv_loopback",
"video:video_loopback",
"video/timing:video_timing_tests",
]
if (use_libfuzzer) {
deps += [ "test/fuzzers" ]
@ -178,10 +175,6 @@ config("common_inherited_config") {
defines += [ "RTC_ENABLE_WIN_WGC" ]
}
if (deprecate_plan_b) {
defines += [ "WEBRTC_DEPRECATE_PLAN_B" ]
}
if (!rtc_use_perfetto) {
# Some tests need to declare their own trace event handlers. If this define is
# not set, the first time TRACE_EVENT_* is called it will store the return
@ -279,6 +272,34 @@ config("rtc_prod_config") {
}
}
group("tracing") {
all_dependent_configs = [ "//third_party/perfetto/gn:public_config" ]
if (rtc_use_perfetto) {
if (build_with_chromium) {
public_deps = # no-presubmit-check TODO(webrtc:8603)
[ "//third_party/perfetto:libperfetto" ]
} else {
public_deps = [ # no-presubmit-check TODO(webrtc:8603)
":webrtc_libperfetto",
"//third_party/perfetto/include/perfetto/tracing",
]
}
} else {
# RingRTC change to disable perfetto linking and save on library size.
# public_deps = # no-presubmit-check TODO(webrtc:8603)
# [ "//third_party/perfetto/include/perfetto/tracing" ]
}
}
if (rtc_use_perfetto) {
rtc_library("webrtc_libperfetto") {
deps = [
"//third_party/perfetto/src/tracing:client_api_without_backends",
"//third_party/perfetto/src/tracing:platform_impl",
]
}
}
config("common_config") {
cflags = []
cflags_c = []
@ -320,24 +341,14 @@ config("common_config") {
defines += [ "RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY" ]
}
# RingRTC change to support Opus DNN features
if (rtc_opus_support_dred || rtc_opus_support_deep_plc) {
defines += [ "WEBRTC_OPUS_SUPPORT_DEEP_PLC=1" ]
} else {
defines += [ "WEBRTC_OPUS_SUPPORT_DEEP_PLC=0" ]
}
# RingRTC change to support Opus DRED
if (rtc_opus_support_dred) {
defines += [ "WEBRTC_OPUS_SUPPORT_DRED=1" ]
} else {
defines += [ "WEBRTC_OPUS_SUPPORT_DRED=0" ]
}
if (rtc_enable_sctp) {
defines += [ "WEBRTC_HAVE_SCTP" ]
}
if (rtc_enable_external_auth) {
defines += [ "ENABLE_EXTERNAL_AUTH" ]
}
if (rtc_use_h264) {
defines += [ "WEBRTC_USE_H264" ]
}
@ -532,6 +543,7 @@ if (!build_with_chromium) {
"api:create_modular_peer_connection_factory",
"api:create_peerconnection_factory",
"api:enable_media",
"api:libjingle_peerconnection_api",
"api:rtc_error",
"api:transport_api",
"api/audio_codecs:opus_audio_decoder_factory",
@ -559,8 +571,8 @@ if (!build_with_chromium) {
"modules/video_capture:video_capture_internal_impl",
"pc:libjingle_peerconnection",
"pc:rtc_pc",
# RingRTC change to build ringrtc ffi
"ringrtc",
"sdk",
"video",
# RingRTC change to support deployments to older Ubuntu targets
@ -588,14 +600,6 @@ if (!build_with_chromium) {
if (rtc_include_internal_audio_device) {
deps += [ "api/audio:create_audio_device_module" ]
}
if (!build_with_chromium) {
if (is_android) {
deps += [ "sdk/android" ]
}
if (is_ios) {
deps += [ "sdk:framework_objc" ]
}
}
}
# TODO(bugs.webrtc.org/430260876): Compile webrtc lib with rust once toolchain
@ -652,7 +656,6 @@ if (rtc_include_tests && !build_with_chromium) {
"api/task_queue:pending_task_safety_flag_unittests",
"api/test/metrics:metrics_unittests",
"api/test/network_emulation:network_queue_unittests",
"api/transport:ecn_marking_unittest",
"api/transport:stun_unittest",
"api/transport/rtp:corruption_detection_message_unittest",
"api/video/test:rtc_api_video_unittests",
@ -672,6 +675,8 @@ if (rtc_include_tests && !build_with_chromium) {
"rtc_base:rtc_numerics_unittests",
"rtc_base:rtc_operations_chain_unittests",
"rtc_base:rtc_task_queue_unittests",
"rtc_base:sigslot_trampoline_unittest",
"rtc_base:sigslot_unittest",
"rtc_base:task_queue_stdlib_unittest",
"rtc_base:untyped_function_unittest",
"rtc_base:weak_ptr_unittests",
@ -681,6 +686,7 @@ if (rtc_include_tests && !build_with_chromium) {
"rtc_base/units:units_unittests",
"sdk:sdk_tests",
"test:rtp_test_utils",
"test:test_main",
"test/network:network_emulation_unittests",
]
@ -712,39 +718,34 @@ if (rtc_include_tests && !build_with_chromium) {
rtc_test("rtc_p2p_unittests") {
testonly = true
deps = [ "p2p:rtc_p2p_unittests" ]
deps = [
"p2p:rtc_p2p_unittests",
"test:test_main",
]
}
if (rtc_enable_google_benchmarks) {
rtc_executable("benchmarks") {
rtc_test("benchmarks") {
testonly = true
deps = [
"rtc_base:base64_benchmark",
"rtc_base/synchronization:mutex_benchmark",
"test:benchmark_main",
]
}
}
rtc_test("audio_engine_tests") {
testonly = true
deps = [ "audio:audio_tests" ]
if (is_android) {
use_default_launcher = false
deps += [ "//build/android/gtest_apk:native_test_instrumentation_test_runner_java" ]
}
}
# TODO(pbos): Rename test suite, this is no longer "just" for video targets.
rtc_test("video_engine_tests") {
testonly = true
deps = [
"audio:audio_tests",
# TODO(eladalon): call_tests aren't actually video-specific, so we
# should move them to a more appropriate test suite.
"call:call_tests",
"call/adaptation:resource_adaptation_tests",
"test:test_common",
"test:test_main",
"test:video_test_common",
"video:video_tests",
"video/adaptation:video_adaptation_tests",
@ -769,6 +770,7 @@ if (rtc_include_tests && !build_with_chromium) {
"modules/audio_coding:audio_coding_perf_tests",
"modules/audio_processing:audio_processing_perf_tests",
"pc:peerconnection_perf_tests",
"test:test_main",
"video:video_full_stack_tests",
"video:video_pc_full_stack_tests",
]
@ -802,6 +804,7 @@ if (rtc_include_tests && !build_with_chromium) {
"audio/voip/test:audio_egress_unittests",
"audio/voip/test:audio_ingress_unittests",
"audio/voip/test:voip_core_unittests",
"test:test_main",
]
}
}

440
DEPS
View File

@ -10,7 +10,7 @@ vars = {
# chromium waterfalls. More info at: crbug.com/570091.
'checkout_configuration': 'default',
'checkout_instrumented_libraries': 'checkout_linux and checkout_configuration == "default"',
'chromium_revision': 'a3f5fcb392f2902650ca2b71820e7e418787e18b',
'chromium_revision': 'd89832c173b4514a8dd58ded5192f037803ab851',
# Fetch the prebuilt binaries for llvm-cov and llvm-profdata. Needed to
# process the raw profiles produced by instrumented targets (built with
@ -33,7 +33,7 @@ vars = {
# By default, download the fuchsia sdk from the public sdk directory.
'fuchsia_sdk_cipd_prefix': 'fuchsia/sdk/core/',
'fuchsia_version': 'version:31.20260204.7.1',
'fuchsia_version': 'version:29.20250927.0.1',
# By default, download the fuchsia images from the fuchsia GCS bucket.
'fuchsia_images_bucket': 'fuchsia',
'checkout_fuchsia': False,
@ -48,9 +48,9 @@ vars = {
# RBE instance to use for running remote builds
'rbe_instance': 'projects/rbe-webrtc-developer/instances/default_instance',
# reclient CIPD package version
'reclient_version': 're_client_version:0.185.0.db415f21-gomaip',
'reclient_version': 're_client_version:0.183.0.3b3097cd-gomaip',
# siso CIPD package version.
'siso_version': 'git_revision:87bad442ede1c60700dfabef5862c4a584621734',
'siso_version': 'git_revision:f7020b54462c37f1b10a16e68563c338c9f14371',
# ninja CIPD package.
'ninja_package': 'infra/3pp/tools/ninja/',
@ -68,9 +68,9 @@ vars = {
}
deps = {
# RingRTC change to use the upstream xiph opus
# RingRTC change to use a the upstream xiph opus
'src/ringrtc/opus/src':
'https://github.com/xiph/opus.git@22244de5a79bd1d6d623c32e72bf1954b56235be',
'https://github.com/xiph/opus.git@55513e81d8f606bd75d0ff773d2144e5f2a732f5',
# RingRTC change to support Oboe for audio on Android
'src/ringrtc/oboe/src': {
@ -79,30 +79,28 @@ deps = {
},
'src/build':
'https://chromium.googlesource.com/chromium/src/build@dd54dd5186566a13bda647123c22540666b12ace',
'https://chromium.googlesource.com/chromium/src/build@045565e91c7360951bddbd0618a20ea59cdd31f3',
'src/buildtools':
'https://chromium.googlesource.com/chromium/src/buildtools@95ed44cf5f06dbb5861030b91c9db9ccb4316762',
'https://chromium.googlesource.com/chromium/src/buildtools@3e6e75d1961a90054ee0e3030ee66b6a04164c10',
# Gradle 6.6.1. Used for testing Android Studio project generation for WebRTC.
'src/examples/androidtests/third_party/gradle': {
'url': 'https://chromium.googlesource.com/external/github.com/gradle/gradle.git@f2d1fb54a951d8b11d25748e4711bec8d128d7e3',
'condition': 'checkout_android',
},
'src/ios': {
'url': 'https://chromium.googlesource.com/chromium/src/ios@b3b1914b7bd50a64ec13fabaf5e42edcf22e99b8',
'url': 'https://chromium.googlesource.com/chromium/src/ios@700b2480a58ddd3e3d95ef8d86c050f319d3f728',
'condition': 'checkout_ios',
},
'src/testing':
'https://chromium.googlesource.com/chromium/src/testing@629b7bb6055714e23d8125bf790cfc8d94a94159',
# RingRTC change for 148 only to pick up crash fix on android
'https://chromium.googlesource.com/chromium/src/testing@c030c132cbab406942fb208b7180f8846aa4abf1',
'src/third_party':
'https://chromium.googlesource.com/chromium/src/third_party@4923971b35e39f6bd9be8bc19c4680785a15c80d',
# End RingRTC change
'https://chromium.googlesource.com/chromium/src/third_party@de738129ebb915bbe34cdf06520c7050ef8aa9d9',
'src/buildtools/linux64': {
'packages': [
{
'package': 'gn/gn/linux-${{arch}}',
'version': 'git_revision:b2ac0e7a9089039e62b84d246eca83f84c540f76',
'version': 'git_revision:81b24e01531ecf0eff12ec9359a555ec3944ec4e',
}
],
'dep_type': 'cipd',
@ -112,7 +110,7 @@ deps = {
'packages': [
{
'package': 'gn/gn/mac-${{arch}}',
'version': 'git_revision:b2ac0e7a9089039e62b84d246eca83f84c540f76',
'version': 'git_revision:81b24e01531ecf0eff12ec9359a555ec3944ec4e',
}
],
'dep_type': 'cipd',
@ -122,7 +120,7 @@ deps = {
'packages': [
{
'package': 'gn/gn/windows-amd64',
'version': 'git_revision:b2ac0e7a9089039e62b84d246eca83f84c540f76',
'version': 'git_revision:81b24e01531ecf0eff12ec9359a555ec3944ec4e',
}
],
'dep_type': 'cipd',
@ -148,157 +146,157 @@ deps = {
'objects': [
{
# The Android libclang_rt.builtins libraries are currently only included in the Linux clang package.
'object_name': 'Linux_x64/clang-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '750b331006635281d7d90696629f67db748ba62004c46675eccb8af144141847',
'size_bytes': 58029996,
'generation': 1772218390302503,
'object_name': 'Linux_x64/clang-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '35a8629534f534aa6771470945fc0baa6906b3fffb28433bc08674d343b84c90',
'size_bytes': 55674480,
'generation': 1758743123214066,
'condition': '(host_os == "linux" or checkout_android) and non_git_source',
},
{
'object_name': 'Linux_x64/clang-tidy-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': 'd53439bb6ac13c8d2c30c20555ded434039802f70d4119c0138bd77d03552223',
'size_bytes': 14392856,
'generation': 1772218390323510,
'object_name': 'Linux_x64/clang-tidy-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '0342c1f9f546b2c87010418c37eaf494b3bcee24e60a351a880046951bf4d47b',
'size_bytes': 14059964,
'generation': 1758743123322050,
'condition': 'host_os == "linux" and checkout_clang_tidy and non_git_source',
},
{
'object_name': 'Linux_x64/clangd-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': 'a24613fb7afce42c076bb95d1b671ac028746b379e88070c126f0aab17a4c34e',
'size_bytes': 14635272,
'generation': 1772218390330947,
'object_name': 'Linux_x64/clangd-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '8b9513babd89f706e928be51b9a4c08a4511dae1c152285808d7a25b299ae94b',
'size_bytes': 14210752,
'generation': 1758743123414815,
'condition': 'host_os == "linux" and checkout_clangd and non_git_source',
},
{
'object_name': 'Linux_x64/llvm-code-coverage-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '8dcd816a83361b7924093ccba92dfe6bd29af2cf8af58bf7ce785b38c5027a8b',
'size_bytes': 2328908,
'generation': 1772218390452408,
'object_name': 'Linux_x64/llvm-code-coverage-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '56bb0093e2e8f71e682f03b0e379d7dac0bacfcc83bfccfd42a4fcd1310fbe75',
'size_bytes': 2272396,
'generation': 1758743123592944,
'condition': 'host_os == "linux" and checkout_clang_coverage_tools and non_git_source',
},
{
'object_name': 'Linux_x64/llvmobjdump-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '0a15d6b8c2b774b0706618d2afa123b9c87af2ec12e74dc44346df4c4690b670',
'size_bytes': 5780116,
'generation': 1772218390340688,
'object_name': 'Linux_x64/llvmobjdump-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '9236697d64fc9444b22c90a112f6b3a76ee1edf5b3891af67de0849deb274514',
'size_bytes': 5666148,
'generation': 1758743123461779,
'condition': '((checkout_linux or checkout_mac or checkout_android) and host_os == "linux") and non_git_source',
},
{
'object_name': 'Mac/clang-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '2661847eb275079358ab186eaf7f85d6139d44c7413a731dfac7f5ed1ec34a01',
'size_bytes': 54827776,
'generation': 1772218392155773,
'object_name': 'Mac/clang-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '90e1a97b91d9a39bafc719f5e3b4c3cd8bf457c39f1dc4a27e4bfc59b9331bc5',
'size_bytes': 53576996,
'generation': 1758743125100350,
'condition': 'host_os == "mac" and host_cpu == "x64"',
},
{
'object_name': 'Mac/clang-mac-runtime-library-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '69918295c163ec5a20aede81d4100bbd41e01142d32e0555366bba05141f7bf2',
'size_bytes': 1010608,
'generation': 1772218399449599,
'object_name': 'Mac/clang-mac-runtime-library-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '7140b54db5936c79bb6f216ea176be70c7e6711f0dec2224369fba76cb9c1572',
'size_bytes': 1004900,
'generation': 1758743135101043,
'condition': 'checkout_mac and not host_os == "mac"',
},
{
'object_name': 'Mac/clang-tidy-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': 'b8013fe5d2410db4f365ec8779972415d1d0a08042a3a43f823a0da712108cff',
'size_bytes': 14280488,
'generation': 1772218392176137,
'object_name': 'Mac/clang-tidy-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '0ef9124d5c56825ebbd10539298400a0b0d1d8d67e0902a7e89b3fecff7f9b0c',
'size_bytes': 14141008,
'generation': 1758743125225488,
'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clang_tidy',
},
{
'object_name': 'Mac/clangd-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '508098b26e74bd7f5cdcc40a2ed2db24e2bdde15e0f1c14ce94f685f991b3dd6',
'size_bytes': 15455912,
'generation': 1772218392186146,
'object_name': 'Mac/clangd-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': 'aec08495162681dbfe4e78bd6c728e6f1f410f3fe6c0e070c095dcf4bfda1382',
'size_bytes': 15632104,
'generation': 1758743125301839,
'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clangd',
},
{
'object_name': 'Mac/llvm-code-coverage-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '46c33f13a68fc14005560c01a91215b5cab54c07e920a714264352e46af1350c',
'size_bytes': 2376304,
'generation': 1772218392292978,
'object_name': 'Mac/llvm-code-coverage-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '36b279a1a6dc9d90e932823138f522e3c2741005e34732bce60fea60881a3963',
'size_bytes': 2321200,
'generation': 1758743125546947,
'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clang_coverage_tools',
},
{
'object_name': 'Mac/llvmobjdump-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '6a92e3f21b3a035f406313d24688bb1b312a9a0ec423ff808752b6638104aff3',
'size_bytes': 5699700,
'generation': 1772218392189830,
'object_name': 'Mac/llvmobjdump-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '29e8b2d333ecb6640cf99d9103b999ff2be0bb13fe8300528b4245bf6b88869c',
'size_bytes': 5582716,
'generation': 1758743125362967,
'condition': 'host_os == "mac" and host_cpu == "x64"',
},
{
'object_name': 'Mac_arm64/clang-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '909be0f896bcf140c710548ccda4673c0aea2480e28d10803c19b1689b36acd5',
'size_bytes': 45847044,
'generation': 1772218401088162,
'object_name': 'Mac_arm64/clang-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '29d82cb9830396c21b967a5784f838dcb3d62abfebd08d67d36821dba6eb4ce8',
'size_bytes': 44576940,
'generation': 1758743136591599,
'condition': 'host_os == "mac" and host_cpu == "arm64"',
},
{
'object_name': 'Mac_arm64/clang-tidy-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '83dc8d90529730ae503e684ea0047a0baec2b0c4a81941d1bb4196feea6ba264',
'size_bytes': 12444972,
'generation': 1772218401143017,
'object_name': 'Mac_arm64/clang-tidy-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '8d7781b19bd032eeda7a94810e5429e0501392ac5585fcd16499a3d72e12ab9e',
'size_bytes': 12142468,
'generation': 1758743136678250,
'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clang_tidy',
},
{
'object_name': 'Mac_arm64/clangd-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '3b7ff06ccd41b0a1fb165e182a35bcd74ae49172f1720cd276eb5feac0e3dd9f',
'size_bytes': 12816980,
'generation': 1772218401144631,
'object_name': 'Mac_arm64/clangd-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '16617a896e7304ba76af9cbcab00edeb63753804237fc5055810b2049d00b3dc',
'size_bytes': 12474420,
'generation': 1758743136764487,
'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clangd',
},
{
'object_name': 'Mac_arm64/llvm-code-coverage-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '67148555d00427a3eaa8aeefb8c4c4e1271d585315bdbf0d28d20fd78957e309',
'size_bytes': 1988008,
'generation': 1772218401224240,
'object_name': 'Mac_arm64/llvm-code-coverage-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '3ae73edf0d6b69d6aa41247c8268aaf292630f708036d55f3e0e5fa2ce340497',
'size_bytes': 1947856,
'generation': 1758743136945536,
'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clang_coverage_tools',
},
{
'object_name': 'Mac_arm64/llvmobjdump-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': 'a31075e7f46ed77c62ecec424722bec8335ef306a4701660f19b713229c49afa',
'size_bytes': 5421552,
'generation': 1772218401116635,
'object_name': 'Mac_arm64/llvmobjdump-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '069266d0ab2b9029908edc0b958af5d5ec3d9cd939b063da7aeeb53548137df9',
'size_bytes': 5277360,
'generation': 1758743136838343,
'condition': 'host_os == "mac" and host_cpu == "arm64"',
},
{
'object_name': 'Win/clang-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': 'f2c9d2a8accf7ed2e3c19b3f67fb94e60365411a536fb9d71391dd2d4e7e14bb',
'size_bytes': 49546756,
'generation': 1772218410442709,
'object_name': 'Win/clang-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': 'bec899a7163ba0d446a5355e554cf8644b5e3db729404c6defb077549bc9f1b4',
'size_bytes': 47645664,
'generation': 1758743148772393,
'condition': 'host_os == "win"',
},
{
'object_name': 'Win/clang-tidy-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '99e00bbb404557db32df4e7a183ac520c526fe0e143ca380dfb2d0c33a2025b5',
'size_bytes': 14462056,
'generation': 1772218410470169,
'object_name': 'Win/clang-tidy-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '10770b3b7b34a0e968cbeb1838b1446080897941c2bb5d192aa6596bbb386c27',
'size_bytes': 14025008,
'generation': 1758743148836717,
'condition': 'host_os == "win" and checkout_clang_tidy',
},
{
'object_name': 'Win/clang-win-runtime-library-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '62e9c022223e0fa6ff855c25dcee524818f04c570127ed7e74895b320a10100a',
'size_bytes': 2597584,
'generation': 1772218417651221,
'object_name': 'Win/clang-win-runtime-library-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': 'fedf17614b4cba1c8edc7f3ad1c4636bb79535068e76ad6fed75fe65515dc4b8',
'size_bytes': 2503180,
'generation': 1758743159444585,
'condition': 'checkout_win and not host_os == "win"',
},
{
'object_name': 'Win/clangd-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '6a3ab3afb8d2e7f4a04eecd8073993586665ede3929308a0fa0119d9382b1e2d',
'size_bytes': 14887416,
'generation': 1772218410483998,
'object_name': 'Win/clangd-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '6dcd1c2f3bd7dbd547f8b93b014a3bc9f9d84b0920fc7632f45a6bfc1b359ae1',
'size_bytes': 14366920,
'generation': 1758743148925930,
'condition': 'host_os == "win" and checkout_clangd',
},
{
'object_name': 'Win/llvm-code-coverage-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '4bd610d2fbcc6e2bd8fd2df8d8c23a915373f8c987701d295314e8b33d457075',
'size_bytes': 2479300,
'generation': 1772218410570017,
'object_name': 'Win/llvm-code-coverage-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '57e86c6eeeccb1e6e5b87d87c2231f01e006d9067e2f3ad50530e32674599ad6',
'size_bytes': 2366460,
'generation': 1758743149180966,
'condition': 'host_os == "win" and checkout_clang_coverage_tools',
},
{
'object_name': 'Win/llvmobjdump-llvmorg-23-init-5669-g8a0be0bc-1.tar.xz',
'sha256sum': '2ee77b6240b76353840439b38e7009d9f1fb8e97930dbbef3b1ff805ee981c5f',
'size_bytes': 5846184,
'generation': 1772218410487302,
'object_name': 'Win/llvmobjdump-llvmorg-22-init-8940-g4d4cb757-1.tar.xz',
'sha256sum': '3f398db586e4f75a48eda2a508be4577a9c54cda78cf03afa57b454801ed5bde',
'size_bytes': 5668924,
'generation': 1758743148999346,
'condition': '(checkout_linux or checkout_mac or checkout_android) and host_os == "win"',
},
]
@ -310,48 +308,48 @@ deps = {
'bucket': 'chromium-browser-clang',
'objects': [
{
'object_name': 'Linux_x64/rust-toolchain-6f54d591c3116ee7f8ce9321ddeca286810cc142-7-llvmorg-23-init-5669-g8a0be0bc.tar.xz',
'sha256sum': 'afbb00d27b8f9f65e6a754fb21e80dff084993285cf7f3c0020dece59c5bd67a',
'size_bytes': 271641712,
'generation': 1773769777991797,
'object_name': 'Linux_x64/rust-toolchain-15283f6fe95e5b604273d13a428bab5fc0788f5a-1-llvmorg-22-init-8940-g4d4cb757.tar.xz',
'sha256sum': '2bdaea0b11cb11a8f2f4dcb79b0dbb4bf38e2bd22479ff8014f55b9b6890e135',
'size_bytes': 142044388,
'generation': 1758743116775859,
'condition': 'host_os == "linux" and non_git_source',
},
{
'object_name': 'Mac/rust-toolchain-6f54d591c3116ee7f8ce9321ddeca286810cc142-7-llvmorg-23-init-5669-g8a0be0bc.tar.xz',
'sha256sum': '70b86e82f1cb55777d40b5828ddcb80afea49510085290424b61251d22e9f959',
'size_bytes': 259443552,
'generation': 1773769780408342,
'object_name': 'Mac/rust-toolchain-15283f6fe95e5b604273d13a428bab5fc0788f5a-1-llvmorg-22-init-8940-g4d4cb757.tar.xz',
'sha256sum': '351347e1930a900c63b3953cdb10775b73572c6145e389f3820ba920816d46ca',
'size_bytes': 135891820,
'generation': 1758743118329536,
'condition': 'host_os == "mac" and host_cpu == "x64"',
},
{
'object_name': 'Mac_arm64/rust-toolchain-6f54d591c3116ee7f8ce9321ddeca286810cc142-7-llvmorg-23-init-5669-g8a0be0bc.tar.xz',
'sha256sum': 'e2e19684f31b653ce9238f6303aec22576085528c294757a7157d4ab5e1926dc',
'size_bytes': 242768940,
'generation': 1773769782590875,
'object_name': 'Mac_arm64/rust-toolchain-15283f6fe95e5b604273d13a428bab5fc0788f5a-1-llvmorg-22-init-8940-g4d4cb757.tar.xz',
'sha256sum': '33d6b8cf4fc6617aa98888a46bc1dbef29ae9a9ebd01c3f248ef8c08ec5f198b',
'size_bytes': 123302332,
'generation': 1758743119839246,
'condition': 'host_os == "mac" and host_cpu == "arm64"',
},
{
'object_name': 'Win/rust-toolchain-6f54d591c3116ee7f8ce9321ddeca286810cc142-7-llvmorg-23-init-5669-g8a0be0bc.tar.xz',
'sha256sum': '37dd250549fed5a9765c3a88e3487409189e0c9c63b691fc77daa0b5f214bced',
'size_bytes': 409536908,
'generation': 1773769784773096,
'object_name': 'Win/rust-toolchain-15283f6fe95e5b604273d13a428bab5fc0788f5a-1-llvmorg-22-init-8940-g4d4cb757.tar.xz',
'sha256sum': '4f6dfa230e5d401bf9aadd804142b412467177b17d50a3f52a8c69c1957aa2db',
'size_bytes': 199998880,
'generation': 1758743121322555,
'condition': 'host_os == "win"',
},
],
},
'src/third_party/clang-format/script':
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/clang/tools/clang-format.git@c2725e0622e1a86d55f14514f2177a39efea4a0e',
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/clang/tools/clang-format.git@37f6e68a107df43b7d7e044fd36a13cbae3413f2',
'src/third_party/compiler-rt/src':
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/compiler-rt.git@bb7645f5e11c9c1d719a890fcb09ccfaaa14580f',
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/compiler-rt.git@dbef1a89100395f128231024d0c07e4dcfe72140',
'src/third_party/libc++/src':
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxx.git@7ab65651aed6802d2599dcb7a73b1f82d5179d05',
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxx.git@b77132b512d5411f8393fd3decb3abaeaf1d3ec8',
'src/third_party/libc++abi/src':
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxxabi.git@8f11bb1d4438d0239d0dfc1bd9456a9f31629dda',
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxxabi.git@864f61dc9253d56586ada34c388278565ef513f6',
'src/third_party/llvm-libc/src':
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libc.git@adccc443070c58badd6414fd9a4380ca8c78e7c4',
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libc.git@0c61a55402c6a0d9d6ca2aeb3c6a2613a8bc8c55',
'src/third_party/libunwind/src':
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libunwind.git@db838d918570d4e381ecf9f5cc70a0098c9c2cd6',
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libunwind.git@322be580a5a193a921c349a15747eeeb9a716ad1',
'src/third_party/test_fonts/test_fonts': {
'dep_type': 'gcs',
@ -393,7 +391,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/android_system_sdk/public',
'version': 'EpgkrtsLblLuw0BrsWCF0h_njBzIZsBNDxQ5VtA4s2UC',
'version': 'Pfb3HDUW_uRir_VVTCYkGhf6bnPPF55NUJO2WXOxIe0C',
},
],
'condition': 'checkout_android and non_git_source',
@ -414,7 +412,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/android_build_tools/aapt2',
'version': 'gsaUgZUqoyD0XG1E9-xesSWknHZINEuS00iSEncvlE0C',
'version': 'vtRNH1sTb9tAlXaPkdqGIH_MDSnuH2GrlWFtT1MhadUC',
},
],
'condition': 'checkout_android',
@ -425,7 +423,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/android_build_tools/bundletool',
'version': '7Vo6ZzIxIaC51ATTBlo_KUkgxJCmmGmXAijlVkXUTpAC',
'version': 'uOjFFaA5gYLXkFeukj3Xd53BGvMYtkkoDeOO7s3qeyQC',
},
],
'condition': 'checkout_android',
@ -447,7 +445,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/android_build_tools/error_prone',
'version': 'ax2FOQ16-lz2R1o1P-xDhd2KOAFoY1wjZ-lQgZkygUYC',
'version': 'qjoXMGvbc36wB6J_7ERVNhYaotHaTDdrny1PpdNJ1qMC',
},
],
'condition': 'checkout_android',
@ -469,7 +467,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/android_build_tools/lint',
'version': 'lBgjWB8NdI2Mhnsy0SHkCyCZ3pbO1Qe4Zk0JZHs3yAIC',
'version': '2tl7Wkl-h3xQcHYGcsqwSrIQpyLSlBLjBl36vQwV8VgC',
},
],
'condition': 'checkout_android and non_git_source',
@ -481,7 +479,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/android_build_tools/nullaway',
'version': 'rYm-c7W2XUUzeDYveLTl3YmrIqc483bjo6OB5rpQUrIC',
'version': 'N8e9CN_YH72RHiFh5wTuXkcMtNbQBBrtot_-HePTmAwC',
},
],
'condition': 'checkout_android and non_git_source',
@ -500,11 +498,11 @@ deps = {
},
'src/third_party/boringssl/src':
'https://boringssl.googlesource.com/boringssl.git@8dce4fd20ab7e768c0a5103edc1d8cb7e54366ba',
'https://boringssl.googlesource.com/boringssl.git@db638238d29708a20b991af3b2488e45a8bbcf71',
'src/third_party/breakpad/breakpad':
'https://chromium.googlesource.com/breakpad/breakpad.git@8be0e3114685fcc1589561067282edf75ea1259a',
'https://chromium.googlesource.com/breakpad/breakpad.git@a1220f673dc44632e821bd1a217089e5a159a203',
'src/third_party/catapult':
'https://chromium.googlesource.com/catapult.git@5a34891efa6e41c8aca8842386b8ee528963ffdf',
'https://chromium.googlesource.com/catapult.git@04c85a1d0e324464c6be4b3d193b47cb6177d03a',
'src/third_party/ced/src': {
'url': 'https://chromium.googlesource.com/external/github.com/google/compact_enc_det.git@ba412eaaacd3186085babcd901679a48863c7dd5',
},
@ -517,28 +515,28 @@ deps = {
'src/third_party/crc32c/src':
'https://chromium.googlesource.com/external/github.com/google/crc32c.git@d3d60ac6e0f16780bcfcc825385e1d338801a558',
'src/third_party/depot_tools':
'https://chromium.googlesource.com/chromium/tools/depot_tools.git@ce1ebad2c35c9387186f01d77edeea28a254c955',
'https://chromium.googlesource.com/chromium/tools/depot_tools.git@675a3a9ccd7cf9367bb4caa58c30f08b56d45ef5',
'src/third_party/ffmpeg':
'https://chromium.googlesource.com/chromium/third_party/ffmpeg.git@b5e18fb9da84e26ceef30d4e4886696bf59337c0',
'https://chromium.googlesource.com/chromium/third_party/ffmpeg.git@9e751092c9498b84bbb77e2e0689ef9f50fe608f',
'src/third_party/flatbuffers/src':
'https://chromium.googlesource.com/external/github.com/google/flatbuffers.git@a86afae9399bbe631d1ea0783f8816e780e236cc',
'https://chromium.googlesource.com/external/github.com/google/flatbuffers.git@1c514626e83c20fffa8557e75641848e1e15cd5e',
'src/third_party/grpc/src': {
'url': 'https://chromium.googlesource.com/external/github.com/grpc/grpc.git@5e9fb9cbfb12a10ff9c16fbc360328d224b838d6',
'url': 'https://chromium.googlesource.com/external/github.com/grpc/grpc.git@de6ce7f32b1bf254d2b4c04e8872b63284632fd3',
},
# Used for embedded builds. CrOS & Linux use the system version.
'src/third_party/fontconfig/src': {
'url': 'https://chromium.googlesource.com/external/fontconfig.git@d62c2ab268d1679335daa8fb0ea6970f35224a76',
'url': 'https://chromium.googlesource.com/external/fontconfig.git@f0ed9c3f43161d3555f6f7a5234b22fe7ca60727',
'condition': 'checkout_linux',
},
'src/third_party/freetype/src':
'https://chromium.googlesource.com/chromium/src/third_party/freetype2.git@99b479dc34728936b006679a31e12b8cf432fc55',
'https://chromium.googlesource.com/chromium/src/third_party/freetype2.git@d3668e00da732654b50e4e81f982544ed6e26390',
'src/third_party/harfbuzz-ng/src':
'https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git@6f4c5cec306d31e6822303f5ba248a14293d588e',
'https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git@7d936359a27abb2d7cb14ecc102463bb15c11843',
'src/third_party/google_benchmark/src': {
'url': 'https://chromium.googlesource.com/external/github.com/google/benchmark.git@188e8278990a9069ffc84441cb5a024fd0bede37',
'url': 'https://chromium.googlesource.com/external/github.com/google/benchmark.git@761305ec3b33abf30e08d50eb829e19a802581cc',
},
'src/third_party/libpfm4/src':
Var('chromium_git') + '/external/git.code.sf.net/p/perfmon2/libpfm4.git' + '@' + '41878eab48c50bb9ec5f741a013e971bb5a9dff2',
Var('chromium_git') + '/external/git.code.sf.net/p/perfmon2/libpfm4.git' + '@' + '964baf9d35d5f88d8422f96d8a82c672042e7064',
# WebRTC-only dependency (not present in Chromium).
'src/third_party/gtest-parallel':
'https://chromium.googlesource.com/external/github.com/google/gtest-parallel@cd488bdedc1d2cffb98201a17afc1b298b0b90f1',
@ -547,9 +545,9 @@ deps = {
'condition': 'checkout_android',
},
'src/third_party/googletest/src':
'https://chromium.googlesource.com/external/github.com/google/googletest.git@4fe3307fb2d9f86d19777c7eb0e4809e9694dde7',
'https://chromium.googlesource.com/external/github.com/google/googletest.git@244cec869d12e53378fa0efb610cd4c32a454ec8',
'src/third_party/icu': {
'url': 'https://chromium.googlesource.com/chromium/deps/icu.git@b4aae6832c06df9d538d41b249403cf0678f16b4',
'url': 'https://chromium.googlesource.com/chromium/deps/icu.git@1b2e3e8a421efae36141a7b932b41e315b089af8',
},
'src/third_party/jdk/current': {
'packages': [
@ -585,7 +583,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/kotlin_stdlib',
'version': 'uq9bdsIxS9Is_mAZr9OWBymcLtxheKkgzeUSLuZKhJUC',
'version': 'v_3lST4iHAGGOm-99HcVIDBNwPuXuzhXvViFePcVg_kC',
},
],
'condition': 'checkout_android',
@ -596,7 +594,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/kotlinc',
'version': 'RcyJsRii1TkItQ8HjsvzQnXGvIZ0FJvpF4bxYeFr7qAC',
'version': '6SrtnuwP3mVyOqcvkuIbYcArs39XuyFEGYlHHo3YsLwC',
},
],
'condition': 'checkout_android',
@ -605,31 +603,31 @@ deps = {
'src/third_party/libFuzzer/src':
'https://chromium.googlesource.com/external/github.com/llvm/llvm-project/compiler-rt/lib/fuzzer.git@bea408a6e01f0f7e6c82a43121fe3af4506c932e',
'src/third_party/fuzztest/src':
'https://chromium.googlesource.com/external/github.com/google/fuzztest.git@dc327134097700121e4ecd6e1d54d1d0a832a18d',
'https://chromium.googlesource.com/external/github.com/google/fuzztest.git@e101ca021a40733d0fa76a3bd9b49b5f76da4f8a',
'src/third_party/libjpeg_turbo':
'https://chromium.googlesource.com/chromium/deps/libjpeg_turbo.git@d1f5f2393e0d51f840207342ae86e55a86443288',
'https://chromium.googlesource.com/chromium/deps/libjpeg_turbo.git@e14cbfaa85529d47f9f55b0f104a579c1061f9ad',
'src/third_party/libsrtp':
'https://chromium.googlesource.com/chromium/deps/libsrtp.git@e8383771af8aa4096f5bcfe3743a5ea128f88a9a',
'https://chromium.googlesource.com/chromium/deps/libsrtp.git@a52756acb1c5e133089c798736dd171567df11f5',
'src/third_party/dav1d/libdav1d':
'https://chromium.googlesource.com/external/github.com/videolan/dav1d.git@d69235dd804b24c04ed05639cffcc912cd6cfd75',
'https://chromium.googlesource.com/external/github.com/videolan/dav1d.git@af5cf2b1e7f03d6f6de84477e1ca8eed1f3eb03d',
'src/third_party/libaom/source/libaom':
'https://aomedia.googlesource.com/aom.git@f3dddebddd0dba76fbfb97b96b6336bcf1d3a30c',
'https://aomedia.googlesource.com/aom.git@dcfc0bd1934130570d04597a3b75de0824dc434d',
'src/third_party/libgav1/src':
Var('chromium_git') + '/codecs/libgav1.git' + '@' + '40f58ed32ff39071c3f2a51056dbc49a070af0dc',
Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'c05bf9be660cf170d7c26bd06bb42b3322180e58',
'src/third_party/libunwindstack': {
'url': 'https://chromium.googlesource.com/chromium/src/third_party/libunwindstack.git@333fcafb91bd3830c5ef814c071ff73df9cdc976',
'url': 'https://chromium.googlesource.com/chromium/src/third_party/libunwindstack.git@0928ad0d25e4af07c8be5ab06d0ca584f9f4ceb5',
'condition': 'checkout_android',
},
'src/third_party/perfetto':
Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '40b1342aa7bd47d9c963c3617fd98ec1551528f9',
Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'd5bbee7afdf259af4212929ccbff467dd5349953',
'src/third_party/protobuf-javascript/src':
Var('chromium_git') + '/external/github.com/protocolbuffers/protobuf-javascript' + '@' + 'e6d763860001ba1a76a63adcff5efb12b1c96024',
'src/third_party/libvpx/source/libvpx':
'https://chromium.googlesource.com/webm/libvpx.git@3fce57ecc905d95a4619f33d09851d68c5a88663',
'https://chromium.googlesource.com/webm/libvpx.git@8d00aca60b951444582b1373e4e47f0ca6e0871c',
'src/third_party/libyuv':
'https://chromium.googlesource.com/libyuv/libyuv.git@30809ff64a9ca5e45f86439c0d474c2d3eef3d05',
'https://chromium.googlesource.com/libyuv/libyuv.git@5b22f31cb5d39c1309a589f148678c2a217e75db',
'src/third_party/lss': {
'url': 'https://chromium.googlesource.com/linux-syscall-support.git@29164a80da4d41134950d76d55199ea33fbb9613',
'url': 'https://chromium.googlesource.com/linux-syscall-support.git@ed31caa60f20a4f6569883b2d752ef7522de51e0',
'condition': 'checkout_android or checkout_linux',
},
'src/third_party/mockito/src': {
@ -643,20 +641,20 @@ deps = {
# Used by boringssl.
'src/third_party/nasm': {
'url': 'https://chromium.googlesource.com/chromium/deps/nasm.git@45252858722aad12e545819b2d0f370eb865431b'
'url': 'https://chromium.googlesource.com/chromium/deps/nasm.git@e2c93c34982b286b27ce8b56dd7159e0b90869a2'
},
'src/third_party/openh264/src':
'https://chromium.googlesource.com/external/github.com/cisco/openh264@652bdb7719f30b52b08e506645a7322ff1b2cc6f',
'src/third_party/re2/src':
'https://chromium.googlesource.com/external/github.com/google/re2.git@972a15cedd008d846f1a39b2e88ce48d7f166cbd',
'https://chromium.googlesource.com/external/github.com/google/re2.git@6569a9a3df256f4c0c3813cb8ee2f8eef6e2c1fb',
'src/third_party/r8/cipd': {
'packages': [
{
'package': 'chromium/third_party/r8',
'version': '8ZRb6CCpZTU5dSpQyDlbusalGCjWV0sVSGTq_0Js3mcC',
'version': 'llWUebGsQPrzc7z3fwJF78NcrdGs1wrUhy0Y-0Wrb-4C',
},
],
'condition': 'checkout_android',
@ -669,7 +667,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/r8',
'version': '8ZRb6CCpZTU5dSpQyDlbusalGCjWV0sVSGTq_0Js3mcC',
'version': 'llWUebGsQPrzc7z3fwJF78NcrdGs1wrUhy0Y-0Wrb-4C',
},
],
'condition': 'checkout_android',
@ -680,7 +678,7 @@ deps = {
'condition': 'checkout_android',
},
'src/tools':
'https://chromium.googlesource.com/chromium/src/tools@f363a79871a91f36322e845e3134e2f04e1fc18a',
'https://chromium.googlesource.com/chromium/src/tools@3b73a00861c1cc1d6308e20786f42045b77864cd',
'src/third_party/espresso': {
'packages': [
@ -719,7 +717,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/androidx',
'version': 'xbJffE4gDOA4g5njwbpWZtgk4ouGMWOHiqq2ymCZ2ggC',
'version': 'u-4GkHeumu0D2o8hkQbMGiMzvACyw_8TYdEfox0QyWYC',
},
],
'condition': 'checkout_android and non_git_source',
@ -730,7 +728,7 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/android_build_tools/manifest_merger',
'version': '5JSVccMXNkpeH9lpydgxJ3QCoNpBC5yvil7NvdsqUasC',
'version': 'dOI-ntBgO0MZG3WmKK37I1njjcGALsDJc00mVeoSfVUC',
},
],
'condition': 'checkout_android',
@ -740,8 +738,8 @@ deps = {
'src/third_party/android_sdk/public': {
'packages': [
{
'package': 'chromium/third_party/android_sdk/public/build-tools/36.1.0',
'version': '-jLl4Ibk_WmgTsZaP-ueQwZDhBwkWf5BsQ4UNrkzXF0C',
'package': 'chromium/third_party/android_sdk/public/build-tools/36.0.0',
'version': 'y3EsZLg4bxPmpW0oYsAHylywNyMnIwPS3kh1VbQLAFAC',
},
{
'package': 'chromium/third_party/android_sdk/public/emulator',
@ -752,12 +750,12 @@ deps = {
'version': 'qTD9QdBlBf3dyHsN1lJ0RH6AhHxR42Hmg2Ih-Vj4zIEC'
},
{
'package': 'chromium/third_party/android_sdk/public/platforms/android-36.1',
'version': 'gxwLT70eR_ObwZJzKK8UIS-N549yAocNTmc0JHgO7gUC',
'package': 'chromium/third_party/android_sdk/public/platforms/android-36',
'version': '_YHemUrK49JrE7Mctdf5DDNOHu1VKBx_PTcWnZ-cbOAC',
},
{
'package': 'chromium/third_party/android_sdk/public/cmdline-tools/linux',
'version': 'LZa8CWNVWS6UUQgQ7IJdFCqRV1Bmx2-alTNqEDJpJkcC',
'package': 'chromium/third_party/android_sdk/public/cmdline-tools',
'version': 'gekOVsZjseS1w9BXAT3FsoW__ByGDJYS9DgqesiwKYoC',
},
],
'condition': 'checkout_android',
@ -798,13 +796,13 @@ deps = {
},
'src/third_party/tflite/src':
Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '8fd527849069a358ad6c2980b9a9b34a53c53717',
Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '313f58ae85278ced9ccc7f90ee630bdf8735c52f',
'src/third_party/turbine/cipd': {
'packages': [
{
'package': 'chromium/third_party/turbine',
'version': '0A4lFRLjqycR4-EvoBz1w2FxPEzzG94cFvwu8v39DRYC',
'version': 'LaDt9HreG5-Q6yBbZLf6LJSvLKqNjamn84VJgZHXSTEC',
},
],
'condition': 'checkout_android',
@ -812,7 +810,7 @@ deps = {
},
'src/third_party/zstd/src': {
'url': Var('chromium_git') + '/external/github.com/facebook/zstd.git' + '@' + '3ae099b48dfcfe02b1b3ba81ab85457f8a922e9f',
'url': Var('chromium_git') + '/external/github.com/facebook/zstd.git' + '@' + '89d685e42dbcf815a16ed0fcd7d050ef74ccad96',
'condition': 'checkout_android',
},
@ -820,15 +818,15 @@ deps = {
'packages': [
{
'package': 'infra/tools/luci/cas/${{platform}}',
'version': 'git_revision:8cb5bd940d5f726f8a538212b2287987fcadf837',
'version': 'git_revision:6645da847edf4e1ebcfe8cf4d860ad75e63b20cb',
},
{
'package': 'infra/tools/luci/isolate/${{platform}}',
'version': 'git_revision:8cb5bd940d5f726f8a538212b2287987fcadf837',
'version': 'git_revision:6645da847edf4e1ebcfe8cf4d860ad75e63b20cb',
},
{
'package': 'infra/tools/luci/swarming/${{platform}}',
'version': 'git_revision:8cb5bd940d5f726f8a538212b2287987fcadf837',
'version': 'git_revision:6645da847edf4e1ebcfe8cf4d860ad75e63b20cb',
}
],
'dep_type': 'cipd',
@ -838,11 +836,11 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/pipewire/linux-amd64',
'version': 'WccKnxvPRn8TBwQ4FUxoHaZRKvHXh0qJjODccy3gPTAC',
'version': 'BaVKmAmwpjdS6O0pnjSaMNSKhO1nmk5mRnyPVAJ2-HEC',
},
{
'package': 'chromium/third_party/wireplumber/linux-amd64',
'version': 'yfe349C2e6pWCcu7DaSPJHNWdwDbNP9FfSQoV9j6A5UC',
'package': 'chromium/third_party/pipewire-media-session/linux-amd64',
'version': 'Y6wUeITvAA0QD1vt8_a7eQdzbp0gkI1B02qfZUMJdowC',
},
],
@ -854,29 +852,29 @@ deps = {
'packages': [
{
'package': 'chromium/third_party/android_deps/autorolled',
'version': 'ioujkn6x8xwFvfYkiQGrRb9lX4Khn3Thhv3nsoN6lrQC',
'version': '6mTuw4XsHFCD5khevukzKQHDaq5tAVpX48i3JG1Izu4C',
},
],
'condition': 'checkout_android and non_git_source',
'dep_type': 'cipd',
},
'src/third_party/pthreadpool/src':
Var('chromium_git') + '/external/github.com/google/pthreadpool.git' + '@' + '9003ee6c137cea3b94161bd5c614fb43be523ee1',
Var('chromium_git') + '/external/github.com/google/pthreadpool.git' + '@' + 'f5a07eddbf4be8f23e29e60a2ccf66b78b71f119',
'src/third_party/xnnpack/src':
Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + '97f3177fd836fff03b48a886bb130591866ad7ca',
Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + '4d098efeac50c44a7c03e6feb1794908db4c3158',
'src/third_party/farmhash/src':
Var('chromium_git') + '/external/github.com/google/farmhash.git' + '@' + '816a4ae622e964763ca0862d9dbd19324a1eaf45',
'src/third_party/ruy/src':
Var('chromium_git') + '/external/github.com/google/ruy.git' + '@' + '2af88863614a8298689cc52b1a47b3fcad7be835',
Var('chromium_git') + '/external/github.com/google/ruy.git' + '@' + '9940fbf1e0c0863907e77e0600b99bb3e2bc2b9f',
'src/third_party/cpuinfo/src':
Var('chromium_git') + '/external/github.com/pytorch/cpuinfo.git' + '@' + '7607ca500436b37ad23fb8d18614bec7796b68a7',
Var('chromium_git') + '/external/github.com/pytorch/cpuinfo.git' + '@' + '877328f188a3c7d1fa855871a278eb48d530c4c0',
'src/third_party/eigen3/src':
Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '002229ce470065878afb7c2f6f96d22c9a9b7ba0',
Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '430e35fbd15d3c946d2d2ba19ec41c16ba217cb3',
'src/third_party/fp16/src':
Var('chromium_git') + '/external/github.com/Maratyszcza/FP16.git' + '@' + '3d2de1816307bac63c16a297e8c4dc501b4076df',
@ -888,12 +886,23 @@ deps = {
Var('chromium_git') + '/external/github.com/Maratyszcza/FXdiv.git' + '@' + '63058eff77e11aa15bf531df5dd34395ec3017c8',
'src/third_party/neon_2_sse/src':
Var('chromium_git') + '/external/github.com/intel/ARM_NEON_2_x86_SSE.git' + '@' + '662a85912e8f86ec808f9b15ce77f8715ba53316',
Var('chromium_git') + '/external/github.com/intel/ARM_NEON_2_x86_SSE.git' + '@' + 'eb8b80b28f956275e291ea04a7beb5ed8289e872',
# Everything coming after this is automatically updated by the auto-roller.
# === ANDROID_DEPS Generated Code Start ===
# Generated by //third_party/android_deps/fetch_all.py
'src/third_party/android_deps/cipd/libs/com_android_support_support_annotations': {
'packages': [
{
'package': 'chromium/third_party/android_deps/libs/com_android_support_support_annotations',
'version': 'version:2@28.0.0.cr2',
},
],
'condition': 'checkout_android and non_git_source',
'dep_type': 'cipd',
},
'src/third_party/android_deps/cipd/libs/com_android_tools_common': {
'packages': [
{
@ -1026,6 +1035,28 @@ deps = {
'dep_type': 'cipd',
},
'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_atomicfu_jvm': {
'packages': [
{
'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_atomicfu_jvm',
'version': 'version:2@0.23.2.cr2',
},
],
'condition': 'checkout_android and non_git_source',
'dep_type': 'cipd',
},
'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_guava': {
'packages': [
{
'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_guava',
'version': 'version:2@1.8.1.cr2',
},
],
'condition': 'checkout_android and non_git_source',
'dep_type': 'cipd',
},
'src/third_party/android_deps/cipd/libs/org_jsoup_jsoup': {
'packages': [
{
@ -1157,6 +1188,7 @@ hooks = [
'action': [ 'python3',
'src/third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
'--no_auth',
'--bucket', 'chromium-browser-clang/ciopfs',
'-s', 'src/build/ciopfs.sha1',
]
@ -1212,6 +1244,7 @@ hooks = [
'action': [ 'python3',
'src/third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
'--no_auth',
'--bucket', 'chromium-browser-clang',
'-s', 'src/tools/clang/dsymutil/bin/dsymutil.arm64.sha1',
'-o', 'src/tools/clang/dsymutil/bin/dsymutil',
@ -1224,6 +1257,7 @@ hooks = [
'action': [ 'python3',
'src/third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
'--no_auth',
'--bucket', 'chromium-browser-clang',
'-s', 'src/tools/clang/dsymutil/bin/dsymutil.x64.sha1',
'-o', 'src/tools/clang/dsymutil/bin/dsymutil',
@ -1237,6 +1271,7 @@ hooks = [
'action': [ 'python3',
'src/third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
'--no_auth',
'--bucket', 'chromium-browser-clang/rc',
'-s', 'src/build/toolchain/win/rc/win/rc.exe.sha1',
],
@ -1248,6 +1283,7 @@ hooks = [
'action': [ 'python3',
'src/third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
'--no_auth',
'--bucket', 'chromium-browser-clang/rc',
'-s', 'src/build/toolchain/win/rc/mac/rc.sha1',
],
@ -1259,6 +1295,7 @@ hooks = [
'action': [ 'python3',
'src/third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
'--no_auth',
'--bucket', 'chromium-browser-clang/rc',
'-s', 'src/build/toolchain/win/rc/linux64/rc.sha1',
],
@ -1270,6 +1307,7 @@ hooks = [
'--directory',
'--recursive',
'--num_threads=10',
'--no_auth',
'--quiet',
'--bucket', 'chromium-webrtc-resources',
'src/resources'],
@ -1328,29 +1366,6 @@ hooks = [
'src/third_party/test_fonts/test_fonts.tar.gz', # Remove after 20240901
],
},
# RingRTC change to download Opus DNN models
{
'name': 'download_opus_models_linux',
'pattern': '.',
'condition': 'host_os != "win"',
'cwd': 'src/ringrtc/opus/src',
'action': ['bash',
'dnn/download_model.sh',
'a5177ec6fb7d15058e99e57029746100121f68e4890b1467d4094aa336b6013e'
],
},
{
'name': 'download_opus_models_win',
'pattern': '.',
'condition': 'host_os == "win"',
'cwd': 'src/ringrtc/opus/src',
'action': ['cmd.exe',
'/c',
'dnn\\download_model.bat',
'a5177ec6fb7d15058e99e57029746100121f68e4890b1467d4094aa336b6013e'
],
},
# end RingRTC change to download Opus DNN models
]
recursedeps = [
@ -1387,7 +1402,6 @@ include_rules = [
"+absl/cleanup/cleanup.h",
"+absl/container",
"-absl/container/fixed_array.h",
"+absl/crc",
"+absl/functional/any_invocable.h",
"+absl/functional/bind_front.h",
"+absl/memory/memory.h",
@ -1409,7 +1423,7 @@ include_rules = [
]
specific_include_rules = {
"webrtc_lib_link_test\\.cc": [
"webrtc_lib_link_test\.cc": [
"+media/engine",
"+modules/audio_device",
"+modules/audio_processing",

View File

@ -1,10 +0,0 @@
# General workflow
@agents/prompts/common.md
# Codebase knowledge
@./g3doc/abseil-in-webrtc.md
@./g3doc/how_to_write_documentation.md
@./g3doc/implementation_basics.md
@./g3doc/style-guide.md

4
OWNERS
View File

@ -1,6 +1,6 @@
danilchap@webrtc.org
eshr@webrtc.org
henrika@webrtc.org
hta@webrtc.org
mflodman@webrtc.org
stefan@webrtc.org
tommi@webrtc.org
include OWNERS_INFRA #{Owners for infra and repo related files}

View File

@ -1,21 +1,19 @@
# Owners for infra and repo related files
#Owners for infra and repo related files
per-file .gitignore=*
per-file AUTHORS=*
per-file DEPS=*
per-file WATCHLISTS=*
per-file whitespace.txt=*
per-file .gn=mbonadei@webrtc.org,jansson@webrtc.org,jleconte@webrtc.org
per-file BUILD.gn=mbonadei@webrtc.org,jansson@webrtc.org,jleconte@webrtc.org
per-file .../BUILD.gn=mbonadei@webrtc.org,jansson@webrtc.org,jleconte@webrtc.org
per-file *.gni=mbonadei@webrtc.org,jansson@webrtc.org,jleconte@webrtc.org
per-file .../*.gni=mbonadei@webrtc.org,jansson@webrtc.org,jleconte@webrtc.org
per-file .vpython=mbonadei@webrtc.org,jansson@webrtc.org,jleconte@webrtc.org
per-file .vpython3=mbonadei@webrtc.org,jansson@webrtc.org,jleconte@webrtc.org
per-file AUTHORS=*
per-file DEPS=*
per-file pylintrc=mbonadei@webrtc.org,jansson@webrtc.org,jleconte@webrtc.org
per-file .rustfmt.toml=boivie@webrtc.org,mbonadei@webrtc.org,jleconte@webrtc.org
per-file pylintrc_old_style=mbonadei@webrtc.org,jansson@webrtc.org,jleconte@webrtc.org
per-file WATCHLISTS=*
per-file native-api.md=mbonadei@webrtc.org
per-file ....lua=titovartem@webrtc.org
per-file .style.yapf=jleconte@webrtc.org
per-file *.py=mbonadei@webrtc.org,jansson@webrtc.org,jleconte@webrtc.org
per-file .rustfmt.toml=boivie@webrtc.org,mbonadei@webrtc.org,jleconte@webrtc.org

View File

@ -662,23 +662,6 @@ def CheckGnGen(input_api, output_api):
return []
def CheckDeps(input_api, output_api):
"""Runs checkdeps """
repo_root = input_api.change.RepositoryRoot()
checkdeps_path = input_api.os_path.join(repo_root, 'buildtools',
'checkdeps')
with _AddToPath(checkdeps_path):
import checkdeps
deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
deps_checker.CheckDirectory(input_api.PresubmitLocalPath())
results = []
if deps_checker.results_formatter.GetResults():
results.append(
output_api.PresubmitError('\n'.join(
deps_checker.results_formatter.GetResults())))
return results
def CheckUnwantedDependencies(input_api, output_api, source_file_filter):
"""Runs checkdeps on #include statements added in this
change. Breaking - rules is an error, breaking ! rules is a
@ -832,7 +815,10 @@ def RunPythonTests(input_api, output_api):
'process_perf_results_test.py',
]
test_directories = [input_api.PresubmitLocalPath()] + [
test_directories = [
input_api.PresubmitLocalPath(),
Join('rtc_tools', 'py_event_log_analyzer'),
] + [
root for root, _, files in os.walk(Join('tools_webrtc')) if any(
f.endswith('_test.py') and f not in excluded_files for f in files)
]
@ -1014,7 +1000,6 @@ def CommonChecks(input_api, output_api):
results.extend(
input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
results.extend(CheckNativeApiHeaderChanges(input_api, output_api))
results.extend(CheckDeps(input_api, output_api))
results.extend(
CheckNoIOStreamInHeaders(input_api,
output_api,

View File

@ -1,14 +1,11 @@
Name: WebRTC
URL: This is the canonical repository
Version: DEPS
CPEPrefix: cpe:/a:webrtc_project:webrtc
License: BSD-3-Clause
URL: http://www.webrtc.org
Version: 90
CPEPrefix: cpe:/a:webrtc_project:webrtc:90
License: BSD
License File: LICENSE
Shipped: yes
Security Critical: yes
Update Mechanism: Manual
Mitigated: CVE-2022-2294
CVE-2022-2294: Fixed by https://crbug.com/40060120.
Description:
WebRTC provides real time voice and video processing

View File

@ -102,41 +102,76 @@
'WATCHLISTS': {
'this_file': [],
'all_webrtc': [],
'root_files': ['peah@webrtc.org'],
'root_files': ['peah@webrtc.org',
'qiang.lu@intel.com',
'yujie.mao@webrtc.org'],
'build_files': ['mbonadei@webrtc.org'],
'common_audio': ['peah@webrtc.org',
'common_audio': ['alessiob@webrtc.org',
'audio-team@agora.io',
'peah@webrtc.org',
'saza@webrtc.org'],
'audio': ['peah@webrtc.org'],
'api': ['hta@webrtc.org',
'peah@webrtc.org'],
'base': ['hta@webrtc.org'],
'call': ['stefan@webrtc.org'],
'video': ['stefan@webrtc.org'],
'video_capture': ['perkj@webrtc.org'],
'audio_device': ['henrika@webrtc.org',
'call': ['mflodman@webrtc.org',
'stefan@webrtc.org'],
'video': ['mflodman@webrtc.org',
'stefan@webrtc.org',
'video-team@agora.io',
'yujie.mao@webrtc.org',
'zhengzhonghou@agora.io'],
'video_capture': ['mflodman@webrtc.org',
'perkj@webrtc.org',
'sdk-team@agora.io',
'zhengzhonghou@agora.io'],
'audio_device': ['audio-team@agora.io',
'henrika@webrtc.org',
'peah@webrtc.org',
'saza@webrtc.org',
'sdk-team@agora.io'],
'audio_coding': ['alessiob@webrtc.org',
'audio-team@agora.io',
'henrik.lundin@webrtc.org',
'peah@webrtc.org',
'saza@webrtc.org'],
'audio_coding': ['henrik.lundin@webrtc.org',
'peah@webrtc.org',
'saza@webrtc.org'],
'neteq': ['henrik.lundin@webrtc.org',
'neteq': ['alessiob@webrtc.org',
'audio-team@agora.io',
'henrik.lundin@webrtc.org',
'saza@webrtc.org'],
'audio_mixer': ['henrik.lundin@webrtc.org',
'audio_mixer': ['aleloi@webrtc.org',
'henrik.lundin@webrtc.org',
'peah@webrtc.org',
'saza@webrtc.org'],
'audio_processing': ['henrik.lundin@webrtc.org',
'audio_processing': ['alessiob@webrtc.org',
'audio-team@agora.io',
'henrik.lundin@webrtc.org',
'peah@webrtc.org',
'saza@webrtc.org'],
'video_coding': ['stefan@webrtc.org'],
'bitrate_controller': ['stefan@webrtc.org'],
'video_coding': ['mflodman@webrtc.org',
'stefan@webrtc.org',
'video-team@agora.io',
'zhengzhonghou@agora.io'],
'bitrate_controller': ['mflodman@webrtc.org',
'stefan@webrtc.org',
'zhuangzesen@agora.io'],
'congestion_controller': [],
'remote_bitrate_estimator': ['stefan@webrtc.org'],
'pacing': ['stefan@webrtc.org'],
'rtp_rtcp': ['stefan@webrtc.org',
'danilchap@webrtc.org'],
'system_wrappers': ['henrika@webrtc.org',
'peah@webrtc.org'],
'pc': [],
'remote_bitrate_estimator': ['mflodman@webrtc.org',
'stefan@webrtc.org',
'zhuangzesen@agora.io'],
'pacing': ['mflodman@webrtc.org',
'stefan@webrtc.org',
'zhuangzesen@agora.io'],
'rtp_rtcp': ['mflodman@webrtc.org',
'stefan@webrtc.org',
'danilchap@webrtc.org',
'zhuangzesen@agora.io'],
'system_wrappers': ['fengyue@agora.io',
'henrika@webrtc.org',
'mflodman@webrtc.org',
'peah@webrtc.org',
'zhengzhonghou@agora.io'],
'pc': ['steveanton+watch@webrtc.org'],
'logging': ['terelius@webrtc.org'],
},
}

View File

@ -1,91 +0,0 @@
@./common.minimal.md
# Workflow Tips
## General Workflow:
* **User Guidance:** Proactively communicate your plan and the reason for each
step.
* **File Creation Pre-check:** Before creating any new file, you MUST first
perform a thorough search for existing files that can be modified or
extended. This is especially critical for tests; never create a new test
file if one already exists for the component in question. Always add new
tests to the existing test file.
* **Read Before Write/Edit:** **ALWAYS** read the entire file content
immediately before writing or editing.
* **File Deletion:** **NEVER** perform actions that might delete files
(either directly via e.g. `rm` or indirectly via e.g. `git clean`)
without first asking the user for permission.
## Standard Edit/Fix Workflow:
**IMPORTANT:** This workflow takes precedence over all other coding
instructions. Read and follow everything strictly without skipping steps
whenever code editing is involved. Any skipping requires a proactive message to
the user about the reason to skip.
1. **Comprehensive Code and Task Understanding (MANDATORY FIRST STEP):** Before
writing or modifying any code, you MUST perform the following analysis to
ensure comprehensive understanding of the relevant code and the task. This
is a non-negotiable prerequisite for all coding tasks.
* **a. Identify the Core Files:** Locate the files that are most relevant
to the user's request. All analysis starts from these files.
* **b. Conduct a Full Audit:**
i. Read the full source of **EVERY** core file.
ii. For each core file, summarize the control flow and ownership
semantics. State the intended purpose of the core file.
* **c. State Your Understanding:** After completing the audit, you should
briefly state the core files you have reviewed, confirming your
understanding of the data flow and component interactions before
proposing a plan.
* **d. Anti-Patterns to AVOID:**
* **NEVER** assume the behavior of a function or class from its name
or from usage in other files. **ALWAYS** read the source
implementation.
* **ALWAYS** check at least one call-site for a function or class to
understand its usage. The context is as important as the
implementation.
2. **Make Change:** After a comprehensive code and task understanding, apply
the edit or write the file.
* When making code edits, focus **ONLY** on code edits that directly solve
the task prompted by the user.
3. **Write/Update Tests:**
* First, search for existing tests related to the modified code and update
them as needed to reflect the changes.
* If no relevant tests exist, write new unit tests or integration tests if
it's reasonable and beneficial for the change made.
* If tests are deemed not applicable for a specific change (e.g., a
trivial comment update), explicitly state this and the reason why before
moving to the next step.
4. **Build:** **ALWAYS** build relevant targets after making edits.
5. **Fix compile errors:** **ALWAYS** follow these steps to fix compile errors.
* **ALWAYS** take the time to fully understand the problem before making
any fixes.
* **ALWAYS** read at least one new file for each compile error.
* **ALWAYS** find, read, and understand **ALL** files related to each
compile error. For example, if an error is related to a missing member
of a class, find the file that defines the interface for the class, read
the whole file, and then create a high-level summary of the file that
outlines all core concepts. Come up with a plan to fix the error.
* **ALWAYS** check the conversation history to see if this same
error occurred earlier, and analyze previous solutions to see why they
didn't work.
* **NEVER** make speculative fixes. You should be confident before
applying any fix that it will work. If you are not confident, read more
files.
6. **Test:** **ALWAYS** run relevant tests after a successful build. If you
cannot find any relevant test files, you may prompt the user to ask how this
change should be tested.
7. **Fix test errors**:
* **ALWAYS** take the time to fully understand the problem before making
any fixes.
8. **Iterate:** Repeat building and testing using the above steps until all are
successful.
## Knowledge base
This file contains rich, helpful, task-oriented guidance for this repository:
@./knowledge_base.md

View File

@ -1,84 +0,0 @@
# Gemini-CLI Specific Directives
Instructions that apply only to gemini-cli.
* When using the `read_file` tool:
* Always set the 'limit' parameter to 20000 to prevent truncation.
* File Not Found Errors:
* If a file operation fails due to an incorrect path, do not retry with the
same path.
* Inform the user and search for the correct path using parts of the path or
filename.
# Common Directives
Instructions that are useful for WebRTC development, and not specific to a
single agentic tool.
## Paths
* All files in WebRTCs source can be read by substituting `webrtc/src` or
`//` for the current workspace (which can be determined by running `gclient
root` and appending `/src` to the output).
## Building
* Do not attempt a build without first establishing the correct output
directory and target. If you have not been given them, and you plan on doing
a build, then stop and ask before starting on any other tasks.
* Unless otherwise instructed, build with: `autoninja --quiet -C {OUT_DIR} {TARGET}`
* If given an `autoninja` command that is missing `--quiet`, add `--quiet`.
## Testing
Unless otherwise instructed, run tests with:
`tools/autotest.py --quiet --run-all --no-try-android-wrappers --no-fast-local-dev -C {OUT_DIR} {RELEVANT_TEST_FILENAMES}`
When using `tools/autotest.py`:
* Do not invoke `autoninja` beforehand because `autotest.py` automatically
builds relevant targets.
* Build targets containing colons (`:`) are not valid inputs for
`{RELEVANT_TEST_FILENAMES}`.
## Coding
* Stay on task: Do not address code health issues or TODOs in code unless it is
required to achieve your given task.
* Add code comments sparingly: Focus on *why* something is done, not *what* is
done.
## Presubmit Checks
When you have finished validating your changes through other means, run:
```sh
git cl format
git cl presubmit -u --force
```
* Fix errors / warnings related to your change, but do not fix pre-existing
warnings (from lines that you did not change).
## JNI
WebRTC on Android uses both Java and C++ frequently. Our JNI uses codegen from
`//third_party/jni_zero`.
Identifying JNI methods:
* In Java, methods annotated with `@CalledByNative` are called by C++.
* In C++, these appear as methods with a "Java_" prefix.
* In Java, methods within interfaces annotated with `@NativeMethods` are calls
into C++.
* In C++, these appear as methods with a "JNI_" prefix.
* If the first parameter is of type `long` and has a prefix of "native",
then it maps to a method of the same name on the C++ class that comes
after the "native" prefix. Eg. `void foo(long nativeBarImpl)` means you
need to find `BarImpl::Foo` in C++.
Finding JNI methods:
* To find the Java side of JNI: search for the file named `{JavaClass}.java`
(where {JavaClass} is taken from the `#include "{JavaClass}_jni.h"`.
* To find the C++ side of JNI: Search for the text `{JavaClass}_jni.h` in C++
files (where {JavaClass} is taken from the .java file name).
When making changes to JNI methods, always make changes to both the .java and
.cc/.h files involved.

View File

@ -1,59 +0,0 @@
# WebRTC Development Assistant - Meta Prompt
This document contains Agentic RAG (Retrieval-Augmented Generation) guidance.
Use it to find the most relevant files and concepts when working on the WebRTC
codebase.
## Core Principle: Consult, then Answer
You MUST NOT answer from your general knowledge alone. The WebRTC codebase is
vast and specific. Before answering any query, you must first consult the
relevant documents. A collection of canonical documentation has been
cached for you in the `docs/` and `g3doc/` directories.
## Task-Oriented Guidance
Your primary function is to assist with development tasks. Use the following
guide to determine which documents to consult.
### **Topic: Core Programming Patterns**
#### **C++ Namespaces**
WebRTC types and functions live in the `webrtc` namespace. Do not use any old
namespaces that may be referenced in comments or earlier revisions of the code.
#### **Modernization**
* **Use Strong Time Types:** Prefer `webrtc::Timestamp` and `webrtc::TimeDelta`
over raw arithmetic types for time values.
See [issue 42223979](https://issues.webrtc.org/42223979).
* **Avoid AutoThread:** Do not use `AutoThread`. In tests, use `webrtc::test::RunLoop`.
See [issue 469327588](https://issues.webrtc.org/469327588).
* **Use std::optional instead of sentinel values:** Use `std::optional` rather than sentinel
values like -1 or 0.
### **Topic: Modifying BUILD.gn files**
* **For best practices and style in `BUILD.gn` files:**
* Run `gn format` to ensure consistent style.
### **Topic: Debugging**
* **For a "header file not found" error:**
* **Consult the "Debugging Workflow for 'Header Not Found'":**
1. **Verify `deps`:** Check the `BUILD.gn` file of the failing
target. Is the dependency providing the header listed in `deps`?
2. **Verify `#include`:** Is the path in the `#include` statement
correct?
3. **Regenerate build files:** Suggest running `gn gen <out_dir>`.
4. **Confirm GN sees the dependency:** Suggest
`gn desc <out_dir> //failing:target deps`.
5. **Check for issues:** Suggest running
`gn check <out_dir> //failing:target`.
* **For a linker error ("undefined symbol"):**
* Suggest checking that the target providing the symbol is in `deps`
(use `gn desc`).
* **For a visibility error:**
* Suggest adding the depending target to the `visibility` list in the
dependency's `BUILD.gn` file.

File diff suppressed because it is too large Load Diff

126
api/DEPS
View File

@ -1,8 +1,6 @@
# This is supposed to be a complete list of top-level directories,
# excepting only api/ itself.
include_rules = [
"-.agents",
"-agents",
"-audio",
"-base",
"-build",
@ -46,115 +44,98 @@ include_rules = [
specific_include_rules = {
# Some internal headers are allowed even in API headers:
".*\\.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": [
"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": [
"audio_encoder_opus\.h": [
"+modules/audio_coding/codecs/opus/audio_encoder_opus.h",
],
"async_resolver_factory\\.h": [
"async_resolver_factory\.h": [
"+rtc_base/async_resolver_interface.h",
],
"async_dns_resolver\\.h": [
"async_dns_resolver\.h": [
"+rtc_base/socket_address.h",
],
"audio_device_defines\\.h": [
"audio_device_defines\.h": [
"+rtc_base/strings/string_builder.h",
],
"audio_format\\.h": [
"audio_format\.h": [
"+rtc_base/strings/string_builder.h",
],
"candidate\\.h": [
"candidate\.h": [
"+rtc_base/network_constants.h",
"+rtc_base/socket_address.h",
],
"create_peerconnection_factory\\.h": [
"create_peerconnection_factory\.h": [
"+rtc_base/thread.h",
],
"data_channel_interface\\.h": [
"data_channel_interface\.h": [
"+rtc_base/copy_on_write_buffer.h",
],
"data_channel_transport_interface\\.h": [
"data_channel_transport_interface\.h": [
"+rtc_base/copy_on_write_buffer.h",
],
"datagram_connection\\.h": [
"datagram_connection\.h": [
"+p2p/base/transport_description.h",
],
"mock_datagram_connection\\.h": [
"+p2p/base/transport_description.h",
],
"datagram_connection_factory\\.h": [
"datagram_connection_factory\.h": [
"+p2p/base/port_allocator.h",
"+rtc_base/rtc_certificate.h",
],
"dtls_transport_interface\\.h": [
"dtls_transport_interface\.h": [
"+rtc_base/ssl_certificate.h",
],
"fec_controller\\.h": [
"fec_controller\.h": [
"+modules/include/module_fec_types.h",
],
"ice_server_parsing\\.h": [
"+p2p/base/port_allocator.h",
"+rtc_base/socket_address.h",
],
"jsep\\.h": [
"jsep\.h": [
"+absl/strings/has_absl_stringify.h",
"+absl/strings/str_format.h",
"+rtc_base/system/no_unique_address.h",
"+rtc_base/thread_annotations.h",
],
"local_network_access_permission\\.h": [
"local_network_access_permission\.h": [
"+rtc_base/socket_address.h",
],
"packet_socket_factory\\.h": [
"packet_socket_factory\.h": [
"+rtc_base/async_packet_socket.h",
"+rtc_base/socket_address.h",
"+rtc_base/ssl_certificate.h",
],
"payload_type\\.h": [
"+absl/strings/str_format.h",
"+rtc_base/strong_alias.h",
],
"turn_customizer\\.h": [
"turn_customizer\.h": [
"+p2p/base/port_interface.h",
],
"peer_connection_interface\\.h": [
"peer_connection_interface\.h": [
"+media/base/media_config.h",
"+media/base/media_engine.h",
"+p2p/base/port.h",
"+p2p/base/port_allocator.h",
"+p2p/dtls/dtls_transport_factory.h",
"+rtc_base/network.h",
"+rtc_base/network_constants.h",
"+rtc_base/network_monitor_factory.h",
@ -164,27 +145,25 @@ specific_include_rules = {
"+rtc_base/socket_factory.h",
"+rtc_base/ssl_certificate.h",
"+rtc_base/ssl_stream_adapter.h",
"+rtc_base/system/plan_b_only.h",
"+rtc_base/thread.h",
],
"proxy\\.h": [
"proxy\.h": [
"+rtc_base/event.h",
"+rtc_base/message_handler.h", # Inherits from it.
"+rtc_base/thread.h",
],
"ref_counted_base\\.h": [
"ref_counted_base\.h": [
"+rtc_base/ref_counter.h",
],
"rtc_error\\.h": [
"rtc_error\.h": [
"+rtc_base/logging.h",
"+rtc_base/strings/string_builder.h",
"+absl/strings/has_absl_stringify.h",
"+absl/strings/str_format.h",
],
"rtc_event_log_output_file\\.h": [
"rtc_event_log_output_file.h": [
# For private member and constructor.
"+rtc_base/system/file_wrapper.h",
],
@ -192,109 +171,100 @@ specific_include_rules = {
"+rtc_base/ref_counted_object.h",
],
"legacy_stats_types\\.h": [
"legacy_stats_types\.h": [
"+rtc_base/thread_annotations.h",
"+rtc_base/thread_checker.h",
],
"audio_decoder\\.h": [
"audio_decoder\.h": [
"+rtc_base/buffer.h",
],
"audio_encoder\\.h": [
"audio_encoder\.h": [
"+rtc_base/buffer.h",
],
"make_ref_counted\\.h": [
"make_ref_counted\.h": [
"+rtc_base/ref_counted_object.h",
],
"mock.*\\.h": [
"mock.*\.h": [
"+test/gmock.h",
],
"mock_peerconnectioninterface\\.h": [
"mock_peerconnectioninterface\.h": [
"+rtc_base/ref_counted_object.h",
],
"mock_video_track\\.h": [
"mock_video_track\.h": [
"+rtc_base/ref_counted_object.h",
],
"notifier\\.h": [
"notifier\.h": [
"+rtc_base/system/no_unique_address.h",
"+rtc_base/thread_annotations.h",
],
"priority\\.h": [
"priority\.h": [
"+rtc_base/strong_alias.h",
],
"sctp_transport_interface\\.h": [
"+absl/strings/str_format.h",
],
"simulated_network\\.h": [
"simulated_network\.h": [
"+rtc_base/random.h",
"+rtc_base/thread_annotations.h",
],
"time_controller\\.h": [
"time_controller\.h": [
"+rtc_base/thread.h",
],
"videocodec_test_fixture\\.h": [
"videocodec_test_fixture\.h": [
"+modules/video_coding/include/video_codec_interface.h"
],
"rtp_parameters\\.h": [
"rtp_parameters\.h": [
"+absl/strings/str_format.h",
"+rtc_base/strings/str_join.h"
],
"sequence_checker\\.h": [
"sequence_checker\.h": [
"+rtc_base/synchronization/sequence_checker_internal.h",
"+rtc_base/thread_annotations.h",
],
"video_encoder_factory_template.*\\.h": [
"video_encoder_factory_template.*\.h": [
"+modules/video_coding",
],
"video_encoder_factory_interface\\.h": [
"video_encoder_factory_interface\.h": [
"+rtc_base/numerics",
],
"video_encoder_interface\\.h": [
"video_encoder_interface\.h": [
"+rtc_base/numerics",
],
"video_quality_test_fixture\\.h": [
"+video/config/video_encoder_config.h",
],
"simple_encoder_wrapper\\.h": [
"simple_encoder_wrapper\.h": [
"+common_video",
"+modules",
],
"video_decoder_factory_template.*\\.h": [
"video_decoder_factory_template.*\.h": [
"+modules/video_coding",
],
"field_trials\\.h": [
"field_trials\.h": [
"+rtc_base/containers/flat_map.h",
],
"video_track_source_proxy_factory\\.h": [
"video_track_source_proxy_factory.h": [
"+rtc_base/thread.h",
],
"field_trials_registry\\.h": [
"field_trials_registry\.h": [
"+rtc_base/containers/flat_set.h",
],
"ice_transport_factory\\.h": [
"ice_transport_factory\.h": [
"+p2p/base/port_allocator.h",
],
@ -302,7 +272,7 @@ specific_include_rules = {
# 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": [
".*\.cc": [
"+audio",
"+call",
"+common_audio",

View File

@ -1,23 +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 peer_connection*=eshr@webrtc.org
per-file peer_connection*=guidou@webrtc.org
per-file DEPS=mbonadei@webrtc.org
per-file uma_metrics.h=kron@webrtc.org
# Adding features via SDP munging requires approval from SDP owners
per-file webrtc_sdp.cc = set noparent
per-file webrtc_sdp.cc = hta@webrtc.org
per-file webrtc_sdp.cc = hbos@webrtc.org
per-file webrtc_sdp.cc = eshr@webrtc.org
# If none of the above are present, may also try one of these
per-file webrtc_sdp.cc = tommi@webrtc.org
per-file webrtc_sdp.cc = guidou@webrtc.org

View File

@ -11,20 +11,331 @@
#ifndef API_ARRAY_VIEW_H_
#define API_ARRAY_VIEW_H_
#include <algorithm>
#include <array>
#include <cstddef>
#include <span>
#include <iterator>
#include <type_traits>
#include "rtc_base/checks.h"
#include "rtc_base/type_traits.h"
namespace webrtc {
template <typename T, size_t extent = std::dynamic_extent>
using ArrayView = std::span<T, extent>;
// tl;dr: 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, Buffer, ...), but it's error-prone because the caller
// has to correctly specify the array length:
//
// Contains17(arr, std::size(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 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(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(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 reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
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_t<
!std::is_same_v<ArrayView, std::remove_reference_t<U>> &&
Size != array_view_internal::kArrayViewVarSize &&
HasDataAndSize<U, T>::value>* = 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_t<
!std::is_same_v<ArrayView, std::remove_reference_t<U>> &&
Size != array_view_internal::kArrayViewVarSize &&
HasDataAndSize<U, T>::value>* = 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>,
// Buffer to ArrayView<uint8_t> or ArrayView<const uint8_t>, and
// const Buffer to ArrayView<const uint8_t>.
template <typename U,
typename std::enable_if_t<
!std::is_same_v<ArrayView, std::remove_reference_t<U>> &&
Size == array_view_internal::kArrayViewVarSize &&
HasDataAndSize<U, T>::value>* = nullptr>
ArrayView(U& u) // NOLINT
: ArrayView(u.data(), u.size()) {}
template <typename U,
typename std::enable_if_t<
!std::is_same_v<ArrayView, std::remove_reference_t<U>> &&
Size == array_view_internal::kArrayViewVarSize &&
HasDataAndSize<U, T>::value>* = 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, "");
// TODO: bugs.webrtc.org/439801349 - deprecate when unused by WebRTC
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 webrtc

View File

@ -13,7 +13,6 @@
#include <array>
#include <cstddef>
#include <cstdint>
#include <span>
#include <string>
#include <utility>
#include <vector>
@ -71,10 +70,10 @@ TEST(ArrayViewDeathTest, TestConstructFromPtrAndArray) {
EXPECT_EQ(arr, wf.data());
ArrayView<char> q(arr, 0);
EXPECT_EQ(0u, q.size());
EXPECT_TRUE(q.empty());
EXPECT_EQ(nullptr, q.data());
ArrayView<char, 0> qf(arr, 0);
static_assert(qf.size() == 0, "");
EXPECT_TRUE(qf.empty());
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), "");
@ -429,8 +428,7 @@ TEST(ArrayViewDeathTest, TestIndexing) {
EXPECT_EQ('Y', y[2]);
EXPECT_EQ('X', z[3]);
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
// DCHECK error (index out of bounds).
EXPECT_DEATH(std::ignore = z[8], "");
EXPECT_DEATH(z[8], ""); // DCHECK error (index out of bounds).
#endif
}
@ -438,6 +436,7 @@ 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.
@ -446,6 +445,7 @@ TEST(ArrayViewTest, TestIterationEmpty) {
// 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.
@ -456,11 +456,13 @@ 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());
}
@ -468,7 +470,9 @@ 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);
@ -487,9 +491,16 @@ 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));
auto it = av.end() - 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);
}
@ -499,7 +510,9 @@ 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);
@ -518,9 +531,16 @@ 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));
auto it = av.end() - 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);
}
@ -531,84 +551,81 @@ TEST(ArrayViewTest, TestEmpty) {
const int a[] = {1, 2, 3};
EXPECT_FALSE(ArrayView<const int>(a).empty());
static_assert(ArrayView<int, 0>().empty());
static_assert(ArrayView<int, 0>::empty(), "");
static_assert(!ArrayView<int, 3>::empty(), "");
}
TEST(ArrayViewTest, TestSubSpanVariable) {
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_THAT(av.subspan(0), ElementsAre(1, 2, 3));
EXPECT_THAT(av.subspan(1), ElementsAre(2, 3));
EXPECT_THAT(av.subspan(2), ElementsAre(3));
EXPECT_THAT(av.subspan(3), IsEmpty());
EXPECT_EQ(av.subview(0), av);
EXPECT_THAT(av.subspan(1, 0), IsEmpty());
EXPECT_THAT(av.subspan(1, 1), ElementsAre(2));
EXPECT_THAT(av.subspan(1, 2), ElementsAre(2, 3));
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, TestSubSpanWithInvalidInput) {
TEST(ArrayViewTest, TestSubViewFixed) {
int a[] = {1, 2, 3};
ArrayView<int> av(a);
EXPECT_DEATH_IF_SUPPORTED(std::ignore = av.subspan(4), "");
EXPECT_DEATH_IF_SUPPORTED(std::ignore = av.subspan(1, 3), "");
}
TEST(ArrayViewTest, SubspanFixed) {
std::array<int, 3> a = {1, 2, 3};
ArrayView<int, 3> av(a);
EXPECT_THAT(av.subspan<0>(), ElementsAre(1, 2, 3));
EXPECT_THAT(av.subspan<1>(), ElementsAre(2, 3));
EXPECT_THAT(av.subspan<2>(), ElementsAre(3));
EXPECT_THAT(av.subspan<3>(), IsEmpty());
EXPECT_EQ(av.subview(0), av);
EXPECT_THAT((av.subspan<1, 0>()), IsEmpty());
EXPECT_THAT((av.subspan<1, 1>()), ElementsAre(2));
EXPECT_THAT((av.subspan<1, 2>()), ElementsAre(2, 3));
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_EQ(av.subspan<1>().extent, 2u);
EXPECT_EQ((av.subspan<1, 1>().extent), 1u);
ArrayView<int> dynamic_av(a);
EXPECT_THAT(dynamic_av.subspan<0>(), ElementsAre(1, 2, 3));
EXPECT_THAT(dynamic_av.subspan<1>(), ElementsAre(2, 3));
EXPECT_THAT(dynamic_av.subspan<2>(), ElementsAre(3));
EXPECT_THAT(dynamic_av.subspan<3>(), IsEmpty());
EXPECT_THAT((dynamic_av.subspan<1, 0>()), IsEmpty());
EXPECT_THAT((dynamic_av.subspan<1, 1>()), ElementsAre(2));
EXPECT_THAT((dynamic_av.subspan<1, 2>()), ElementsAre(2, 3));
EXPECT_EQ(dynamic_av.subspan<1>().extent, std::dynamic_extent);
EXPECT_EQ((dynamic_av.subspan<1, 1>()).extent, 1u);
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, FirstFixed) {
std::array<int, 3> a = {1, 2, 3};
ArrayView<int> av(a);
EXPECT_THAT(av.first<0>(), IsEmpty());
EXPECT_THAT(av.first<1>(), ElementsAre(1));
EXPECT_THAT(av.first<2>(), ElementsAre(1, 2));
EXPECT_THAT(av.first<3>(), ElementsAre(1, 2, 3));
EXPECT_EQ((av.first<0>()).extent, 0u);
EXPECT_EQ((av.first<2>()).extent, 2u);
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, LastFixed) {
std::array<int, 3> a = {1, 2, 3};
ArrayView<int> av(a);
EXPECT_THAT(av.last<0>(), IsEmpty());
EXPECT_THAT(av.last<1>(), ElementsAre(3));
EXPECT_THAT(av.last<2>(), ElementsAre(2, 3));
EXPECT_THAT(av.last<3>(), ElementsAre(1, 2, 3));
EXPECT_EQ((av.last<0>()).extent, 0u);
EXPECT_EQ((av.last<2>()).extent, 2u);
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 webrtc

View File

@ -48,11 +48,11 @@ rtc_library("audio_frame_api") {
]
deps = [
"..:array_view",
"..:rtp_packet_info",
"../../rtc_base:checks",
"../../rtc_base:logging",
"../../rtc_base:timeutils",
"//third_party/abseil-cpp/absl/algorithm:container",
]
}
@ -83,6 +83,7 @@ rtc_library("audio_processing") {
":aec3_config",
":audio_processing_statistics",
":echo_control",
"..:array_view",
"..:ref_count",
"..:scoped_refptr",
"../../rtc_base:checks",
@ -174,32 +175,7 @@ rtc_source_set("echo_control") {
rtc_source_set("neural_residual_echo_estimator_api") {
visibility = [ "*" ]
sources = [ "neural_residual_echo_estimator.h" ]
deps = [ ":aec3_config" ]
}
if (rtc_enable_protobuf) {
rtc_library("neural_residual_echo_estimator_creator") {
visibility = [ "*" ]
allow_poison = [ "default_neural_residual_echo_estimator" ]
configs += [ "../../modules/audio_processing:apm_debug_dump" ]
sources = [
"neural_residual_echo_estimator_creator.cc",
"neural_residual_echo_estimator_creator.h",
]
deps = [
":neural_residual_echo_estimator_api",
"../../modules/audio_processing/aec3/neural_residual_echo_estimator:neural_residual_echo_estimator_impl",
"../../rtc_base:checks",
"../../rtc_base/system:rtc_export",
"//third_party/abseil-cpp/absl/base:nullability",
"//third_party/abseil-cpp/absl/strings:string_view",
]
if (build_with_chromium) {
deps += [ "//third_party/tflite" ]
} else {
deps += [ "//third_party/tflite:tflite_standalone" ]
}
}
deps = [ "..:array_view" ]
}
rtc_library("echo_detector_creator") {

View File

@ -1,5 +0,0 @@
specific_include_rules = {
"neural_residual_echo_estimator_creator\\.h" : [
"+third_party/tflite",
],
}

View File

@ -1,4 +1,2 @@
devicentepena@webrtc.org
gustaf@webrtc.org
peah@webrtc.org
saza@webrtc.org

View File

@ -13,9 +13,8 @@
#include <cstdint>
#include <cstring>
#include <optional>
#include <span>
#include "absl/algorithm/container.h"
#include "api/array_view.h"
#include "api/audio/audio_view.h"
#include "api/audio/channel_layout.h"
#include "api/rtp_packet_infos.h"
@ -103,7 +102,7 @@ void AudioFrame::CopyFrom(const AudioFrame& src) {
// copying over new values. If we don't, msan might complain in some tests.
// Consider locking down construction, avoiding the default constructor and
// prefering construction that initializes all state.
absl::c_fill(data_, 0);
ClearSamples(data_);
}
timestamp_ = src.timestamp_;
@ -127,16 +126,18 @@ void AudioFrame::CopyFrom(const AudioFrame& src) {
}
const int16_t* AudioFrame::data() const {
return muted_ ? zeroed_data().data() : data_.data();
return muted_ ? zeroed_data().begin() : data_.data();
}
InterleavedView<const int16_t> AudioFrame::data_view() const {
// If you get a nullptr from `data_view()`, it's likely because the
// samples_per_channel_ and/or num_channels_ members haven't been properly
// set. `data_view()` returns an InterleavedView<> which internally
// uses std::span<>. So, even when an AudioFrame is muted and we want to
// return `zeroed_data()`, if samples_per_channel_ or num_channels_ is 0,
// the view might point to nullptr.
// set. Since `data_view()` returns an InterleavedView<> (which internally
// uses ArrayView<>), we inherit the behavior in InterleavedView when
// the view size is 0 that ArrayView<>::data() returns nullptr. So, even when
// an AudioFrame is muted and we want to return `zeroed_data()`, if
// samples_per_channel_ or num_channels_ is 0, the view will point to
// nullptr.
return InterleavedView<const int16_t>(muted_ ? &zeroed_data()[0] : &data_[0],
samples_per_channel_, num_channels_);
}
@ -146,7 +147,7 @@ int16_t* AudioFrame::mutable_data() {
// Consider instead if we should rather zero the buffer when `muted_` is set
// to `true`.
if (muted_) {
absl::c_fill(data_, 0);
ClearSamples(data_);
muted_ = false;
}
return &data_[0];
@ -169,7 +170,7 @@ InterleavedView<int16_t> AudioFrame::mutable_data(size_t samples_per_channel,
// Consider instead if we should rather zero the whole buffer when `muted_` is
// set to `true`.
if (muted_) {
absl::c_fill_n(data_, total_samples, 0);
ClearSamples(data_, total_samples);
muted_ = false;
}
samples_per_channel_ = samples_per_channel;
@ -211,9 +212,9 @@ void AudioFrame::SetSampleRateAndChannelSize(int sample_rate) {
}
// static
std::span<const int16_t> AudioFrame::zeroed_data() {
ArrayView<const int16_t> AudioFrame::zeroed_data() {
static int16_t* null_data = new int16_t[kMaxDataSizeSamples]();
return std::span<const int16_t>(null_data, kMaxDataSizeSamples);
return ArrayView<const int16_t>(null_data, kMaxDataSizeSamples);
}
} // namespace webrtc

View File

@ -16,8 +16,8 @@
#include <array>
#include <optional>
#include <span>
#include "api/array_view.h"
#include "api/audio/audio_view.h"
#include "api/audio/channel_layout.h"
#include "api/rtp_packet_infos.h"
@ -199,7 +199,7 @@ class AudioFrame {
// A permanently zeroed out buffer to represent muted frames. This is a
// header-only class, so the only way to avoid creating a separate zeroed
// buffer per translation unit is to wrap a static in an inline function.
static std::span<const int16_t> zeroed_data();
static ArrayView<const int16_t> zeroed_data();
std::array<int16_t, kMaxDataSizeSamples> data_;
bool muted_ = true;

View File

@ -145,6 +145,7 @@ std::string AudioProcessing::Config::ToString() const {
<< capture_level_adjustment.analog_mic_gain_emulation.initial_level
<< " }}, high_pass_filter: { enabled: " << high_pass_filter.enabled
<< " }, echo_canceller: { enabled: " << echo_canceller.enabled
<< ", mobile_mode: " << echo_canceller.mobile_mode
<< ", enforce_high_pass_filtering: "
<< echo_canceller.enforce_high_pass_filtering
<< " }, noise_suppression: { enabled: " << noise_suppression.enabled

View File

@ -18,11 +18,11 @@
#include <cstring>
#include <memory>
#include <optional>
#include <span>
#include <string>
#include "absl/base/nullability.h"
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/audio/audio_processing_statistics.h"
#include "api/audio/echo_control.h"
#include "api/environment/environment.h"
@ -80,6 +80,7 @@ class EchoDetector;
//
// AudioProcessing::Config config;
// config.echo_canceller.enabled = true;
// config.echo_canceller.mobile_mode = false;
//
// config.gain_controller1.enabled = true;
// config.gain_controller1.mode =
@ -139,23 +140,20 @@ class RTC_EXPORT AudioProcessing : public RefCountInterface {
// Ways to downmix a multi-channel track to mono.
enum class DownmixMethod {
kAverageChannels, // Average across channels.
kUseFirstChannel, // Use the first channel.
kAdaptive // Adaptively choose how to downmix.
kUseFirstChannel // Use the first channel.
};
// Maximum allowed processing rate used internally. May only be set to
// 32000 or 48000 and any differing values will be treated as 48000.
int maximum_internal_processing_rate = 32000;
int maximum_internal_processing_rate = 48000;
// Allow multi-channel processing of render audio.
bool multi_channel_render = true;
bool multi_channel_render = false;
// Allow multi-channel processing of capture audio when AEC3 is active
// or a custom AEC is injected.
bool multi_channel_capture = true;
// or a custom AEC is injected..
bool multi_channel_capture = false;
// Indicates how to downmix multi-channel capture audio to mono (when
// needed).
DownmixMethod capture_downmix_method = DownmixMethod::kAverageChannels;
DownmixMethod capture_downmix_method_stereo_aec =
DownmixMethod::kAverageChannels;
} pipeline;
// Enabled the pre-amplifier. It amplifies the capture signal
@ -198,8 +196,10 @@ class RTC_EXPORT AudioProcessing : public RefCountInterface {
struct EchoCanceller {
bool enabled = false;
bool mobile_mode = false;
bool export_linear_aec_output = false;
// Enforce the highpass filter to be on.
// Enforce the highpass filter to be on (has no effect for the mobile
// mode).
bool enforce_high_pass_filtering = true;
} echo_canceller;
@ -393,8 +393,8 @@ class RTC_EXPORT AudioProcessing : public RefCountInterface {
// Play-out audio device properties.
struct PlayoutAudioDeviceInfo {
int id = 0; // Identifies the audio device.
int max_volume = 0; // Maximum play-out volume.
int id; // Identifies the audio device.
int max_volume; // Maximum play-out volume.
};
RuntimeSetting() : type_(Type::kNotSpecified), value_(0.0f) {}
@ -592,7 +592,7 @@ class RTC_EXPORT AudioProcessing : public RefCountInterface {
// representation of the input is returned. Returns true/false to indicate
// whether an output returned.
virtual bool GetLinearAecOutput(
std::span<std::array<float, 160>> linear_output) const = 0;
ArrayView<std::array<float, 160>> linear_output) const = 0;
// This must be called prior to ProcessStream() if and only if adaptive analog
// gain control is enabled, to pass the current analog level from the audio
@ -874,10 +874,10 @@ class EchoDetector : public RefCountInterface {
int num_render_channels) = 0;
// Analysis (not changing) of the first channel of the render signal.
virtual void AnalyzeRenderAudio(std::span<const float> render_audio) = 0;
virtual void AnalyzeRenderAudio(ArrayView<const float> render_audio) = 0;
// Analysis (not changing) of the capture signal.
virtual void AnalyzeCaptureAudio(std::span<const float> capture_audio) = 0;
virtual void AnalyzeCaptureAudio(ArrayView<const float> capture_audio) = 0;
struct Metrics {
std::optional<double> echo_likelihood;

View File

@ -13,11 +13,10 @@
#include <cstddef>
#include <iterator>
#include <span>
#include <variant>
#include <vector>
#include "absl/algorithm/container.h"
#include "api/array_view.h"
#include "rtc_base/checks.h"
namespace webrtc {
@ -34,7 +33,7 @@ namespace webrtc {
// buffer. Channels can be enumerated and accessing the individual channel
// data is done via MonoView<>.
//
// The views are comparable to and built on std::span<> but add
// The views are comparable to and built on ArrayView<> but add
// audio specific properties for the dimensions of the buffer and the above
// specialized [de]interleaved support.
//
@ -45,13 +44,14 @@ namespace webrtc {
// can be either an single channel (mono) interleaved buffer (e.g. AudioFrame),
// or a de-interleaved channel (e.g. from AudioBuffer).
template <typename T>
using MonoView = std::span<T>;
using MonoView = ArrayView<T>;
// The maximum number of audio channels supported by WebRTC encoders, decoders
// and the AudioFrame class.
// AudioFrame's max number of samples is 7680, which can hold 16 10ms 16bit
// channels at 48 kHz.
static constexpr size_t kMaxNumberOfAudioChannels = 16;
// TODO(peah, tommi): Should kMaxNumberOfAudioChannels be 16 rather than 24?
// The reason is that AudioFrame's max number of samples is 7680, which can
// hold 16 10ms 16bit channels at 48 kHz (and not 24 channels).
static constexpr size_t kMaxNumberOfAudioChannels = 24;
// InterleavedView<> is a view over an interleaved audio buffer (e.g. from
// AudioFrame).
@ -59,8 +59,6 @@ template <typename T>
class InterleavedView {
public:
using value_type = T;
using iterator = typename std::span<T>::iterator;
using const_iterator = typename std::span<const T>::iterator;
InterleavedView() = default;
@ -90,7 +88,7 @@ class InterleavedView {
size_t num_channels() const { return num_channels_; }
size_t samples_per_channel() const { return samples_per_channel_; }
std::span<T> data() const { return data_; }
ArrayView<T> data() const { return data_; }
bool empty() const { return data_.empty(); }
size_t size() const { return data_.size(); }
@ -114,16 +112,14 @@ class InterleavedView {
}
T& operator[](size_t idx) const { return data_[idx]; }
iterator begin() const { return data_.begin(); }
iterator end() const { return data_.end(); }
const_iterator cbegin() const { return data_.begin(); }
const_iterator cend() const { return data_.end(); }
std::reverse_iterator<iterator> rbegin() const { return data_.rbegin(); }
std::reverse_iterator<iterator> rend() const { return data_.rend(); }
std::reverse_iterator<const_iterator> crbegin() const {
return data_.rbegin();
}
std::reverse_iterator<const_iterator> crend() const { return data_.rend(); }
T* begin() const { return data_.begin(); }
T* end() const { return data_.end(); }
const T* cbegin() const { return data_.cbegin(); }
const T* cend() const { return data_.cend(); }
std::reverse_iterator<T*> rbegin() const { return data_.rbegin(); }
std::reverse_iterator<T*> rend() const { return data_.rend(); }
std::reverse_iterator<const T*> crbegin() const { return data_.crbegin(); }
std::reverse_iterator<const T*> crend() const { return data_.crend(); }
private:
// TODO(tommi): Consider having these both be stored as uint16_t to
@ -131,7 +127,7 @@ class InterleavedView {
// construction.
size_t num_channels_ = 0u;
size_t samples_per_channel_ = 0u;
std::span<T> data_;
ArrayView<T> data_;
};
template <typename T>
@ -211,7 +207,7 @@ class DeinterleavedView {
void Clear() {
for (size_t i = 0u; i < num_channels_; ++i) {
MonoView<T> view = (*this)[i];
absl::c_fill(view, 0);
ClearSamples(view);
}
}
@ -308,6 +304,22 @@ void CopySamples(D& destination, const S& source) {
source.size() * sizeof(typename S::value_type));
}
// Sets all the samples in a view to 0. This template function is a simple
// wrapper around `memset()` but adds the benefit of automatically calculating
// the byte size from the number of samples and sample type.
template <typename T>
void ClearSamples(T& view) {
memset(&view[0], 0, view.size() * sizeof(typename T::value_type));
}
// Same as `ClearSamples()` above but allows for clearing only the first
// `sample_count` number of samples.
template <typename T>
void ClearSamples(T& view, size_t sample_count) {
RTC_DCHECK_LE(sample_count, view.size());
memset(&view[0], 0, sample_count * sizeof(typename T::value_type));
}
} // namespace webrtc
#endif // API_AUDIO_AUDIO_VIEW_H_

View File

@ -51,7 +51,7 @@ struct RTC_EXPORT EchoCanceller3Config {
struct DelaySelectionThresholds {
int initial;
int converged;
} delay_selection_thresholds = {.initial = 5, .converged = 20};
} delay_selection_thresholds = {5, 20};
bool use_external_delay_estimator = false;
bool log_warning_on_delay_changes = false;
struct AlignmentMixing {
@ -60,16 +60,8 @@ struct RTC_EXPORT EchoCanceller3Config {
float activity_power_threshold;
bool prefer_first_two_channels;
};
AlignmentMixing render_alignment_mixing = {
.downmix = false,
.adaptive_selection = true,
.activity_power_threshold = 10000.f,
.prefer_first_two_channels = true};
AlignmentMixing capture_alignment_mixing = {
.downmix = false,
.adaptive_selection = true,
.activity_power_threshold = 10000.f,
.prefer_first_two_channels = false};
AlignmentMixing render_alignment_mixing = {false, true, 10000.f, true};
AlignmentMixing capture_alignment_mixing = {false, true, 10000.f, false};
bool detect_pre_echo = true;
} delay;
@ -89,25 +81,13 @@ struct RTC_EXPORT EchoCanceller3Config {
float noise_gate;
};
RefinedConfiguration refined = {.length_blocks = 13,
.leakage_converged = 0.00005f,
.leakage_diverged = 0.05f,
.error_floor = 0.001f,
.error_ceil = 2.f,
.noise_gate = 20075344.f};
CoarseConfiguration coarse = {.length_blocks = 13,
.rate = 0.7f,
.noise_gate = 20075344.f};
RefinedConfiguration refined = {13, 0.00005f, 0.05f,
0.001f, 2.f, 20075344.f};
CoarseConfiguration coarse = {13, 0.7f, 20075344.f};
RefinedConfiguration refined_initial = {.length_blocks = 12,
.leakage_converged = 0.005f,
.leakage_diverged = 0.5f,
.error_floor = 0.001f,
.error_ceil = 2.f,
.noise_gate = 20075344.f};
CoarseConfiguration coarse_initial = {.length_blocks = 12,
.rate = 0.9f,
.noise_gate = 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;
@ -242,8 +222,8 @@ struct RTC_EXPORT EchoCanceller3Config {
size_t low;
size_t high;
};
SubbandRegion subband1 = {.low = 1, .high = 1};
SubbandRegion subband2 = {.low = 1, .high = 1};
SubbandRegion subband1 = {1, 1};
SubbandRegion subband2 = {1, 1};
float nearend_threshold = 1.f;
float snr_threshold = 1.f;
} subband_nearend_detection;

View File

@ -12,12 +12,10 @@
#define API_AUDIO_NEURAL_RESIDUAL_ECHO_ESTIMATOR_H_
#include <array>
#include <span>
#include "api/audio/echo_canceller3_config.h"
#include "api/array_view.h"
namespace webrtc {
class Block;
// Interface for a neural residual echo estimator module injected into the echo
// canceller.
@ -26,14 +24,13 @@ class Block;
class NeuralResidualEchoEstimator {
public:
virtual ~NeuralResidualEchoEstimator() {}
// Estimates residual echo power spectrum in the signal after linear AEC
// subtraction. Returns two estimates:
// * R2: A conservative estimate.
// * R2_unbounded: A less conservative estimate.
//
// Input signals:
// * render: Render block (time-domain)
// * x: Render signal (time-domain)
// * y: Microphone signal (time-domain)
// * e: Output from linear subtraction stage (time-domain)
//
@ -41,29 +38,14 @@ class NeuralResidualEchoEstimator {
// * S2: Linear echo estimate
// * Y2: Microphone input
// * E2: Output of linear stage
//
// Other inputs:
// * dominant_nearend: True if dominant nearend is active
virtual void Estimate(const Block& render,
std::span<const std::array<float, 64>> y,
std::span<const std::array<float, 64>> e,
std::span<const std::array<float, 65>> S2,
std::span<const std::array<float, 65>> Y2,
std::span<const std::array<float, 65>> E2,
bool dominant_nearend,
std::span<std::array<float, 65>> R2,
std::span<std::array<float, 65>> R2_unbounded) = 0;
// Returns a recommended AEC3 configuration for this estimator.
virtual EchoCanceller3Config GetConfiguration(bool multi_channel) const = 0;
// Adjusts the provided AEC3 suppressor configuration based on the estimator's
// requirements.
virtual EchoCanceller3Config::Suppressor AdjustConfig(
const EchoCanceller3Config::Suppressor& config) const = 0;
// Resets the internal state of the estimator.
virtual void Reset() = 0;
virtual void Estimate(ArrayView<const float> x,
ArrayView<const std::array<float, 64>> y,
ArrayView<const std::array<float, 64>> e,
ArrayView<const std::array<float, 65>> S2,
ArrayView<const std::array<float, 65>> Y2,
ArrayView<const std::array<float, 65>> E2,
ArrayView<std::array<float, 65>> R2,
ArrayView<std::array<float, 65>> R2_unbounded) = 0;
};
} // namespace webrtc

View File

@ -1,32 +0,0 @@
/*
* Copyright (c) 2025 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can 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/neural_residual_echo_estimator_creator.h"
#include <memory>
#include "absl/base/nullability.h"
#include "api/audio/neural_residual_echo_estimator.h"
#include "modules/audio_processing/aec3/neural_residual_echo_estimator/neural_residual_echo_estimator_impl.h"
#include "rtc_base/checks.h"
#include "third_party/tflite/src/tensorflow/lite/model_builder.h"
#include "third_party/tflite/src/tensorflow/lite/op_resolver.h"
namespace webrtc {
absl_nullable std::unique_ptr<NeuralResidualEchoEstimator>
CreateNeuralResidualEchoEstimator(const tflite::FlatBufferModel* model,
const tflite::OpResolver* absl_nonnull
op_resolver) {
RTC_CHECK(op_resolver);
return NeuralResidualEchoEstimatorImpl::Create(model, *op_resolver);
}
} // namespace webrtc

View File

@ -1,40 +0,0 @@
/*
* Copyright (c) 2025 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* 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_NEURAL_RESIDUAL_ECHO_ESTIMATOR_CREATOR_H_
#define API_AUDIO_NEURAL_RESIDUAL_ECHO_ESTIMATOR_CREATOR_H_
#include <memory>
#include "absl/base/nullability.h"
#include "api/audio/neural_residual_echo_estimator.h"
#include "rtc_base/system/rtc_export.h"
#include "third_party/tflite/src/tensorflow/lite/model_builder.h"
namespace tflite {
class OpResolver;
} // namespace tflite
namespace webrtc {
// Returns an instance of the WebRTC implementation of a residual echo detector.
// Returns nullptr if unable to read the file or initialize a model from the
// file contents.
//
// Beware: This is an experimental API and may change without notice.
RTC_EXPORT
absl_nullable std::unique_ptr<NeuralResidualEchoEstimator>
CreateNeuralResidualEchoEstimator(const tflite::FlatBufferModel* model,
const tflite::OpResolver* absl_nonnull
op_resolver);
} // namespace webrtc
#endif // API_AUDIO_NEURAL_RESIDUAL_ECHO_ESTIMATOR_CREATOR_H_

View File

@ -23,6 +23,7 @@ if (rtc_include_tests) {
deps = [
"..:aec3_config",
"..:audio_frame_api",
"../..:array_view",
"../../../modules/audio_processing:aec3_config_json",
"../../../rtc_base:checks",
"../../../test:test_support",

View File

@ -66,7 +66,7 @@ TEST(AudioFrameTest, FrameStartsZeroedAndMuted) {
EXPECT_TRUE(AllSamplesAre(0, frame));
}
// TODO: b/335805780 - Delete test when `mutable_data()` returns std::span.
// TODO: b/335805780 - Delete test when `mutable_data()` returns ArrayView.
TEST(AudioFrameTest, UnmutedFrameIsInitiallyZeroedLegacy) {
AudioFrame frame(kSampleRateHz, kNumChannelsMono, CHANNEL_LAYOUT_NONE);
frame.mutable_data();
@ -88,7 +88,7 @@ TEST(AudioFrameTest, UnmutedFrameIsInitiallyZeroed) {
TEST(AudioFrameTest, MutedFrameBufferIsZeroed) {
AudioFrame frame;
int16_t* frame_data =
frame.mutable_data(kSamplesPerChannel, kNumChannelsMono).data().data();
frame.mutable_data(kSamplesPerChannel, kNumChannelsMono).begin();
EXPECT_FALSE(frame.muted());
// Fill the reserved buffer with non-zero data.
for (size_t i = 0; i < frame.max_16bit_samples(); i++) {

View File

@ -13,9 +13,9 @@
#include <array>
#include <cstddef>
#include <cstdint>
#include <span>
#include <vector>
#include "api/array_view.h"
#include "test/gtest.h"
namespace webrtc {
@ -37,7 +37,7 @@ void Increment(int16_t& t) {
// Fills a given buffer with monotonically increasing values.
template <typename T>
void FillBuffer(std::span<T> buffer) {
void FillBuffer(ArrayView<T> buffer) {
T value = {};
for (T& t : buffer) {
Increment<T>(value);
@ -50,7 +50,7 @@ void FillBuffer(std::span<T> buffer) {
TEST(AudioViewTest, MonoView) {
const size_t kArraySize = 100u;
int16_t arr[kArraySize];
FillBuffer(std::span<int16_t>(arr));
FillBuffer(ArrayView<int16_t>(arr));
MonoView<int16_t> mono(arr);
MonoView<const int16_t> const_mono(arr);
@ -69,16 +69,15 @@ TEST(AudioViewTest, MonoView) {
TEST(AudioViewTest, InterleavedView) {
const size_t kArraySize = 100u;
int16_t arr[kArraySize];
FillBuffer(std::span<int16_t>(arr));
FillBuffer(ArrayView<int16_t>(arr));
InterleavedView<int16_t> interleaved(arr, kArraySize, 1);
EXPECT_EQ(NumChannels(interleaved), 1u);
EXPECT_TRUE(IsMono(interleaved));
EXPECT_EQ(SamplesPerChannel(interleaved), kArraySize);
EXPECT_EQ(interleaved.AsMono().size(), std::size(arr));
EXPECT_EQ(interleaved.AsMono().data(), std::data(arr));
EXPECT_EQ(interleaved.AsMono().size(), interleaved.data().size());
EXPECT_EQ(interleaved.AsMono().data(), interleaved.data().data());
EXPECT_EQ(interleaved.AsMono().size(), kArraySize);
EXPECT_EQ(&interleaved.AsMono()[0], &arr[0]);
EXPECT_EQ(interleaved.AsMono(), interleaved.data());
// Basic iterator test.
int i = 0;
@ -122,9 +121,7 @@ TEST(AudioViewTest, DeinterleavedView) {
auto mono_ch = di.AsMono();
EXPECT_EQ(NumChannels(mono_ch), 1u);
EXPECT_EQ(SamplesPerChannel(mono_ch), 10u);
// first channel should be same as mono.
EXPECT_EQ(di[0].data(), mono_ch.data());
EXPECT_EQ(di[0].size(), mono_ch.size());
EXPECT_EQ(di[0], mono_ch); // first channel should be same as mono.
di = DeinterleavedView<int16_t>(arr, 50, 2);
// Test assignment.
@ -144,7 +141,7 @@ TEST(AudioViewTest, CopySamples) {
const size_t kArraySize = 100u;
int16_t source_arr[kArraySize] = {};
int16_t dest_arr[kArraySize] = {};
FillBuffer(std::span<int16_t>(source_arr));
FillBuffer(ArrayView<int16_t>(source_arr));
InterleavedView<const int16_t> source(source_arr, 2);
InterleavedView<int16_t> destination(dest_arr, 2);
@ -165,6 +162,36 @@ TEST(AudioViewTest, CopySamples) {
}
}
TEST(AudioViewTest, ClearSamples) {
std::array<int16_t, 100u> samples = {};
FillBuffer(ArrayView<int16_t>(samples));
ASSERT_NE(samples[0], 0);
ClearSamples(samples);
for (const auto s : samples) {
ASSERT_EQ(s, 0);
}
std::array<float, 100u> samples_f = {};
FillBuffer(ArrayView<float>(samples_f));
ASSERT_NE(samples_f[0], 0.0);
ClearSamples(samples_f);
for (const auto s : samples_f) {
ASSERT_EQ(s, 0.0);
}
// Clear only half of the buffer
FillBuffer(ArrayView<int16_t>(samples));
const auto half_way = samples.size() / 2;
ClearSamples(samples, half_way);
for (size_t i = 0u; i < samples.size(); ++i) {
if (i < half_way) {
ASSERT_EQ(samples[i], 0);
} else {
ASSERT_NE(samples[i], 0);
}
}
}
TEST(AudioViewTest, DeinterleavedViewPointerArray) {
// Create vectors of varying sizes to guarantee that they don't end up
// aligned in memory.

View File

@ -29,6 +29,7 @@ rtc_library("audio_codecs_api") {
"audio_format.h",
]
deps = [
"..:array_view",
"..:bitrate_allocation",
"..:make_ref_counted",
"..:ref_count",

View File

@ -1,2 +1,3 @@
alessiob@webrtc.org
henrik.lundin@webrtc.org
jakobi@webrtc.org

View File

@ -14,10 +14,10 @@
#include <cstdint>
#include <memory>
#include <optional>
#include <span>
#include <utility>
#include <vector>
#include "api/array_view.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/sanitizer.h"
@ -41,7 +41,7 @@ class OldStyleEncodedFrame final : public AudioDecoder::EncodedAudioFrame {
}
std::optional<DecodeResult> Decode(
std::span<int16_t> decoded) const override {
ArrayView<int16_t> decoded) const override {
auto speech_type = AudioDecoder::kSpeech;
const int ret = decoder_->Decode(
payload_.data(), payload_.size(), decoder_->SampleRateHz(),
@ -87,16 +87,6 @@ std::vector<AudioDecoder::ParseResult> AudioDecoder::ParsePayload(
return results;
}
// RingRTC change to support Opus DRED
#if WEBRTC_OPUS_SUPPORT_DRED
std::vector<AudioDecoder::ParseResult> AudioDecoder::ParsePayloadRedundancy(
Buffer&& payload,
uint32_t timestamp,
uint32_t recovery_timestamp_offset) {
return ParsePayload(std::move(payload), timestamp);
}
#endif
int AudioDecoder::Decode(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
@ -104,7 +94,7 @@ int AudioDecoder::Decode(const uint8_t* encoded,
int16_t* decoded,
SpeechType* speech_type) {
TRACE_EVENT0("webrtc", "AudioDecoder::Decode");
MsanCheckInitialized(std::span(encoded, encoded_len));
MsanCheckInitialized(MakeArrayView(encoded, encoded_len));
int duration = PacketDuration(encoded, encoded_len);
if (duration >= 0 &&
duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {
@ -121,7 +111,7 @@ int AudioDecoder::DecodeRedundant(const uint8_t* encoded,
int16_t* decoded,
SpeechType* speech_type) {
TRACE_EVENT0("webrtc", "AudioDecoder::DecodeRedundant");
MsanCheckInitialized(std::span(encoded, encoded_len));
MsanCheckInitialized(MakeArrayView(encoded, encoded_len));
int duration = PacketDurationRedundant(encoded, encoded_len);
if (duration >= 0 &&
duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {

View File

@ -16,13 +16,11 @@
#include <memory>
#include <optional>
#include <span>
#include <vector>
#include "api/array_view.h"
#include "api/audio/audio_view.h"
#include "rtc_base/buffer.h"
// RingRTC Change to configure opus
#include "rtc_base/logging.h"
namespace webrtc {
@ -65,7 +63,7 @@ class AudioDecoder {
// decoder produced comfort noise or speech. On failure, returns an empty
// std::optional. Decode may be called at most once per frame object.
virtual std::optional<DecodeResult> Decode(
std::span<int16_t> decoded) const = 0;
ArrayView<int16_t> decoded) const = 0;
};
struct ParseResult {
@ -96,14 +94,6 @@ class AudioDecoder {
virtual std::vector<ParseResult> ParsePayload(Buffer&& payload,
uint32_t timestamp);
// RingRTC change to support Opus DRED
#if WEBRTC_OPUS_SUPPORT_DRED
virtual std::vector<ParseResult> ParsePayloadRedundancy(
Buffer&& payload,
uint32_t timestamp,
uint32_t recovery_timestamp_offset);
#endif
// TODO(bugs.webrtc.org/10098): The Decode and DecodeRedundant methods are
// obsolete; callers should call ParsePayload instead. For now, subclasses
// must still implement DecodeInternal.
@ -186,28 +176,6 @@ class AudioDecoder {
// The maximum number of audio channels supported by WebRTC decoders.
static constexpr int kMaxNumberOfChannels = kMaxNumberOfAudioChannels;
// RingRTC change to configure opus
// Very OPUS-specific
struct Config {
// DNN weights blob
const void* dnn_weights_data = nullptr;
int32_t dnn_weights_length = 0;
// Decoder complexity:
// -1: Use NetEq PLC (default)
// 0: Use Opus PLC
// 4: Use Opus BWE (not supported)
// 5: Use Opus Deep PLC
// 6: Use Opus Deep PLC and LACE (not supported)
// 7: Use Opus Deep PLC and NoLACE (not supported)
int32_t complexity = -1;
};
virtual bool Configure(const Config& config) {
RTC_LOG(LS_WARNING) << "Default AudioDecoder::Configure(...) does nothing!";
return false;
}
// end RingRTC change to configure opus
protected:
static SpeechType ConvertSpeechType(int16_t type);

View File

@ -31,24 +31,24 @@ class AudioDecoderFactory : public RefCountInterface {
virtual bool IsSupportedDecoder(const SdpAudioFormat& format) = 0;
// Creates a new decoder instance.
virtual absl_nullable std::unique_ptr<AudioDecoder> Create(
const Environment& env,
const SdpAudioFormat& format) {
return Create(env, format, std::nullopt);
}
// Backwards compatible call format. The "codec_pair_id" refers to deleted
// functionality for linking encoders to decoders; this is no longer used.
// TODO: https://issues.webrtc.org/398550915 - remove when no longer used,
// and make above method pure virtual.
// 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::Create() and a AudioDecoderFactory::Create() 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 absl_nullable std::unique_ptr<AudioDecoder> Create(
const Environment& env,
const SdpAudioFormat& format,
std::optional<AudioCodecPairId> /* codec_pair_id */) {
// Note: If neither method is implemented, this default implementation
// will result in a stack overflow.
return Create(env, format);
}
std::optional<AudioCodecPairId> codec_pair_id) = 0;
};
} // namespace webrtc

View File

@ -53,37 +53,7 @@ struct Helper<> {
// Use ranked overloads (abseil.io/tips/229) for dispatching.
struct Rank0 {};
struct Rank1 : Rank0 {};
struct Rank2 : Rank1 {};
struct Rank3 : Rank2 {};
template <typename Trait,
typename = std::enable_if_t<std::is_convertible_v<
decltype(Trait::MakeAudioDecoder(
std::declval<Environment>(),
std::declval<typename Trait::Config>())),
std::unique_ptr<AudioDecoder>>>>
absl_nullable std::unique_ptr<AudioDecoder> CreateDecoder(
Rank3,
const Environment& env,
typename Trait::Config config,
std::optional<AudioCodecPairId> /* codec_pair_id */) {
return Trait::MakeAudioDecoder(env, std::move(config));
}
template <typename Trait,
typename = std::enable_if_t<std::is_convertible_v<
decltype(Trait::MakeAudioDecoder(
std::declval<typename Trait::Config>())),
std::unique_ptr<AudioDecoder>>>>
absl_nullable std::unique_ptr<AudioDecoder> CreateDecoder(
Rank2,
const Environment& /* env */,
typename Trait::Config config,
std::optional<AudioCodecPairId> /* codec_pair_id */) {
return Trait::MakeAudioDecoder(std::move(config));
}
// For backwards compatibility: With CodecPairId argument in decoder
template <typename Trait,
typename = std::enable_if_t<std::is_convertible_v<
decltype(Trait::MakeAudioDecoder(
@ -94,9 +64,9 @@ template <typename Trait,
absl_nullable std::unique_ptr<AudioDecoder> CreateDecoder(
Rank1,
const Environment& env,
typename Trait::Config config,
const typename Trait::Config& config,
std::optional<AudioCodecPairId> codec_pair_id) {
return Trait::MakeAudioDecoder(env, std::move(config), codec_pair_id);
return Trait::MakeAudioDecoder(env, config, codec_pair_id);
}
template <typename Trait,
@ -108,9 +78,9 @@ template <typename Trait,
absl_nullable std::unique_ptr<AudioDecoder> CreateDecoder(
Rank0,
const Environment& /* env */,
typename Trait::Config config,
const typename Trait::Config& config,
std::optional<AudioCodecPairId> codec_pair_id) {
return Trait::MakeAudioDecoder(std::move(config), codec_pair_id);
return Trait::MakeAudioDecoder(config, codec_pair_id);
}
// Inductive case: Called with n + 1 template parameters; calls subroutines
@ -136,8 +106,7 @@ struct Helper<T, Ts...> {
std::optional<AudioCodecPairId> codec_pair_id) {
auto opt_config = T::SdpToConfig(format);
return opt_config.has_value()
? CreateDecoder<T>(Rank3{}, env, *std::move(opt_config),
codec_pair_id)
? CreateDecoder<T>(Rank1{}, env, *opt_config, codec_pair_id)
: Helper<Ts...>::MakeAudioDecoder(env, format, codec_pair_id);
}
};

View File

@ -14,9 +14,9 @@
#include <cstdint>
#include <memory>
#include <optional>
#include <span>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/call/bitrate_allocation.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
@ -45,7 +45,7 @@ int AudioEncoder::RtpTimestampRateHz() const {
}
AudioEncoder::EncodedInfo AudioEncoder::Encode(uint32_t rtp_timestamp,
std::span<const int16_t> audio,
ArrayView<const int16_t> audio,
Buffer* encoded) {
TRACE_EVENT0("webrtc", "AudioEncoder::Encode");
RTC_CHECK_EQ(audio.size(),
@ -77,9 +77,9 @@ void AudioEncoder::SetMaxPlaybackRate(int /* frequency_hz */) {}
void AudioEncoder::SetTargetBitrate(int /* target_bps */) {}
std::span<std::unique_ptr<AudioEncoder>>
ArrayView<std::unique_ptr<AudioEncoder>>
AudioEncoder::ReclaimContainedEncoders() {
return {};
return nullptr;
}
bool AudioEncoder::EnableAudioNetworkAdaptor(absl::string_view /*config*/) {

View File

@ -16,12 +16,12 @@
#include <memory>
#include <optional>
#include <span>
#include <utility>
#include <vector>
#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/audio/audio_view.h"
#include "api/call/bitrate_allocation.h"
#include "api/units/data_rate.h"
@ -117,7 +117,7 @@ class AudioEncoder {
std::vector<EncodedInfoLeaf> redundant;
};
// RingRTC change to configure opus
// RingRTC change to enable configuring OPUS
// Very OPUS-specific
struct Config {
// AKA ptime or frame size
@ -154,16 +154,6 @@ class AudioEncoder {
// In-band FEC is enabled by default
bool enable_fec = true;
// DRED duration (1 to 100), 0 to disable
int32_t dred_duration = 0;
// Minimum packet loss percentage (0-100)
int32_t min_packet_loss_percent = 0;
// DNN weights blob
const void* dnn_weights_data = nullptr;
int32_t dnn_weights_length = 0;
};
virtual ~AudioEncoder() = default;
@ -200,7 +190,7 @@ class AudioEncoder {
// EncodeImpl() which does the actual work, and then checks some
// postconditions.
EncodedInfo Encode(uint32_t rtp_timestamp,
std::span<const int16_t> audio,
ArrayView<const int16_t> audio,
Buffer* encoded);
// Resets the encoder to its starting state, discarding any input that has
@ -246,7 +236,7 @@ class AudioEncoder {
// 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 std::span<std::unique_ptr<AudioEncoder>> ReclaimContainedEncoders();
virtual ArrayView<std::unique_ptr<AudioEncoder>> ReclaimContainedEncoders();
// Enables audio network adaptor. Returns true if successful.
virtual bool EnableAudioNetworkAdaptor(absl::string_view config);
@ -316,7 +306,7 @@ class AudioEncoder {
// Subclasses implement this to perform the actual encoding. Called by
// Encode().
virtual EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
std::span<const int16_t> audio,
ArrayView<const int16_t> audio,
Buffer* encoded) = 0;
};
} // namespace webrtc

View File

@ -53,7 +53,6 @@ struct Helper<> {
// Use ranked overloads (abseil.io/tips/229) for dispatching.
struct Rank0 {};
struct Rank1 : Rank0 {};
struct Rank2 : Rank1 {};
template <typename Trait,
typename = std::enable_if_t<std::is_convertible_v<
@ -63,25 +62,11 @@ template <typename Trait,
std::declval<AudioEncoderFactory::Options>())),
std::unique_ptr<AudioEncoder>>>>
absl_nullable std::unique_ptr<AudioEncoder> CreateEncoder(
Rank2, // most preferred
Rank1,
const Environment& env,
typename Trait::Config config,
const AudioEncoderFactory::Options& options) {
return Trait::MakeAudioEncoder(env, std::move(config), options);
}
template <
typename Trait,
typename = std::enable_if_t<std::is_convertible_v<
decltype(Trait::MakeAudioEncoder(std::declval<typename Trait::Config>(),
int{})),
std::unique_ptr<AudioEncoder>>>>
absl_nullable std::unique_ptr<AudioEncoder> CreateEncoder(
Rank1, // Preferred over version with AudioCodecPairId
const Environment& /* env */,
const typename Trait::Config& config,
const AudioEncoderFactory::Options& options) {
return Trait::MakeAudioEncoder(config, options.payload_type);
return Trait::MakeAudioEncoder(env, config, options);
}
template <typename Trait,
@ -94,9 +79,9 @@ template <typename Trait,
absl_nullable std::unique_ptr<AudioEncoder> CreateEncoder(
Rank0,
const Environment& /* env */,
typename Trait::Config config,
const typename Trait::Config& config,
const AudioEncoderFactory::Options& options) {
return Trait::MakeAudioEncoder(std::move(config), options.payload_type,
return Trait::MakeAudioEncoder(config, options.payload_type,
options.codec_pair_id);
}
@ -125,7 +110,7 @@ struct Helper<T, Ts...> {
const SdpAudioFormat& format,
const AudioEncoderFactory::Options& options) {
if (auto opt_config = T::SdpToConfig(format); opt_config.has_value()) {
return CreateEncoder<T>(Rank2{}, env, *opt_config, options);
return CreateEncoder<T>(Rank1{}, env, *opt_config, options);
}
return Helper<Ts...>::CreateAudioEncoder(env, format, options);
}
@ -182,10 +167,6 @@ class AudioEncoderFactoryT : public AudioEncoderFactory {
// or
// std::unique_ptr<AudioEncoder> MakeAudioEncoder(
// const ConfigType& config,
// int payload_type);
// or (for backwards compatibility)
// std::unique_ptr<AudioEncoder> MakeAudioEncoder(
// const ConfigType& config,
// int payload_type,
// std::optional<AudioCodecPairId> codec_pair_id);
//

View File

@ -12,7 +12,6 @@
#include <memory>
#include <optional>
#include <utility>
#include <vector>
#include "api/audio_codecs/L16/audio_decoder_L16.h"
@ -45,9 +44,9 @@ struct NotAdvertised {
// Don't advertise support for anything.
}
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
Config config,
const Config& config,
std::optional<AudioCodecPairId> codec_pair_id = std::nullopt) {
return T::MakeAudioDecoder(std::move(config), codec_pair_id);
return T::MakeAudioDecoder(config, codec_pair_id);
}
};

View File

@ -12,7 +12,6 @@
#include <memory>
#include <optional>
#include <utility>
#include <vector>
#include "api/audio_codecs/L16/audio_encoder_L16.h"
@ -49,11 +48,11 @@ struct NotAdvertised {
return T::QueryAudioEncoder(config);
}
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
Config config,
const Config& config,
int payload_type,
std::optional<AudioCodecPairId> codec_pair_id = std::nullopt,
const FieldTrialsView* field_trials = nullptr) {
return T::MakeAudioEncoder(std::move(config), payload_type, codec_pair_id,
return T::MakeAudioEncoder(config, payload_type, codec_pair_id,
field_trials);
}
};

View File

@ -16,8 +16,10 @@
#include <vector>
#include "absl/strings/match.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 "modules/audio_coding/codecs/g711/audio_decoder_pcm.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_conversions.h"
@ -47,12 +49,14 @@ void AudioDecoderG711::AppendSupportedDecoders(
std::vector<AudioCodecSpec>* specs) {
// RingRTC change to disable unused audio codecs
// for (const char* type : {"PCMU", "PCMA"}) {
// specs->push_back({.format = {type, 8000, 1}, .info = {8000, 1, 64000}});
// specs->push_back({{type, 8000, 1}, {8000, 1, 64000}});
// }
}
std::unique_ptr<AudioDecoder> AudioDecoderG711::MakeAudioDecoder(
const Config& config) {
const Config& config,
std::optional<AudioCodecPairId> /*codec_pair_id*/,
const FieldTrialsView* /* field_trials */) {
if (!config.IsOk()) {
RTC_DCHECK_NOTREACHED();
return nullptr;

View File

@ -15,8 +15,10 @@
#include <optional>
#include <vector>
#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 {
@ -36,7 +38,10 @@ struct RTC_EXPORT AudioDecoderG711 {
};
static std::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format);
static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(const Config& config);
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
const Config& config,
std::optional<AudioCodecPairId> codec_pair_id = std::nullopt,
const FieldTrialsView* field_trials = nullptr);
};
} // namespace webrtc

View File

@ -18,8 +18,10 @@
#include <vector>
#include "absl/strings/match.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 "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_conversions.h"
@ -59,7 +61,7 @@ void AudioEncoderG711::AppendSupportedEncoders(
std::vector<AudioCodecSpec>* specs) {
// RingRTC change to disable unused audio codecs
// for (const char* type : {"PCMU", "PCMA"}) {
// specs->push_back({.format = {type, 8000, 1}, .info = {8000, 1, 64000}});
// specs->push_back({{type, 8000, 1}, {8000, 1, 64000}});
// }
}
@ -71,7 +73,9 @@ AudioCodecInfo AudioEncoderG711::QueryAudioEncoder(const Config& config) {
std::unique_ptr<AudioEncoder> AudioEncoderG711::MakeAudioEncoder(
const Config& config,
int payload_type) {
int payload_type,
std::optional<AudioCodecPairId> /*codec_pair_id*/,
const FieldTrialsView* /* field_trials */) {
if (!config.IsOk()) {
RTC_DCHECK_NOTREACHED();
return nullptr;

View File

@ -15,8 +15,10 @@
#include <optional>
#include <vector>
#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 {
@ -40,8 +42,11 @@ struct RTC_EXPORT AudioEncoderG711 {
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);
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
const Config& config,
int payload_type,
std::optional<AudioCodecPairId> codec_pair_id = std::nullopt,
const FieldTrialsView* field_trials = nullptr);
};
} // namespace webrtc

View File

@ -38,7 +38,7 @@ std::optional<AudioDecoderG722::Config> AudioDecoderG722::SdpToConfig(
void AudioDecoderG722::AppendSupportedDecoders(
std::vector<AudioCodecSpec>* specs) {
// RingRTC change to disable unused audio codecs
// specs->push_back({.format = {"G722", 8000, 1}, .info = {16000, 1, 64000}});
// specs->push_back({{"G722", 8000, 1}, {16000, 1, 64000}});
}
std::unique_ptr<AudioDecoder> AudioDecoderG722::MakeAudioDecoder(

View File

@ -59,7 +59,7 @@ void AudioEncoderG722::AppendSupportedEncoders(
// RingRTC change to disable unused audio codecs
// const SdpAudioFormat fmt = {"G722", 8000, 1};
// const AudioCodecInfo info = QueryAudioEncoder(*SdpToConfig(fmt));
// specs->push_back({.format = fmt, .info = info});
// specs->push_back({fmt, info});
}
AudioCodecInfo AudioEncoderG722::QueryAudioEncoder(

View File

@ -34,14 +34,8 @@ rtc_library("audio_encoder_opus_config") {
rtc_source_set("audio_decoder_opus_config") {
visibility = [ "*" ]
sources = [
"audio_decoder_multi_channel_opus_config.h",
"audio_decoder_opus_config.h",
]
deps = [
"..:audio_codecs_api",
"../../../rtc_base/system:rtc_export",
]
sources = [ "audio_decoder_multi_channel_opus_config.h" ]
deps = [ "..:audio_codecs_api" ]
}
rtc_library("audio_encoder_opus") {
@ -69,7 +63,6 @@ rtc_library("audio_decoder_opus") {
"audio_decoder_opus.h",
]
deps = [
":audio_decoder_opus_config",
"..:audio_codecs_api",
"../..:field_trials_view",
"../../../modules/audio_coding:webrtc_opus",

View File

@ -47,8 +47,7 @@ void AudioDecoderMultiChannelOpus::AppendSupportedDecoders(
{"channel_mapping", "0,4,1,2,3,5"},
{"num_streams", "4"},
{"coupled_streams", "2"}}});
specs->push_back(
{.format = std::move(opus_format), .info = surround_5_1_opus_info});
specs->push_back({std::move(opus_format), surround_5_1_opus_info});
}
{
AudioCodecInfo surround_7_1_opus_info{48000, 8,
@ -63,8 +62,7 @@ void AudioDecoderMultiChannelOpus::AppendSupportedDecoders(
{"channel_mapping", "0,6,1,2,3,4,5,7"},
{"num_streams", "5"},
{"coupled_streams", "3"}}});
specs->push_back(
{.format = std::move(opus_format), .info = surround_7_1_opus_info});
specs->push_back({std::move(opus_format), surround_7_1_opus_info});
}
}
@ -72,6 +70,6 @@ std::unique_ptr<AudioDecoder> AudioDecoderMultiChannelOpus::MakeAudioDecoder(
AudioDecoderMultiChannelOpusConfig config,
std::optional<AudioCodecPairId> /*codec_pair_id*/,
const FieldTrialsView* /* field_trials */) {
return AudioDecoderMultiChannelOpusImpl::MakeAudioDecoder(std::move(config));
return AudioDecoderMultiChannelOpusImpl::MakeAudioDecoder(config);
}
} // namespace webrtc

View File

@ -35,6 +35,15 @@ int GetDefaultNumChannels(const FieldTrialsView& field_trials) {
} // namespace
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;
}
return !num_channels.has_value() || *num_channels == 1 || *num_channels == 2;
}
std::optional<AudioDecoderOpus::Config> AudioDecoderOpus::SdpToConfig(
const SdpAudioFormat& format) {
if (!absl::EqualsIgnoreCase(format.name, "opus") ||
@ -72,7 +81,7 @@ void AudioDecoderOpus::AppendSupportedDecoders(
opus_info.supports_network_adaption = true;
SdpAudioFormat opus_format(
{"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}});
specs->push_back({.format = std::move(opus_format), .info = opus_info});
specs->push_back({std::move(opus_format), opus_info});
}
std::unique_ptr<AudioDecoder> AudioDecoderOpus::MakeAudioDecoder(

View File

@ -13,13 +13,11 @@
#include <memory>
#include <optional>
#include <utility>
#include <vector>
#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_opus_config.h"
#include "api/environment/environment.h"
#include "rtc_base/system/rtc_export.h"
@ -28,7 +26,11 @@ namespace webrtc {
// Opus decoder API for use as a template parameter to
// CreateAudioDecoderFactory<...>().
struct RTC_EXPORT AudioDecoderOpus {
using Config = AudioDecoderOpusConfig;
struct Config {
bool IsOk() const; // Checks if the values are currently OK.
int sample_rate_hz = 48000;
std::optional<int> num_channels;
};
static std::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format);
static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);
@ -38,7 +40,7 @@ struct RTC_EXPORT AudioDecoderOpus {
const Environment& env,
Config config,
std::optional<AudioCodecPairId> /*codec_pair_id*/) {
return MakeAudioDecoder(env, std::move(config));
return MakeAudioDecoder(env, config);
}
};

View File

@ -1,35 +0,0 @@
/*
* Copyright (c) 2026 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* 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_CONFIG_H_
#define API_AUDIO_CODECS_OPUS_AUDIO_DECODER_OPUS_CONFIG_H_
#include <optional>
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
struct RTC_EXPORT AudioDecoderOpusConfig {
bool IsOk() const {
if (sample_rate_hz != 16'000 && sample_rate_hz != 48'000) {
return false;
}
return !num_channels.has_value() || *num_channels == 1 ||
*num_channels == 2;
}
int sample_rate_hz = 48'000;
std::optional<int> num_channels;
};
} // namespace webrtc
#endif // API_AUDIO_CODECS_OPUS_AUDIO_DECODER_OPUS_CONFIG_H_

View File

@ -47,8 +47,7 @@ void AudioEncoderMultiChannelOpus::AppendSupportedEncoders(
{"channel_mapping", "0,4,1,2,3,5"},
{"num_streams", "4"},
{"coupled_streams", "2"}}});
specs->push_back(
{.format = std::move(opus_format), .info = surround_5_1_opus_info});
specs->push_back({std::move(opus_format), surround_5_1_opus_info});
}
{
AudioCodecInfo surround_7_1_opus_info{48000, 8,
@ -63,8 +62,7 @@ void AudioEncoderMultiChannelOpus::AppendSupportedEncoders(
{"channel_mapping", "0,6,1,2,3,4,5,7"},
{"num_streams", "5"},
{"coupled_streams", "3"}}});
specs->push_back(
{.format = std::move(opus_format), .info = surround_7_1_opus_info});
specs->push_back({std::move(opus_format), surround_7_1_opus_info});
}
}
@ -74,11 +72,11 @@ AudioCodecInfo AudioEncoderMultiChannelOpus::QueryAudioEncoder(
}
std::unique_ptr<AudioEncoder> AudioEncoderMultiChannelOpus::MakeAudioEncoder(
AudioEncoderMultiChannelOpusConfig config,
const AudioEncoderMultiChannelOpusConfig& config,
int payload_type,
std::optional<AudioCodecPairId> /*codec_pair_id*/,
const FieldTrialsView* /* field_trials */) {
return AudioEncoderMultiChannelOpusImpl::MakeAudioEncoder(std::move(config),
return AudioEncoderMultiChannelOpusImpl::MakeAudioEncoder(config,
payload_type);
}

View File

@ -32,7 +32,7 @@ struct RTC_EXPORT AudioEncoderMultiChannelOpus {
static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs);
static AudioCodecInfo QueryAudioEncoder(const Config& config);
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
Config config,
const Config& config,
int payload_type,
std::optional<AudioCodecPairId> codec_pair_id = std::nullopt,
const FieldTrialsView* field_trials = nullptr);

View File

@ -17,6 +17,29 @@
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)

View File

@ -21,38 +21,43 @@ namespace webrtc {
struct RTC_EXPORT AudioEncoderMultiChannelOpusConfig {
static constexpr int kDefaultFrameSizeMs = 20;
static constexpr int kDefaultComplexity = 9;
// 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;
bool IsOk() const;
AudioEncoderMultiChannelOpusConfig();
AudioEncoderMultiChannelOpusConfig(const AudioEncoderMultiChannelOpusConfig&);
~AudioEncoderMultiChannelOpusConfig();
AudioEncoderMultiChannelOpusConfig& operator=(
const AudioEncoderMultiChannelOpusConfig&);
int frame_size_ms = kDefaultFrameSizeMs;
size_t num_channels = 1;
int frame_size_ms;
size_t num_channels;
enum class ApplicationMode { kVoip, kAudio };
ApplicationMode application = ApplicationMode::kVoip;
int bitrate_bps = 32000;
bool fec_enabled = false;
bool cbr_enabled = false;
bool dtx_enabled = false;
int max_playback_rate_hz = 48000;
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 = kDefaultComplexity;
int complexity;
// Number of mono/stereo Opus streams.
int num_streams = -1;
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 = -1;
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

View File

@ -12,7 +12,6 @@
#include <memory>
#include <optional>
#include <utility>
#include <vector>
#include "api/audio_codecs/audio_encoder.h"
@ -42,13 +41,13 @@ AudioCodecInfo AudioEncoderOpus::QueryAudioEncoder(
std::unique_ptr<AudioEncoder> AudioEncoderOpus::MakeAudioEncoder(
const Environment& env,
AudioEncoderOpusConfig config,
const AudioEncoderOpusConfig& config,
const AudioEncoderFactory::Options& options) {
if (!config.IsOk()) {
RTC_DCHECK_NOTREACHED();
return nullptr;
}
return std::make_unique<AudioEncoderOpusImpl>(env, std::move(config),
return std::make_unique<AudioEncoderOpusImpl>(env, config,
options.payload_type);
}

View File

@ -34,7 +34,7 @@ struct RTC_EXPORT AudioEncoderOpus {
static AudioCodecInfo QueryAudioEncoder(const AudioEncoderOpusConfig& config);
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
const Environment& env,
AudioEncoderOpusConfig config,
const AudioEncoderOpusConfig& config,
const AudioEncoderFactory::Options& options);
};

View File

@ -14,9 +14,41 @@
namespace webrtc {
const int AudioEncoderOpusConfig::kDefaultLowRateComplexity =
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
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;
@ -36,10 +68,6 @@ bool AudioEncoderOpusConfig::IsOk() const {
return false;
if (low_rate_complexity < 0 || low_rate_complexity > 10)
return false;
// RingRTC change to support Opus DRED
if (dred_duration < 0 || dred_duration > 100)
return false;
// end RingRTC change to support Opus DRED
return true;
}
} // namespace webrtc

View File

@ -21,44 +21,34 @@
namespace webrtc {
struct RTC_EXPORT AudioEncoderOpusConfig {
static const int kDefaultLowRateComplexity;
// RingRTC change to ensure that opus encoders start with 60ms frame size
static constexpr int kDefaultFrameSizeMs = 60;
// 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 = 6'000;
static constexpr int kMaxBitrateBps = 510'000;
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
static constexpr int kDefaultComplexity = 5;
#else
static constexpr int kDefaultComplexity = 9;
#endif
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 = kDefaultFrameSizeMs;
int sample_rate_hz = 48'000;
size_t num_channels = 1;
int frame_size_ms;
int sample_rate_hz;
size_t num_channels;
enum class ApplicationMode { kVoip, kAudio };
ApplicationMode application = ApplicationMode::kVoip;
ApplicationMode application;
// NOTE: This member must always be set.
// TODO(kwiberg): Turn it into just an int.
std::optional<int> bitrate_bps = 32'000;
std::optional<int> bitrate_bps;
bool fec_enabled = false;
// RingRTC change to support Opus DRED
int dred_duration = 0;
// RingRTC change to support Opus DNN features
const void* dnn_weights_data = nullptr; // Pointer is borrowed; the buffer must outlive the encoder.
int dnn_weights_length = 0;
// end RingRTC change to support Opus DNN features
bool cbr_enabled = false;
int max_playback_rate_hz = 48'000;
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`;
@ -66,18 +56,18 @@ struct RTC_EXPORT AudioEncoderOpusConfig {
// `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 = kDefaultComplexity;
int low_rate_complexity = kDefaultLowRateComplexity;
int complexity_threshold_bps = 12500;
int complexity_threshold_window_bps = 1500;
int complexity;
int low_rate_complexity;
int complexity_threshold_bps;
int complexity_threshold_window_bps;
bool dtx_enabled = false;
bool dtx_enabled;
std::vector<int> supported_frame_lengths_ms;
int uplink_bandwidth_update_interval_ms = 200;
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 = -1;
int payload_type;
};
} // namespace webrtc

View File

@ -12,7 +12,6 @@
#include <memory>
#include <optional>
#include <utility>
#include <vector>
#include "api/audio_codecs/audio_codec_pair_id.h"
@ -40,9 +39,9 @@ struct NotAdvertised {
// Don't advertise support for anything.
}
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
Config config,
const Config& config,
std::optional<AudioCodecPairId> codec_pair_id = std::nullopt) {
return T::MakeAudioDecoder(std::move(config), codec_pair_id);
return T::MakeAudioDecoder(config, codec_pair_id);
}
};

View File

@ -12,7 +12,6 @@
#include <memory>
#include <optional>
#include <utility>
#include <vector>
#include "api/audio_codecs/audio_codec_pair_id.h"
@ -43,11 +42,11 @@ struct NotAdvertised {
return T::QueryAudioEncoder(config);
}
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
Config config,
const Config& config,
int payload_type,
std::optional<AudioCodecPairId> codec_pair_id = std::nullopt,
const FieldTrialsView* field_trials = nullptr) {
return T::MakeAudioEncoder(std::move(config), payload_type, codec_pair_id,
return T::MakeAudioEncoder(config, payload_type, codec_pair_id,
field_trials);
}
};

View File

@ -103,32 +103,13 @@ struct BaseAudioDecoderApi {
}
};
struct TraitWithFourMakeAudioDecoders : BaseAudioDecoderApi {
struct TraitWithTwoMakeAudioDecoders : BaseAudioDecoderApi {
// Create Decoders with different sample rates depending if it is created
// through one or another `MakeAudioDecoder` so that a test may detect which
// through one or another `MAkeAudioDecoder` so that a test may detect which
// method was used.
static constexpr int kRateWithoutEnv = 10'000;
static constexpr int kRateWithEnv = 20'000;
static constexpr int kRateWithEnvWithoutCodecId = 30'000;
static constexpr int kRateWithoutEnvWithoutCodecId = 40'000;
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
const Config& /* config */) {
auto decoder = std::make_unique<NiceMock<MockAudioDecoder>>();
ON_CALL(*decoder, SampleRateHz)
.WillByDefault(Return(kRateWithoutEnvWithoutCodecId));
return decoder;
}
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
const Environment& /* env */,
const Config& /* config */) {
auto decoder = std::make_unique<NiceMock<MockAudioDecoder>>();
ON_CALL(*decoder, SampleRateHz)
.WillByDefault(Return(kRateWithEnvWithoutCodecId));
return decoder;
}
// Testing backwards compatible case
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
const Config& /* config */,
std::optional<AudioCodecPairId> /* codec_pair_id */) {
@ -150,12 +131,11 @@ struct TraitWithFourMakeAudioDecoders : BaseAudioDecoderApi {
TEST(AudioDecoderFactoryTemplateTest,
PrefersToPassEnvironmentToMakeAudioDecoder) {
const Environment env = CreateEnvironment();
auto factory = CreateAudioDecoderFactory<TraitWithFourMakeAudioDecoders>();
auto factory = CreateAudioDecoderFactory<TraitWithTwoMakeAudioDecoders>();
EXPECT_THAT(factory->Create(env, BaseAudioDecoderApi::AudioFormat(), {}),
Pointer(Property(
&AudioDecoder::SampleRateHz,
TraitWithFourMakeAudioDecoders::kRateWithEnvWithoutCodecId)));
Pointer(Property(&AudioDecoder::SampleRateHz,
TraitWithTwoMakeAudioDecoders::kRateWithEnv)));
}
struct AudioDecoderApiWithV1Make : BaseAudioDecoderApi {

View File

@ -92,7 +92,6 @@ struct BaseAudioEncoderApi {
// Create Encoders with different sample rates depending if it is created
// through V1 or V2 method so that a test may detect which method was used.
static constexpr int kV1SameRate = 10'000;
static constexpr int kV1NoCodecPairSameRate = 15'000;
static constexpr int kV2SameRate = 20'000;
struct Config {};
@ -106,7 +105,7 @@ struct BaseAudioEncoderApi {
}
static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {
specs->push_back({.format = AudioFormat(), .info = CodecInfo()});
specs->push_back({AudioFormat(), CodecInfo()});
}
static AudioCodecInfo QueryAudioEncoder(const Config&) { return CodecInfo(); }
@ -123,17 +122,6 @@ struct AudioEncoderApiWithV1Make : BaseAudioEncoderApi {
}
};
struct AudioEncoderApiWithV1AndNoCodecPairId : BaseAudioEncoderApi {
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
const Config&,
int /* payload_type */) {
auto encoder = std::make_unique<NiceMock<MockAudioEncoder>>();
ON_CALL(*encoder, SampleRateHz)
.WillByDefault(Return(kV1NoCodecPairSameRate));
return encoder;
}
};
struct AudioEncoderApiWithV2Make : BaseAudioEncoderApi {
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
const Environment& /* env */,
@ -175,17 +163,6 @@ TEST(AudioEncoderFactoryTemplateTest,
BaseAudioEncoderApi::kV1SameRate)));
}
TEST(AudioEncoderFactoryTemplateTest,
UsesV1NoCodecPairMakeAudioEncoderWhenV2IsNotAvailable) {
const Environment env = CreateEnvironment();
auto factory =
CreateAudioEncoderFactory<AudioEncoderApiWithV1AndNoCodecPairId>();
EXPECT_THAT(factory->Create(env, BaseAudioEncoderApi::AudioFormat(), {}),
Pointer(Property(&AudioEncoder::SampleRateHz,
BaseAudioEncoderApi::kV1NoCodecPairSameRate)));
}
TEST(AudioEncoderFactoryTemplateTest,
PreferV2MakeAudioEncoderWhenBothAreAvailable) {
const Environment env = CreateEnvironment();

View File

@ -13,6 +13,7 @@
#include <optional>
#include <string>
#include "api/array_view.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc {

View File

@ -13,7 +13,7 @@
#include <stdint.h>
#include <span>
#include "api/array_view.h"
namespace webrtc {
@ -41,9 +41,9 @@ struct PacketOptions {
class Transport {
public:
virtual bool SendRtp(std::span<const uint8_t> packet,
virtual bool SendRtp(ArrayView<const uint8_t> packet,
const PacketOptions& options) = 0;
virtual bool SendRtcp(std::span<const uint8_t> packet,
virtual bool SendRtcp(ArrayView<const uint8_t> packet,
const PacketOptions& options) = 0;
protected:

View File

@ -11,338 +11,38 @@
#include "api/candidate.h"
#include <algorithm> // IWYU pragma: keep
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "api/rtc_error.h"
#include "p2p/base/p2p_constants.h"
#include "rtc_base/checks.h"
#include "rtc_base/crc32.h"
#include "rtc_base/crypto_random.h"
#include "rtc_base/ip_address.h"
#include "rtc_base/net_helper.h"
#include "rtc_base/network_constants.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/string_encode.h"
#include "rtc_base/strings/string_builder.h"
using webrtc::IceCandidateType;
namespace webrtc {
namespace {
constexpr char kLineTypeAttributes = 'a';
constexpr char kAttributeCandidate[] = "candidate";
constexpr char kAttributeCandidateTyp[] = "typ";
constexpr char kAttributeCandidateRaddr[] = "raddr";
constexpr char kAttributeCandidateRport[] = "rport";
constexpr char kAttributeCandidateUfrag[] = "ufrag";
constexpr char kAttributeCandidateGeneration[] = "generation";
constexpr char kAttributeCandidateNetworkId[] = "network-id";
constexpr char kAttributeCandidateNetworkCost[] = "network-cost";
constexpr char kAttributeCandidatePwd[] = "pwd";
constexpr absl::string_view kSdpDelimiterColon = ":";
constexpr char kSdpDelimiterColonChar = kSdpDelimiterColon[0];
constexpr char kSdpDelimiterSpaceChar = ' ';
constexpr char kSdpDelimiterEqualChar = '=';
constexpr char kNewLineChar = '\n';
constexpr char kReturnChar = '\r';
constexpr char kCandidateHost[] = "host";
constexpr char kCandidateSrflx[] = "srflx";
constexpr char kCandidatePrflx[] = "prflx";
constexpr char kCandidateRelay[] = "relay";
// Backwards compatibility.
constexpr char kTcpCandidateType[] = "tcptype";
absl::string_view TrimReturnChar(absl::string_view line) {
if (!line.empty() && line.back() == kReturnChar) {
line.remove_suffix(1);
}
return line;
}
bool IsValidPort(int port) {
return port >= 0 && port <= 65535;
}
// Returns the `candidate-attribute` as described in:
// https://www.rfc-editor.org/rfc/rfc5245#section-15.1
std::string BuildCandidate(const Candidate& candidate, bool include_ufrag) {
StringBuilder os;
os << kAttributeCandidate;
absl::string_view type = candidate.type_name();
os << kSdpDelimiterColon << candidate.foundation() << " "
<< candidate.component() << " " << candidate.protocol() << " "
<< candidate.priority() << " "
<< (candidate.address().ipaddr().IsNil()
? candidate.address().hostname()
: candidate.address().ipaddr().ToString())
<< " " << candidate.address().PortAsString() << " "
<< kAttributeCandidateTyp << " " << type << " ";
// Related address
if (!candidate.related_address().IsNil()) {
os << kAttributeCandidateRaddr << " "
<< candidate.related_address().ipaddr().ToString() << " "
<< kAttributeCandidateRport << " "
<< candidate.related_address().PortAsString() << " ";
}
// Note that we allow the tcptype to be missing, for backwards
// compatibility; the implementation treats this as a passive candidate.
// TODO(bugs.webrtc.org/11466): Treat a missing tcptype as an error?
if (candidate.protocol() == TCP_PROTOCOL_NAME &&
!candidate.tcptype().empty()) {
os << kTcpCandidateType << " " << candidate.tcptype() << " ";
}
// Extensions
os << kAttributeCandidateGeneration << " " << candidate.generation();
if (include_ufrag && !candidate.username().empty()) {
os << " " << kAttributeCandidateUfrag << " " << candidate.username();
}
if (candidate.network_id() > 0) {
os << " " << kAttributeCandidateNetworkId << " " << candidate.network_id();
}
if (candidate.network_cost() > 0) {
os << " " << kAttributeCandidateNetworkCost << " "
<< candidate.network_cost();
}
return os.str();
}
// From WebRTC draft section 4.8.1.1 candidate-attribute should be
// candidate:<candidate> when trickled.
RTCErrorOr<Candidate> ParseCandidate(absl::string_view message) {
// Makes sure `message` contains only one line.
absl::string_view first_line;
size_t line_end = message.find(kNewLineChar);
if (line_end == absl::string_view::npos) {
first_line = message;
} else if (line_end + 1 == message.size()) {
first_line = message.substr(0, line_end);
} else {
return RTCError::InvalidParameter() << "Expect one line only";
}
// For backwards compatibility, don't fail if the supplied string is in the
// form of "a=candidate...". If we encounter that, ignore the first 2
// characters and continue.
if (first_line.length() > 2 && first_line[0] == kLineTypeAttributes &&
first_line[1] == kSdpDelimiterEqualChar) {
first_line = first_line.substr(2);
}
// Trim return char, if any.
first_line = TrimReturnChar(first_line);
std::string attribute_candidate;
std::string candidate_value;
// `first_line` must be in the form of "candidate:<value>".
if (!tokenize_first(first_line, kSdpDelimiterColonChar, &attribute_candidate,
&candidate_value) ||
attribute_candidate != kAttributeCandidate) {
return RTCError::InvalidParameter() << "Expected " << kAttributeCandidate
<< " got " << attribute_candidate;
}
std::vector<absl::string_view> fields =
split(candidate_value, kSdpDelimiterSpaceChar);
// RFC 5245
// a=candidate:<foundation> <component-id> <transport> <priority>
// <connection-address> <port> typ <candidate-types>
// [raddr <connection-address>] [rport <port>]
// *(SP extension-att-name SP extension-att-value)
const size_t expected_min_fields = 8;
if (fields.size() < expected_min_fields ||
(fields[6] != kAttributeCandidateTyp)) {
return RTCError::InvalidParameter()
<< "Expect at least " << expected_min_fields << " fields.";
}
const absl::string_view foundation = fields[0];
int component_id = 0;
if (!FromString(fields[1], &component_id)) {
return RTCError(RTCErrorType::SYNTAX_ERROR, "Invalid component id");
}
const absl::string_view transport = fields[2];
uint32_t priority = 0;
if (!FromString(fields[3], &priority)) {
return RTCError(RTCErrorType::SYNTAX_ERROR, "Invalid priority");
}
int port = 0;
if (!FromString(fields[5], &port) || !IsValidPort(port)) {
return RTCError(RTCErrorType::SYNTAX_ERROR, "Invalid port");
}
const absl::string_view connection_address = fields[4];
SocketAddress address(connection_address, port);
std::optional<ProtocolType> protocol = StringToProto(transport);
if (!protocol) {
return RTCError::InvalidParameter() << "Unsupported transport type";
}
bool tcp_protocol = false;
switch (*protocol) {
// Supported protocols.
case PROTO_UDP:
break;
case PROTO_TCP:
case PROTO_SSLTCP:
tcp_protocol = true;
break;
default:
return RTCError::InvalidParameter() << "Unsupported protocol";
}
IceCandidateType candidate_type;
const absl::string_view type = fields[7];
if (type == kCandidateHost) {
candidate_type = IceCandidateType::kHost;
} else if (type == kCandidateSrflx) {
candidate_type = IceCandidateType::kSrflx;
} else if (type == kCandidateRelay) {
candidate_type = IceCandidateType::kRelay;
} else if (type == kCandidatePrflx) {
candidate_type = IceCandidateType::kPrflx;
} else {
return RTCError::InvalidParameter() << "Unsupported candidate type";
}
size_t current_position = expected_min_fields;
SocketAddress related_address;
// The 2 optional fields for related address
// [raddr <connection-address>] [rport <port>]
if (fields.size() >= (current_position + 2) &&
fields[current_position] == kAttributeCandidateRaddr) {
related_address.SetIP(fields[++current_position]);
++current_position;
}
if (fields.size() >= (current_position + 2) &&
fields[current_position] == kAttributeCandidateRport) {
int related_port = 0;
if (!FromString(fields[++current_position], &related_port) ||
!IsValidPort(related_port)) {
return RTCError(RTCErrorType::SYNTAX_ERROR, "Invalid port");
}
related_address.SetPort(related_port);
++current_position;
}
// If this is a TCP candidate, it has additional extension as defined in
// RFC 6544.
absl::string_view tcptype;
if (fields.size() >= (current_position + 2) &&
fields[current_position] == kTcpCandidateType) {
tcptype = fields[++current_position];
++current_position;
if (tcptype != TCPTYPE_ACTIVE_STR && tcptype != TCPTYPE_PASSIVE_STR &&
tcptype != TCPTYPE_SIMOPEN_STR) {
return RTCError(RTCErrorType::SYNTAX_ERROR, "Invalid TCP candidate type");
}
if (!tcp_protocol) {
return RTCError(RTCErrorType::SYNTAX_ERROR, "Invalid non-TCP candidate");
}
} else if (tcp_protocol) {
// We allow the tcptype to be missing, for backwards compatibility,
// treating it as a passive candidate.
// TODO(bugs.webrtc.org/11466): Treat a missing tcptype as an error?
tcptype = TCPTYPE_PASSIVE_STR;
}
// Extension
// Though non-standard, we support the ICE ufrag and pwd being signaled on
// the candidate to avoid issues with confusing which generation a candidate
// belongs to when trickling multiple generations at the same time.
absl::string_view username;
absl::string_view password;
uint32_t generation = 0;
uint16_t network_id = 0;
uint16_t network_cost = 0;
for (size_t i = current_position; i + 1 < fields.size(); ++i) {
// RFC 5245
// *(SP extension-att-name SP extension-att-value)
if (fields[i] == kAttributeCandidateGeneration) {
if (!FromString(fields[++i], &generation)) {
return RTCError(
RTCErrorType::SYNTAX_ERROR,
absl::StrCat("Invalid ", kAttributeCandidateGeneration));
}
} else if (fields[i] == kAttributeCandidateUfrag) {
username = fields[++i];
} else if (fields[i] == kAttributeCandidatePwd) {
password = fields[++i];
} else if (fields[i] == kAttributeCandidateNetworkId) {
if (!FromString(fields[++i], &network_id)) {
return RTCError(RTCErrorType::SYNTAX_ERROR,
absl::StrCat("Invalid ", kAttributeCandidateNetworkId));
}
} else if (fields[i] == kAttributeCandidateNetworkCost) {
if (!FromString(fields[++i], &network_cost)) {
return RTCError(
RTCErrorType::SYNTAX_ERROR,
absl::StrCat("Invalid ", kAttributeCandidateNetworkCost));
}
network_cost = std::min(network_cost, kNetworkCostMax);
} else {
// Skip the unknown extension.
++i;
}
}
Candidate candidate(component_id, ProtoToString(*protocol), address, priority,
username, password, candidate_type, generation,
foundation, network_id, network_cost);
candidate.set_related_address(related_address);
candidate.set_tcptype(tcptype);
return candidate;
}
} // namespace
absl::string_view IceCandidateTypeToString(IceCandidateType type) {
switch (type) {
case IceCandidateType::kHost:
return kCandidateHost;
return "host";
case IceCandidateType::kSrflx:
return kCandidateSrflx;
return "srflx";
case IceCandidateType::kPrflx:
return kCandidatePrflx;
return "prflx";
case IceCandidateType::kRelay:
return kCandidateRelay;
return "relay";
}
}
} // namespace webrtc
std::optional<IceCandidateType> StringToIceCandidateType(
absl::string_view type) {
if (type == kCandidateHost) {
return IceCandidateType::kHost;
} else if (type == kCandidateSrflx) {
return IceCandidateType::kSrflx;
} else if (type == kCandidatePrflx) {
return IceCandidateType::kPrflx;
} else if (type == kCandidateRelay) {
return IceCandidateType::kRelay;
}
return std::nullopt;
}
// static
RTCErrorOr<Candidate> Candidate::ParseCandidateString(
absl::string_view message) {
return ParseCandidate(message);
}
namespace webrtc {
Candidate::Candidate()
: id_(CreateRandomString(8)),
@ -435,10 +135,6 @@ std::string Candidate::ToStringInternal(bool sensitive) const {
return ost.Release();
}
std::string Candidate::ToCandidateAttribute(bool include_ufrag) const {
return BuildCandidate(*this, include_ufrag);
}
uint32_t Candidate::GetPriority(uint32_t type_preference,
int network_adapter_preference,
int relay_preference,

View File

@ -14,11 +14,9 @@
#include <stddef.h>
#include <stdint.h>
#include <optional>
#include <string>
#include "absl/strings/string_view.h"
#include "api/rtc_error.h"
#include "rtc_base/checks.h"
#include "rtc_base/network_constants.h"
#include "rtc_base/socket_address.h"
@ -28,14 +26,17 @@ namespace webrtc {
enum class IceCandidateType : int { kHost, kSrflx, kPrflx, kRelay };
RTC_EXPORT absl::string_view IceCandidateTypeToString(IceCandidateType);
RTC_EXPORT std::optional<IceCandidateType> StringToIceCandidateType(
absl::string_view);
// RFC 6544, TCP candidate encoding rules.
static constexpr int DISCARD_PORT = 9;
static constexpr char TCPTYPE_ACTIVE_STR[] = "active";
static constexpr char TCPTYPE_PASSIVE_STR[] = "passive";
static constexpr char TCPTYPE_SIMOPEN_STR[] = "so";
// TODO(tommi): Remove. No usage in WebRTC now, remove once downstream projects
// don't have reliance.
[[deprecated("Use IceCandidateType")]] static constexpr char LOCAL_PORT_TYPE[] =
"local";
[[deprecated("Use IceCandidateType")]] static constexpr char STUN_PORT_TYPE[] =
"stun";
[[deprecated("Use IceCandidateType")]] static constexpr char PRFLX_PORT_TYPE[] =
"prflx";
[[deprecated("Use IceCandidateType")]] static constexpr char RELAY_PORT_TYPE[] =
"relay";
// TURN servers are limited to 32 in accordance with
// https://w3c.github.io/webrtc-pc/#dom-rtcconfiguration-iceservers
@ -59,14 +60,6 @@ class RTC_EXPORT Candidate {
Candidate(const Candidate&);
~Candidate();
// Parses the `candidate-attribute` as described in:
// https://www.rfc-editor.org/rfc/rfc5245#section-15.1
// The `message` string must start with "candidate:", not "a=candidate:" and
// contain the candidate description in a single line.
// Returns a constructed Candidate instance on success, or error information
// if parsing failed.
static RTCErrorOr<Candidate> ParseCandidateString(absl::string_view message);
// 8 character long randomized ID string for logging purposes.
const std::string& id() const { return id_; }
// Generates a new, 8 character long, id.
@ -213,14 +206,6 @@ class RTC_EXPORT Candidate {
std::string ToSensitiveString() const { return ToStringInternal(true); }
// Returns the `candidate-attribute` as described in:
// https://www.rfc-editor.org/rfc/rfc5245#section-15.1
// The returned string will start with "candidate:", not "a=candidate:" and
// will not end with "\r\n".
// include_ufrag: Controls whether or not the username is included in the
// returned string.
std::string ToCandidateAttribute(bool include_ufrag) const;
uint32_t GetPriority(uint32_t type_preference,
int network_adapter_preference,
int relay_preference,

View File

@ -10,28 +10,15 @@
#include "api/candidate.h"
#include <cstdint>
#include <string>
#include "absl/strings/string_view.h"
#include "api/rtc_error.h"
#include "p2p/base/p2p_constants.h"
#include "rtc_base/socket_address.h"
#include "test/gtest.h"
using webrtc::IceCandidateType;
namespace webrtc {
namespace {
constexpr absl::string_view kRawCandidate =
"candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host generation 2";
constexpr absl::string_view kRawHostnameCandidate =
"candidate:a0+B/1 1 udp 2130706432 a.test 1234 typ host generation 2";
constexpr char kSdpTcpActiveCandidate[] =
"candidate:a0+B/1 1 tcp 2130706432 192.168.1.5 9 typ host "
"tcptype active generation 2";
constexpr uint32_t kCandidatePriority = 2130706432U; // pref = 1.0
constexpr uint32_t kCandidateGeneration = 2;
constexpr char kCandidateFoundation1[] = "a0+B/1";
} // namespace
TEST(CandidateTest, Id) {
Candidate c;
@ -113,159 +100,4 @@ TEST(CandidateTest, Foundation) {
EXPECT_NE(foundation1, c.foundation());
}
TEST(CandidateTest, ToCandidateAttribute) {
SocketAddress address("192.168.1.5", 1234);
Candidate candidate(ICE_CANDIDATE_COMPONENT_RTP, "udp", address,
kCandidatePriority, "", "", IceCandidateType::kHost,
kCandidateGeneration, kCandidateFoundation1);
EXPECT_EQ(candidate.ToCandidateAttribute(true), kRawCandidate);
Candidate candidate_with_ufrag(candidate);
candidate_with_ufrag.set_username("ABC");
EXPECT_EQ(candidate_with_ufrag.ToCandidateAttribute(true),
std::string(kRawCandidate) + " ufrag ABC");
EXPECT_EQ(candidate_with_ufrag.ToCandidateAttribute(false), kRawCandidate);
Candidate candidate_with_network_info(candidate);
candidate_with_network_info.set_network_id(1);
EXPECT_EQ(candidate_with_network_info.ToCandidateAttribute(true),
std::string(kRawCandidate) + " network-id 1");
candidate_with_network_info.set_network_cost(999);
EXPECT_EQ(candidate_with_network_info.ToCandidateAttribute(true),
std::string(kRawCandidate) + " network-id 1 network-cost 999");
}
TEST(CandidateTest, ToCandidateAttributeHostnameCandidate) {
SocketAddress address("a.test", 1234);
Candidate candidate(ICE_CANDIDATE_COMPONENT_RTP, "udp", address,
kCandidatePriority, "", "", IceCandidateType::kHost,
kCandidateGeneration, kCandidateFoundation1);
EXPECT_EQ(candidate.ToCandidateAttribute(true), kRawHostnameCandidate);
}
TEST(CandidateTest, ToCandidateAttributeTcpCandidates) {
Candidate candidate(ICE_CANDIDATE_COMPONENT_RTP, "tcp",
SocketAddress("192.168.1.5", 9), kCandidatePriority, "",
"", IceCandidateType::kHost, kCandidateGeneration,
kCandidateFoundation1);
candidate.set_tcptype(TCPTYPE_ACTIVE_STR);
EXPECT_EQ(candidate.ToCandidateAttribute(true), kSdpTcpActiveCandidate);
}
TEST(CandidateTest, TypeToString) {
EXPECT_EQ(IceCandidateTypeToString(IceCandidateType::kHost), "host");
EXPECT_EQ(IceCandidateTypeToString(IceCandidateType::kSrflx), "srflx");
EXPECT_EQ(IceCandidateTypeToString(IceCandidateType::kPrflx), "prflx");
EXPECT_EQ(IceCandidateTypeToString(IceCandidateType::kRelay), "relay");
}
TEST(CandidateTest, StringToType) {
EXPECT_EQ(*StringToIceCandidateType("host"), IceCandidateType::kHost);
EXPECT_EQ(*StringToIceCandidateType("srflx"), IceCandidateType::kSrflx);
EXPECT_EQ(*StringToIceCandidateType("prflx"), IceCandidateType::kPrflx);
EXPECT_EQ(*StringToIceCandidateType("relay"), IceCandidateType::kRelay);
EXPECT_FALSE(StringToIceCandidateType("blah"));
EXPECT_FALSE(StringToIceCandidateType(""));
}
TEST(CandidateTest, Parse) {
constexpr char kCand1[] =
"candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
"generation 2";
RTCErrorOr<Candidate> ret = Candidate::ParseCandidateString(kCand1);
ASSERT_TRUE(ret.ok());
Candidate c = ret.MoveValue();
EXPECT_FALSE(c.id().empty());
EXPECT_EQ(c.foundation(), "a0+B/1");
EXPECT_EQ(c.component(), 1);
EXPECT_EQ(c.protocol(), "udp");
EXPECT_EQ(c.priority(), 2130706432u); // 0x7F000000
EXPECT_EQ(c.address().ToString(), "192.168.1.5:1234");
EXPECT_EQ(c.type(), IceCandidateType::kHost);
EXPECT_EQ(c.generation(), 2u);
// Test compatibility with the same string as an attribute line.
ret = Candidate::ParseCandidateString(std::string("a=") + kCand1);
ASSERT_TRUE(ret.ok());
EXPECT_TRUE(ret.value().IsEquivalent(c));
// Test some bogus strings.
EXPECT_FALSE(Candidate::ParseCandidateString("").ok());
EXPECT_FALSE(
Candidate::ParseCandidateString(std::string("x=") + kCand1).ok());
EXPECT_FALSE(Candidate::ParseCandidateString("a=").ok());
// Run through a few more test strings that should all pass.
struct Expectation {
absl::string_view candidate_string;
IceCandidateType type;
absl::string_view foundation;
absl::string_view protocol;
absl::string_view address_str;
absl::string_view related_address_str = "";
int component;
uint32_t priority;
uint32_t generation;
} const test_candidates[] = {
{.candidate_string =
"candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host "
"generation 2",
.type = IceCandidateType::kHost,
.foundation = "a0+B/1",
.protocol = "udp",
.address_str = "192.168.1.5:1234",
.component = 1,
.priority = 2130706432u,
.generation = 2u},
{.candidate_string =
"candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1235 typ host "
"generation 2",
.type = IceCandidateType::kHost,
.foundation = "a0+B/1",
.protocol = "udp",
.address_str = "192.168.1.5:1235",
.component = 2,
.priority = 2130706432u,
.generation = 2u},
{.candidate_string =
"candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host generation 2",
.type = IceCandidateType::kHost,
.foundation = "a0+B/2",
.protocol = "udp",
.address_str = "[::1]:1238",
.component = 1,
.priority = 2130706432u,
.generation = 2u},
{.candidate_string =
"candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx "
"raddr 192.168.1.5 rport 2346 generation 2",
.type = IceCandidateType::kSrflx,
.foundation = "a0+B/3",
.protocol = "udp",
.address_str = "74.125.127.126:2345",
.related_address_str = "192.168.1.5:2346",
.component = 1,
.priority = 2130706432u,
.generation = 2u},
};
for (const auto& test : test_candidates) {
ret = Candidate::ParseCandidateString(test.candidate_string);
ASSERT_TRUE(ret.ok()) << test.candidate_string;
c = ret.MoveValue();
EXPECT_FALSE(c.id().empty());
EXPECT_EQ(c.foundation(), test.foundation);
EXPECT_EQ(c.component(), test.component);
EXPECT_EQ(c.protocol(), test.protocol);
EXPECT_EQ(c.priority(), test.priority);
EXPECT_EQ(c.address().ToString(), test.address_str);
EXPECT_EQ(c.type(), test.type);
EXPECT_EQ(c.generation(), test.generation);
if (!test.related_address_str.empty()) {
EXPECT_EQ(c.related_address().ToString(), test.related_address_str);
}
}
}
} // namespace webrtc

View File

@ -35,6 +35,7 @@ rtc_source_set("frame_decryptor_interface") {
visibility = [ "*" ]
sources = [ "frame_decryptor_interface.h" ]
deps = [
"..:array_view",
"..:ref_count",
"..:rtp_parameters",
"../../rtc_base:refcount",
@ -45,6 +46,7 @@ rtc_source_set("frame_encryptor_interface") {
visibility = [ "*" ]
sources = [ "frame_encryptor_interface.h" ]
deps = [
"..:array_view",
"..:ref_count",
"..:rtp_parameters",
"../../rtc_base:refcount",

View File

@ -13,9 +13,9 @@
#include <cstddef>
#include <cstdint>
#include <span>
#include <vector>
#include "api/array_view.h"
#include "api/media_types.h"
#include "api/ref_count.h"
@ -62,9 +62,9 @@ class FrameDecryptorInterface : public RefCountInterface {
// cases.
virtual Result Decrypt(MediaType media_type,
const std::vector<uint32_t>& csrcs,
std::span<const uint8_t> additional_data,
std::span<const uint8_t> encrypted_frame,
std::span<uint8_t> frame) = 0;
ArrayView<const uint8_t> additional_data,
ArrayView<const uint8_t> encrypted_frame,
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

View File

@ -13,8 +13,8 @@
#include <cstddef>
#include <cstdint>
#include <span>
#include "api/array_view.h"
#include "api/media_types.h"
#include "api/ref_count.h"
@ -40,9 +40,9 @@ class FrameEncryptorInterface : public RefCountInterface {
// selected by the implementer to represent error codes.
virtual int Encrypt(MediaType media_type,
uint32_t ssrc,
std::span<const uint8_t> additional_data,
std::span<const uint8_t> frame,
std::span<uint8_t> encrypted_frame,
ArrayView<const uint8_t> additional_data,
ArrayView<const uint8_t> frame,
ArrayView<uint8_t> encrypted_frame,
size_t* bytes_written) = 0;
// Returns the total required length in bytes for the output of the

View File

@ -12,11 +12,11 @@
#define API_DATA_CHANNEL_EVENT_OBSERVER_INTERFACE_H_
#include <cstdint>
#include <span>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/array_view.h"
namespace webrtc {
@ -55,7 +55,7 @@ class DataChannelEventObserverInterface {
void set_data_type(DataType type) { data_type_ = type; }
const std::vector<uint8_t>& data() const { return data_; }
void set_data(std::span<const uint8_t> d) {
void set_data(ArrayView<const uint8_t> d) {
data_.assign(d.begin(), d.end());
}

View File

@ -196,8 +196,8 @@ class RTC_EXPORT DataChannelInterface : public RefCountInterface {
// 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 message is
// not sent due to other errors (e.g. full buffer, oversized message)
// 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.
// TODO(tommi): Remove this method once downstream implementations don't refer
// to it.

View File

@ -10,16 +10,12 @@
#ifndef API_DATAGRAM_CONNECTION_H_
#define API_DATAGRAM_CONNECTION_H_
#include <cstddef>
#include <cstdint>
#include <span>
#include <string_view>
#include <memory>
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/candidate.h"
#include "api/ref_count.h"
#include "api/units/timestamp.h"
#include "p2p/base/transport_description.h"
#include "rtc_base/system/rtc_export.h"
@ -33,43 +29,14 @@ namespace webrtc {
// networking internals.
class RTC_EXPORT DatagramConnection : public RefCountInterface {
public:
enum class WireProtocol {
kDtls,
kDtlsSrtp,
};
using PacketId = uint32_t;
class Observer {
public:
virtual ~Observer() = default;
virtual void OnCandidateGathered(const Candidate& candidate) = 0;
struct PacketMetadata {
Timestamp receive_time;
};
virtual void OnPacketReceived(std::span<const uint8_t> data,
PacketMetadata metadata) = 0;
// Notification of outcome of an earlier call to SendPacket.
struct SendOutcome {
PacketId id;
enum class Status {
kSuccess,
kNotSent,
};
Status status;
// Time sent on network.
Timestamp send_time = Timestamp::MinusInfinity();
// Actual UDP payload bytes sent on the network.
size_t bytes_sent = 0;
};
virtual void OnSendOutcome(SendOutcome send_outcome) {}
// TODO(crbug.com/443019066): Migrate to OnSendOutcome.
virtual void OnSendError() {}
virtual void OnPacketReceived(ArrayView<const uint8_t> data) = 0;
// Notification of an asynchronous failure to an earlier call to SendPacket.
// TODO(crbug.com/443019066): Associate this with a specific send call.
virtual void OnSendError() = 0;
// Notification of an error unrelated to sending. Observers should
// check the current state of the connection.
virtual void OnConnectionError() = 0;
@ -77,7 +44,7 @@ class RTC_EXPORT DatagramConnection : public RefCountInterface {
virtual void OnWritableChange() = 0;
};
~DatagramConnection() override = default;
virtual ~DatagramConnection() = default;
virtual void SetRemoteIceParameters(const IceParameters& ice_parameters) = 0;
virtual void AddRemoteCandidate(const Candidate& candidate) = 0;
@ -91,26 +58,13 @@ class RTC_EXPORT DatagramConnection : public RefCountInterface {
const uint8_t* digest,
size_t digest_len,
SSLRole ssl_role) = 0;
struct PacketSendParameters {
// Used to tie to async feedback of the sending outcome. No deduping is
// performed, the caller is responsible for ensuring uniqueness and handing
// rollovers.
PacketId id = 0;
std::span<const uint8_t> payload;
};
// Send a batch of packets on this connection. Listen to
// Observer::OnSendOutcome for notification of whether each was sent
// successfully.
virtual void SendPackets(std::span<PacketSendParameters> packets) = 0;
// SendPacket on this connection, returning whether the send succeeded.
virtual bool SendPacket(ArrayView<const uint8_t> data) = 0;
// Initiate closing connection and releasing resources. Must be called before
// destruction.
virtual void Terminate(
absl::AnyInvocable<void()> terminate_complete_callback) = 0;
virtual std::string_view IceUsernameFragment() = 0;
virtual std::string_view IcePassword() = 0;
};
} // namespace webrtc

View File

@ -12,14 +12,7 @@
#include <memory>
#include <utility>
#include "absl/strings/string_view.h"
#include "api/datagram_connection.h"
#include "api/environment/environment.h"
#include "api/make_ref_counted.h"
#include "api/scoped_refptr.h"
#include "p2p/base/port_allocator.h"
#include "pc/datagram_connection_internal.h"
#include "rtc_base/rtc_certificate.h"
namespace webrtc {
@ -30,10 +23,9 @@ scoped_refptr<DatagramConnection> CreateDatagramConnection(
absl::string_view transport_name,
bool ice_controlling,
scoped_refptr<RTCCertificate> certificate,
std::unique_ptr<DatagramConnection::Observer> observer,
DatagramConnection::WireProtocol wire_protocol) {
std::unique_ptr<DatagramConnection::Observer> observer) {
return make_ref_counted<DatagramConnectionInternal>(
env, std::move(port_allocator), transport_name, ice_controlling,
certificate, std::move(observer), wire_protocol);
certificate, std::move(observer));
}
} // namespace webrtc

View File

@ -12,12 +12,10 @@
#include <memory>
#include "absl/strings/string_view.h"
#include "api/datagram_connection.h"
#include "api/environment/environment.h"
#include "api/scoped_refptr.h"
#include "api/ref_count.h"
#include "p2p/base/port_allocator.h"
#include "rtc_base/rtc_certificate.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
@ -28,9 +26,7 @@ RTC_EXPORT scoped_refptr<DatagramConnection> CreateDatagramConnection(
absl::string_view transport_name,
bool ice_controlling,
scoped_refptr<RTCCertificate> certificate,
std::unique_ptr<DatagramConnection::Observer> observer,
DatagramConnection::WireProtocol wire_protocol =
DatagramConnection::WireProtocol::kDtlsSrtp);
std::unique_ptr<DatagramConnection::Observer> observer);
} // namespace webrtc
#endif // API_DATAGRAM_CONNECTION_FACTORY_H_

View File

@ -26,8 +26,7 @@ rtc_source_set("environment") {
rtc_library("deprecated_global_field_trials") {
visibility = [
":environment_factory",
"../../sdk:peerconnectionfactory_base_objc",
"../../sdk/android:peerconnection_jni",
"../../system_wrappers:field_trial",
]
allow_poison = [ "environment_construction" ]
sources = [
@ -36,8 +35,6 @@ rtc_library("deprecated_global_field_trials") {
]
deps = [
"../:field_trials_registry",
"../../rtc_base:checks",
"../../rtc_base:logging",
"//third_party/abseil-cpp/absl/strings:string_view",
]
}

View File

@ -10,64 +10,18 @@
#include "api/environment/deprecated_global_field_trials.h"
#include <cstddef>
#include <map>
#include <string>
#include "absl/strings/string_view.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
namespace webrtc {
namespace {
constinit const char* global_field_trial_string = nullptr;
// Validates the given field trial string.
// E.g.:
// "WebRTC-experimentFoo/Enabled/WebRTC-experimentBar/Enabled100kbps/"
// Assigns the process to group "Enabled" on WebRTCExperimentFoo trial
// and to group "Enabled100kbps" on WebRTCExperimentBar.
//
// E.g. invalid config:
// "WebRTC-experiment1/Enabled" (note missing / separator at the end).
bool FieldTrialsStringIsValid(absl::string_view trials) {
if (trials.empty())
return true;
size_t next_item = 0;
std::map<absl::string_view, absl::string_view> field_trials;
while (next_item < trials.length()) {
size_t name_end = trials.find('/', next_item);
if (name_end == absl::string_view::npos || next_item == name_end)
return false;
size_t group_name_end = trials.find('/', name_end + 1);
if (group_name_end == absl::string_view::npos ||
name_end + 1 == group_name_end)
return false;
absl::string_view name = trials.substr(next_item, name_end - next_item);
absl::string_view group_name =
trials.substr(name_end + 1, group_name_end - name_end - 1);
next_item = group_name_end + 1;
// Fail if duplicate with different group name.
auto [it, inserted] = field_trials.emplace(name, group_name);
if (!inserted && it->second != group_name) {
return false;
}
}
return true;
}
} // namespace
void DeprecatedGlobalFieldTrials::Set(const char* field_trials) {
RTC_LOG(LS_INFO) << "Setting field trial string:" << field_trials;
if (field_trials != nullptr) {
RTC_DCHECK(FieldTrialsStringIsValid(field_trials))
<< "Invalid field trials string:" << field_trials;
}
global_field_trial_string = field_trials;
}

View File

@ -93,7 +93,7 @@ TEST(EnvironmentTest, DefaultEnvironmentHasAllUtilities) {
// Try to use each utility, expect no crashes.
env.clock().CurrentTime();
EXPECT_THAT(env.task_queue_factory().CreateTaskQueue(
"test", TaskQueueFactory::Priority::kNormal),
"test", TaskQueueFactory::Priority::NORMAL),
NotNull());
env.event_log().Log(std::make_unique<FakeEvent>());
env.field_trials().Lookup("WebRTC-Debugging-RtpDump");

View File

@ -14,9 +14,9 @@
#include <cstdint>
#include <memory>
#include <optional>
#include <span>
#include <string>
#include "api/array_view.h"
#include "api/ref_count.h"
#include "api/scoped_refptr.h"
#include "api/units/time_delta.h"
@ -46,10 +46,10 @@ class TransformableFrameInterface {
// Returns the frame payload data. The data is valid until the next non-const
// method call.
virtual std::span<const uint8_t> GetData() const = 0;
virtual ArrayView<const uint8_t> GetData() const = 0;
// Copies `data` into the owned frame payload data.
virtual void SetData(std::span<const uint8_t> data) = 0;
virtual void SetData(ArrayView<const uint8_t> data) = 0;
virtual uint8_t GetPayloadType() const = 0;
virtual bool CanSetPayloadType() const { return false; }
@ -112,10 +112,11 @@ class TransformableFrameInterface {
class TransformableVideoFrameInterface : public TransformableFrameInterface {
public:
RTC_EXPORT explicit TransformableVideoFrameInterface(Passkey passkey);
~TransformableVideoFrameInterface() override = default;
virtual ~TransformableVideoFrameInterface() = default;
virtual bool IsKeyFrame() const = 0;
virtual std::optional<std::string> Rid() const { return std::nullopt; }
virtual VideoFrameMetadata Metadata() const = 0;
virtual void SetMetadata(const VideoFrameMetadata&) = 0;
};
@ -123,9 +124,9 @@ class TransformableVideoFrameInterface : public TransformableFrameInterface {
class TransformableAudioFrameInterface : public TransformableFrameInterface {
public:
RTC_EXPORT explicit TransformableAudioFrameInterface(Passkey passkey);
~TransformableAudioFrameInterface() override = default;
virtual ~TransformableAudioFrameInterface() = default;
virtual std::span<const uint32_t> GetContributingSources() const = 0;
virtual ArrayView<const uint32_t> GetContributingSources() const = 0;
virtual const std::optional<uint16_t> SequenceNumber() const = 0;

View File

@ -1,30 +0,0 @@
/*
* Copyright 2025 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can 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_server_parsing.h"
#include <set>
#include <vector>
#include "api/peer_connection_interface.h"
#include "api/rtc_error.h"
#include "p2p/base/port_allocator.h"
#include "pc/ice_server_parsing.h"
#include "rtc_base/socket_address.h"
namespace webrtc {
RTCError ParseIceServers(const PeerConnectionInterface::IceServers& servers,
std::set<SocketAddress>* stun_servers,
std::vector<RelayServerConfig>* turn_servers) {
return ParseIceServersOrError(servers, stun_servers, turn_servers);
}
} // namespace webrtc

View File

@ -1,35 +0,0 @@
/*
* Copyright 2025 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* 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_SERVER_PARSING_H_
#define API_ICE_SERVER_PARSING_H_
#include <set>
#include <vector>
#include "api/peer_connection_interface.h"
#include "api/rtc_error.h"
#include "p2p/base/port_allocator.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
// Parses the URLs for each server in `servers` to build `stun_servers` and
// `turn_servers`. Can return SYNTAX_ERROR if the URL is malformed, or
// INVALID_PARAMETER if a TURN server is missing `username` or `password`.
[[nodiscard]] RTC_EXPORT RTCError
ParseIceServers(const PeerConnectionInterface::IceServers& servers,
std::set<SocketAddress>* stun_servers,
std::vector<RelayServerConfig>* turn_servers);
} // namespace webrtc
#endif // API_ICE_SERVER_PARSING_H_

View File

@ -10,103 +10,11 @@
#include "api/jsep.h"
#include <algorithm>
#include <cstddef>
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "api/candidate.h"
#include "api/sequence_checker.h"
#include "api/webrtc_sdp.h"
#include "p2p/base/p2p_constants.h"
#include "p2p/base/transport_info.h"
#include "pc/session_description.h"
#include "rtc_base/checks.h"
#include "rtc_base/ip_address.h"
#include "rtc_base/net_helper.h"
#include "rtc_base/net_helpers.h"
#include "rtc_base/socket_address.h"
namespace webrtc {
namespace {
constexpr char kDummyAddress[] = "0.0.0.0";
constexpr int kDummyPort = 9;
// Update the connection address for the MediaContentDescription based on the
// candidates.
void UpdateConnectionAddress(const IceCandidateCollection& candidate_collection,
MediaContentDescription* media_desc) {
int port = kDummyPort;
std::string ip = kDummyAddress;
std::string hostname;
int current_preference = 0; // Start with lowest preference.
int current_family = AF_UNSPEC;
for (size_t i = 0; i < candidate_collection.count(); ++i) {
const IceCandidate* jsep_candidate = candidate_collection.at(i);
if (jsep_candidate->candidate().component() !=
ICE_CANDIDATE_COMPONENT_RTP) {
continue;
}
// Default destination should be UDP only.
if (jsep_candidate->candidate().protocol() != UDP_PROTOCOL_NAME) {
continue;
}
const int preference = jsep_candidate->candidate().type_preference();
const int family = jsep_candidate->candidate().address().ipaddr().family();
// See if this candidate is more preferable then the current one if it's the
// same family. Or if the current family is IPv4 already so we could safely
// ignore all IPv6 ones. WebRTC bug 4269.
// http://code.google.com/p/webrtc/issues/detail?id=4269
if ((preference <= current_preference && current_family == family) ||
(current_family == AF_INET && family == AF_INET6)) {
continue;
}
current_preference = preference;
current_family = family;
const SocketAddress& candidate_addr = jsep_candidate->candidate().address();
port = candidate_addr.port();
ip = candidate_addr.ipaddr().ToString();
hostname = candidate_addr.hostname();
}
SocketAddress connection_addr(ip, port);
if (IPIsUnspec(connection_addr.ipaddr()) && !hostname.empty()) {
// When a hostname candidate becomes the (default) connection address,
// we use the dummy address 0.0.0.0 and port 9 in the c= and the m= lines.
//
// We have observed in deployment that with a FQDN in a c= line, SDP parsing
// could fail in other JSEP implementations. We note that the wildcard
// addresses (0.0.0.0 or ::) with port 9 are given the exception as the
// connection address that will not result in an ICE mismatch
// (draft-ietf-mmusic-ice-sip-sdp). Also, 0.0.0.0 or :: can be used as the
// connection address in the initial offer or answer with trickle ICE
// if the offerer or answerer does not want to include the host IP address
// (draft-ietf-mmusic-trickle-ice-sip), and in particular 0.0.0.0 has been
// widely deployed for this use without outstanding compatibility issues.
// Combining the above considerations, we use 0.0.0.0 with port 9 to
// populate the c= and the m= lines. See `BuildMediaDescription` in
// webrtc_sdp.cc for the SDP generation with
// `media_desc->connection_address()`.
connection_addr = SocketAddress(kDummyAddress, kDummyPort);
}
media_desc->set_connection_address(connection_addr);
}
std::vector<IceCandidateCollection> CloneCandidateCollection(
const std::vector<IceCandidateCollection>& original) {
std::vector<IceCandidateCollection> ret;
ret.reserve(original.size());
for (const auto& collection : original) {
ret.push_back(collection.Clone());
}
return ret;
}
} // namespace
const char SessionDescriptionInterface::kOffer[] = "offer";
const char SessionDescriptionInterface::kPrAnswer[] = "pranswer";
@ -141,213 +49,4 @@ std::optional<SdpType> SdpTypeFromString(const std::string& type_str) {
}
}
std::unique_ptr<IceCandidate> CreateIceCandidate(absl::string_view sdp_mid,
int sdp_mline_index,
const Candidate& candidate) {
return std::make_unique<IceCandidate>(sdp_mid, sdp_mline_index, candidate);
}
IceCandidate* CreateIceCandidate(absl::string_view sdp_mid,
int sdp_mline_index,
const std::string& sdp,
SdpParseError* error) {
return IceCandidate::Create(sdp_mid, sdp_mline_index, sdp, error).release();
}
std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
SdpType type,
absl::string_view sdp) {
return CreateSessionDescription(type, sdp, nullptr);
}
std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
SdpType type,
absl::string_view sdp,
SdpParseError* error_out) {
if (type == SdpType::kRollback) {
return CreateRollbackSessionDescription();
}
return SdpDeserialize(type, sdp, error_out);
}
std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
SdpType type,
absl::string_view session_id,
absl::string_view session_version,
std::unique_ptr<SessionDescription> description) {
return SessionDescriptionInterface::Create(type, std::move(description),
session_id, session_version);
}
std::unique_ptr<SessionDescriptionInterface> CreateRollbackSessionDescription(
absl::string_view session_id,
absl::string_view session_version) {
return SessionDescriptionInterface::Create(
SdpType::kRollback, /*description=*/nullptr, session_id, session_version);
}
// static
std::unique_ptr<SessionDescriptionInterface>
SessionDescriptionInterface::Create(
SdpType type,
std::unique_ptr<SessionDescription> description,
absl::string_view id,
absl::string_view version,
std::vector<IceCandidateCollection> candidates) {
if (!description && type != SdpType::kRollback)
return nullptr;
return absl::WrapUnique(new SessionDescriptionInterface(
type, std::move(description), id, version, std::move(candidates)));
}
SessionDescriptionInterface::~SessionDescriptionInterface() = default;
void SessionDescriptionInterface::RelinquishThreadOwnership() {
// Ideally we should require that the method can only be called from the
// thread that the sequence checker is currently attached to. However that's
// not compatible with some cases outside of webrtc where initializations
// happens on one thread and then the object is moved to a second thread (e.g.
// signaling) where a call is made into webrtc. At that point we'd hit a
// dcheck like this in webrtc: RTC_DCHECK_RUN_ON(&sequence_checker_);
sequence_checker_.Detach();
// Tie the checker to the current thread, which permits iterating
// `candidate_collection_`
RTC_DCHECK_RUN_ON(&sequence_checker_);
for (IceCandidateCollection& collection : candidate_collection_) {
collection.RelinquishThreadOwnership();
}
sequence_checker_.Detach(); // Unties the checker from the current thread.
}
SessionDescriptionInterface::SessionDescriptionInterface(
SdpType type,
std::unique_ptr<SessionDescription> desc,
absl::string_view id,
absl::string_view version,
std::vector<IceCandidateCollection> candidates)
: sdp_type_(type),
id_(id),
version_(version),
description_(std::move(desc)),
candidate_collection_(std::move(candidates)) {
RTC_DCHECK(description() || type == SdpType::kRollback);
RTC_DCHECK(candidate_collection_.empty() ||
candidate_collection_.size() == number_of_mediasections());
candidate_collection_.resize(number_of_mediasections());
}
size_t SessionDescriptionInterface::number_of_mediasections() const {
return description_ ? description_->contents().size() : 0u;
}
std::unique_ptr<SessionDescriptionInterface>
SessionDescriptionInterface::Clone() const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
return SessionDescriptionInterface::Create(
sdp_type_, description() ? description()->Clone() : nullptr, id(),
version(), CloneCandidateCollection(candidate_collection_));
}
bool SessionDescriptionInterface::AddCandidate(const IceCandidate* candidate) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
if (!candidate)
return false;
size_t index = 0;
if (!GetMediasectionIndex(candidate, &index)) {
return false;
}
ContentInfo& content = description()->contents()[index];
const TransportInfo* transport_info =
description()->GetTransportInfoByName(content.mid());
if (!transport_info) {
return false;
}
Candidate updated_candidate = candidate->candidate();
if (updated_candidate.username().empty()) {
updated_candidate.set_username(transport_info->description.ice_ufrag);
}
if (updated_candidate.password().empty()) {
updated_candidate.set_password(transport_info->description.ice_pwd);
}
// Use `content.mid()` as the mid for the updated candidate. The
// `candidate->sdp_mid()` property *should* be the same. However, in some
// cases specifying an empty mid but a valid index is a way to add a candidate
// without knowing (or caring about) the mid. This is done in several tests.
RTC_DCHECK(candidate->sdp_mid().empty() ||
candidate->sdp_mid() == content.mid())
<< "sdp_mid='" << candidate->sdp_mid() << "' content.mid()='"
<< content.mid() << "'";
auto updated_candidate_wrapper = std::make_unique<IceCandidate>(
content.mid(), static_cast<int>(index), updated_candidate);
IceCandidateCollection& candidates = candidate_collection_[index];
if (!candidates.HasCandidate(updated_candidate_wrapper.get())) {
candidates.add(std::move(updated_candidate_wrapper));
UpdateConnectionAddress(candidates, content.media_description());
}
return true;
}
bool SessionDescriptionInterface::RemoveCandidate(
const IceCandidate* candidate) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
size_t index = 0u;
if (!GetMediasectionIndex(candidate, &index)) {
return false;
}
IceCandidateCollection& candidates = candidate_collection_[index];
if (!candidates.remove(candidate)) {
return false;
}
UpdateConnectionAddress(candidates,
description()->contents()[index].media_description());
return true;
}
const IceCandidateCollection* SessionDescriptionInterface::candidates(
size_t mediasection_index) const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
if (mediasection_index >= candidate_collection_.size())
return nullptr;
return &candidate_collection_[mediasection_index];
}
std::string SessionDescriptionInterface::ToString() const {
return SdpSerialize(*this);
}
bool SessionDescriptionInterface::IsValidMLineIndex(int index) const {
RTC_DCHECK(description());
return index >= 0 &&
index < static_cast<int>(description()->contents().size());
}
bool SessionDescriptionInterface::GetMediasectionIndex(
const IceCandidate* candidate,
size_t* index) const {
if (!candidate || !index || !description()) {
return false;
}
auto mid = candidate->sdp_mid();
if (!mid.empty()) {
*index = GetMediasectionIndex(mid);
} else {
// An sdp_mline_index of -1 will be treated as invalid.
*index = static_cast<size_t>(candidate->sdp_mline_index());
}
return IsValidMLineIndex(*index);
}
int SessionDescriptionInterface::GetMediasectionIndex(
absl::string_view mid) const {
const auto& contents = description()->contents();
auto it =
std::find_if(contents.begin(), contents.end(),
[&](const auto& content) { return mid == content.mid(); });
return it == contents.end() ? -1 : std::distance(contents.begin(), it);
}
} // namespace webrtc

View File

@ -37,7 +37,6 @@
#include "api/sequence_checker.h"
#include "rtc_base/system/no_unique_address.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/thread_annotations.h"
namespace webrtc {
@ -122,14 +121,14 @@ using IceCandidateInterface = IceCandidate;
// Creates an IceCandidate based on SDP string.
// Returns null if the sdp string can't be parsed.
// `error` may be null.
RTC_EXPORT IceCandidate* CreateIceCandidate(absl::string_view sdp_mid,
RTC_EXPORT IceCandidate* CreateIceCandidate(const std::string& sdp_mid,
int sdp_mline_index,
const std::string& sdp,
SdpParseError* error);
// Creates an IceCandidate based on a parsed candidate structure.
RTC_EXPORT std::unique_ptr<IceCandidate> CreateIceCandidate(
absl::string_view sdp_mid,
const std::string& sdp_mid,
int sdp_mline_index,
const Candidate& candidate);
@ -150,14 +149,8 @@ class IceCandidateCollection final {
IceCandidateCollection(const IceCandidateCollection&) = delete;
IceCandidateCollection& operator=(const IceCandidateCollection&) = delete;
size_t count() const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
return candidates_.size();
}
bool empty() const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
return candidates_.empty();
}
size_t count() const { return candidates_.size(); }
bool empty() const { return candidates_.empty(); }
const IceCandidate* at(size_t index) const;
// Adds and takes ownership of the IceCandidate.
@ -181,14 +174,14 @@ class IceCandidateCollection final {
bool HasCandidate(const IceCandidate* candidate) const;
IceCandidateCollection Clone() const;
void RelinquishThreadOwnership();
private:
RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_;
std::vector<std::unique_ptr<IceCandidate>> candidates_
RTC_GUARDED_BY(sequence_checker_);
std::vector<std::unique_ptr<IceCandidate>> candidates_;
};
// TODO: webrtc:406795492 - Deprecate.
using JsepCandidateCollection = IceCandidateCollection;
// Enum that describes the type of the SessionDescriptionInterface.
// Corresponds to RTCSdpType in the WebRTC specification.
// https://w3c.github.io/webrtc-pc/#dom-rtcsdptype
@ -218,13 +211,66 @@ void AbslStringify(Sink& sink, SdpType sdp_type) {
RTC_EXPORT std::optional<SdpType> SdpTypeFromString(
const std::string& type_str);
// TODO: bugs.webrtc.org/442220720 - This class is temporarily here while
// SessionDescriptionInterface transforms from a pure interface into a simple
// non-virtual class. The purpose of `SessionDescriptionInternal` is to provide
// protected methods to classes currently inheriting from
// SessionDescriptionInterface, the basic implementation that satisified the
// interface. Once the migration of the implementation is complete, the
// SessionDescriptionInterface class can be made non-virtual, final and
// SessionDescriptionInternal can effectively be renamed to
// SessionDescriptionInterface. The reason for all of this is that access to and
// modification of the internal state needs to be made thread aware so that
// concurrent operations aren't executed on different threads or that the
// state can be declared const when no known modifications are pending.
class SessionDescriptionInternal {
public:
explicit SessionDescriptionInternal(
SdpType type,
absl_nullable std::unique_ptr<SessionDescription> description,
absl::string_view id,
absl::string_view version);
~SessionDescriptionInternal();
// Resets the internal sequence_checker_ to not be attached to a particular
// thread. Used when transfering object ownership between threads. Must be
// called by the thread that currently owns the object before transferring the
// ownership.
void RelinquishThreadOwnership();
protected:
// Only meant for the SessionDescriptionInterface implementation.
SdpType sdp_type() const { return sdp_type_; }
absl::string_view id() const { return id_; }
absl::string_view version() const { return version_; }
const SessionDescription* description() const { return description_.get(); }
SessionDescription* description() { return description_.get(); }
size_t mediasection_count() const;
protected:
// This method is necessarily `protected`, and not private, while
// the SessionDescriptionInterface implementation is being consolidated
// into a single class.
const SequenceChecker* sequence_checker() const { return &sequence_checker_; }
private:
RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_{
SequenceChecker::kDetached};
const SdpType sdp_type_;
const std::string id_;
const std::string version_;
absl_nullable const std::unique_ptr<SessionDescription> description_;
};
// 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 final {
class RTC_EXPORT SessionDescriptionInterface
: public SessionDescriptionInternal {
public:
static std::unique_ptr<SessionDescriptionInterface> Create(
SdpType type,
@ -243,30 +289,31 @@ class RTC_EXPORT SessionDescriptionInterface final {
static const char kAnswer[];
static const char kRollback[];
~SessionDescriptionInterface();
virtual ~SessionDescriptionInterface() {}
// Create a new SessionDescriptionInterface object
// with the same values as the old object.
std::unique_ptr<SessionDescriptionInterface> Clone() const;
absl::string_view id() const { return id_; }
absl::string_view version() const { return version_; }
virtual std::unique_ptr<SessionDescriptionInterface> Clone() const;
// Only for use internally.
const SessionDescription* description() const { return description_.get(); }
SessionDescription* description() { return description_.get(); }
virtual SessionDescription* description() {
return SessionDescriptionInternal::description();
}
virtual const SessionDescription* description() const {
return SessionDescriptionInternal::description();
}
// Get the session id and session version, which are defined based on
// RFC 4566 for the SDP o= line.
std::string session_id() const { return std::string(id()); }
std::string session_version() const { return std::string(version()); }
virtual std::string session_id() const { return std::string(id()); }
virtual std::string session_version() const { return std::string(version()); }
// Returns the type of this session description as an SdpType. Descriptions of
// the various types are found in the SdpType documentation.
SdpType GetType() const { return sdp_type_; }
virtual SdpType GetType() const { return sdp_type(); }
// TODO(steveanton): Remove this in favor of `GetType` that returns SdpType.
std::string type() const { return SdpTypeToString(sdp_type_); }
virtual std::string type() const { return SdpTypeToString(sdp_type()); }
// Adds the specified candidate to the description.
//
@ -275,7 +322,7 @@ class RTC_EXPORT SessionDescriptionInterface final {
// Returns false if the session description does not have a media section
// that corresponds to `candidate.sdp_mid()` or
// `candidate.sdp_mline_index()`.
bool AddCandidate(const IceCandidate* candidate);
virtual bool AddCandidate(const IceCandidate* candidate);
// Removes the first matching candidate (at most 1) from the description
// that meets the `Candidate::MatchesForRemoval()` requirement and matches
@ -283,46 +330,35 @@ class RTC_EXPORT SessionDescriptionInterface final {
// `IceCandidate::sdp_mline_index()`.
//
// Returns false if no matching candidate was found (and removed).
bool RemoveCandidate(const IceCandidate* candidate);
virtual bool RemoveCandidate(const IceCandidate* candidate);
// Returns the number of m= sections in the session description.
size_t number_of_mediasections() const;
virtual size_t number_of_mediasections() const {
return mediasection_count();
}
// Returns a collection of all candidates that belong to a certain m=
// section.
const IceCandidateCollection* candidates(size_t mediasection_index) const;
virtual const IceCandidateCollection* candidates(
size_t mediasection_index) const;
// Serializes the description to SDP.
bool ToString(std::string* out) const {
if (!out)
return false;
*out = ToString();
return !out->empty();
}
// Serializes the description to SDP.
std::string ToString() const;
virtual bool ToString(std::string* out) const;
template <typename Sink>
friend void AbslStringify(Sink& sink, const SessionDescriptionInterface& p) {
sink.Append("\n--- BEGIN SDP ");
absl::Format(&sink, "%v", p.GetType());
sink.Append(" ---\n");
std::string temp = p.ToString();
if (!temp.empty()) {
std::string temp;
if (p.ToString(&temp)) {
sink.Append(temp);
} else {
sink.Append("<no session description>\n");
sink.Append("Error in ToString\n");
}
sink.Append("--- END SDP ---\n");
}
// Resets the internal sequence_checker_ to not be attached to a particular
// thread. Used when transfering object ownership between threads. Must be
// called by the thread that currently owns the object before transferring the
// ownership.
void RelinquishThreadOwnership();
protected:
explicit SessionDescriptionInterface(
SdpType type,
@ -336,15 +372,8 @@ class RTC_EXPORT SessionDescriptionInterface final {
bool GetMediasectionIndex(const IceCandidate* candidate, size_t* index) const;
int GetMediasectionIndex(absl::string_view mid) const;
const SdpType sdp_type_;
const std::string id_;
const std::string version_;
absl_nullable const std::unique_ptr<SessionDescription> description_;
RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_{
SequenceChecker::kDetached};
std::vector<IceCandidateCollection> candidate_collection_
RTC_GUARDED_BY(sequence_checker_);
RTC_GUARDED_BY(sequence_checker());
};
// Creates a SessionDescriptionInterface based on the SDP string and the type.
@ -352,18 +381,18 @@ class RTC_EXPORT SessionDescriptionInterface final {
// 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, absl::string_view sdp);
CreateSessionDescription(SdpType type, const std::string& sdp);
RTC_EXPORT std::unique_ptr<SessionDescriptionInterface>
CreateSessionDescription(SdpType type,
absl::string_view sdp,
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,
absl::string_view session_id,
absl::string_view session_version,
const std::string& session_id,
const std::string& session_version,
std::unique_ptr<SessionDescription> description);
// Creates a rollback session description object (SdpType::kRollback).

View File

@ -12,20 +12,16 @@
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <limits>
#include <memory>
#include <string>
#include <utility>
#include "absl/algorithm/container.h"
#include "absl/base/nullability.h"
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "api/candidate.h"
#include "api/jsep.h"
#include "api/rtc_error.h"
#include "api/sequence_checker.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
@ -43,23 +39,6 @@ int EnsureValidMLineIndex(int sdp_mline_index) {
}
} // namespace
// static
std::unique_ptr<IceCandidate> IceCandidate::Create(absl::string_view mid,
int sdp_mline_index,
absl::string_view sdp,
SdpParseError* absl_nullable
error /*= nullptr*/) {
RTCErrorOr<Candidate> c = Candidate::ParseCandidateString(sdp);
if (!c.ok()) {
if (error) {
error->line = sdp;
error->description = c.error().message();
}
return nullptr;
}
return std::make_unique<IceCandidate>(mid, sdp_mline_index, c.value());
}
IceCandidate::IceCandidate(absl::string_view sdp_mid,
int sdp_mline_index,
const Candidate& candidate)
@ -72,30 +51,24 @@ IceCandidate::IceCandidate(absl::string_view sdp_mid,
}
void IceCandidateCollection::add(std::unique_ptr<IceCandidate> candidate) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
candidates_.push_back(std::move(candidate));
}
void IceCandidateCollection::add(IceCandidate* candidate) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
candidates_.push_back(absl::WrapUnique(candidate));
}
void IceCandidateCollection::Append(IceCandidateCollection collection) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_DCHECK_RUN_ON(&collection.sequence_checker_);
candidates_.insert(candidates_.end(),
std::make_move_iterator(collection.candidates_.begin()),
std::make_move_iterator(collection.candidates_.end()));
}
const IceCandidate* IceCandidateCollection::at(size_t index) const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
return candidates_[index].get();
}
bool IceCandidateCollection::HasCandidate(const IceCandidate* candidate) const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
const auto sdp_mid = candidate->sdp_mid(); // avoid string copy per entry.
return absl::c_any_of(
candidates_, [&](const std::unique_ptr<IceCandidate>& entry) {
@ -111,22 +84,8 @@ bool IceCandidateCollection::HasCandidate(const IceCandidate* candidate) const {
});
}
IceCandidateCollection IceCandidateCollection::Clone() const {
IceCandidateCollection new_collection;
RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_DCHECK_RUN_ON(&new_collection.sequence_checker_);
new_collection.candidates_.reserve(candidates_.size());
for (const auto& candidate : candidates_) {
new_collection.candidates_.push_back(std::make_unique<IceCandidate>(
candidate->sdp_mid(), candidate->sdp_mline_index(),
candidate->candidate()));
}
return new_collection;
}
size_t IceCandidateCollection::remove(const IceCandidate* candidate) {
size_t JsepCandidateCollection::remove(const IceCandidate* candidate) {
RTC_DCHECK(candidate);
RTC_DCHECK_RUN_ON(&sequence_checker_);
auto iter =
absl::c_find_if(candidates_, [&](const std::unique_ptr<IceCandidate>& c) {
return c->candidate().MatchesForRemoval(candidate->candidate());
@ -138,12 +97,4 @@ size_t IceCandidateCollection::remove(const IceCandidate* candidate) {
return 0u;
}
void IceCandidateCollection::RelinquishThreadOwnership() {
sequence_checker_.Detach();
}
std::string IceCandidate::ToString() const {
return candidate_.ToCandidateAttribute(true);
}
} // namespace webrtc

View File

@ -0,0 +1,52 @@
/*
* 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 <cstddef>
#include <memory>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/jsep.h"
namespace webrtc {
class SessionDescription;
// Implementation of SessionDescriptionInterface.
class JsepSessionDescription final : public SessionDescriptionInterface {
public:
// TODO: bugs.webrtc.org/442220720 - Remove this constructor and make sure
// that JsepSessionDescription can only be constructed with a valid
// SessionDescription object (with the exception of kRollback).
[[deprecated(
"JsepSessionDescription needs to be initialized with a valid description "
"object")]]
explicit JsepSessionDescription(SdpType type);
JsepSessionDescription(SdpType type,
std::unique_ptr<SessionDescription> description,
absl::string_view session_id,
absl::string_view session_version,
std::vector<IceCandidateCollection> candidates = {});
~JsepSessionDescription() override;
JsepSessionDescription(const JsepSessionDescription&) = delete;
JsepSessionDescription& operator=(const JsepSessionDescription&) = delete;
};
} // namespace webrtc
#endif // API_JSEP_SESSION_DESCRIPTION_H_

View File

@ -253,7 +253,7 @@ class RTC_EXPORT StatsReport {
// this Equals() function. It simply calls the protected (and overridden)
// Equals() method.
bool Equals(const scoped_refptr<IdBase>& other) const {
return Equals(*other);
return Equals(*other.get());
}
virtual std::string ToString() const = 0;

View File

@ -17,6 +17,7 @@ rtc_library("neteq_api") {
]
deps = [
"..:array_view",
"..:rtp_headers",
"..:rtp_packet_info",
"..:scoped_refptr",

Some files were not shown because too many files have changed in this diff Show More