Compare commits
3 Commits
main
...
adel/alter
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2631ea6c2a | ||
|
|
b3a7810f2b | ||
|
|
856ed7ef95 |
@ -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.
|
||||
@ -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).
|
||||
@ -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`).
|
||||
@ -1,7 +1,7 @@
|
||||
---
|
||||
---
|
||||
Checks: '-*,
|
||||
bugprone-argument-comment,
|
||||
bugprone-argument-comment
|
||||
llvm-namespace-comment,
|
||||
modernize-use-designated-initializers,
|
||||
modernize-use-override,
|
||||
|
||||
@ -32,5 +32,3 @@ c018bae80743596694db91478b879815f19dfb74
|
||||
bceec84aeedcb9f5992d30dae0b477fb5e227fee
|
||||
# Format the rest
|
||||
7220ee97aafaa33a914f578e0f04184a94d17974
|
||||
# Run clang-tidy on the repo
|
||||
97b46e12582606a238d4f0c8524365cf5bdcb411
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -34,13 +34,11 @@
|
||||
.cproject
|
||||
.gdb_history
|
||||
.gdbinit
|
||||
.gemini
|
||||
.landmines
|
||||
.metadata
|
||||
.project
|
||||
.pydevproject
|
||||
.settings
|
||||
.siso_failed_targets
|
||||
.sw?
|
||||
/Makefile
|
||||
/base
|
||||
|
||||
9
.gn
9
.gn
@ -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
|
||||
}
|
||||
|
||||
@ -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
10
AUTHORS
@ -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.
|
||||
|
||||
91
BUILD.gn
91
BUILD.gn
@ -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
440
DEPS
@ -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",
|
||||
|
||||
10
GEMINI.md
10
GEMINI.md
@ -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
4
OWNERS
@ -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}
|
||||
|
||||
16
OWNERS_INFRA
16
OWNERS_INFRA
@ -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
|
||||
|
||||
23
PRESUBMIT.py
23
PRESUBMIT.py
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
77
WATCHLISTS
77
WATCHLISTS
@ -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'],
|
||||
},
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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 WebRTC’s 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.
|
||||
@ -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.
|
||||
639
api/BUILD.gn
639
api/BUILD.gn
File diff suppressed because it is too large
Load Diff
126
api/DEPS
126
api/DEPS
@ -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",
|
||||
|
||||
13
api/OWNERS
13
api/OWNERS
@ -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
|
||||
|
||||
319
api/array_view.h
319
api/array_view.h
@ -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
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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") {
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
specific_include_rules = {
|
||||
"neural_residual_echo_estimator_creator\\.h" : [
|
||||
"+third_party/tflite",
|
||||
],
|
||||
}
|
||||
@ -1,4 +1,2 @@
|
||||
devicentepena@webrtc.org
|
||||
gustaf@webrtc.org
|
||||
peah@webrtc.org
|
||||
saza@webrtc.org
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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_
|
||||
@ -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",
|
||||
|
||||
@ -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++) {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -29,6 +29,7 @@ rtc_library("audio_codecs_api") {
|
||||
"audio_format.h",
|
||||
]
|
||||
deps = [
|
||||
"..:array_view",
|
||||
"..:bitrate_allocation",
|
||||
"..:make_ref_counted",
|
||||
"..:ref_count",
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
alessiob@webrtc.org
|
||||
henrik.lundin@webrtc.org
|
||||
jakobi@webrtc.org
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@ -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*/) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
//
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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_
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -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:
|
||||
|
||||
316
api/candidate.cc
316
api/candidate.cc
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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",
|
||||
]
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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_
|
||||
301
api/jsep.cc
301
api/jsep.cc
@ -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
|
||||
|
||||
151
api/jsep.h
151
api/jsep.h
@ -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).
|
||||
|
||||
@ -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
|
||||
|
||||
52
api/jsep_session_description.h
Normal file
52
api/jsep_session_description.h
Normal 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_
|
||||
@ -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;
|
||||
|
||||
@ -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
Loading…
Reference in New Issue
Block a user