Compare commits
123 Commits
Author | SHA1 | Date | |
---|---|---|---|
846fe90a28 | |||
8f445c36cc | |||
a24b45cc19 | |||
a9f97c9fdd | |||
f8a6ea0a9a | |||
222790ad57 | |||
1818e5eb50 | |||
c555fb6eaf | |||
845e79a2a7 | |||
0743cb5ce5 | |||
971f026d55 | |||
774ac54e71 | |||
54a632f018 | |||
d63a2c9714 | |||
73aed233b2 | |||
2493b6e659 | |||
fc5a4946af | |||
b7a194f824 | |||
6c914be933 | |||
8b0255991e | |||
b22ce018c8 | |||
a1ccd6c700 | |||
297fd4f2ef | |||
ecb8817972 | |||
6119c05d7d | |||
2a318149f8 | |||
4a17c682e9 | |||
5252919799 | |||
85556fd38b | |||
da757ff09f | |||
fed81a77c9 | |||
c144c53039 | |||
0d4c5f27b5 | |||
9b194c2d99 | |||
d090f7a927 | |||
ad563b095c | |||
b5c48b97f6 | |||
8bdb53d91c | |||
ced0ff6765 | |||
1ff1a0b860 | |||
867e2d875b | |||
a729ccfe0f | |||
4c81b31652 | |||
0a0050746b | |||
06157f1659 | |||
c6abf6cd3f | |||
9a202fb8c2 | |||
a949f1de2d | |||
f89958d824 | |||
8e258a1933 | |||
0691ae20d8 | |||
c9b0a675e4 | |||
315b2222a8 | |||
bc401b3cbf | |||
92a4765a7e | |||
c76b8bf340 | |||
cdec109331 | |||
096b0eaed2 | |||
b24229cbbc | |||
55239c4ca2 | |||
a47df351ca | |||
4125ace620 | |||
aa32d179d0 | |||
9a362bd149 | |||
8366ff0ce0 | |||
ca1186946d | |||
26f4493405 | |||
e31340c243 | |||
5a5aa66ada | |||
0cc2ebeda2 | |||
6064932abf | |||
8bf9efad15 | |||
ff85c98683 | |||
57ec282d4f | |||
6e37f37c4e | |||
b8ad0dfc22 | |||
e47b68df57 | |||
e74894baeb | |||
589a744585 | |||
8ac052ad6f | |||
b34c1d5746 | |||
3f9907f93d | |||
ce1a78887a | |||
8ce8bebb7d | |||
00ae7eb234 | |||
d353e92425 | |||
6a4d14d5c0 | |||
6a67b5ba7e | |||
e5402cd638 | |||
e23c10c5e0 | |||
d938d2cf52 | |||
593986ec5e | |||
2fabea79e0 | |||
21d78a4267 | |||
bcec8b0b21 | |||
b1b02581d3 | |||
a54ffa1220 | |||
34efc689c2 | |||
f13529b5b8 | |||
f2003f80d1 | |||
301110c655 | |||
9def8cf10d | |||
27e93ee86b | |||
682857751b | |||
b47c302cef | |||
eb398328ab | |||
e882a5442a | |||
ee8cfef49b | |||
0d937fbc71 | |||
ff77a85c28 | |||
7d15b10fb0 | |||
7a37a8bca3 | |||
b8be6d1095 | |||
c9cffb9e3d | |||
1378babdf0 | |||
75ef0de241 | |||
6ad2f51e9e | |||
db2f422578 | |||
bf6b9de143 | |||
12ac8441f7 | |||
44cf7726ca | |||
560f300a3d | |||
bf25c45e54 |
25
.gitignore
vendored
25
.gitignore
vendored
@ -1,30 +1,11 @@
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
*.pc
|
||||
.*.swp
|
||||
*~
|
||||
.deps*
|
||||
.dirstamp
|
||||
.libs*
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.rpath
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
build/
|
||||
depcomp
|
||||
install-sh
|
||||
libltdl
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
stamp-*
|
||||
install/
|
||||
subprojects/*/
|
||||
|
299
.gitlab-ci.yml
Normal file
299
.gitlab-ci.yml
Normal file
@ -0,0 +1,299 @@
|
||||
# The build has two stages. The 'container' stage is used to build a Docker
|
||||
# container and push it to the project's container registry on fd.o GitLab.
|
||||
# This step is only run when the tag for the container changes, else it is
|
||||
# effectively a no-op. All of this infrastructure is inherited from the
|
||||
# wayland/ci-templates repository which is the recommended way to set up CI
|
||||
# infrastructure on fd.o GitLab.
|
||||
#
|
||||
# Once the container stage is done, we move on to the 'build' stage where we
|
||||
# run an autotools and meson build in parallel. Currently, tests are also run
|
||||
# as part of the build stage as there doesn't seem to be significant value to
|
||||
# splitting the stages at the moment.
|
||||
|
||||
# Create merge request pipelines for open merge requests, branch pipelines
|
||||
# otherwise. This allows MRs for new users to run CI, and prevents duplicate
|
||||
# pipelines for branches with open MRs.
|
||||
workflow:
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
||||
when: never
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
|
||||
stages:
|
||||
- container
|
||||
- build
|
||||
|
||||
variables:
|
||||
# Update this tag when you want to trigger a rebuild the container in which
|
||||
# CI runs, for example when adding new packages to FDO_DISTRIBUTION_PACKAGES.
|
||||
# The tag is an arbitrary string that identifies the exact container
|
||||
# contents.
|
||||
BASE_TAG: '2024-12-26.0'
|
||||
FDO_DISTRIBUTION_VERSION: '41'
|
||||
FDO_UPSTREAM_REPO: 'pulseaudio/webrtc-audio-processing'
|
||||
|
||||
include:
|
||||
# We pull templates from master to avoid the overhead of periodically
|
||||
# scanning for changes upstream. This does means builds might occasionally
|
||||
# break due to upstream changing things, so if you see unexpected build
|
||||
# failures, this might be one cause.
|
||||
- project: 'freedesktop/ci-templates'
|
||||
ref: 'master'
|
||||
file: '/templates/fedora.yml'
|
||||
|
||||
# Common container build template
|
||||
.fedora-container-build:
|
||||
variables:
|
||||
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
|
||||
|
||||
# Remember to update FDO_DISTRIBUTION_TAG when modifying this package list!
|
||||
# Otherwise the changes won't have effect since an old container image will
|
||||
# be used.
|
||||
FDO_DISTRIBUTION_PACKAGES: >-
|
||||
ca-certificates
|
||||
g++
|
||||
gcc
|
||||
git-core
|
||||
cmake
|
||||
abseil-cpp-devel
|
||||
meson
|
||||
ninja-build
|
||||
pkg-config
|
||||
python3-setuptools
|
||||
|
||||
# Used to extend both container and build jobs
|
||||
.fedora-x86_64:
|
||||
variables:
|
||||
FDO_DISTRIBUTION_TAG: "x86_64-$BASE_TAG"
|
||||
|
||||
# Used to extend both container and build jobs
|
||||
.fedora-aarch64:
|
||||
tags:
|
||||
- aarch64
|
||||
variables:
|
||||
FDO_DISTRIBUTION_TAG: "aarch64-$BASE_TAG"
|
||||
|
||||
build-container-x86_64:
|
||||
extends:
|
||||
- .fdo.container-build@fedora@x86_64
|
||||
- .fedora-container-build
|
||||
- .fedora-x86_64
|
||||
stage: container
|
||||
|
||||
build-container-aarch64:
|
||||
extends:
|
||||
- .fdo.container-build@fedora@aarch64
|
||||
- .fedora-container-build
|
||||
- .fedora-aarch64
|
||||
stage: container
|
||||
|
||||
# Common build template
|
||||
.build-distro-absl:
|
||||
stage: build
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
script:
|
||||
- meson setup --wrap-mode=nofallback --prefix=/usr --libdir=lib builddir
|
||||
- ninja -C builddir
|
||||
- DESTDIR=$PWD/_install ninja install -C builddir
|
||||
# Test that the pc files are usable
|
||||
- PKG_CONFIG_PATH=$PWD/_install/usr/lib/pkgconfig pkg-config --cflags --libs webrtc-audio-processing-2
|
||||
artifacts:
|
||||
expire_in: '5 days'
|
||||
when: 'always'
|
||||
paths:
|
||||
- "builddir/meson-logs/*txt"
|
||||
|
||||
.build-vendored-absl:
|
||||
stage: build
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
script:
|
||||
- meson setup --force-fallback-for=abseil-cpp --prefix=/usr --libdir=lib builddir
|
||||
- ninja -C builddir
|
||||
- DESTDIR=$PWD/_install ninja install -C builddir
|
||||
# Test that the pc files are usable
|
||||
- PKG_CONFIG_LIBDIR=$PWD/_install/usr/lib/pkgconfig pkg-config --cflags --libs webrtc-audio-processing-2
|
||||
artifacts:
|
||||
expire_in: '5 days'
|
||||
when: 'always'
|
||||
paths:
|
||||
- "builddir/meson-logs/*txt"
|
||||
|
||||
build-distro-absl-x86_64:
|
||||
extends:
|
||||
- .build-distro-absl
|
||||
- .fedora-x86_64
|
||||
|
||||
build-vendored-absl-x86_64:
|
||||
extends:
|
||||
- .build-vendored-absl
|
||||
- .fedora-x86_64
|
||||
|
||||
build-distro-absl-aarch64:
|
||||
extends:
|
||||
- .build-distro-absl
|
||||
- .fedora-aarch64
|
||||
|
||||
build-vendored-absl-aarch64:
|
||||
extends:
|
||||
- .build-vendored-absl
|
||||
- .fedora-aarch64
|
||||
|
||||
# Update from:
|
||||
# https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/main/.gitlab-ci.yml
|
||||
# https://gitlab.freedesktop.org/gstreamer/orc/-/blob/main/.gitlab-ci.yml
|
||||
vs2019 amd64:
|
||||
# Update from https://gitlab.freedesktop.org/gstreamer/gstreamer/container_registry
|
||||
image: 'registry.freedesktop.org/gstreamer/gstreamer/amd64/windows:2023-04-21.0-main'
|
||||
stage: 'build'
|
||||
tags:
|
||||
- 'docker'
|
||||
- 'windows'
|
||||
- '2022'
|
||||
artifacts:
|
||||
expire_in: '5 days'
|
||||
when: 'always'
|
||||
paths:
|
||||
- "builddir/meson-logs/*txt"
|
||||
variables:
|
||||
# Make sure any failure in PowerShell scripts is fatal
|
||||
ErrorActionPreference: 'Stop'
|
||||
WarningPreference: 'Stop'
|
||||
ARCH: 'amd64'
|
||||
PLAT: 'Desktop'
|
||||
before_script:
|
||||
# Make sure meson is up to date, so we don't need to rebuild the image with each release
|
||||
- pip3 install -U meson ninja
|
||||
script:
|
||||
# Gitlab executes PowerShell in docker, but VsDevCmd.bat is a batch script.
|
||||
# Environment variables substitutions is done by PowerShell before calling
|
||||
# cmd.exe, that's why we use $env:FOO instead of %FOO%
|
||||
- cmd.exe /C "C:\BuildTools\Common7\Tools\VsDevCmd.bat -host_arch=amd64 -arch=$env:ARCH -app_platform=$env:PLAT &&
|
||||
meson setup builddir -Dcpp_std=c++20 &&
|
||||
meson compile --verbose -C builddir"
|
||||
|
||||
# Update from:
|
||||
# https://gitlab.freedesktop.org/gstreamer/cerbero/-/blob/main/.gitlab-ci.yml
|
||||
# https://gitlab.freedesktop.org/gstreamer/orc/-/blob/main/.gitlab-ci.yml
|
||||
macos x86_64:
|
||||
stage: 'build'
|
||||
tags:
|
||||
- gst-macos-13
|
||||
artifacts:
|
||||
expire_in: '5 days'
|
||||
when: 'always'
|
||||
paths:
|
||||
- "builddir/meson-logs/*txt"
|
||||
before_script:
|
||||
- pip3 install --upgrade pip
|
||||
# Need to install certificates for python
|
||||
- pip3 install --upgrade certifi
|
||||
# Anther way to install certificates
|
||||
- open /Applications/Python\ 3.8/Install\ Certificates.command
|
||||
# Make sure meson and ninja are up to date
|
||||
- pip3 install -U meson ninja
|
||||
script:
|
||||
- CERT_PATH=$(python3 -m certifi) && export SSL_CERT_FILE=${CERT_PATH} && export REQUESTS_CA_BUNDLE=${CERT_PATH}
|
||||
- meson setup builddir
|
||||
- meson compile --verbose -C builddir
|
||||
|
||||
# Update from:
|
||||
# https://gitlab.freedesktop.org/gstreamer/cerbero/-/blob/main/.gitlab-ci.yml
|
||||
# https://gitlab.freedesktop.org/gstreamer/orc/-/blob/main/.gitlab-ci.yml
|
||||
ios arm64:
|
||||
stage: 'build'
|
||||
tags:
|
||||
- gst-ios-16
|
||||
artifacts:
|
||||
name: "${CI_JOB_NAME}_${CI_COMMIT_SHA}"
|
||||
expire_in: '5 days'
|
||||
when: 'always'
|
||||
paths:
|
||||
- "builddir/meson-logs/*txt"
|
||||
before_script:
|
||||
- pip3 install --upgrade pip
|
||||
# Need to install certificates for python
|
||||
- pip3 install --upgrade certifi
|
||||
# Anther way to install certificates
|
||||
- open /Applications/Python\ 3.8/Install\ Certificates.command
|
||||
# Make sure meson and ninja are up to date
|
||||
- pip3 install -U meson ninja
|
||||
script:
|
||||
- CERT_PATH=$(python3 -m certifi) && export SSL_CERT_FILE=${CERT_PATH} && export REQUESTS_CA_BUNDLE=${CERT_PATH}
|
||||
- |
|
||||
cat > ios-cross-file.txt <<EOF
|
||||
[host_machine]
|
||||
system = 'darwin'
|
||||
cpu_family = 'aarch64'
|
||||
cpu = 'aarch64'
|
||||
endian = 'little'
|
||||
|
||||
[properties]
|
||||
c_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
|
||||
objc_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
|
||||
cpp_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
|
||||
objcpp_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
|
||||
c_link_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
|
||||
objc_link_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
|
||||
cpp_link_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
|
||||
objcpp_link_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
|
||||
|
||||
[binaries]
|
||||
ar = '$(xcrun --find --sdk iphoneos ar)'
|
||||
c = '$(xcrun --find --sdk iphoneos clang)'
|
||||
objc = '$(xcrun --find --sdk iphoneos clang)'
|
||||
cpp = '$(xcrun --find --sdk iphoneos clang++)'
|
||||
objcpp = '$(xcrun --find --sdk iphoneos clang++)'
|
||||
ranlib = '$(xcrun --find --sdk iphoneos ranlib)'
|
||||
strip = '$(xcrun --find --sdk iphoneos strip)'
|
||||
pkgconfig = 'false'
|
||||
cmake = 'false'
|
||||
EOF
|
||||
- meson setup --cross-file ios-cross-file.txt builddir
|
||||
- meson compile --verbose -C builddir
|
||||
|
||||
# Update from:
|
||||
# https://gitlab.freedesktop.org/gstreamer/cerbero/-/blob/main/.gitlab-ci.yml
|
||||
# https://gitlab.freedesktop.org/gstreamer/orc/-/blob/main/.gitlab-ci.yml
|
||||
android fedora arm64:
|
||||
# Update from https://gitlab.freedesktop.org/gstreamer/cerbero/container_registry
|
||||
image: 'registry.freedesktop.org/gstreamer/cerbero/amd64/android-fedora:2021-10-22.0-1.18'
|
||||
stage: 'build'
|
||||
artifacts:
|
||||
expire_in: '5 days'
|
||||
when: 'always'
|
||||
paths:
|
||||
- "builddir/meson-logs/*.txt"
|
||||
before_script:
|
||||
- dnf install -y python3-pip gcc ninja-build
|
||||
- pip3 install --user meson
|
||||
script:
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- |
|
||||
cat > android-cross-file.txt <<EOF
|
||||
[constants]
|
||||
ndk_path = '/android/ndk'
|
||||
toolchain = ndk_path + '/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android'
|
||||
api = '28'
|
||||
|
||||
[host_machine]
|
||||
system = 'android'
|
||||
cpu_family = 'aarch64'
|
||||
cpu = 'aarch64'
|
||||
endian = 'little'
|
||||
|
||||
[properties]
|
||||
sys_root = ndk_path + '/sysroot'
|
||||
c_link_args = ['-fuse-ld=gold']
|
||||
cpp_link_args = ['-fuse-ld=gold']
|
||||
|
||||
[binaries]
|
||||
c = toolchain + api + '-clang'
|
||||
cpp = toolchain + api + '-clang++'
|
||||
ar = toolchain + '-ar'
|
||||
strip = toolchain + '-strip'
|
||||
EOF
|
||||
- meson setup --cross-file android-cross-file.txt builddir
|
||||
- meson compile --verbose -C builddir
|
23
Makefile.am
23
Makefile.am
@ -1,23 +0,0 @@
|
||||
SUBDIRS = webrtc
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = webrtc-audio-processing.pc
|
||||
|
||||
webrtcincludedir = $(includedir)/webrtc_audio_processing
|
||||
nobase_webrtcinclude_HEADERS = webrtc/base/arraysize.h \
|
||||
webrtc/base/checks.h \
|
||||
webrtc/base/constructormagic.h \
|
||||
webrtc/base/basictypes.h \
|
||||
webrtc/base/maybe.h \
|
||||
webrtc/base/platform_file.h \
|
||||
webrtc/common.h \
|
||||
webrtc/common_types.h \
|
||||
webrtc/typedefs.h \
|
||||
webrtc/modules/audio_processing/beamformer/array_util.h \
|
||||
webrtc/modules/audio_processing/include/audio_processing.h \
|
||||
webrtc/modules/interface/module_common_types.h \
|
||||
webrtc/system_wrappers/include/trace.h
|
||||
|
||||
EXTRA_DIST = NEWS \
|
||||
README.md \
|
||||
UPDATING.md
|
70
NEWS
70
NEWS
@ -1,3 +1,73 @@
|
||||
Release 2.1
|
||||
-----------
|
||||
|
||||
Build-system fixups to install more headers, add a missing absl dependency, and
|
||||
forward port some missing patches to fix Windows builds.
|
||||
|
||||
|
||||
Release 2.0
|
||||
-----------
|
||||
|
||||
Bump to code from WebRTC M131 version.
|
||||
|
||||
Changes include:
|
||||
|
||||
* Minor (breaking) API changes upstream
|
||||
* Various improvements to the AEC implementation
|
||||
* Transient suppression is removed
|
||||
* ExperimentalAgc and ExperimentalNs are removed
|
||||
* iSAC and the webrtc-audio-coding library were removed
|
||||
* abseil-cpp dependency bumped to 20240722
|
||||
* NEON runtime detection dropped following upstream
|
||||
* Fixes for building on i686 and MIPS
|
||||
* Support for BSDs is added
|
||||
* Other build-system cleanups
|
||||
* Patches to upstream are now also tracked in patches/
|
||||
|
||||
|
||||
Release 1.3
|
||||
-----------
|
||||
|
||||
Fix for generate pkg-config file.
|
||||
|
||||
|
||||
Release 1.2
|
||||
-----------
|
||||
|
||||
Improvements for building with abseil-cpp as a subproject, and pkg-config
|
||||
improvements for abseil dependency detection.
|
||||
|
||||
|
||||
Release 1.1
|
||||
-----------
|
||||
|
||||
Build fixes for various platforms.
|
||||
|
||||
|
||||
Release 1.0
|
||||
-----------
|
||||
|
||||
This is an API breaking release (as a reminder, the AudioProcessing module does
|
||||
not provide a stable public API, so we expose whatever API exists in the
|
||||
upstream project).
|
||||
|
||||
In order to make package management easier with these inevitable breakages, the
|
||||
package is now suffixed with a version (currently it is
|
||||
webrtc-audio-processing-1). When the next API break happens, we will bump the
|
||||
major version, allowing incompatible versions to coexist. This also means that
|
||||
the previous version can also coexist with this one. Non-breaking changes will
|
||||
see a minor version update only.
|
||||
|
||||
Changes:
|
||||
* The code base is now updated to correspond to the version shipping with the
|
||||
Chromium 88.0.4290.1 tag
|
||||
* There are a very large number changes to the underlying AEC implementation
|
||||
since the last update was a while ago. Most visibly the use of the AEC3
|
||||
canceller by default, the deletion of the beamformer code
|
||||
* The autotools build system is replaced by meson
|
||||
* The pkg-config name is changed as described above
|
||||
|
||||
|
||||
Release 0.3
|
||||
-----------
|
||||
|
||||
|
43
README.md
43
README.md
@ -1,9 +1,9 @@
|
||||
About
|
||||
=====
|
||||
# About
|
||||
|
||||
This is meant to be a more Linux packaging friendly copy of the AudioProcessing
|
||||
module from the WebRTC[1][2] project. The ideal case is that we make no changes to
|
||||
the code to make tracking upstream code easy.
|
||||
module from the [ WebRTC ](https://webrtc.googlesource.com/src) project. The
|
||||
ideal case is that we make no changes to the code to make tracking upstream
|
||||
code easy.
|
||||
|
||||
This package currently only includes the AudioProcessing bits, but I am very
|
||||
open to collaborating with other projects that wish to distribute other bits of
|
||||
@ -11,26 +11,33 @@ the code and hopefully eventually have a single point of packaging all the
|
||||
WebRTC code to help people reuse the code and avoid keeping private copies in
|
||||
several different projects.
|
||||
|
||||
[1] http://code.google.com/p/webrtc/
|
||||
[2] https://chromium.googlesource.com/external/webrtc/trunk/webrtc.git
|
||||
# Building
|
||||
|
||||
Feedback
|
||||
========
|
||||
This project uses the [Meson build system](https://mesonbuild.com/). The
|
||||
quickest way to build is:
|
||||
|
||||
Patches, suggestions welcome. You can send them to the PulseAudio mailing
|
||||
list[2] or to me at the address below.
|
||||
```sh
|
||||
# Initialise into the build/ directory, for a prefixed install into the
|
||||
# install/ directory
|
||||
meson . build -Dprefix=$PWD/install
|
||||
|
||||
-- Arun Raghavan <mail@arunraghavan.net>
|
||||
# Run the actual build
|
||||
ninja -C build
|
||||
|
||||
[3] http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
|
||||
# Install locally
|
||||
ninja -C build install
|
||||
|
||||
Notes
|
||||
====
|
||||
# The libraries, headers, and pkg-config files are now in the install/
|
||||
# directory
|
||||
```
|
||||
|
||||
1. Some files need to be patch to avoid pulling in the gtest framework. This
|
||||
should ideally be pushed upstream in some way so we're able to just pull
|
||||
in what we need without changing anything.
|
||||
# Feedback
|
||||
|
||||
2. It might be nice to try LTO on the library. We build a lot of code as part
|
||||
Patches, suggestions welcome. You can file an issue on our Gitlab
|
||||
[repository](https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing/).
|
||||
|
||||
# Notes
|
||||
|
||||
1. It might be nice to try LTO on the library. We build a lot of code as part
|
||||
of the main AudioProcessing module deps, and it's possible that this could
|
||||
provide significant space savings.
|
||||
|
64
RELEASING.md
Normal file
64
RELEASING.md
Normal file
@ -0,0 +1,64 @@
|
||||
# Release process
|
||||
|
||||
## Update the code
|
||||
|
||||
Follow the instructions in `UPDATING.md` to update the code.
|
||||
|
||||
## Update the package version
|
||||
|
||||
If there is no API breakage, update the minor version (X.y -> X.y+1). If there
|
||||
is API breakage, update the major version (X.y -> X+1.0).
|
||||
|
||||
## Make sure builds are successful on all platforms
|
||||
|
||||
There is CI for `x86_64` and `aarch64` builds, but 32-bit ARM and MIPS builds
|
||||
need manual verfification (or testing downstream).
|
||||
|
||||
## Tag the release
|
||||
|
||||
Tag the release with:
|
||||
|
||||
```sh
|
||||
git tag -s -m 'WebRTC AudioProcessing v<X.y>' v<X.y>
|
||||
```
|
||||
|
||||
## Make a tarball
|
||||
|
||||
```sh
|
||||
# The output will be in build/meson-dist/
|
||||
meson dist -C build --formats=gztar,xztar --include-subprojects
|
||||
```
|
||||
|
||||
## Do a test build
|
||||
|
||||
```sh
|
||||
tar xvf webrtc-audio-processing-X.y.tar.xz
|
||||
cd webrtc-audio-processing-X.y
|
||||
meson . build -Dprefix=$PWD/install
|
||||
ninja -C build
|
||||
ninja -C build install
|
||||
cd ..
|
||||
```
|
||||
|
||||
## Publish the files
|
||||
|
||||
```sh
|
||||
scp webrtc-audio-processing-*.tar.* \
|
||||
annarchy.freedesktop.org:/srv/www.freedesktop.org/www/software/pulseaudio/webrtc-audio-processing/
|
||||
```
|
||||
|
||||
## Push the tag
|
||||
|
||||
```sh
|
||||
git push origin master
|
||||
git push origin vX.y
|
||||
```
|
||||
|
||||
## Update the website
|
||||
|
||||
This is currently an embarrassing manual process.
|
||||
|
||||
## Send out a release announcement
|
||||
|
||||
This goes to the `pulseaudio-discuss` and `gstreamer-devel` mailing lists, and
|
||||
possibly `discuss-webrtc` if it seems relevant.
|
19
UPDATING.md
19
UPDATING.md
@ -8,7 +8,7 @@ project source code.
|
||||
webrtc git repository Chromium uses.
|
||||
|
||||
2. Instructions on checking out the Chromium tree are on the
|
||||
[Chromium site][get-chromium]. As a shortcut, you can look at the DEPS file
|
||||
[WebRTC repo][get-webrtc]. As a shortcut, you can look at the DEPS file
|
||||
in the Chromium tree for the current webrtc version being used, and then
|
||||
just use that commit hash with the webrtc tree.
|
||||
|
||||
@ -29,7 +29,7 @@ project source code.
|
||||
system upstreama.
|
||||
|
||||
* Arch-specific files usually have special handling in the corresponding
|
||||
Makefile.am.
|
||||
meson.build.
|
||||
|
||||
4. Once everything has been copied and updated, everything needs to be built.
|
||||
Missing dependencies (files that were not copied, or new modules that are
|
||||
@ -43,25 +43,24 @@ project source code.
|
||||
|
||||
* The current policy is that we mirror upstream API as-is.
|
||||
|
||||
* Update configure.ac with the appropriate version info based on how the
|
||||
* Update soversion in meson.build with the appropriate version info based on how the
|
||||
code has changed. Details on how to do this are included in the
|
||||
[libtool documentation][libtool-version-info].
|
||||
|
||||
5. Build PulseAudio (and/or any other dependent projects) against the new code.
|
||||
The easy way to do this is via a prefixed install.
|
||||
|
||||
* Run ```configure``` webrtc-audio-processing with
|
||||
```--prefix=/some/local/path```, then do a ```make``` and
|
||||
```make install```.
|
||||
* Configure webrtc-audio-processing with
|
||||
```meson build -D prefix=$(pwd)/install```, then do a ```ninja -C build/ install```
|
||||
|
||||
* Run ```configure``` on PulseAudio with
|
||||
```PKG_CONFIG_PATH=/some/local/path/lib/pkgconfig```, which will cause the
|
||||
build to pick up the prefixed install. Then do a ```make```, run the built
|
||||
* Configure PulseAudio with
|
||||
```meson build -D pkg_config_path=/path/to/webrtc-audio-processing/install/lib64/pkgconfig/```, which will cause the
|
||||
build to pick up the prefixed install. Then do a ```ninja -C build```, run the built
|
||||
PulseAudio, and load ```module-echo-cancel``` to make sure it loads fine.
|
||||
|
||||
* Run some test streams through the canceller to make sure it is working
|
||||
fine.
|
||||
|
||||
[get-chromium]: http://dev.chromium.org/developers/how-tos/get-the-code
|
||||
[get-webrtc]: https://webrtc.googlesource.com/src/
|
||||
[meld]: http://meldmerge.org/
|
||||
[libtool-version-info]: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
|
@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
libtoolize
|
||||
aclocal
|
||||
automake --add-missing --copy
|
||||
autoconf
|
||||
./configure ${@}
|
123
configure.ac
123
configure.ac
@ -1,123 +0,0 @@
|
||||
AC_INIT([webrtc-audio-processing], [0.3])
|
||||
AM_INIT_AUTOMAKE([dist-xz subdir-objects tar-ustar])
|
||||
|
||||
AC_SUBST(LIBWEBRTC_AUDIO_PROCESSING_VERSION_INFO, [1:0:0])
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
# Set up the host_* variables
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_LIBTOOL
|
||||
AC_PROG_INSTALL
|
||||
AM_PROG_AS
|
||||
|
||||
AC_LANG_C
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
AC_ARG_WITH([ns-mode],
|
||||
AS_HELP_STRING([--with-ns-mode=float|fixed], [Noise suppresion mode to use. Default is float]))
|
||||
|
||||
AS_CASE(["x${with_ns_mode}"],
|
||||
["fixed"], [NS_FIXED=1],
|
||||
["float"], [NS_FIXED=0],
|
||||
[NS_FIXED=0])
|
||||
AM_CONDITIONAL(NS_FIXED, [test "x${NS_FIXED}" = "x1"])
|
||||
|
||||
|
||||
# Borrowed from gst-plugins-bad
|
||||
AC_CHECK_HEADER(MobileCoreServices/MobileCoreServices.h, HAVE_IOS="yes", HAVE_IOS="no", [-])
|
||||
|
||||
# Based on gst-plugins-bad configure.ac and defines in
|
||||
# <chromium source>/build/config/BUILDCONFIG.gn and
|
||||
# webrtc/BUILD.gn
|
||||
AS_CASE(["${host}"],
|
||||
[*android*],
|
||||
[
|
||||
OS_CFLAGS="-DWEBRTC_ANDROID -DWEBRTC_LINUX"
|
||||
PLATFORM_CFLAGS="-DWEBRTC_POSIX"
|
||||
],
|
||||
[*-*linux*],
|
||||
[
|
||||
OS_CFLAGS="-DWEBRTC_LINUX"
|
||||
PLATFORM_CFLAGS="-DWEBRTC_POSIX"
|
||||
],
|
||||
[*-*darwin*],
|
||||
[
|
||||
AS_IF([test "$HAVE_IOS" = "yes"],
|
||||
[OS_FLAGS="-DWEBRTC_MAC -DWEBRTC_IOS"],
|
||||
[OS_FLAGS="-DWEBRTC_MAC"])
|
||||
PLATFORM_CFLAGS="-DWEBRTC_POSIX"
|
||||
]
|
||||
# FIXME: Add Windows support
|
||||
)
|
||||
AC_SUBST(PLATFORM_CFLAGS)
|
||||
|
||||
AS_CASE(["${host_cpu}"],
|
||||
[i?86|x86_64],
|
||||
[
|
||||
HAVE_X86=1
|
||||
],
|
||||
[armv7*|armv8*],
|
||||
[
|
||||
HAVE_ARM=1
|
||||
HAVE_ARMV7=1
|
||||
ARCH_CFLAGS="-DWEBRTC_ARCH_ARM -DWEBRTC_ARCH_ARM_V7"
|
||||
],
|
||||
[arm*],
|
||||
[
|
||||
HAVE_ARM=1
|
||||
ARCH_CFLAGS="-DWEBRTC_ARCH_ARM"
|
||||
]
|
||||
# FIXME: Add MIPS support, see webrtc/BUILD.gn for defines
|
||||
)
|
||||
AM_CONDITIONAL(HAVE_X86, [test "x${HAVE_X86}" = "x1"])
|
||||
AM_CONDITIONAL(HAVE_ARM, [test "x${HAVE_ARM}" = "x1"])
|
||||
AM_CONDITIONAL(HAVE_ARMV7, [test "x${HAVE_ARMV7}" = "x1"])
|
||||
|
||||
# Borrowed from pulseaudio's configure.ac
|
||||
AC_ARG_ENABLE([neon],
|
||||
AS_HELP_STRING([--enable-neon], [Enable NEON optimisations on ARM CPUs that support it (yes|no|auto|runtime)]))
|
||||
|
||||
AS_IF([test "x$enable_neon" != "xno"],
|
||||
AS_IF([test "x$enable_neon" != "xruntime"],
|
||||
[
|
||||
save_CXXFLAGS="$CXXFLAGS"; CXXFLAGS="-mfpu=neon $CXXFLAGS"
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[
|
||||
#include <arm_neon.h>
|
||||
], [])],
|
||||
[
|
||||
HAVE_NEON=1
|
||||
ARCH_CFLAGS="$ARCH_CFLAGS -DWEBRTC_HAS_NEON -mfpu=neon"
|
||||
])
|
||||
CXXFLAGS="$save_CXXFLAGS"
|
||||
],
|
||||
[
|
||||
HAVE_NEON=1
|
||||
ARCH_CFLAGS="$ARCH_CFLAGS -DWEBRTC_DETECT_NEON -mfpu=neon"
|
||||
])
|
||||
)
|
||||
AM_CONDITIONAL([HAVE_NEON], [test "x$HAVE_NEON" = "x1"])
|
||||
|
||||
COMMON_CFLAGS="-DWEBRTC_AUDIO_PROCESSING_ONLY_BUILD ${PLATFORM_CFLAGS} ${OS_CFLAGS} ${ARCH_CFLAGS} -DNDEBUG -I\$(top_srcdir)"
|
||||
COMMON_CXXFLAGS="-std=c++11 -DWEBRTC_AUDIO_PROCESSING_ONLY_BUILD ${PLATFORM_CFLAGS} ${OS_CFLAGS} ${ARCH_CFLAGS} -DNDEBUG -I\$(top_srcdir)"
|
||||
AC_SUBST([COMMON_CFLAGS])
|
||||
AC_SUBST([COMMON_CXXFLAGS])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
webrtc-audio-processing.pc
|
||||
Makefile
|
||||
webrtc/Makefile
|
||||
webrtc/base/Makefile
|
||||
webrtc/common_audio/Makefile
|
||||
webrtc/system_wrappers/Makefile
|
||||
webrtc/modules/Makefile
|
||||
webrtc/modules/audio_coding/Makefile
|
||||
webrtc/modules/audio_processing/Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
8
examples/meson.build
Normal file
8
examples/meson.build
Normal file
@ -0,0 +1,8 @@
|
||||
top_incdir = include_directories('..')
|
||||
|
||||
executable('run-offline',
|
||||
'run-offline.cpp',
|
||||
install: false,
|
||||
include_directories: top_incdir,
|
||||
dependencies: [audio_processing_dep, absl_dep]
|
||||
)
|
67
examples/run-offline.cpp
Normal file
67
examples/run-offline.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Asymptotic Inc. All Rights Reserved.
|
||||
* Author: Arun Raghavan <arun@asymptotic.io>
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/scoped_refptr.h"
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <webrtc/modules/audio_processing/include/audio_processing.h>
|
||||
|
||||
#define DEFAULT_BLOCK_MS 10
|
||||
#define DEFAULT_RATE 32000
|
||||
#define DEFAULT_CHANNELS 1
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 4) {
|
||||
std::cerr << "Usage: " << argv[0] << " <play_file> <rec_file> <out_file>" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::ifstream play_file(argv[1], std::ios::binary);
|
||||
std::ifstream rec_file(argv[2], std::ios::binary);
|
||||
std::ofstream aec_file(argv[3], std::ios::binary);
|
||||
|
||||
rtc::scoped_refptr<webrtc::AudioProcessing> apm = webrtc::AudioProcessingBuilder().Create();
|
||||
|
||||
webrtc::AudioProcessing::Config config;
|
||||
config.echo_canceller.enabled = true;
|
||||
config.echo_canceller.mobile_mode = false;
|
||||
config.gain_controller1.enabled = true;
|
||||
config.gain_controller1.mode = webrtc::AudioProcessing::Config::GainController1::kAdaptiveAnalog;
|
||||
|
||||
config.gain_controller2.enabled = true;
|
||||
|
||||
config.high_pass_filter.enabled = true;
|
||||
|
||||
apm->ApplyConfig(config);
|
||||
|
||||
webrtc::StreamConfig stream_config(DEFAULT_RATE, DEFAULT_CHANNELS);
|
||||
|
||||
while (!play_file.eof() && !rec_file.eof()) {
|
||||
int16_t play_frame[DEFAULT_RATE * DEFAULT_BLOCK_MS / 1000 * DEFAULT_CHANNELS];
|
||||
int16_t rec_frame[DEFAULT_RATE * DEFAULT_BLOCK_MS / 1000 * DEFAULT_CHANNELS];
|
||||
|
||||
play_file.read(reinterpret_cast<char *>(play_frame), sizeof(play_frame));
|
||||
rec_file.read(reinterpret_cast<char *>(rec_frame), sizeof(rec_frame));
|
||||
|
||||
apm->ProcessReverseStream(play_frame, stream_config, stream_config, play_frame);
|
||||
apm->ProcessStream(rec_frame, stream_config, stream_config, rec_frame);
|
||||
|
||||
aec_file.write(reinterpret_cast<char *>(rec_frame), sizeof(rec_frame));
|
||||
}
|
||||
|
||||
play_file.close();
|
||||
rec_file.close();
|
||||
aec_file.close();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
217
meson.build
Normal file
217
meson.build
Normal file
@ -0,0 +1,217 @@
|
||||
project('webrtc-audio-processing', 'c', 'cpp',
|
||||
version : '2.1',
|
||||
meson_version : '>= 0.63',
|
||||
default_options : [ 'warning_level=1',
|
||||
'buildtype=debugoptimized',
|
||||
'c_std=c11',
|
||||
'cpp_std=c++17',
|
||||
]
|
||||
)
|
||||
|
||||
version_split = meson.project_version().split('.')
|
||||
# This will be incremented each time a breaking API change occurs
|
||||
major_version = version_split[0]
|
||||
# This will be incremented when there are backwards-compatible changes
|
||||
minor_version = version_split[1]
|
||||
|
||||
# We maintain per-package versions to not have to break API for one if only the
|
||||
# other has breaking changes
|
||||
|
||||
apm_major_version = major_version
|
||||
apm_minor_version = minor_version
|
||||
apm_project_name = 'webrtc-audio-processing-' + apm_major_version
|
||||
|
||||
include_subdir = apm_project_name
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
cpp = meson.get_compiler('cpp')
|
||||
|
||||
host_system = host_machine.system()
|
||||
|
||||
# Don't rely on the cross file setting the system properly when targeting ios
|
||||
if host_system == 'darwin' and meson.is_cross_build()
|
||||
ios_test_code = '''#include <TargetConditionals.h>
|
||||
#if ! TARGET_OS_IPHONE
|
||||
#error "Not iOS/tvOS/watchOS/iPhoneSimulator"
|
||||
#endif'''
|
||||
if cc.compiles(ios_test_code, name : 'building for iOS')
|
||||
host_system = 'ios'
|
||||
endif
|
||||
endif
|
||||
|
||||
platform_cflags = []
|
||||
os_cflags = []
|
||||
os_deps = []
|
||||
have_posix = false
|
||||
have_win = false
|
||||
|
||||
# Let's use pkg-config if available. This will also fallback to the subproject
|
||||
# if pkg-config is not found, which is really the most reliable way of building
|
||||
# abseil due to strict C++ standard match requirements.
|
||||
absl_dep = [
|
||||
dependency('absl_base', default_options: ['cpp_std=c++17'], version: '>=20240722'),
|
||||
dependency('absl_flags'),
|
||||
dependency('absl_strings'),
|
||||
dependency('absl_numeric'),
|
||||
dependency('absl_synchronization'),
|
||||
dependency('absl_bad_optional_access'),
|
||||
]
|
||||
|
||||
if absl_dep[0].type_name() == 'internal'
|
||||
absl_subproj = subproject('abseil-cpp')
|
||||
headers = [
|
||||
absl_subproj.get_variable('absl_base_headers'),
|
||||
absl_subproj.get_variable('absl_flags_headers'),
|
||||
absl_subproj.get_variable('absl_strings_headers'),
|
||||
absl_subproj.get_variable('absl_numeric_headers'),
|
||||
absl_subproj.get_variable('absl_synchronization_headers'),
|
||||
absl_subproj.get_variable('absl_types_headers'),
|
||||
]
|
||||
install_headers(headers, preserve_path: true)
|
||||
pc_requires = []
|
||||
else
|
||||
pc_requires = [absl_dep[0]]
|
||||
endif
|
||||
|
||||
if ['darwin', 'ios'].contains(host_system)
|
||||
os_cflags = ['-DWEBRTC_MAC']
|
||||
if host_system == 'ios'
|
||||
os_cflags += ['-DWEBRTC_IOS']
|
||||
endif
|
||||
have_posix = true
|
||||
elif host_system == 'android'
|
||||
os_cflags += ['-DWEBRTC_ANDROID', '-DWEBRTC_LINUX']
|
||||
os_deps += [cc.find_library('log')]
|
||||
os_deps += [dependency('gnustl', required : get_option('gnustl'))]
|
||||
have_posix = true
|
||||
elif host_system == 'linux'
|
||||
os_cflags += ['-DWEBRTC_LINUX']
|
||||
os_deps += [cc.find_library('rt', required : false)]
|
||||
os_deps += [dependency('threads')]
|
||||
have_posix = true
|
||||
elif (host_system == 'dragonfly' or host_system == 'freebsd' or
|
||||
host_system == 'netbsd' or host_system == 'openbsd')
|
||||
os_cflags += ['-DWEBRTC_BSD']
|
||||
os_deps += [dependency('threads')]
|
||||
have_posix = true
|
||||
elif host_system == 'windows'
|
||||
platform_cflags += ['-DWEBRTC_WIN', '-D_WIN32']
|
||||
# this one is for MinGW to get format specifiers from inttypes.h in C++
|
||||
platform_cflags += ['-D__STDC_FORMAT_MACROS=1']
|
||||
# Avoid min/max from windows.h which breaks std::min/max
|
||||
platform_cflags += ['-DNOMINMAX']
|
||||
# Ensure M_PI etc are defined
|
||||
platform_cflags += ['-D_USE_MATH_DEFINES']
|
||||
os_deps += [cc.find_library('winmm')]
|
||||
have_win = true
|
||||
endif
|
||||
|
||||
if have_posix
|
||||
platform_cflags += ['-DWEBRTC_POSIX']
|
||||
endif
|
||||
|
||||
arch_cflags = []
|
||||
have_arm = false
|
||||
have_armv7 = false
|
||||
have_arm64 = false
|
||||
have_neon = false
|
||||
have_mips = false
|
||||
have_mips64 = false
|
||||
have_x86 = false
|
||||
have_inline_sse = false
|
||||
have_avx2 = false
|
||||
if host_machine.cpu_family() == 'arm'
|
||||
if cc.compiles('''#ifndef __ARM_ARCH_ISA_ARM
|
||||
#error no arm arch
|
||||
#endif''')
|
||||
have_arm = true
|
||||
arch_cflags += ['-DWEBRTC_ARCH_ARM']
|
||||
endif
|
||||
if cc.compiles('''#ifndef __ARM_ARCH_7A__
|
||||
#error no armv7 arch
|
||||
#endif''')
|
||||
have_armv7 = true
|
||||
arch_cflags += ['-DWEBRTC_ARCH_ARM_V7']
|
||||
endif
|
||||
if cc.compiles('#include <arm_neon.h>', args : '-mfpu=neon')
|
||||
have_neon = true
|
||||
endif
|
||||
endif
|
||||
if host_machine.cpu_family() == 'aarch64'
|
||||
have_arm64 = true
|
||||
have_neon = true
|
||||
arch_cflags += ['-DWEBRTC_ARCH_ARM64']
|
||||
endif
|
||||
if ['mips', 'mips64'].contains(host_machine.cpu_family())
|
||||
have_mips = true
|
||||
endif
|
||||
if host_machine.cpu_family() == 'mips64'
|
||||
have_mips64 = true
|
||||
endif
|
||||
if ['x86', 'x86_64'].contains(host_machine.cpu_family())
|
||||
have_x86 = true
|
||||
# AVX2 support is unconditionally available, since all the code (compiled
|
||||
# with -mavx2) is in separate files from runtime detection (which should not
|
||||
# be compiled with SIMD flags for cases where the CPU does not support it).
|
||||
# Unfortunately, a bunch of SSE code is inline with the runtime detection,
|
||||
# and we can't support that on systems that don't support SSE.
|
||||
have_avx2 = true
|
||||
arch_cflags += ['-DWEBRTC_ENABLE_AVX2']
|
||||
if get_option('inline-sse')
|
||||
have_inline_sse = true
|
||||
else
|
||||
have_inline_sse = false
|
||||
arch_cflags += ['-DWAP_DISABLE_INLINE_SSE']
|
||||
endif
|
||||
endif
|
||||
|
||||
neon_opt = get_option('neon').require(have_neon)
|
||||
|
||||
if neon_opt.enabled()
|
||||
arch_cflags += ['-DWEBRTC_HAS_NEON']
|
||||
if not have_arm64
|
||||
arch_cflags += ['-mfpu=neon']
|
||||
endif
|
||||
endif
|
||||
|
||||
common_cflags = [
|
||||
'-DWEBRTC_LIBRARY_IMPL',
|
||||
'-DWEBRTC_ENABLE_SYMBOL_EXPORT',
|
||||
# avoid windows.h/winsock2.h conflicts
|
||||
'-D_WINSOCKAPI_',
|
||||
'-DNDEBUG'
|
||||
] + platform_cflags + os_cflags + arch_cflags
|
||||
common_cxxflags = common_cflags
|
||||
common_deps = os_deps + [absl_dep]
|
||||
webrtc_inc = include_directories('.')
|
||||
|
||||
# FIXME: use the unstable-simd module instead
|
||||
if cc.get_define('_MSC_VER') != ''
|
||||
avx_flags = ['/arch:AVX2']
|
||||
else
|
||||
avx_flags = ['-mavx2', '-mfma']
|
||||
endif
|
||||
|
||||
subdir('webrtc')
|
||||
|
||||
pkgconfig = import('pkgconfig')
|
||||
|
||||
pkgconfig.generate(
|
||||
libwebrtc_audio_processing,
|
||||
description: 'WebRTC Audio Processing library',
|
||||
subdirs: include_subdir,
|
||||
requires: pc_requires,
|
||||
extra_cflags: [
|
||||
'-DWEBRTC_LIBRARY_IMPL',
|
||||
] + platform_cflags,
|
||||
)
|
||||
|
||||
audio_processing_dep = declare_dependency(
|
||||
link_with: libwebrtc_audio_processing,
|
||||
dependencies: [absl_dep],
|
||||
include_directories: [webrtc_inc]
|
||||
)
|
||||
|
||||
meson.override_dependency(apm_project_name, audio_processing_dep)
|
||||
|
||||
subdir('examples')
|
9
meson_options.txt
Normal file
9
meson_options.txt
Normal file
@ -0,0 +1,9 @@
|
||||
option('gnustl', type: 'feature',
|
||||
value: 'auto',
|
||||
description: 'Use gnustl for a c++ library implementation (only used on Android)')
|
||||
option('neon', type: 'feature',
|
||||
value: 'auto',
|
||||
description: 'Enable NEON optimisations')
|
||||
option('inline-sse', type: 'boolean',
|
||||
value: true,
|
||||
description: 'Enable inline SSE/SSE2 optimisations (i.e. assume CPU supports SSE/SSE2)')
|
@ -0,0 +1,68 @@
|
||||
From 297fd4f2efc53b6d49433eaad91a8e09a0f9cbec Mon Sep 17 00:00:00 2001
|
||||
From: Alper Nebi Yasak <alpernebiyasak@gmail.com>
|
||||
Date: Fri, 25 Oct 2024 00:40:59 +0300
|
||||
Subject: [PATCH] AECM: MIPS: Use uintptr_t for pointer arithmetic
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Trying to compile the MIPS-specific AECM audio processing file for
|
||||
mips64el on Debian results in the following errors:
|
||||
|
||||
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc: In function ‘int webrtc::WebRtcAecm_ProcessBlock(AecmCore*, const int16_t*, const int16_t*, const int16_t*, int16_t*)’:
|
||||
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:955:30: error: cast from ‘int16_t*’ {aka ‘short int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
|
||||
955 | int16_t* fft = (int16_t*)(((uint32_t)fft_buf + 31) & ~31);
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:955:18: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
|
||||
955 | int16_t* fft = (int16_t*)(((uint32_t)fft_buf + 31) & ~31);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:956:36: error: cast from ‘int32_t*’ {aka ‘int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
|
||||
956 | int32_t* echoEst32 = (int32_t*)(((uint32_t)echoEst32_buf + 31) & ~31);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~
|
||||
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:956:24: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
|
||||
956 | int32_t* echoEst32 = (int32_t*)(((uint32_t)echoEst32_buf + 31) & ~31);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:957:40: error: cast from ‘int32_t*’ {aka ‘int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
|
||||
957 | ComplexInt16* dfw = (ComplexInt16*)(((uint32_t)dfw_buf + 31) & ~31);
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:957:23: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
|
||||
957 | ComplexInt16* dfw = (ComplexInt16*)(((uint32_t)dfw_buf + 31) & ~31);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:958:40: error: cast from ‘int32_t*’ {aka ‘int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
|
||||
958 | ComplexInt16* efw = (ComplexInt16*)(((uint32_t)efw_buf + 31) & ~31);
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:958:23: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
|
||||
958 | ComplexInt16* efw = (ComplexInt16*)(((uint32_t)efw_buf + 31) & ~31);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Presumably, this file was written for 32-bit MIPS so the author used
|
||||
uint32_t to do pointer arithmetic over these arrays. Fix the errors by
|
||||
using uintptr_t to work with pointers.
|
||||
|
||||
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
|
||||
---
|
||||
webrtc/modules/audio_processing/aecm/aecm_core_mips.cc | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/webrtc/modules/audio_processing/aecm/aecm_core_mips.cc b/webrtc/modules/audio_processing/aecm/aecm_core_mips.cc
|
||||
index 16b03cf..07c785e 100644
|
||||
--- a/webrtc/modules/audio_processing/aecm/aecm_core_mips.cc
|
||||
+++ b/webrtc/modules/audio_processing/aecm/aecm_core_mips.cc
|
||||
@@ -952,10 +952,10 @@ int WebRtcAecm_ProcessBlock(AecmCore* aecm,
|
||||
int32_t dfw_buf[PART_LEN2 + 8];
|
||||
int32_t efw_buf[PART_LEN2 + 8];
|
||||
|
||||
- int16_t* fft = (int16_t*)(((uint32_t)fft_buf + 31) & ~31);
|
||||
- int32_t* echoEst32 = (int32_t*)(((uint32_t)echoEst32_buf + 31) & ~31);
|
||||
- ComplexInt16* dfw = (ComplexInt16*)(((uint32_t)dfw_buf + 31) & ~31);
|
||||
- ComplexInt16* efw = (ComplexInt16*)(((uint32_t)efw_buf + 31) & ~31);
|
||||
+ int16_t* fft = (int16_t*)(((uintptr_t)fft_buf + 31) & ~31);
|
||||
+ int32_t* echoEst32 = (int32_t*)(((uintptr_t)echoEst32_buf + 31) & ~31);
|
||||
+ ComplexInt16* dfw = (ComplexInt16*)(((uintptr_t)dfw_buf + 31) & ~31);
|
||||
+ ComplexInt16* efw = (ComplexInt16*)(((uintptr_t)efw_buf + 31) & ~31);
|
||||
|
||||
int16_t hnl[PART_LEN1];
|
||||
int16_t numPosCoef = 0;
|
||||
--
|
||||
2.47.1
|
||||
|
110
patches/0001-Add-support-for-BSD-systems.patch
Normal file
110
patches/0001-Add-support-for-BSD-systems.patch
Normal file
@ -0,0 +1,110 @@
|
||||
From 2a318149f8d5094c82306b8091a7a8b5194bf9c1 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Beich <jbeich@FreeBSD.org>
|
||||
Date: Tue, 7 Jan 2020 18:08:24 +0000
|
||||
Subject: [PATCH] Add support for BSD systems
|
||||
|
||||
webrtc/rtc_base/checks.cc:158:28: error: use of undeclared identifier 'LAST_SYSTEM_ERROR'
|
||||
158 | file, line, LAST_SYSTEM_ERROR, message);
|
||||
| ^
|
||||
webrtc/rtc_base/checks.cc:220:16: error: use of undeclared identifier 'LAST_SYSTEM_ERROR'
|
||||
220 | LAST_SYSTEM_ERROR);
|
||||
| ^
|
||||
In file included from webrtc/rtc_base/platform_thread_types.cc:11:
|
||||
webrtc/rtc_base/platform_thread_types.h:47:1: error: unknown type name 'PlatformThreadId'
|
||||
47 | PlatformThreadId CurrentThreadId();
|
||||
| ^
|
||||
webrtc/rtc_base/platform_thread_types.h:52:1: error: unknown type name 'PlatformThreadRef'
|
||||
52 | PlatformThreadRef CurrentThreadRef();
|
||||
| ^
|
||||
webrtc/rtc_base/platform_thread_types.h:55:29: error: unknown type name 'PlatformThreadRef'
|
||||
55 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b);
|
||||
| ^
|
||||
webrtc/rtc_base/platform_thread_types.h:55:57: error: unknown type name 'PlatformThreadRef'
|
||||
55 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b);
|
||||
| ^
|
||||
webrtc/rtc_base/platform_thread_types.cc:37:1: error: unknown type name 'PlatformThreadId'
|
||||
37 | PlatformThreadId CurrentThreadId() {
|
||||
| ^
|
||||
webrtc/rtc_base/platform_thread_types.cc:58:1: error: unknown type name 'PlatformThreadRef'
|
||||
58 | PlatformThreadRef CurrentThreadRef() {
|
||||
| ^
|
||||
webrtc/rtc_base/platform_thread_types.cc:68:29: error: unknown type name 'PlatformThreadRef'
|
||||
68 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) {
|
||||
| ^
|
||||
webrtc/rtc_base/platform_thread_types.cc:68:57: error: unknown type name 'PlatformThreadRef'
|
||||
68 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) {
|
||||
| ^
|
||||
In file included from webrtc/rtc_base/event_tracer.cc:30:
|
||||
In file included from webrtc/api/sequence_checker.h:15:
|
||||
In file included from webrtc/rtc_base/synchronization/sequence_checker_internal.h:18:
|
||||
webrtc/rtc_base/synchronization/mutex.h:28:2: error: Unsupported platform.
|
||||
28 | #error Unsupported platform.
|
||||
| ^
|
||||
webrtc/rtc_base/synchronization/mutex.h:52:3: error: unknown type name 'MutexImpl'
|
||||
52 | MutexImpl impl_;
|
||||
| ^
|
||||
---
|
||||
meson.build | 5 +++++
|
||||
webrtc/rtc_base/platform_thread_types.cc | 16 ++++++++++++++++
|
||||
2 files changed, 21 insertions(+)
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 8d85d56..05a434a 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -87,6 +87,11 @@ elif host_system == 'linux'
|
||||
os_deps += [cc.find_library('rt', required : false)]
|
||||
os_deps += [dependency('threads')]
|
||||
have_posix = true
|
||||
+elif (host_system == 'dragonfly' or host_system == 'freebsd' or
|
||||
+ host_system == 'netbsd' or host_system == 'openbsd')
|
||||
+ os_cflags += ['-DWEBRTC_BSD', '-DWEBRTC_THREAD_RR']
|
||||
+ os_deps += [dependency('threads')]
|
||||
+ have_posix = true
|
||||
elif host_system == 'windows'
|
||||
platform_cflags += ['-DWEBRTC_WIN', '-D_WIN32']
|
||||
# this one is for MinGW to get format specifiers from inttypes.h in C++
|
||||
diff --git a/webrtc/rtc_base/platform_thread_types.cc b/webrtc/rtc_base/platform_thread_types.cc
|
||||
index d64ea68..e98e8ec 100644
|
||||
--- a/webrtc/rtc_base/platform_thread_types.cc
|
||||
+++ b/webrtc/rtc_base/platform_thread_types.cc
|
||||
@@ -15,6 +15,12 @@
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
+#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) // WEBRTC_BSD
|
||||
+#include <pthread_np.h>
|
||||
+#elif defined(__NetBSD__) // WEBRTC_BSD
|
||||
+#include <lwp.h>
|
||||
+#endif
|
||||
+
|
||||
#if defined(WEBRTC_WIN)
|
||||
#include "rtc_base/arraysize.h"
|
||||
|
||||
@@ -46,6 +52,12 @@ PlatformThreadId CurrentThreadId() {
|
||||
return zx_thread_self();
|
||||
#elif defined(WEBRTC_LINUX)
|
||||
return syscall(__NR_gettid);
|
||||
+#elif defined(__DragonFly__) || defined(__FreeBSD__) // WEBRTC_BSD
|
||||
+ return pthread_getthreadid_np();
|
||||
+#elif defined(__NetBSD__) // WEBRTC_BSD
|
||||
+ return _lwp_self();
|
||||
+#elif defined(__OpenBSD__) // WEBRTC_BSD
|
||||
+ return getthrid();
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
return static_cast<PlatformThreadId>(pthread_self());
|
||||
#else
|
||||
@@ -116,6 +128,10 @@ void SetCurrentThreadName(const char* name) {
|
||||
prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name)); // NOLINT
|
||||
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
|
||||
pthread_setname_np(name);
|
||||
+#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) // WEBRTC_BSD
|
||||
+ pthread_set_name_np(pthread_self(), name);
|
||||
+#elif defined(__NetBSD__) // WEBRTC_BSD
|
||||
+ pthread_setname_np(pthread_self(), "%s", (void*)name);
|
||||
#elif defined(WEBRTC_FUCHSIA)
|
||||
zx_status_t status = zx_object_set_property(zx_thread_self(), ZX_PROP_NAME,
|
||||
name, strlen(name));
|
||||
--
|
||||
2.47.1
|
||||
|
336
patches/0001-Allow-disabling-inline-SSE.patch
Normal file
336
patches/0001-Allow-disabling-inline-SSE.patch
Normal file
@ -0,0 +1,336 @@
|
||||
From fed81a77c9a9bc366556f732324cdc5f9e7b09e9 Mon Sep 17 00:00:00 2001
|
||||
From: Arun Raghavan <arun@asymptotic.io>
|
||||
Date: Thu, 26 Dec 2024 14:24:40 -0500
|
||||
Subject: [PATCH] Allow disabling inline SSE
|
||||
|
||||
Should make building on i686 without SSE feasible.
|
||||
|
||||
Fixes: https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing/-/issues/5
|
||||
---
|
||||
meson.build | 14 ++++++++++++--
|
||||
meson_options.txt | 5 ++++-
|
||||
.../audio_processing/aec3/adaptive_fir_filter.cc | 14 ++++++++++----
|
||||
.../aec3/adaptive_fir_filter_erl.cc | 6 ++++--
|
||||
webrtc/modules/audio_processing/aec3/fft_data.h | 4 +++-
|
||||
.../audio_processing/aec3/matched_filter.cc | 6 ++++--
|
||||
webrtc/modules/audio_processing/aec3/vector_math.h | 8 +++++---
|
||||
.../audio_processing/agc2/rnn_vad/vector_math.h | 4 +++-
|
||||
webrtc/third_party/pffft/meson.build | 2 +-
|
||||
9 files changed, 46 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 811d795..ebf053a 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -110,6 +110,7 @@ have_neon = false
|
||||
have_mips = false
|
||||
have_mips64 = false
|
||||
have_x86 = false
|
||||
+have_inline_sse = false
|
||||
have_avx2 = false
|
||||
if host_machine.cpu_family() == 'arm'
|
||||
if cc.compiles('''#ifndef __ARM_ARCH_ISA_ARM
|
||||
@@ -140,10 +141,19 @@ if host_machine.cpu_family() == 'mips64'
|
||||
endif
|
||||
if ['x86', 'x86_64'].contains(host_machine.cpu_family())
|
||||
have_x86 = true
|
||||
- # This is unconditionally enabled for now, actual usage is determined by
|
||||
- # runtime CPU detection, so we're just assuming the compiler supports avx2
|
||||
+ # AVX2 support is unconditionally available, since all the code (compiled
|
||||
+ # with -mavx2) is in separate files from runtime detection (which should not
|
||||
+ # be compiled with SIMD flags for cases where the CPU does not support it).
|
||||
+ # Unfortunately, a bunch of SSE code is inline with the runtime detection,
|
||||
+ # and we can't support that on systems that don't support SSE.
|
||||
have_avx2 = true
|
||||
arch_cflags += ['-DWEBRTC_ENABLE_AVX2']
|
||||
+ if get_option('inline-sse')
|
||||
+ have_inline_sse = true
|
||||
+ else
|
||||
+ have_inline_sse = false
|
||||
+ arch_cflags += ['-DWAP_DISABLE_INLINE_SSE']
|
||||
+ endif
|
||||
endif
|
||||
|
||||
neon_opt = get_option('neon')
|
||||
diff --git a/meson_options.txt b/meson_options.txt
|
||||
index c939fb9..d08f356 100644
|
||||
--- a/meson_options.txt
|
||||
+++ b/meson_options.txt
|
||||
@@ -3,4 +3,7 @@ option('gnustl', type: 'feature',
|
||||
description: 'Use gnustl for a c++ library implementation (only used on Android)')
|
||||
option('neon', type: 'combo',
|
||||
choices: ['no', 'yes', 'auto', 'runtime'],
|
||||
- description: '')
|
||||
+ description: 'Enable NEON optimisations')
|
||||
+option('inline-sse', type: 'boolean',
|
||||
+ value: true,
|
||||
+ description: 'Enable inline SSE/SSE2 optimisations (i.e. assume CPU supports SSE/SSE2)')
|
||||
diff --git a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc
|
||||
index 917aa95..ded0511 100644
|
||||
--- a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc
|
||||
+++ b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc
|
||||
@@ -16,7 +16,7 @@
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
@@ -88,7 +88,7 @@ void ComputeFrequencyResponse_Neon(
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
// Computes and stores the frequency response of the filter.
|
||||
void ComputeFrequencyResponse_Sse2(
|
||||
size_t num_partitions,
|
||||
@@ -212,7 +212,7 @@ void AdaptPartitions_Neon(const RenderBuffer& render_buffer,
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
// Adapts the filter partitions. (SSE2 variant)
|
||||
void AdaptPartitions_Sse2(const RenderBuffer& render_buffer,
|
||||
const FftData& G,
|
||||
@@ -377,7 +377,7 @@ void ApplyFilter_Neon(const RenderBuffer& render_buffer,
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
// Produces the filter output (SSE2 variant).
|
||||
void ApplyFilter_Sse2(const RenderBuffer& render_buffer,
|
||||
size_t num_partitions,
|
||||
@@ -557,9 +557,11 @@ void AdaptiveFirFilter::Filter(const RenderBuffer& render_buffer,
|
||||
RTC_DCHECK(S);
|
||||
switch (optimization_) {
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if !defined(WAP_DISABLE_INLINE_SSE)
|
||||
case Aec3Optimization::kSse2:
|
||||
aec3::ApplyFilter_Sse2(render_buffer, current_size_partitions_, H_, S);
|
||||
break;
|
||||
+#endif
|
||||
case Aec3Optimization::kAvx2:
|
||||
aec3::ApplyFilter_Avx2(render_buffer, current_size_partitions_, H_, S);
|
||||
break;
|
||||
@@ -601,9 +603,11 @@ void AdaptiveFirFilter::ComputeFrequencyResponse(
|
||||
|
||||
switch (optimization_) {
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if !defined(WAP_DISABLE_INLINE_SSE)
|
||||
case Aec3Optimization::kSse2:
|
||||
aec3::ComputeFrequencyResponse_Sse2(current_size_partitions_, H_, H2);
|
||||
break;
|
||||
+#endif
|
||||
case Aec3Optimization::kAvx2:
|
||||
aec3::ComputeFrequencyResponse_Avx2(current_size_partitions_, H_, H2);
|
||||
break;
|
||||
@@ -626,10 +630,12 @@ void AdaptiveFirFilter::AdaptAndUpdateSize(const RenderBuffer& render_buffer,
|
||||
// Adapt the filter.
|
||||
switch (optimization_) {
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if !defined(WAP_DISABLE_INLINE_SSE)
|
||||
case Aec3Optimization::kSse2:
|
||||
aec3::AdaptPartitions_Sse2(render_buffer, G, current_size_partitions_,
|
||||
&H_);
|
||||
break;
|
||||
+#endif
|
||||
case Aec3Optimization::kAvx2:
|
||||
aec3::AdaptPartitions_Avx2(render_buffer, G, current_size_partitions_,
|
||||
&H_);
|
||||
diff --git a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc
|
||||
index 45b8813..920d51c 100644
|
||||
--- a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc
|
||||
+++ b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc
|
||||
@@ -16,7 +16,7 @@
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
@@ -54,7 +54,7 @@ void ErlComputer_NEON(
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
// Computes and stores the echo return loss estimate of the filter, which is the
|
||||
// sum of the partition frequency responses.
|
||||
void ErlComputer_SSE2(
|
||||
@@ -82,9 +82,11 @@ void ComputeErl(const Aec3Optimization& optimization,
|
||||
// Update the frequency response and echo return loss for the filter.
|
||||
switch (optimization) {
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if !defined(WAP_DISABLE_INLINE_SSE)
|
||||
case Aec3Optimization::kSse2:
|
||||
aec3::ErlComputer_SSE2(H2, erl);
|
||||
break;
|
||||
+#endif
|
||||
case Aec3Optimization::kAvx2:
|
||||
aec3::ErlComputer_AVX2(H2, erl);
|
||||
break;
|
||||
diff --git a/webrtc/modules/audio_processing/aec3/fft_data.h b/webrtc/modules/audio_processing/aec3/fft_data.h
|
||||
index 9c25e78..892407d 100644
|
||||
--- a/webrtc/modules/audio_processing/aec3/fft_data.h
|
||||
+++ b/webrtc/modules/audio_processing/aec3/fft_data.h
|
||||
@@ -14,7 +14,7 @@
|
||||
// Defines WEBRTC_ARCH_X86_FAMILY, used below.
|
||||
#include "rtc_base/system/arch.h"
|
||||
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
@@ -49,6 +49,7 @@ struct FftData {
|
||||
RTC_DCHECK_EQ(kFftLengthBy2Plus1, power_spectrum.size());
|
||||
switch (optimization) {
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if !defined(WAP_DISABLE_INLINE_SSE)
|
||||
case Aec3Optimization::kSse2: {
|
||||
constexpr int kNumFourBinBands = kFftLengthBy2 / 4;
|
||||
constexpr int kLimit = kNumFourBinBands * 4;
|
||||
@@ -63,6 +64,7 @@ struct FftData {
|
||||
power_spectrum[kFftLengthBy2] = re[kFftLengthBy2] * re[kFftLengthBy2] +
|
||||
im[kFftLengthBy2] * im[kFftLengthBy2];
|
||||
} break;
|
||||
+#endif
|
||||
case Aec3Optimization::kAvx2:
|
||||
SpectrumAVX2(power_spectrum);
|
||||
break;
|
||||
diff --git a/webrtc/modules/audio_processing/aec3/matched_filter.cc b/webrtc/modules/audio_processing/aec3/matched_filter.cc
|
||||
index 59a3b46..86f365a 100644
|
||||
--- a/webrtc/modules/audio_processing/aec3/matched_filter.cc
|
||||
+++ b/webrtc/modules/audio_processing/aec3/matched_filter.cc
|
||||
@@ -15,7 +15,7 @@
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
@@ -286,7 +286,7 @@ void MatchedFilterCore_NEON(size_t x_start_index,
|
||||
|
||||
#endif
|
||||
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
|
||||
void MatchedFilterCore_AccumulatedError_SSE2(
|
||||
size_t x_start_index,
|
||||
@@ -695,12 +695,14 @@ void MatchedFilter::Update(const DownsampledRenderBuffer& render_buffer,
|
||||
|
||||
switch (optimization_) {
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if !defined(WAP_DISABLE_INLINE_SSE)
|
||||
case Aec3Optimization::kSse2:
|
||||
aec3::MatchedFilterCore_SSE2(
|
||||
x_start_index, x2_sum_threshold, smoothing, render_buffer.buffer, y,
|
||||
filters_[n], &filters_updated, &error_sum, compute_pre_echo,
|
||||
instantaneous_accumulated_error_, scratch_memory_);
|
||||
break;
|
||||
+#endif
|
||||
case Aec3Optimization::kAvx2:
|
||||
aec3::MatchedFilterCore_AVX2(
|
||||
x_start_index, x2_sum_threshold, smoothing, render_buffer.buffer, y,
|
||||
diff --git a/webrtc/modules/audio_processing/aec3/vector_math.h b/webrtc/modules/audio_processing/aec3/vector_math.h
|
||||
index e4d1381..1506a44 100644
|
||||
--- a/webrtc/modules/audio_processing/aec3/vector_math.h
|
||||
+++ b/webrtc/modules/audio_processing/aec3/vector_math.h
|
||||
@@ -17,7 +17,7 @@
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
@@ -43,7 +43,7 @@ class VectorMath {
|
||||
void SqrtAVX2(rtc::ArrayView<float> x);
|
||||
void Sqrt(rtc::ArrayView<float> x) {
|
||||
switch (optimization_) {
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
case Aec3Optimization::kSse2: {
|
||||
const int x_size = static_cast<int>(x.size());
|
||||
const int vector_limit = x_size >> 2;
|
||||
@@ -123,7 +123,7 @@ class VectorMath {
|
||||
RTC_DCHECK_EQ(z.size(), x.size());
|
||||
RTC_DCHECK_EQ(z.size(), y.size());
|
||||
switch (optimization_) {
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
case Aec3Optimization::kSse2: {
|
||||
const int x_size = static_cast<int>(x.size());
|
||||
const int vector_limit = x_size >> 2;
|
||||
@@ -174,6 +174,7 @@ class VectorMath {
|
||||
RTC_DCHECK_EQ(z.size(), x.size());
|
||||
switch (optimization_) {
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if !defined(WAP_DISABLE_INLINE_SSE)
|
||||
case Aec3Optimization::kSse2: {
|
||||
const int x_size = static_cast<int>(x.size());
|
||||
const int vector_limit = x_size >> 2;
|
||||
@@ -190,6 +191,7 @@ class VectorMath {
|
||||
z[j] += x[j];
|
||||
}
|
||||
} break;
|
||||
+#endif
|
||||
case Aec3Optimization::kAvx2:
|
||||
AccumulateAVX2(x, z);
|
||||
break;
|
||||
diff --git a/webrtc/modules/audio_processing/agc2/rnn_vad/vector_math.h b/webrtc/modules/audio_processing/agc2/rnn_vad/vector_math.h
|
||||
index 47f6811..f965086 100644
|
||||
--- a/webrtc/modules/audio_processing/agc2/rnn_vad/vector_math.h
|
||||
+++ b/webrtc/modules/audio_processing/agc2/rnn_vad/vector_math.h
|
||||
@@ -17,7 +17,7 @@
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
-#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,7 @@ class VectorMath {
|
||||
if (cpu_features_.avx2) {
|
||||
return DotProductAvx2(x, y);
|
||||
} else if (cpu_features_.sse2) {
|
||||
+#if !defined(WAP_DISABLE_INLINE_SSE)
|
||||
__m128 accumulator = _mm_setzero_ps();
|
||||
constexpr int kBlockSizeLog2 = 2;
|
||||
constexpr int kBlockSize = 1 << kBlockSizeLog2;
|
||||
@@ -72,6 +73,7 @@ class VectorMath {
|
||||
dot_product += x[i] * y[i];
|
||||
}
|
||||
return dot_product;
|
||||
+#endif
|
||||
}
|
||||
#elif defined(WEBRTC_HAS_NEON) && defined(WEBRTC_ARCH_ARM64)
|
||||
if (cpu_features_.neon) {
|
||||
diff --git a/webrtc/third_party/pffft/meson.build b/webrtc/third_party/pffft/meson.build
|
||||
index c1eb5c6..cf4c9c7 100644
|
||||
--- a/webrtc/third_party/pffft/meson.build
|
||||
+++ b/webrtc/third_party/pffft/meson.build
|
||||
@@ -4,7 +4,7 @@ pffft_sources = [
|
||||
|
||||
pffft_cflags = [ '-D_GNU_SOURCE' ]
|
||||
|
||||
-if (have_arm and not have_neon) or (have_mips and host_machine.endian() == 'little') or have_mips64
|
||||
+if not have_inline_sse or (have_arm and not have_neon) or (have_mips and host_machine.endian() == 'little') or have_mips64
|
||||
pffft_cflags += [ '-DPFFFT_SIMD_DISABLE' ]
|
||||
endif
|
||||
|
||||
--
|
||||
2.47.1
|
||||
|
68
patches/0001-Fix-up-XMM-intrinsics-usage-on-MSVC.patch
Normal file
68
patches/0001-Fix-up-XMM-intrinsics-usage-on-MSVC.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From ad563b095cea13730ca95e77d50e352ea9e344a9 Mon Sep 17 00:00:00 2001
|
||||
From: Arun Raghavan <arun@asymptotic.io>
|
||||
Date: Fri, 15 Dec 2023 16:06:05 -0500
|
||||
Subject: [PATCH] Fix up XMM intrinsics usage on MSVC
|
||||
|
||||
Repplying 0a0050746bc20ef970b9f260d485e4367c7ba854 after M131 bump.
|
||||
---
|
||||
.../aec3/matched_filter_avx2.cc | 30 ++++++++++++-------
|
||||
1 file changed, 20 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/webrtc/modules/audio_processing/aec3/matched_filter_avx2.cc b/webrtc/modules/audio_processing/aec3/matched_filter_avx2.cc
|
||||
index 8c2ffcb..65a1b76 100644
|
||||
--- a/webrtc/modules/audio_processing/aec3/matched_filter_avx2.cc
|
||||
+++ b/webrtc/modules/audio_processing/aec3/matched_filter_avx2.cc
|
||||
@@ -13,6 +13,16 @@
|
||||
#include "modules/audio_processing/aec3/matched_filter.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
+#ifdef _MSC_VER
|
||||
+// Visual Studio
|
||||
+#define LOOKUP_M128(v, i) v.m128_f32[i]
|
||||
+#define LOOKUP_M256(v, i) v.m256_f32[i]
|
||||
+#else
|
||||
+// GCC/Clang
|
||||
+#define LOOKUP_M128(v, i) v[i]
|
||||
+#define LOOKUP_M256(v, i) v[i]
|
||||
+#endif
|
||||
+
|
||||
namespace webrtc {
|
||||
namespace aec3 {
|
||||
|
||||
@@ -81,14 +91,14 @@ void MatchedFilterCore_AccumulatedError_AVX2(
|
||||
s_inst_256_8 = _mm256_mul_ps(h_k_8, x_k_8);
|
||||
s_inst_hadd_256 = _mm256_hadd_ps(s_inst_256, s_inst_256_8);
|
||||
s_inst_hadd_256 = _mm256_hadd_ps(s_inst_hadd_256, s_inst_hadd_256);
|
||||
- s_acum += s_inst_hadd_256[0];
|
||||
- e_128[0] = s_acum - y[i];
|
||||
- s_acum += s_inst_hadd_256[4];
|
||||
- e_128[1] = s_acum - y[i];
|
||||
- s_acum += s_inst_hadd_256[1];
|
||||
- e_128[2] = s_acum - y[i];
|
||||
- s_acum += s_inst_hadd_256[5];
|
||||
- e_128[3] = s_acum - y[i];
|
||||
+ s_acum += LOOKUP_M256(s_inst_hadd_256, 0);
|
||||
+ LOOKUP_M128(e_128, 0) = s_acum - y[i];
|
||||
+ s_acum += LOOKUP_M256(s_inst_hadd_256,4);
|
||||
+ LOOKUP_M128(e_128, 1) = s_acum - y[i];
|
||||
+ s_acum += LOOKUP_M256(s_inst_hadd_256,1);
|
||||
+ LOOKUP_M128(e_128, 2) = s_acum - y[i];
|
||||
+ s_acum += LOOKUP_M256(s_inst_hadd_256,5);
|
||||
+ LOOKUP_M128(e_128, 3) = s_acum - y[i];
|
||||
|
||||
__m128 accumulated_error = _mm_load_ps(a_p);
|
||||
accumulated_error = _mm_fmadd_ps(e_128, e_128, accumulated_error);
|
||||
@@ -209,8 +219,8 @@ void MatchedFilterCore_AVX2(size_t x_start_index,
|
||||
x2_sum_256 = _mm256_add_ps(x2_sum_256, x2_sum_256_8);
|
||||
s_256 = _mm256_add_ps(s_256, s_256_8);
|
||||
__m128 sum = hsum_ab(x2_sum_256, s_256);
|
||||
- x2_sum += sum[0];
|
||||
- s += sum[1];
|
||||
+ x2_sum += LOOKUP_M128(sum, 0);
|
||||
+ s += LOOKUP_M128(sum, 1);
|
||||
|
||||
// Compute the matched filter error.
|
||||
float e = y[i] - s;
|
||||
--
|
||||
2.47.1
|
||||
|
51
patches/0001-Some-fixes-for-MinGW.patch
Normal file
51
patches/0001-Some-fixes-for-MinGW.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From a9f97c9fdd490e35bd43d6463424eee5b44c4a7d Mon Sep 17 00:00:00 2001
|
||||
From: Arun Raghavan <arun@asymptotic.io>
|
||||
Date: Fri, 18 Jun 2021 18:40:32 -0400
|
||||
Subject: [PATCH] Some fixes for MinGW
|
||||
|
||||
* Rename Windows.h uses to windows.h
|
||||
* Comment out structured exception handling usage
|
||||
|
||||
Makes MinGW happier. Mostly the same as previous work by
|
||||
Nicolas Dufresne <nicolas.dufresne@collabora.com>, with the exception
|
||||
that we now don't try to invoke RaiseException which would fail in MinGW
|
||||
as it raises a Windows structured exception.
|
||||
---
|
||||
webrtc/rtc_base/platform_thread_types.cc | 2 ++
|
||||
webrtc/rtc_base/system/file_wrapper.cc | 2 +-
|
||||
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/webrtc/rtc_base/platform_thread_types.cc b/webrtc/rtc_base/platform_thread_types.cc
|
||||
index e98e8ec..1a24881 100644
|
||||
--- a/webrtc/rtc_base/platform_thread_types.cc
|
||||
+++ b/webrtc/rtc_base/platform_thread_types.cc
|
||||
@@ -118,11 +118,13 @@ void SetCurrentThreadName(const char* name) {
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 6320 6322)
|
||||
+#ifndef __MINGW32__
|
||||
__try {
|
||||
::RaiseException(0x406D1388, 0, sizeof(threadname_info) / sizeof(ULONG_PTR),
|
||||
reinterpret_cast<ULONG_PTR*>(&threadname_info));
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) { // NOLINT
|
||||
}
|
||||
+#endif
|
||||
#pragma warning(pop)
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
|
||||
prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name)); // NOLINT
|
||||
diff --git a/webrtc/rtc_base/system/file_wrapper.cc b/webrtc/rtc_base/system/file_wrapper.cc
|
||||
index 12c27a5..3203bc6 100644
|
||||
--- a/webrtc/rtc_base/system/file_wrapper.cc
|
||||
+++ b/webrtc/rtc_base/system/file_wrapper.cc
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
-#include <Windows.h>
|
||||
+#include <windows.h>
|
||||
#else
|
||||
#endif
|
||||
|
||||
--
|
||||
2.47.1
|
||||
|
@ -0,0 +1,45 @@
|
||||
From 4a17c682e9a173c27feec9e67fb8c4c36090b1a6 Mon Sep 17 00:00:00 2001
|
||||
From: Alper Nebi Yasak <alpernebiyasak@gmail.com>
|
||||
Date: Fri, 25 Oct 2024 01:53:16 +0300
|
||||
Subject: [PATCH] common_audio: Add MIPS_DSP_R1_LE guard for vector scaling ops
|
||||
|
||||
The MIPS-specific source for vector scaling operations fails to build on
|
||||
Debian's mips64el:
|
||||
|
||||
[97/303] Compiling C object webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o
|
||||
FAILED: webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o
|
||||
cc [...] webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o.d -o webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o -c ../webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c
|
||||
/tmp/cc7UGPkY.s: Assembler messages:
|
||||
/tmp/cc7UGPkY.s:57: Error: opcode not supported on this processor: mips64r2 (mips64r2) `extrv_r.w $3,$ac0,$8'
|
||||
ninja: build stopped: subcommand failed.
|
||||
|
||||
The EXTRV_R.W instruction it uses is part of DSP extensions for this
|
||||
architecture. In signal_processing_library.h, this function's prototype
|
||||
is guarded with #if defined(MIPS_DSP_R1_LE). Guard the implementation
|
||||
like that as well to fix the error.
|
||||
|
||||
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
|
||||
---
|
||||
.../signal_processing/vector_scaling_operations_mips.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c b/webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c
|
||||
index ba2d26d..08ca293 100644
|
||||
--- a/webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c
|
||||
+++ b/webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "common_audio/signal_processing/include/signal_processing_library.h"
|
||||
|
||||
+#if defined(MIPS_DSP_R1_LE)
|
||||
int WebRtcSpl_ScaleAndAddVectorsWithRound_mips(const int16_t* in_vector1,
|
||||
int16_t in_vector1_scale,
|
||||
const int16_t* in_vector2,
|
||||
@@ -55,3 +56,4 @@ int WebRtcSpl_ScaleAndAddVectorsWithRound_mips(const int16_t* in_vector1,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+#endif
|
||||
--
|
||||
2.47.1
|
||||
|
46
patches/0001-meson-Fixes-for-MSVC-build.patch
Normal file
46
patches/0001-meson-Fixes-for-MSVC-build.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From c555fb6eaf0568c2205bbd197ebbcc0e85714c77 Mon Sep 17 00:00:00 2001
|
||||
From: Nirbheek Chauhan <nirbheek@centricular.com>
|
||||
Date: Fri, 26 May 2023 02:20:56 +0530
|
||||
Subject: [PATCH] meson: Fixes for MSVC build
|
||||
|
||||
winsock2.h must be included before windows.h or alternative
|
||||
definitions of `struct sockaddr` are defined.
|
||||
|
||||
```
|
||||
FAILED: webrtc/rtc_base/liblibbase.a.p/logging.cc.obj
|
||||
"cl" "-Iwebrtc\rtc_base\liblibbase.a.p" "-Iwebrtc\rtc_base" "-I..\webrtc\rtc_base" "-Iwebrtc" "-I..\webrtc" "-Isubprojects\abseil-cpp-20230125.1" "-I..\subprojects\abseil-cpp-20230125.1" "/MD" "/nologo" "/showIncludes" "/utf-8" "/Zc:__cplusplus" "/W2" "/EHsc" "/std:c++17" "/permissive-" "/O2" "/Zi" "-DWEBRTC_LIBRARY_
|
||||
IMPL" "-DWEBRTC_ENABLE_SYMBOL_EXPORT" "-DNDEBUG" "-DWEBRTC_WIN" "-D_WIN32" "-U__STRICT_ANSI__" "-D__STDC_FORMAT_MACROS=1" "-DNOMINMAX" "-DWEBRTC_ENABLE_AVX2" "/Fdwebrtc\rtc_base\liblibbase.a.p\logging.cc.pdb" /Fowebrtc/rtc_base/liblibbase.a.p/logging.cc.obj "/c" ../webrtc/rtc_base/logging.cc
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(103): warning C4005: 'AF_IPX': macro redefinition
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(457): note: see previous definition of 'AF_IPX'
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(147): warning C4005: 'AF_MAX': macro redefinition
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(476): note: see previous definition of 'AF_MAX'
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(187): warning C4005: 'SO_DONTLINGER': macro redefinition
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(399): note: see previous definition of 'SO_DONTLINGER'
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(240): error C2011: 'sockaddr': 'struct' type redefinition
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(482): note: see declaration of 'sockaddr'
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(442): error C2143: syntax error: missing '}' before 'constant'
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(442): error C2059: syntax error: 'constant'
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C2143: syntax error: missing ';' before '}'
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
|
||||
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
|
||||
...
|
||||
```
|
||||
---
|
||||
webrtc/rtc_base/logging.cc | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/webrtc/rtc_base/logging.cc b/webrtc/rtc_base/logging.cc
|
||||
index 61a3c66..825c686 100644
|
||||
--- a/webrtc/rtc_base/logging.cc
|
||||
+++ b/webrtc/rtc_base/logging.cc
|
||||
@@ -15,6 +15,7 @@
|
||||
#if RTC_LOG_ENABLED()
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
+#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#if _MSC_VER < 1900
|
||||
#define snprintf _snprintf
|
||||
--
|
||||
2.47.1
|
||||
|
108
subprojects/abseil-cpp.wrap
Normal file
108
subprojects/abseil-cpp.wrap
Normal file
@ -0,0 +1,108 @@
|
||||
[wrap-file]
|
||||
directory = abseil-cpp-20240722.0
|
||||
source_url = https://github.com/abseil/abseil-cpp/releases/download/20240722.0/abseil-cpp-20240722.0.tar.gz
|
||||
source_filename = abseil-cpp-20240722.0.tar.gz
|
||||
source_hash = f50e5ac311a81382da7fa75b97310e4b9006474f9560ac46f54a9967f07d4ae3
|
||||
patch_filename = abseil-cpp_20240722.0-3_patch.zip
|
||||
patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20240722.0-3/get_patch
|
||||
patch_hash = 12dd8df1488a314c53e3751abd2750cf233b830651d168b6a9f15e7d0cf71f7b
|
||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/abseil-cpp_20240722.0-3/abseil-cpp-20240722.0.tar.gz
|
||||
wrapdb_version = 20240722.0-3
|
||||
|
||||
[provide]
|
||||
absl_base = absl_base_dep
|
||||
absl_container = absl_container_dep
|
||||
absl_debugging = absl_debugging_dep
|
||||
absl_log = absl_log_dep
|
||||
absl_flags = absl_flags_dep
|
||||
absl_hash = absl_hash_dep
|
||||
absl_crc = absl_crc_dep
|
||||
absl_numeric = absl_numeric_dep
|
||||
absl_profiling = absl_profiling_dep
|
||||
absl_random = absl_random_dep
|
||||
absl_status = absl_status_dep
|
||||
absl_strings = absl_strings_dep
|
||||
absl_synchronization = absl_synchronization_dep
|
||||
absl_time = absl_time_dep
|
||||
absl_types = absl_types_dep
|
||||
absl_algorithm_container = absl_base_dep
|
||||
absl_any_invocable = absl_base_dep
|
||||
absl_bad_any_cast_impl = absl_types_dep
|
||||
absl_bad_optional_access = absl_types_dep
|
||||
absl_bad_variant_access = absl_types_dep
|
||||
absl_bind_front = absl_base_dep
|
||||
absl_city = absl_hash_dep
|
||||
absl_civil_time = absl_time_dep
|
||||
absl_cleanup = absl_base_dep
|
||||
absl_cord = absl_strings_dep
|
||||
absl_cord_internal = absl_strings_dep
|
||||
absl_cordz_functions = absl_strings_dep
|
||||
absl_cordz_handle = absl_strings_dep
|
||||
absl_cordz_info = absl_strings_dep
|
||||
absl_cordz_sample_token = absl_strings_dep
|
||||
absl_core_headers = absl_base_dep
|
||||
absl_crc32c = absl_crc_dep
|
||||
absl_debugging_internal = absl_debugging_dep
|
||||
absl_demangle_internal = absl_debugging_dep
|
||||
absl_die_if_null = absl_log_dep
|
||||
absl_examine_stack = absl_debugging_dep
|
||||
absl_exponential_biased = absl_profiling_dep
|
||||
absl_failure_signal_handler = absl_debugging_dep
|
||||
absl_flags_commandlineflag = absl_flags_dep
|
||||
absl_flags_commandlineflag_internal = absl_flags_dep
|
||||
absl_flags_config = absl_flags_dep
|
||||
absl_flags_internal = absl_flags_dep
|
||||
absl_flags_marshalling = absl_flags_dep
|
||||
absl_flags_parse = absl_flags_dep
|
||||
absl_flags_private_handle_accessor = absl_flags_dep
|
||||
absl_flags_program_name = absl_flags_dep
|
||||
absl_flags_reflection = absl_flags_dep
|
||||
absl_flags_usage = absl_flags_dep
|
||||
absl_flags_usage_internal = absl_flags_dep
|
||||
absl_flat_hash_map = absl_container_dep
|
||||
absl_flat_hash_set = absl_container_dep
|
||||
absl_function_ref = absl_base_dep
|
||||
absl_graphcycles_internal = absl_synchronization_dep
|
||||
absl_hashtablez_sampler = absl_container_dep
|
||||
absl_inlined_vector = absl_container_dep
|
||||
absl_int128 = absl_numeric_dep
|
||||
absl_leak_check = absl_debugging_dep
|
||||
absl_log_initialize = absl_log_dep
|
||||
absl_log_internal_check_op = absl_log_dep
|
||||
absl_log_internal_message = absl_log_dep
|
||||
absl_log_severity = absl_base_dep
|
||||
absl_low_level_hash = absl_hash_dep
|
||||
absl_memory = absl_base_dep
|
||||
absl_optional = absl_types_dep
|
||||
absl_periodic_sampler = absl_profiling_dep
|
||||
absl_random_bit_gen_ref = absl_random_dep
|
||||
absl_random_distributions = absl_random_dep
|
||||
absl_random_internal_distribution_test_util = absl_random_dep
|
||||
absl_random_internal_platform = absl_random_dep
|
||||
absl_random_internal_pool_urbg = absl_random_dep
|
||||
absl_random_internal_randen = absl_random_dep
|
||||
absl_random_internal_randen_hwaes = absl_random_dep
|
||||
absl_random_internal_randen_hwaes_impl = absl_random_dep
|
||||
absl_random_internal_randen_slow = absl_random_dep
|
||||
absl_random_internal_seed_material = absl_random_dep
|
||||
absl_random_random = absl_random_dep
|
||||
absl_random_seed_gen_exception = absl_random_dep
|
||||
absl_random_seed_sequences = absl_random_dep
|
||||
absl_raw_hash_set = absl_container_dep
|
||||
absl_raw_logging_internal = absl_base_dep
|
||||
absl_scoped_set_env = absl_base_dep
|
||||
absl_span = absl_types_dep
|
||||
absl_spinlock_wait = absl_base_dep
|
||||
absl_stacktrace = absl_debugging_dep
|
||||
absl_statusor = absl_status_dep
|
||||
absl_str_format = absl_strings_dep
|
||||
absl_str_format_internal = absl_strings_dep
|
||||
absl_strerror = absl_base_dep
|
||||
absl_string_view = absl_strings_dep
|
||||
absl_strings_internal = absl_strings_dep
|
||||
absl_symbolize = absl_debugging_dep
|
||||
absl_throw_delegate = absl_base_dep
|
||||
absl_time_zone = absl_time_dep
|
||||
absl_type_traits = absl_base_dep
|
||||
absl_utility = absl_base_dep
|
||||
absl_variant = absl_types_dep
|
@ -1,10 +0,0 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: webrtc-audio-processing
|
||||
Description: WebRTC Audio Processing library
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -lwebrtc_audio_processing
|
||||
Cflags: -DWEBRTC_AUDIO_PROCESSING_ONLY_BUILD -I${includedir}/webrtc_audio_processing @PLATFORM_CFLAGS@
|
859
webrtc/BUILD.gn
859
webrtc/BUILD.gn
@ -6,22 +6,188 @@
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
# TODO(kjellander): Rebase this to webrtc/build/common.gypi changes after r6330.
|
||||
# This is the root build file for GN. GN will start processing by loading this
|
||||
# file, and recursively load all dependencies until all dependencies are either
|
||||
# resolved or known not to exist (which will cause the build to fail). So if
|
||||
# you add a new build file, there must be some path of dependencies from this
|
||||
# file to your new one or GN won't know about it.
|
||||
|
||||
# Use of visibility = clauses:
|
||||
# The default visibility for all rtc_ targets is equivalent to "//*", or
|
||||
# "all targets in webrtc can depend on this, nothing outside can".
|
||||
#
|
||||
# When overriding, the choices are:
|
||||
# - visibility = [ "*" ] - public. Stuff outside webrtc can use this.
|
||||
# - visibility = [ ":*" ] - directory private.
|
||||
# As a general guideline, only targets in api/ should have public visibility.
|
||||
|
||||
import("//build/config/crypto.gni")
|
||||
import("//build/config/linux/pkg_config.gni")
|
||||
import("build/webrtc.gni")
|
||||
import("//build/config/sanitizers/sanitizers.gni")
|
||||
import("webrtc.gni")
|
||||
if (rtc_enable_protobuf) {
|
||||
import("//third_party/protobuf/proto_library.gni")
|
||||
}
|
||||
if (is_android) {
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/android/rules.gni")
|
||||
import("//third_party/jni_zero/jni_zero.gni")
|
||||
}
|
||||
|
||||
if (!build_with_chromium) {
|
||||
# This target should (transitively) cause everything to be built; if you run
|
||||
# 'ninja default' and then 'ninja all', the second build should do no work.
|
||||
group("default") {
|
||||
testonly = true
|
||||
deps = [ ":webrtc" ]
|
||||
if (rtc_build_examples) {
|
||||
deps += [ "examples" ]
|
||||
}
|
||||
if (rtc_build_tools) {
|
||||
deps += [ "rtc_tools" ]
|
||||
}
|
||||
if (rtc_include_tests) {
|
||||
deps += [
|
||||
":rtc_unittests",
|
||||
":video_engine_tests",
|
||||
":voip_unittests",
|
||||
":webrtc_nonparallel_tests",
|
||||
":webrtc_perf_tests",
|
||||
"common_audio:common_audio_unittests",
|
||||
"common_video:common_video_unittests",
|
||||
"examples:examples_unittests",
|
||||
"media:rtc_media_unittests",
|
||||
"modules:modules_tests",
|
||||
"modules:modules_unittests",
|
||||
"modules/audio_coding:audio_coding_tests",
|
||||
"modules/audio_processing:audio_processing_tests",
|
||||
"modules/remote_bitrate_estimator:rtp_to_text",
|
||||
"modules/rtp_rtcp:test_packet_masks_metrics",
|
||||
"modules/video_capture:video_capture_internal_impl",
|
||||
"modules/video_coding:video_codec_perf_tests",
|
||||
"net/dcsctp:dcsctp_unittests",
|
||||
"pc:peerconnection_unittests",
|
||||
"pc:rtc_pc_unittests",
|
||||
"pc:slow_peer_connection_unittests",
|
||||
"pc:svc_tests",
|
||||
"rtc_tools:rtp_generator",
|
||||
"rtc_tools:video_encoder",
|
||||
"rtc_tools:video_replay",
|
||||
"stats:rtc_stats_unittests",
|
||||
"system_wrappers:system_wrappers_unittests",
|
||||
"test",
|
||||
"video:screenshare_loopback",
|
||||
"video:sv_loopback",
|
||||
"video:video_loopback",
|
||||
]
|
||||
if (use_libfuzzer) {
|
||||
deps += [ "test/fuzzers" ]
|
||||
}
|
||||
if (!is_asan) {
|
||||
# Do not build :webrtc_lib_link_test because lld complains on some OS
|
||||
# (e.g. when target_os = "mac") when is_asan=true. For more details,
|
||||
# see bugs.webrtc.org/11027#c5.
|
||||
deps += [ ":webrtc_lib_link_test" ]
|
||||
}
|
||||
if (is_ios) {
|
||||
deps += [
|
||||
"examples:apprtcmobile_tests",
|
||||
"sdk:sdk_framework_unittests",
|
||||
"sdk:sdk_unittests",
|
||||
]
|
||||
}
|
||||
if (is_android) {
|
||||
deps += [
|
||||
"examples:android_examples_junit_tests",
|
||||
"sdk/android:android_instrumentation_test_apk",
|
||||
"sdk/android:android_sdk_junit_tests",
|
||||
]
|
||||
} else {
|
||||
deps += [ "modules/video_capture:video_capture_tests" ]
|
||||
}
|
||||
if (rtc_enable_protobuf) {
|
||||
deps += [
|
||||
"logging:rtc_event_log_rtp_dump",
|
||||
"tools_webrtc/perf:webrtc_dashboard_upload",
|
||||
]
|
||||
}
|
||||
if ((is_linux || is_chromeos) && rtc_use_pipewire) {
|
||||
deps += [ "modules/desktop_capture:shared_screencast_stream_test" ]
|
||||
}
|
||||
}
|
||||
if (target_os == "android") {
|
||||
deps += [ "tools_webrtc:binary_version_check" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Abseil Flags by default doesn't register command line flags on mobile
|
||||
# platforms, WebRTC tests requires them (e.g. on simualtors) so this
|
||||
# config will be applied to testonly targets globally (see webrtc.gni).
|
||||
config("absl_flags_configs") {
|
||||
defines = [ "ABSL_FLAGS_STRIP_NAMES=0" ]
|
||||
}
|
||||
|
||||
config("library_impl_config") {
|
||||
# Build targets that contain WebRTC implementation need this macro to
|
||||
# be defined in order to correctly export symbols when is_component_build
|
||||
# is true.
|
||||
# For more info see: rtc_base/build/rtc_export.h.
|
||||
defines = [ "WEBRTC_LIBRARY_IMPL" ]
|
||||
}
|
||||
|
||||
# Contains the defines and includes in common.gypi that are duplicated both as
|
||||
# target_defaults and direct_dependent_settings.
|
||||
config("common_inherited_config") {
|
||||
defines = []
|
||||
if (build_with_mozilla) {
|
||||
defines += [ "WEBRTC_MOZILLA_BUILD" ]
|
||||
cflags = []
|
||||
ldflags = []
|
||||
|
||||
if (rtc_objc_prefix != "") {
|
||||
defines += [ "RTC_OBJC_TYPE_PREFIX=${rtc_objc_prefix}" ]
|
||||
}
|
||||
|
||||
if (rtc_dlog_always_on) {
|
||||
defines += [ "DLOG_ALWAYS_ON" ]
|
||||
}
|
||||
|
||||
if (rtc_enable_symbol_export || is_component_build) {
|
||||
defines += [ "WEBRTC_ENABLE_SYMBOL_EXPORT" ]
|
||||
}
|
||||
if (rtc_enable_objc_symbol_export) {
|
||||
defines += [ "WEBRTC_ENABLE_OBJC_SYMBOL_EXPORT" ]
|
||||
}
|
||||
|
||||
if (!rtc_builtin_ssl_root_certificates) {
|
||||
defines += [ "WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS" ]
|
||||
}
|
||||
|
||||
if (rtc_disable_check_msg) {
|
||||
defines += [ "RTC_DISABLE_CHECK_MSG" ]
|
||||
}
|
||||
|
||||
if (rtc_enable_avx2) {
|
||||
defines += [ "WEBRTC_ENABLE_AVX2" ]
|
||||
}
|
||||
|
||||
if (rtc_enable_win_wgc) {
|
||||
defines += [ "RTC_ENABLE_WIN_WGC" ]
|
||||
}
|
||||
|
||||
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
|
||||
# value for the current handler in an static variable, so that subsequent
|
||||
# changes to the handler for that TRACE_EVENT_* will be ignored.
|
||||
# So when tests are included, we set this define, making it possible to use
|
||||
# different event handlers in different tests.
|
||||
if (rtc_include_tests) {
|
||||
defines += [ "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=1" ]
|
||||
} else {
|
||||
defines += [ "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0" ]
|
||||
}
|
||||
}
|
||||
if (build_with_chromium) {
|
||||
defines = [ "WEBRTC_CHROMIUM_BUILD" ]
|
||||
defines += [ "WEBRTC_CHROMIUM_BUILD" ]
|
||||
include_dirs = [
|
||||
# The overrides must be included first as that is the mechanism for
|
||||
# selecting the override headers in Chromium.
|
||||
@ -29,10 +195,18 @@ config("common_inherited_config") {
|
||||
|
||||
# Allow includes to be prefixed with webrtc/ in case it is not an
|
||||
# immediate subdirectory of the top-level.
|
||||
"..",
|
||||
".",
|
||||
|
||||
# Just like the root WebRTC directory is added to include path, the
|
||||
# corresponding directory tree with generated files needs to be added too.
|
||||
# Note: this path does not change depending on the current target, e.g.
|
||||
# it is always "//gen/third_party/webrtc" when building with Chromium.
|
||||
# See also: http://cs.chromium.org/?q=%5C"default_include_dirs
|
||||
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_gen_dir
|
||||
target_gen_dir,
|
||||
]
|
||||
}
|
||||
if (is_posix) {
|
||||
if (is_posix || is_fuchsia) {
|
||||
defines += [ "WEBRTC_POSIX" ]
|
||||
}
|
||||
if (is_ios) {
|
||||
@ -41,15 +215,15 @@ config("common_inherited_config") {
|
||||
"WEBRTC_IOS",
|
||||
]
|
||||
}
|
||||
if (is_ios && rtc_use_objc_h264) {
|
||||
defines += [ "WEBRTC_OBJC_H264" ]
|
||||
}
|
||||
if (is_linux) {
|
||||
if (is_linux || is_chromeos) {
|
||||
defines += [ "WEBRTC_LINUX" ]
|
||||
}
|
||||
if (is_mac) {
|
||||
defines += [ "WEBRTC_MAC" ]
|
||||
}
|
||||
if (is_fuchsia) {
|
||||
defines += [ "WEBRTC_FUCHSIA" ]
|
||||
}
|
||||
if (is_win) {
|
||||
defines += [ "WEBRTC_WIN" ]
|
||||
}
|
||||
@ -58,52 +232,184 @@ config("common_inherited_config") {
|
||||
"WEBRTC_LINUX",
|
||||
"WEBRTC_ANDROID",
|
||||
]
|
||||
|
||||
if (build_with_mozilla) {
|
||||
defines += [ "WEBRTC_ANDROID_OPENSLES" ]
|
||||
}
|
||||
}
|
||||
if (is_chromeos) {
|
||||
defines += [ "CHROMEOS" ]
|
||||
}
|
||||
|
||||
if (rtc_sanitize_coverage != "") {
|
||||
assert(is_clang, "sanitizer coverage requires clang")
|
||||
cflags += [ "-fsanitize-coverage=${rtc_sanitize_coverage}" ]
|
||||
ldflags += [ "-fsanitize-coverage=${rtc_sanitize_coverage}" ]
|
||||
}
|
||||
|
||||
if (is_ubsan) {
|
||||
cflags += [ "-fsanitize=float-cast-overflow" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_have_dbus_glib) {
|
||||
pkg_config("dbus-glib") {
|
||||
packages = [ "dbus-glib-1" ]
|
||||
# TODO(bugs.webrtc.org/9693): Remove the possibility to suppress this warning
|
||||
# as soon as WebRTC compiles without it.
|
||||
config("no_global_constructors") {
|
||||
if (is_clang) {
|
||||
cflags = [ "-Wno-global-constructors" ]
|
||||
}
|
||||
}
|
||||
|
||||
config("rtc_prod_config") {
|
||||
# Ideally, WebRTC production code (but not test code) should have these flags.
|
||||
if (is_clang) {
|
||||
cflags = [
|
||||
"-Wexit-time-destructors",
|
||||
"-Wglobal-constructors",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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 = []
|
||||
cflags_cc = []
|
||||
if (rtc_restrict_logging) {
|
||||
defines = [ "WEBRTC_RESTRICT_LOGGING" ]
|
||||
cflags_objc = []
|
||||
defines = []
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
defines += [ "WEBRTC_ENABLE_PROTOBUF=1" ]
|
||||
} else {
|
||||
defines += [ "WEBRTC_ENABLE_PROTOBUF=0" ]
|
||||
}
|
||||
|
||||
if (rtc_have_dbus_glib) {
|
||||
defines += [ "HAVE_DBUS_GLIB" ]
|
||||
if (rtc_strict_field_trials == "") {
|
||||
defines += [ "WEBRTC_STRICT_FIELD_TRIALS=0" ]
|
||||
} else if (rtc_strict_field_trials == "dcheck") {
|
||||
defines += [ "WEBRTC_STRICT_FIELD_TRIALS=1" ]
|
||||
} else if (rtc_strict_field_trials == "warn") {
|
||||
defines += [ "WEBRTC_STRICT_FIELD_TRIALS=2" ]
|
||||
} else {
|
||||
assert(false,
|
||||
"Unsupported value for rtc_strict_field_trials: " +
|
||||
"$rtc_strict_field_trials")
|
||||
}
|
||||
|
||||
# TODO(kjellander): Investigate this, it seems like include <dbus/dbus.h>
|
||||
# is still not found even if the execution of
|
||||
# build/config/linux/pkg-config.py dbus-glib-1 returns correct include
|
||||
# dirs on Linux.
|
||||
all_dependent_configs = [ "dbus-glib" ]
|
||||
if (rtc_include_internal_audio_device) {
|
||||
defines += [ "WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE" ]
|
||||
}
|
||||
|
||||
if (rtc_libvpx_build_vp9) {
|
||||
defines += [ "RTC_ENABLE_VP9" ]
|
||||
}
|
||||
|
||||
if (rtc_use_h265) {
|
||||
defines += [ "RTC_ENABLE_H265" ]
|
||||
}
|
||||
|
||||
if (rtc_include_dav1d_in_internal_decoder_factory) {
|
||||
defines += [ "RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY" ]
|
||||
}
|
||||
|
||||
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" ]
|
||||
}
|
||||
|
||||
if (rtc_use_absl_mutex) {
|
||||
defines += [ "WEBRTC_ABSL_MUTEX" ]
|
||||
}
|
||||
|
||||
if (rtc_enable_libevent) {
|
||||
defines += [ "WEBRTC_ENABLE_LIBEVENT" ]
|
||||
}
|
||||
|
||||
if (rtc_disable_logging) {
|
||||
defines += [ "RTC_DISABLE_LOGGING" ]
|
||||
}
|
||||
|
||||
if (rtc_disable_trace_events) {
|
||||
defines += [ "RTC_DISABLE_TRACE_EVENTS" ]
|
||||
}
|
||||
|
||||
if (rtc_disable_metrics) {
|
||||
defines += [ "RTC_DISABLE_METRICS" ]
|
||||
}
|
||||
|
||||
if (rtc_exclude_audio_processing_module) {
|
||||
defines += [ "WEBRTC_EXCLUDE_AUDIO_PROCESSING_MODULE" ]
|
||||
}
|
||||
|
||||
if (is_clang) {
|
||||
cflags += [
|
||||
# TODO(webrtc:13219): Fix -Wshadow instances and enable.
|
||||
"-Wno-shadow",
|
||||
|
||||
# See https://reviews.llvm.org/D56731 for details about this
|
||||
# warning.
|
||||
"-Wctad-maybe-unsupported",
|
||||
]
|
||||
}
|
||||
|
||||
if (build_with_chromium) {
|
||||
defines += [ "LOGGING_INSIDE_WEBRTC" ]
|
||||
} else {
|
||||
if (is_posix) {
|
||||
# -Wextra is currently disabled in Chromium"s common.gypi. Enable
|
||||
# for targets that can handle it. For Android/arm64 right now
|
||||
# there will be an "enumeral and non-enumeral type in conditional
|
||||
# expression" warning in android_tools/ndk_experimental"s version
|
||||
# of stlport.
|
||||
# See: https://code.google.com/p/chromium/issues/detail?id=379699
|
||||
if (current_cpu != "arm64" || !is_android) {
|
||||
cflags = [
|
||||
"-Wextra",
|
||||
|
||||
# We need to repeat some flags from Chromium"s common.gypi
|
||||
# here that get overridden by -Wextra.
|
||||
"-Wno-unused-parameter",
|
||||
"-Wno-missing-field-initializers",
|
||||
"-Wno-strict-overflow",
|
||||
defines += [
|
||||
# NOTICE: Since common_inherited_config is used in public_configs for our
|
||||
# targets, there's no point including the defines in that config here.
|
||||
# TODO(kjellander): Cleanup unused ones and move defines closer to the
|
||||
# source when webrtc:4256 is completed.
|
||||
"HAVE_WEBRTC_VIDEO",
|
||||
"LOGGING_INSIDE_WEBRTC",
|
||||
]
|
||||
} else {
|
||||
if (is_posix || is_fuchsia) {
|
||||
cflags_c += [
|
||||
# TODO(bugs.webrtc.org/9029): enable commented compiler flags.
|
||||
# Some of these flags should also be added to cflags_objc.
|
||||
|
||||
# "-Wextra", (used when building C++ but not when building C)
|
||||
# "-Wmissing-prototypes", (C/Obj-C only)
|
||||
# "-Wmissing-declarations", (ensure this is always used C/C++, etc..)
|
||||
"-Wstrict-prototypes",
|
||||
|
||||
# "-Wpointer-arith", (ensure this is always used C/C++, etc..)
|
||||
# "-Wbad-function-cast", (C/Obj-C only)
|
||||
# "-Wnested-externs", (C/Obj-C only)
|
||||
]
|
||||
cflags_objc += [ "-Wstrict-prototypes" ]
|
||||
cflags_cc = [
|
||||
"-Wnon-virtual-dtor",
|
||||
|
||||
@ -111,10 +417,25 @@ config("common_config") {
|
||||
"-Woverloaded-virtual",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_clang) {
|
||||
cflags += [ "-Wthread-safety" ]
|
||||
cflags += [
|
||||
"-Wc++11-narrowing",
|
||||
"-Wundef",
|
||||
"-Wunused-lambda-capture",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_win && !is_clang) {
|
||||
# MSVC warning suppressions (needed to use Abseil).
|
||||
# TODO(bugs.webrtc.org/9274): Remove these warnings as soon as MSVC allows
|
||||
# external headers warning suppression (or fix them upstream).
|
||||
cflags += [ "/wd4702" ] # unreachable code
|
||||
|
||||
# MSVC 2019 warning suppressions for C++17 compiling
|
||||
cflags +=
|
||||
[ "/wd5041" ] # out-of-line definition for constexpr static data
|
||||
# member is not needed and is deprecated in C++17
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,8 +450,6 @@ config("common_config") {
|
||||
defines += [ "WEBRTC_ARCH_ARM_V7" ]
|
||||
if (arm_use_neon) {
|
||||
defines += [ "WEBRTC_HAS_NEON" ]
|
||||
} else if (arm_optionally_use_neon) {
|
||||
defines += [ "WEBRTC_DETECT_NEON" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -163,119 +482,385 @@ config("common_config") {
|
||||
"-fno-builtin-sinf",
|
||||
]
|
||||
}
|
||||
|
||||
if (use_fuzzing_engine) {
|
||||
# Used in Chromium's overrides to disable logging
|
||||
defines += [ "WEBRTC_UNSAFE_FUZZER_MODE" ]
|
||||
}
|
||||
|
||||
source_set("webrtc") {
|
||||
sources = [
|
||||
"call.h",
|
||||
"config.h",
|
||||
"frame_callback.h",
|
||||
"transport.h",
|
||||
]
|
||||
|
||||
defines = []
|
||||
configs += [ ":common_config" ]
|
||||
public_configs = [ ":common_inherited_config" ]
|
||||
|
||||
deps = [
|
||||
"audio",
|
||||
":webrtc_common",
|
||||
"base:rtc_base",
|
||||
"call",
|
||||
"common_audio",
|
||||
"common_video",
|
||||
"modules/audio_coding",
|
||||
"modules/audio_conference_mixer",
|
||||
"modules/audio_device",
|
||||
"modules/audio_processing",
|
||||
"modules/bitrate_controller",
|
||||
"modules/desktop_capture",
|
||||
"modules/media_file",
|
||||
"modules/rtp_rtcp",
|
||||
"modules/utility",
|
||||
"modules/video_coding",
|
||||
"modules/video_processing",
|
||||
"system_wrappers",
|
||||
"tools",
|
||||
"video",
|
||||
"voice_engine",
|
||||
]
|
||||
|
||||
if (build_with_chromium) {
|
||||
deps += [
|
||||
"modules/video_capture",
|
||||
"modules/video_render",
|
||||
if (!build_with_chromium && rtc_win_undef_unicode) {
|
||||
cflags += [
|
||||
"/UUNICODE",
|
||||
"/U_UNICODE",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
defines += [ "ENABLE_RTC_EVENT_LOG" ]
|
||||
deps += [ ":rtc_event_log_proto" ]
|
||||
if (rtc_use_perfetto) {
|
||||
defines += [ "RTC_USE_PERFETTO" ]
|
||||
}
|
||||
}
|
||||
|
||||
config("common_objc") {
|
||||
frameworks = [ "Foundation.framework" ]
|
||||
}
|
||||
|
||||
if (!rtc_build_ssl) {
|
||||
config("external_ssl_library") {
|
||||
if (rtc_ssl_root != "") {
|
||||
include_dirs = [ rtc_ssl_root ]
|
||||
}
|
||||
libs = [
|
||||
"crypto",
|
||||
"ssl",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (!build_with_chromium) {
|
||||
executable("webrtc_tests") {
|
||||
# Target to build all the WebRTC production code.
|
||||
rtc_static_library("webrtc") {
|
||||
# Only the root target and the test should depend on this.
|
||||
visibility = [
|
||||
"//:default",
|
||||
"//:webrtc_lib_link_test",
|
||||
]
|
||||
|
||||
sources = []
|
||||
complete_static_lib = true
|
||||
suppressed_configs += [ "//build/config/compiler:thin_archive" ]
|
||||
defines = []
|
||||
|
||||
deps = [
|
||||
"api:create_peerconnection_factory",
|
||||
"api:enable_media",
|
||||
"api:libjingle_peerconnection_api",
|
||||
"api:rtc_error",
|
||||
"api:transport_api",
|
||||
"api/audio_codecs:opus_audio_decoder_factory",
|
||||
"api/crypto",
|
||||
"api/rtc_event_log:rtc_event_log_factory",
|
||||
"api/task_queue",
|
||||
"api/task_queue:default_task_queue_factory",
|
||||
"api/test/metrics",
|
||||
"api/video_codecs:video_decoder_factory_template",
|
||||
"api/video_codecs:video_decoder_factory_template_dav1d_adapter",
|
||||
"api/video_codecs:video_decoder_factory_template_libvpx_vp8_adapter",
|
||||
"api/video_codecs:video_decoder_factory_template_libvpx_vp9_adapter",
|
||||
"api/video_codecs:video_decoder_factory_template_open_h264_adapter",
|
||||
"api/video_codecs:video_encoder_factory_template",
|
||||
"api/video_codecs:video_encoder_factory_template_libaom_av1_adapter",
|
||||
"api/video_codecs:video_encoder_factory_template_libvpx_vp8_adapter",
|
||||
"api/video_codecs:video_encoder_factory_template_libvpx_vp9_adapter",
|
||||
"api/video_codecs:video_encoder_factory_template_open_h264_adapter",
|
||||
"audio",
|
||||
"call",
|
||||
"common_audio",
|
||||
"common_video",
|
||||
"logging:rtc_event_log_api",
|
||||
"media",
|
||||
"modules",
|
||||
"modules/video_capture:video_capture_internal_impl",
|
||||
"p2p:rtc_p2p",
|
||||
"pc:libjingle_peerconnection",
|
||||
"pc:rtc_pc",
|
||||
"sdk",
|
||||
"video",
|
||||
]
|
||||
|
||||
if (rtc_include_builtin_audio_codecs) {
|
||||
deps += [
|
||||
"api/audio_codecs:builtin_audio_decoder_factory",
|
||||
"api/audio_codecs:builtin_audio_encoder_factory",
|
||||
]
|
||||
}
|
||||
|
||||
if (build_with_mozilla) {
|
||||
deps += [
|
||||
"api/video:video_frame",
|
||||
"api/video:video_rtp_headers",
|
||||
]
|
||||
} else {
|
||||
deps += [
|
||||
"api",
|
||||
"logging",
|
||||
"p2p",
|
||||
"pc",
|
||||
"stats",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
deps += [ "logging:rtc_event_log_proto" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_include_tests && !is_asan) {
|
||||
rtc_executable("webrtc_lib_link_test") {
|
||||
testonly = true
|
||||
|
||||
# This target is used for checking to link, so do not check dependencies
|
||||
# on gn check.
|
||||
check_includes = false # no-presubmit-check TODO(bugs.webrtc.org/12785)
|
||||
|
||||
sources = [ "webrtc_lib_link_test.cc" ]
|
||||
deps = [
|
||||
# NOTE: Don't add deps here. If this test fails to link, it means you
|
||||
# need to add stuff to the webrtc static lib target above.
|
||||
":webrtc",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (use_libfuzzer || use_afl) {
|
||||
# This target is only here for gn to discover fuzzer build targets under
|
||||
# webrtc/test/fuzzers/.
|
||||
group("webrtc_fuzzers_dummy") {
|
||||
testonly = true
|
||||
deps = [ "test/fuzzers:webrtc_fuzzer_main" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_include_tests && !build_with_chromium) {
|
||||
rtc_unittests_resources = [ "resources/reference_video_640x360_30fps.y4m" ]
|
||||
|
||||
if (is_ios) {
|
||||
bundle_data("rtc_unittests_bundle_data") {
|
||||
testonly = true
|
||||
sources = rtc_unittests_resources
|
||||
outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_test("rtc_unittests") {
|
||||
testonly = true
|
||||
|
||||
deps = [
|
||||
"api:compile_all_headers",
|
||||
"api:rtc_api_unittests",
|
||||
"api/audio/test:audio_api_unittests",
|
||||
"api/audio_codecs/test:audio_codecs_api_unittests",
|
||||
"api/numerics:numerics_unittests",
|
||||
"api/task_queue:pending_task_safety_flag_unittests",
|
||||
"api/test/metrics:metrics_unittests",
|
||||
"api/transport:stun_unittest",
|
||||
"api/video/test:rtc_api_video_unittests",
|
||||
"api/video_codecs:libaom_av1_encoder_factory_test",
|
||||
"api/video_codecs:simple_encoder_wrapper_unittests",
|
||||
"api/video_codecs/test:video_codecs_api_unittests",
|
||||
"api/voip:compile_all_headers",
|
||||
"call:fake_network_pipe_unittests",
|
||||
"p2p:libstunprober_unittests",
|
||||
"p2p:rtc_p2p_unittests",
|
||||
"rtc_base:async_dns_resolver_unittests",
|
||||
"rtc_base:async_packet_socket_unittest",
|
||||
"rtc_base:callback_list_unittests",
|
||||
"rtc_base:rtc_base_approved_unittests",
|
||||
"rtc_base:rtc_base_unittests",
|
||||
"rtc_base:rtc_json_unittests",
|
||||
"rtc_base:rtc_numerics_unittests",
|
||||
"rtc_base:rtc_operations_chain_unittests",
|
||||
"rtc_base:rtc_task_queue_unittests",
|
||||
"rtc_base:sigslot_unittest",
|
||||
"rtc_base:task_queue_stdlib_unittest",
|
||||
"rtc_base:untyped_function_unittest",
|
||||
"rtc_base:weak_ptr_unittests",
|
||||
"rtc_base/experiments:experiments_unittests",
|
||||
"rtc_base/system:file_wrapper_unittests",
|
||||
"rtc_base/task_utils:repeating_task_unittests",
|
||||
"rtc_base/units:units_unittests",
|
||||
"sdk:sdk_tests",
|
||||
"test:rtp_test_utils",
|
||||
"test:test_main",
|
||||
"test/network:network_emulation_unittests",
|
||||
]
|
||||
|
||||
data = rtc_unittests_resources
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
deps += [
|
||||
"api/test/network_emulation:network_config_schedule_proto",
|
||||
"logging:rtc_event_log_tests",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_ios) {
|
||||
deps += [ ":rtc_unittests_bundle_data" ]
|
||||
}
|
||||
|
||||
if (is_android) {
|
||||
# Do not use Chromium's launcher. native_unittests defines its own JNI_OnLoad.
|
||||
use_default_launcher = false
|
||||
|
||||
deps += [
|
||||
"sdk/android:native_unittests",
|
||||
"sdk/android:native_unittests_java",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
shard_timeout = 900
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_enable_google_benchmarks) {
|
||||
rtc_test("benchmarks") {
|
||||
testonly = true
|
||||
deps = [
|
||||
":webrtc",
|
||||
"modules/video_render:video_render_internal_impl",
|
||||
"modules/video_capture:video_capture_internal_impl",
|
||||
"test",
|
||||
"rtc_base/synchronization:mutex_benchmark",
|
||||
"test:benchmark_main",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
source_set("webrtc_common") {
|
||||
sources = [
|
||||
"common_types.cc",
|
||||
"common_types.h",
|
||||
"config.cc",
|
||||
"config.h",
|
||||
"engine_configurations.h",
|
||||
"typedefs.h",
|
||||
# TODO(pbos): Rename test suite, this is no longer "just" for video targets.
|
||||
video_engine_tests_resources = [
|
||||
"resources/foreman_cif_short.yuv",
|
||||
"resources/voice_engine/audio_long16.pcm",
|
||||
]
|
||||
|
||||
configs += [ ":common_config" ]
|
||||
public_configs = [ ":common_inherited_config" ]
|
||||
}
|
||||
|
||||
source_set("gtest_prod") {
|
||||
sources = [
|
||||
"test/testsupport/gtest_prod_util.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
proto_library("rtc_event_log_proto") {
|
||||
sources = [
|
||||
"call/rtc_event_log.proto",
|
||||
]
|
||||
proto_out_dir = "webrtc/call"
|
||||
if (is_ios) {
|
||||
bundle_data("video_engine_tests_bundle_data") {
|
||||
testonly = true
|
||||
sources = video_engine_tests_resources
|
||||
outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
|
||||
}
|
||||
}
|
||||
|
||||
source_set("rtc_event_log") {
|
||||
sources = [
|
||||
"call/rtc_event_log.cc",
|
||||
"call/rtc_event_log.h",
|
||||
]
|
||||
|
||||
defines = []
|
||||
configs += [ ":common_config" ]
|
||||
public_configs = [ ":common_inherited_config" ]
|
||||
|
||||
rtc_test("video_engine_tests") {
|
||||
testonly = true
|
||||
deps = [
|
||||
":webrtc_common",
|
||||
"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",
|
||||
]
|
||||
data = video_engine_tests_resources
|
||||
if (is_android) {
|
||||
use_default_launcher = false
|
||||
deps += [
|
||||
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
|
||||
"//testing/android/native_test:native_test_java",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
shard_timeout = 900
|
||||
}
|
||||
if (is_ios) {
|
||||
deps += [ ":video_engine_tests_bundle_data" ]
|
||||
}
|
||||
}
|
||||
|
||||
webrtc_perf_tests_resources = [
|
||||
"resources/ConferenceMotion_1280_720_50.yuv",
|
||||
"resources/audio_coding/speech_mono_16kHz.pcm",
|
||||
"resources/audio_coding/speech_mono_32_48kHz.pcm",
|
||||
"resources/audio_coding/testfile32kHz.pcm",
|
||||
"resources/difficult_photo_1850_1110.yuv",
|
||||
"resources/foreman_cif.yuv",
|
||||
"resources/paris_qcif.yuv",
|
||||
"resources/photo_1850_1110.yuv",
|
||||
"resources/presentation_1850_1110.yuv",
|
||||
"resources/voice_engine/audio_long16.pcm",
|
||||
"resources/web_screenshot_1850_1110.yuv",
|
||||
]
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
defines += [ "ENABLE_RTC_EVENT_LOG" ]
|
||||
deps += [ ":rtc_event_log_proto" ]
|
||||
}
|
||||
if (is_clang && !is_nacl) {
|
||||
# Suppress warnings from Chrome's Clang plugins.
|
||||
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
|
||||
configs -= [ "//build/config/clang:find_bad_constructs" ]
|
||||
if (is_ios) {
|
||||
bundle_data("webrtc_perf_tests_bundle_data") {
|
||||
testonly = true
|
||||
sources = webrtc_perf_tests_resources
|
||||
outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_test("webrtc_perf_tests") {
|
||||
testonly = true
|
||||
deps = [
|
||||
"call:call_perf_tests",
|
||||
"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",
|
||||
]
|
||||
|
||||
data = webrtc_perf_tests_resources
|
||||
if (is_android) {
|
||||
use_default_launcher = false
|
||||
deps += [
|
||||
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
|
||||
"//testing/android/native_test:native_test_java",
|
||||
"//testing/android/native_test:native_test_support",
|
||||
]
|
||||
shard_timeout = 4500
|
||||
}
|
||||
if (is_ios) {
|
||||
deps += [ ":webrtc_perf_tests_bundle_data" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_test("webrtc_nonparallel_tests") {
|
||||
testonly = true
|
||||
deps = [ "rtc_base:rtc_base_nonparallel_tests" ]
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
shard_timeout = 900
|
||||
}
|
||||
}
|
||||
|
||||
rtc_test("voip_unittests") {
|
||||
testonly = true
|
||||
deps = [
|
||||
"api/voip:compile_all_headers",
|
||||
"api/voip:voip_engine_factory_unittests",
|
||||
"audio/voip/test:audio_channel_unittests",
|
||||
"audio/voip/test:audio_egress_unittests",
|
||||
"audio/voip/test:audio_ingress_unittests",
|
||||
"audio/voip/test:voip_core_unittests",
|
||||
"test:test_main",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# Build target for standalone dcsctp
|
||||
rtc_static_library("dcsctp") {
|
||||
# Only the root target should depend on this.
|
||||
visibility = [ "//:default" ]
|
||||
sources = []
|
||||
complete_static_lib = true
|
||||
suppressed_configs += [ "//build/config/compiler:thin_archive" ]
|
||||
defines = []
|
||||
deps = [
|
||||
"net/dcsctp/public:factory",
|
||||
"net/dcsctp/public:socket",
|
||||
"net/dcsctp/public:types",
|
||||
"net/dcsctp/socket:dcsctp_socket",
|
||||
"net/dcsctp/timer:task_queue_timeout",
|
||||
]
|
||||
}
|
||||
|
||||
# ---- Poisons ----
|
||||
#
|
||||
# Here is one empty dummy target for each poison type (needed because
|
||||
# "being poisonous with poison type foo" is implemented as "depends on
|
||||
# //:poison_foo").
|
||||
#
|
||||
# The set of poison_* targets needs to be kept in sync with the
|
||||
# `all_poison_types` list in webrtc.gni.
|
||||
#
|
||||
group("poison_audio_codecs") {
|
||||
}
|
||||
|
||||
group("poison_default_echo_detector") {
|
||||
}
|
||||
|
||||
group("poison_environment_construction") {
|
||||
}
|
||||
|
||||
group("poison_software_video_codecs") {
|
||||
}
|
||||
|
29
webrtc/LICENSE
Normal file
29
webrtc/LICENSE
Normal file
@ -0,0 +1,29 @@
|
||||
Copyright (c) 2011, The WebRTC project authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of Google nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -1,419 +0,0 @@
|
||||
This source tree contains third party source code which is governed by third
|
||||
party licenses. Paths to the files and associated licenses are collected here.
|
||||
|
||||
Files governed by third party licenses:
|
||||
common_audio/fft4g.c
|
||||
common_audio/signal_processing/spl_sqrt_floor.c
|
||||
common_audio/signal_processing/spl_sqrt_floor_arm.S
|
||||
modules/audio_coding/codecs/g711/main/source/g711.c
|
||||
modules/audio_coding/codecs/g711/main/source/g711.h
|
||||
modules/audio_coding/codecs/g722/main/source/g722_decode.c
|
||||
modules/audio_coding/codecs/g722/main/source/g722_enc_dec.h
|
||||
modules/audio_coding/codecs/g722/main/source/g722_encode.c
|
||||
modules/audio_coding/codecs/isac/main/source/fft.c
|
||||
modules/audio_device/mac/portaudio/pa_memorybarrier.h
|
||||
modules/audio_device/mac/portaudio/pa_ringbuffer.c
|
||||
modules/audio_device/mac/portaudio/pa_ringbuffer.h
|
||||
modules/audio_processing/aec/aec_rdft.c
|
||||
system_wrappers/source/condition_variable_event_win.cc
|
||||
system_wrappers/source/set_thread_name_win.h
|
||||
system_wrappers/source/spreadsortlib/constants.hpp
|
||||
system_wrappers/source/spreadsortlib/spreadsort.hpp
|
||||
|
||||
Individual licenses for each file:
|
||||
-------------------------------------------------------------------------------
|
||||
Files:
|
||||
common_audio/signal_processing/spl_sqrt_floor.c
|
||||
common_audio/signal_processing/spl_sqrt_floor_arm.S
|
||||
|
||||
License:
|
||||
/*
|
||||
* Written by Wilco Dijkstra, 1996. The following email exchange establishes the
|
||||
* license.
|
||||
*
|
||||
* From: Wilco Dijkstra <Wilco.Dijkstra@ntlworld.com>
|
||||
* Date: Fri, Jun 24, 2011 at 3:20 AM
|
||||
* Subject: Re: sqrt routine
|
||||
* To: Kevin Ma <kma@google.com>
|
||||
* Hi Kevin,
|
||||
* Thanks for asking. Those routines are public domain (originally posted to
|
||||
* comp.sys.arm a long time ago), so you can use them freely for any purpose.
|
||||
* Cheers,
|
||||
* Wilco
|
||||
*
|
||||
* ----- Original Message -----
|
||||
* From: "Kevin Ma" <kma@google.com>
|
||||
* To: <Wilco.Dijkstra@ntlworld.com>
|
||||
* Sent: Thursday, June 23, 2011 11:44 PM
|
||||
* Subject: Fwd: sqrt routine
|
||||
* Hi Wilco,
|
||||
* I saw your sqrt routine from several web sites, including
|
||||
* http://www.finesse.demon.co.uk/steven/sqrt.html.
|
||||
* Just wonder if there's any copyright information with your Successive
|
||||
* approximation routines, or if I can freely use it for any purpose.
|
||||
* Thanks.
|
||||
* Kevin
|
||||
*/
|
||||
-------------------------------------------------------------------------------
|
||||
Files:
|
||||
modules/audio_coding/codecs/g711/main/source/g711.c
|
||||
modules/audio_coding/codecs/g711/main/source/g711.h
|
||||
|
||||
License:
|
||||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* g711.h - In line A-law and u-law conversion routines
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2001 Steve Underwood
|
||||
*
|
||||
* Despite my general liking of the GPL, I place this code in the
|
||||
* public domain for the benefit of all mankind - even the slimy
|
||||
* ones who might try to proprietize my work and use it to my
|
||||
* detriment.
|
||||
*/
|
||||
-------------------------------------------------------------------------------
|
||||
Files:
|
||||
modules/audio_coding/codecs/g722/main/source/g722_decode.c
|
||||
modules/audio_coding/codecs/g722/main/source/g722_enc_dec.h
|
||||
modules/audio_coding/codecs/g722/main/source/g722_encode.c
|
||||
|
||||
License:
|
||||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* g722_decode.c - The ITU G.722 codec, decode part.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2005 Steve Underwood
|
||||
*
|
||||
* Despite my general liking of the GPL, I place my own contributions
|
||||
* to this code in the public domain for the benefit of all mankind -
|
||||
* even the slimy ones who might try to proprietize my work and use it
|
||||
* to my detriment.
|
||||
*
|
||||
* Based in part on a single channel G.722 codec which is:
|
||||
*
|
||||
* Copyright (c) CMU 1993
|
||||
* Computer Science, Speech Group
|
||||
* Chengxiang Lu and Alex Hauptmann
|
||||
*/
|
||||
-------------------------------------------------------------------------------
|
||||
Files:
|
||||
modules/audio_coding/codecs/isac/main/source/fft.c
|
||||
|
||||
License:
|
||||
/*
|
||||
* Copyright(c)1995,97 Mark Olesen <olesen@me.QueensU.CA>
|
||||
* Queen's Univ at Kingston (Canada)
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for
|
||||
* any purpose without fee is hereby granted, provided that this
|
||||
* entire notice is included in all copies of any software which is
|
||||
* or includes a copy or modification of this software and in all
|
||||
* copies of the supporting documentation for such software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR QUEEN'S
|
||||
* UNIVERSITY AT KINGSTON MAKES ANY REPRESENTATION OR WARRANTY OF ANY
|
||||
* KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
|
||||
* FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*
|
||||
* All of which is to say that you can do what you like with this
|
||||
* source code provided you don't try to sell it as your own and you
|
||||
* include an unaltered copy of this message (including the
|
||||
* copyright).
|
||||
*
|
||||
* It is also implicitly understood that bug fixes and improvements
|
||||
* should make their way back to the general Internet community so
|
||||
* that everyone benefits.
|
||||
*/
|
||||
-------------------------------------------------------------------------------
|
||||
Files:
|
||||
modules/audio_device/mac/portaudio/pa_memorybarrier.h
|
||||
modules/audio_device/mac/portaudio/pa_ringbuffer.c
|
||||
modules/audio_device/mac/portaudio/pa_ringbuffer.h
|
||||
|
||||
License:
|
||||
/*
|
||||
* $Id: pa_memorybarrier.h 1240 2007-07-17 13:05:07Z bjornroche $
|
||||
* Portable Audio I/O Library
|
||||
* Memory barrier utilities
|
||||
*
|
||||
* Author: Bjorn Roche, XO Audio, LLC
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The text above constitutes the entire PortAudio license; however,
|
||||
* the PortAudio community also makes the following non-binding requests:
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version. It is also
|
||||
* requested that these non-binding requests be included along with the
|
||||
* license above.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: pa_ringbuffer.c 1421 2009-11-18 16:09:05Z bjornroche $
|
||||
* Portable Audio I/O Library
|
||||
* Ring Buffer utility.
|
||||
*
|
||||
* Author: Phil Burk, http://www.softsynth.com
|
||||
* modified for SMP safety on Mac OS X by Bjorn Roche
|
||||
* modified for SMP safety on Linux by Leland Lucius
|
||||
* also, allowed for const where possible
|
||||
* modified for multiple-byte-sized data elements by Sven Fischer
|
||||
*
|
||||
* Note that this is safe only for a single-thread reader and a
|
||||
* single-thread writer.
|
||||
*
|
||||
* This program uses the PortAudio Portable Audio Library.
|
||||
* For more information see: http://www.portaudio.com
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The text above constitutes the entire PortAudio license; however,
|
||||
* the PortAudio community also makes the following non-binding requests:
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version. It is also
|
||||
* requested that these non-binding requests be included along with the
|
||||
* license above.
|
||||
*/
|
||||
-------------------------------------------------------------------------------
|
||||
Files:
|
||||
common_audio/fft4g.c
|
||||
modules/audio_processing/aec/aec_rdft.c
|
||||
|
||||
License:
|
||||
/*
|
||||
* http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html
|
||||
* Copyright Takuya OOURA, 1996-2001
|
||||
*
|
||||
* You may use, copy, modify and distribute this code for any purpose (include
|
||||
* commercial use) and without fee. Please refer to this package when you modify
|
||||
* this code.
|
||||
*/
|
||||
-------------------------------------------------------------------------------
|
||||
Files:
|
||||
system_wrappers/source/condition_variable_event_win.cc
|
||||
|
||||
Source:
|
||||
http://www1.cse.wustl.edu/~schmidt/ACE-copying.html
|
||||
|
||||
License:
|
||||
Copyright and Licensing Information for ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM),
|
||||
and CoSMIC(TM)
|
||||
|
||||
ACE(TM), TAO(TM), CIAO(TM), DAnCE>(TM), and CoSMIC(TM) (henceforth referred to
|
||||
as "DOC software") are copyrighted by Douglas C. Schmidt and his research
|
||||
group at Washington University, University of California, Irvine, and
|
||||
Vanderbilt University, Copyright (c) 1993-2009, all rights reserved. Since DOC
|
||||
software is open-source, freely available software, you are free to use,
|
||||
modify, copy, and distribute--perpetually and irrevocably--the DOC software
|
||||
source code and object code produced from the source, as well as copy and
|
||||
distribute modified versions of this software. You must, however, include this
|
||||
copyright statement along with any code built using DOC software that you
|
||||
release. No copyright statement needs to be provided if you just ship binary
|
||||
executables of your software products.
|
||||
You can use DOC software in commercial and/or binary software releases and are
|
||||
under no obligation to redistribute any of your source code that is built
|
||||
using DOC software. Note, however, that you may not misappropriate the DOC
|
||||
software code, such as copyrighting it yourself or claiming authorship of the
|
||||
DOC software code, in a way that will prevent DOC software from being
|
||||
distributed freely using an open-source development model. You needn't inform
|
||||
anyone that you're using DOC software in your software, though we encourage
|
||||
you to let us know so we can promote your project in the DOC software success
|
||||
stories.
|
||||
|
||||
The ACE, TAO, CIAO, DAnCE, and CoSMIC web sites are maintained by the DOC
|
||||
Group at the Institute for Software Integrated Systems (ISIS) and the Center
|
||||
for Distributed Object Computing of Washington University, St. Louis for the
|
||||
development of open-source software as part of the open-source software
|
||||
community. Submissions are provided by the submitter ``as is'' with no
|
||||
warranties whatsoever, including any warranty of merchantability,
|
||||
noninfringement of third party intellectual property, or fitness for any
|
||||
particular purpose. In no event shall the submitter be liable for any direct,
|
||||
indirect, special, exemplary, punitive, or consequential damages, including
|
||||
without limitation, lost profits, even if advised of the possibility of such
|
||||
damages. Likewise, DOC software is provided as is with no warranties of any
|
||||
kind, including the warranties of design, merchantability, and fitness for a
|
||||
particular purpose, noninfringement, or arising from a course of dealing,
|
||||
usage or trade practice. Washington University, UC Irvine, Vanderbilt
|
||||
University, their employees, and students shall have no liability with respect
|
||||
to the infringement of copyrights, trade secrets or any patents by DOC
|
||||
software or any part thereof. Moreover, in no event will Washington
|
||||
University, UC Irvine, or Vanderbilt University, their employees, or students
|
||||
be liable for any lost revenue or profits or other special, indirect and
|
||||
consequential damages.
|
||||
|
||||
DOC software is provided with no support and without any obligation on the
|
||||
part of Washington University, UC Irvine, Vanderbilt University, their
|
||||
employees, or students to assist in its use, correction, modification, or
|
||||
enhancement. A number of companies around the world provide commercial support
|
||||
for DOC software, however. DOC software is Y2K-compliant, as long as the
|
||||
underlying OS platform is Y2K-compliant. Likewise, DOC software is compliant
|
||||
with the new US daylight savings rule passed by Congress as "The Energy Policy
|
||||
Act of 2005," which established new daylight savings times (DST) rules for the
|
||||
United States that expand DST as of March 2007. Since DOC software obtains
|
||||
time/date and calendaring information from operating systems users will not be
|
||||
affected by the new DST rules as long as they upgrade their operating systems
|
||||
accordingly.
|
||||
|
||||
The names ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), CoSMIC(TM), Washington
|
||||
University, UC Irvine, and Vanderbilt University, may not be used to endorse
|
||||
or promote products or services derived from this source without express
|
||||
written permission from Washington University, UC Irvine, or Vanderbilt
|
||||
University. This license grants no permission to call products or services
|
||||
derived from this source ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), or CoSMIC(TM),
|
||||
nor does it grant permission for the name Washington University, UC Irvine, or
|
||||
Vanderbilt University to appear in their names.
|
||||
-------------------------------------------------------------------------------
|
||||
Files:
|
||||
system_wrappers/source/set_thread_name_win.h
|
||||
|
||||
Source:
|
||||
http://msdn.microsoft.com/en-us/cc300389.aspx#P
|
||||
|
||||
License:
|
||||
This license governs use of code marked as “sample” or “example” available on
|
||||
this web site without a license agreement, as provided under the section above
|
||||
titled “NOTICE SPECIFIC TO SOFTWARE AVAILABLE ON THIS WEB SITE.” If you use
|
||||
such code (the “software”), you accept this license. If you do not accept the
|
||||
license, do not use the software.
|
||||
|
||||
1. Definitions
|
||||
|
||||
The terms “reproduce,” “reproduction,” “derivative works,” and “distribution”
|
||||
have the same meaning here as under U.S. copyright law.
|
||||
|
||||
A “contribution” is the original software, or any additions or changes to the
|
||||
software.
|
||||
|
||||
A “contributor” is any person that distributes its contribution under this
|
||||
license.
|
||||
|
||||
“Licensed patents” are a contributor’s patent claims that read directly on its
|
||||
contribution.
|
||||
|
||||
2. Grant of Rights
|
||||
|
||||
(A) Copyright Grant - Subject to the terms of this license, including the
|
||||
license conditions and limitations in section 3, each contributor grants you a
|
||||
non-exclusive, worldwide, royalty-free copyright license to reproduce its
|
||||
contribution, prepare derivative works of its contribution, and distribute its
|
||||
contribution or any derivative works that you create.
|
||||
|
||||
(B) Patent Grant - Subject to the terms of this license, including the license
|
||||
conditions and limitations in section 3, each contributor grants you a
|
||||
non-exclusive, worldwide, royalty-free license under its licensed patents to
|
||||
make, have made, use, sell, offer for sale, import, and/or otherwise dispose
|
||||
of its contribution in the software or derivative works of the contribution in
|
||||
the software.
|
||||
|
||||
3. Conditions and Limitations
|
||||
|
||||
(A) No Trademark License- This license does not grant you rights to use any
|
||||
contributors’ name, logo, or trademarks.
|
||||
|
||||
(B) If you bring a patent claim against any contributor over patents that you
|
||||
claim are infringed by the software, your patent license from such contributor
|
||||
to the software ends automatically.
|
||||
|
||||
(C) If you distribute any portion of the software, you must retain all
|
||||
copyright, patent, trademark, and attribution notices that are present in the
|
||||
software.
|
||||
|
||||
(D) If you distribute any portion of the software in source code form, you may
|
||||
do so only under this license by including a complete copy of this license
|
||||
with your distribution. If you distribute any portion of the software in
|
||||
compiled or object code form, you may only do so under a license that complies
|
||||
with this license.
|
||||
|
||||
(E) The software is licensed “as-is.” You bear the risk of using it. The
|
||||
contributors give no express warranties, guarantees or conditions. You may
|
||||
have additional consumer rights under your local laws which this license
|
||||
cannot change. To the extent permitted under your local laws, the contributors
|
||||
exclude the implied warranties of merchantability, fitness for a particular
|
||||
purpose and non-infringement.
|
||||
|
||||
(F) Platform Limitation - The licenses granted in sections 2(A) and 2(B)
|
||||
extend only to the software or derivative works that you create that run on a
|
||||
Microsoft Windows operating system product.
|
||||
-------------------------------------------------------------------------------
|
||||
Files:
|
||||
system_wrappers/source/spreadsortlib/constants.hpp
|
||||
system_wrappers/source/spreadsortlib/spreadsort.hpp
|
||||
|
||||
License:
|
||||
/*Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.*/
|
@ -1,12 +0,0 @@
|
||||
SUBDIRS = . base common_audio system_wrappers modules
|
||||
|
||||
noinst_HEADERS = common.h \
|
||||
common_types.h \
|
||||
typedefs.h
|
||||
|
||||
noinst_LTLIBRARIES = libwebrtc.la
|
||||
|
||||
libwebrtc_la_SOURCES = common_types.cc
|
||||
libwebrtc_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS)
|
||||
|
||||
EXTRA_DIST = BUILD.gn PATENTS LICENSE_THIRD_PARTY
|
335
webrtc/api/array_view.h
Normal file
335
webrtc/api/array_view.h
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
* Copyright 2015 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_ARRAY_VIEW_H_
|
||||
#define API_ARRAY_VIEW_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/type_traits.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// tl;dr: rtc::ArrayView is the same thing as gsl::span from the Guideline
|
||||
// Support Library.
|
||||
//
|
||||
// Many functions read from or write to arrays. The obvious way to do this is
|
||||
// to use two arguments, a pointer to the first element and an element count:
|
||||
//
|
||||
// bool Contains17(const int* arr, size_t size) {
|
||||
// for (size_t i = 0; i < size; ++i) {
|
||||
// if (arr[i] == 17)
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// This is flexible, since it doesn't matter how the array is stored (C array,
|
||||
// std::vector, rtc::Buffer, ...), but it's error-prone because the caller has
|
||||
// to correctly specify the array length:
|
||||
//
|
||||
// Contains17(arr, arraysize(arr)); // C array
|
||||
// Contains17(arr.data(), arr.size()); // std::vector
|
||||
// Contains17(arr, size); // pointer + size
|
||||
// ...
|
||||
//
|
||||
// It's also kind of messy to have two separate arguments for what is
|
||||
// conceptually a single thing.
|
||||
//
|
||||
// Enter rtc::ArrayView<T>. It contains a T pointer (to an array it doesn't
|
||||
// own) and a count, and supports the basic things you'd expect, such as
|
||||
// indexing and iteration. It allows us to write our function like this:
|
||||
//
|
||||
// bool Contains17(rtc::ArrayView<const int> arr) {
|
||||
// for (auto e : arr) {
|
||||
// if (e == 17)
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// And even better, because a bunch of things will implicitly convert to
|
||||
// ArrayView, we can call it like this:
|
||||
//
|
||||
// Contains17(arr); // C array
|
||||
// Contains17(arr); // std::vector
|
||||
// Contains17(rtc::ArrayView<int>(arr, size)); // pointer + size
|
||||
// Contains17(nullptr); // nullptr -> empty ArrayView
|
||||
// ...
|
||||
//
|
||||
// ArrayView<T> stores both a pointer and a size, but you may also use
|
||||
// ArrayView<T, N>, which has a size that's fixed at compile time (which means
|
||||
// it only has to store the pointer).
|
||||
//
|
||||
// One important point is that ArrayView<T> and ArrayView<const T> are
|
||||
// different types, which allow and don't allow mutation of the array elements,
|
||||
// respectively. The implicit conversions work just like you'd hope, so that
|
||||
// e.g. vector<int> will convert to either ArrayView<int> or ArrayView<const
|
||||
// int>, but const vector<int> will convert only to ArrayView<const int>.
|
||||
// (ArrayView itself can be the source type in such conversions, so
|
||||
// ArrayView<int> will convert to ArrayView<const int>.)
|
||||
//
|
||||
// Note: ArrayView is tiny (just a pointer and a count if variable-sized, just
|
||||
// a pointer if fix-sized) and trivially copyable, so it's probably cheaper to
|
||||
// pass it by value than by const reference.
|
||||
|
||||
namespace array_view_internal {
|
||||
|
||||
// Magic constant for indicating that the size of an ArrayView is variable
|
||||
// instead of fixed.
|
||||
enum : std::ptrdiff_t { kArrayViewVarSize = -4711 };
|
||||
|
||||
// Base class for ArrayViews of fixed nonzero size.
|
||||
template <typename T, std::ptrdiff_t Size>
|
||||
class ArrayViewBase {
|
||||
static_assert(Size > 0, "ArrayView size must be variable or non-negative");
|
||||
|
||||
public:
|
||||
ArrayViewBase(T* data, size_t size) : data_(data) {}
|
||||
|
||||
static constexpr size_t size() { return Size; }
|
||||
static constexpr bool empty() { return false; }
|
||||
T* data() const { return data_; }
|
||||
|
||||
protected:
|
||||
static constexpr bool fixed_size() { return true; }
|
||||
|
||||
private:
|
||||
T* data_;
|
||||
};
|
||||
|
||||
// Specialized base class for ArrayViews of fixed zero size.
|
||||
template <typename T>
|
||||
class ArrayViewBase<T, 0> {
|
||||
public:
|
||||
explicit ArrayViewBase(T* data, size_t size) {}
|
||||
|
||||
static constexpr size_t size() { return 0; }
|
||||
static constexpr bool empty() { return true; }
|
||||
T* data() const { return nullptr; }
|
||||
|
||||
protected:
|
||||
static constexpr bool fixed_size() { return true; }
|
||||
};
|
||||
|
||||
// Specialized base class for ArrayViews of variable size.
|
||||
template <typename T>
|
||||
class ArrayViewBase<T, array_view_internal::kArrayViewVarSize> {
|
||||
public:
|
||||
ArrayViewBase(T* data, size_t size)
|
||||
: data_(size == 0 ? nullptr : data), size_(size) {}
|
||||
|
||||
size_t size() const { return size_; }
|
||||
bool empty() const { return size_ == 0; }
|
||||
T* data() const { return data_; }
|
||||
|
||||
protected:
|
||||
static constexpr bool fixed_size() { return false; }
|
||||
|
||||
private:
|
||||
T* data_;
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
} // namespace array_view_internal
|
||||
|
||||
template <typename T,
|
||||
std::ptrdiff_t Size = array_view_internal::kArrayViewVarSize>
|
||||
class ArrayView final : public array_view_internal::ArrayViewBase<T, Size> {
|
||||
public:
|
||||
using value_type = T;
|
||||
using 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<Size != array_view_internal::kArrayViewVarSize &&
|
||||
HasDataAndSize<U, T>::value>::type* = nullptr>
|
||||
ArrayView(U& u) // NOLINT
|
||||
: ArrayView(u.data(), u.size()) {
|
||||
static_assert(U::size() == Size, "Sizes must match exactly");
|
||||
}
|
||||
template <
|
||||
typename U,
|
||||
typename std::enable_if<Size != array_view_internal::kArrayViewVarSize &&
|
||||
HasDataAndSize<U, T>::value>::type* = nullptr>
|
||||
ArrayView(const U& u) // NOLINT(runtime/explicit)
|
||||
: ArrayView(u.data(), u.size()) {
|
||||
static_assert(U::size() == Size, "Sizes must match exactly");
|
||||
}
|
||||
|
||||
// (Only if size is variable.) Construct an ArrayView from any type U that
|
||||
// has a size() method whose return value converts implicitly to size_t, and
|
||||
// a data() method whose return value converts implicitly to T*. In
|
||||
// particular, this means we allow conversion from ArrayView<T> to
|
||||
// ArrayView<const T>, but not the other way around. Other allowed
|
||||
// conversions include
|
||||
// ArrayView<T, N> to ArrayView<T> or ArrayView<const T>,
|
||||
// std::vector<T> to ArrayView<T> or ArrayView<const T>,
|
||||
// const std::vector<T> to ArrayView<const T>,
|
||||
// rtc::Buffer to ArrayView<uint8_t> or ArrayView<const uint8_t>, and
|
||||
// const rtc::Buffer to ArrayView<const uint8_t>.
|
||||
template <
|
||||
typename U,
|
||||
typename std::enable_if<Size == array_view_internal::kArrayViewVarSize &&
|
||||
HasDataAndSize<U, T>::value>::type* = nullptr>
|
||||
ArrayView(U& u) // NOLINT
|
||||
: ArrayView(u.data(), u.size()) {}
|
||||
template <
|
||||
typename U,
|
||||
typename std::enable_if<Size == array_view_internal::kArrayViewVarSize &&
|
||||
HasDataAndSize<U, T>::value>::type* = nullptr>
|
||||
ArrayView(const U& u) // NOLINT(runtime/explicit)
|
||||
: ArrayView(u.data(), u.size()) {}
|
||||
|
||||
// Indexing and iteration. These allow mutation even if the ArrayView is
|
||||
// const, because the ArrayView doesn't own the array. (To prevent mutation,
|
||||
// use a const element type.)
|
||||
T& operator[](size_t idx) const {
|
||||
RTC_DCHECK_LT(idx, this->size());
|
||||
RTC_DCHECK(this->data());
|
||||
return this->data()[idx];
|
||||
}
|
||||
T* begin() const { return this->data(); }
|
||||
T* end() const { return this->data() + this->size(); }
|
||||
const T* cbegin() const { return this->data(); }
|
||||
const T* cend() const { return this->data() + this->size(); }
|
||||
std::reverse_iterator<T*> rbegin() const {
|
||||
return std::make_reverse_iterator(end());
|
||||
}
|
||||
std::reverse_iterator<T*> rend() const {
|
||||
return std::make_reverse_iterator(begin());
|
||||
}
|
||||
std::reverse_iterator<const T*> crbegin() const {
|
||||
return std::make_reverse_iterator(cend());
|
||||
}
|
||||
std::reverse_iterator<const T*> crend() const {
|
||||
return std::make_reverse_iterator(cbegin());
|
||||
}
|
||||
|
||||
ArrayView<T> subview(size_t offset, size_t size) const {
|
||||
return offset < this->size()
|
||||
? ArrayView<T>(this->data() + offset,
|
||||
std::min(size, this->size() - offset))
|
||||
: ArrayView<T>();
|
||||
}
|
||||
ArrayView<T> subview(size_t offset) const {
|
||||
return subview(offset, this->size());
|
||||
}
|
||||
};
|
||||
|
||||
// Comparing two ArrayViews compares their (pointer,size) pairs; it does *not*
|
||||
// dereference the pointers.
|
||||
template <typename T, std::ptrdiff_t Size1, std::ptrdiff_t Size2>
|
||||
bool operator==(const ArrayView<T, Size1>& a, const ArrayView<T, Size2>& b) {
|
||||
return a.data() == b.data() && a.size() == b.size();
|
||||
}
|
||||
template <typename T, std::ptrdiff_t Size1, std::ptrdiff_t Size2>
|
||||
bool operator!=(const ArrayView<T, Size1>& a, const ArrayView<T, Size2>& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
// Variable-size ArrayViews are the size of two pointers; fixed-size ArrayViews
|
||||
// are the size of one pointer. (And as a special case, fixed-size ArrayViews
|
||||
// of size 0 require no storage.)
|
||||
static_assert(sizeof(ArrayView<int>) == 2 * sizeof(int*), "");
|
||||
static_assert(sizeof(ArrayView<int, 17>) == sizeof(int*), "");
|
||||
static_assert(std::is_empty<ArrayView<int, 0>>::value, "");
|
||||
|
||||
template <typename T>
|
||||
inline ArrayView<T> MakeArrayView(T* data, size_t size) {
|
||||
return ArrayView<T>(data, size);
|
||||
}
|
||||
|
||||
// Only for primitive types that have the same size and aligment.
|
||||
// Allow reinterpret cast of the array view to another primitive type of the
|
||||
// same size.
|
||||
// Template arguments order is (U, T, Size) to allow deduction of the template
|
||||
// arguments in client calls: reinterpret_array_view<target_type>(array_view).
|
||||
template <typename U, typename T, std::ptrdiff_t Size>
|
||||
inline ArrayView<U, Size> reinterpret_array_view(ArrayView<T, Size> view) {
|
||||
static_assert(sizeof(U) == sizeof(T) && alignof(U) == alignof(T),
|
||||
"ArrayView reinterpret_cast is only supported for casting "
|
||||
"between views that represent the same chunk of memory.");
|
||||
static_assert(
|
||||
std::is_fundamental<T>::value && std::is_fundamental<U>::value,
|
||||
"ArrayView reinterpret_cast is only supported for casting between "
|
||||
"fundamental types.");
|
||||
return ArrayView<U, Size>(reinterpret_cast<U*>(view.data()), view.size());
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // API_ARRAY_VIEW_H_
|
235
webrtc/api/audio/audio_frame.cc
Normal file
235
webrtc/api/audio/audio_frame.cc
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio/audio_frame.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "api/audio/audio_view.h"
|
||||
#include "api/audio/channel_layout.h"
|
||||
#include "api/rtp_packet_infos.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/time_utils.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
AudioFrame::AudioFrame() {
|
||||
// Visual Studio doesn't like this in the class definition.
|
||||
static_assert(sizeof(data_) == kMaxDataSizeBytes, "kMaxDataSizeBytes");
|
||||
}
|
||||
|
||||
AudioFrame::AudioFrame(int sample_rate_hz,
|
||||
size_t num_channels,
|
||||
ChannelLayout layout /*= CHANNEL_LAYOUT_UNSUPPORTED*/)
|
||||
: samples_per_channel_(SampleRateToDefaultChannelSize(sample_rate_hz)),
|
||||
sample_rate_hz_(sample_rate_hz),
|
||||
num_channels_(num_channels),
|
||||
channel_layout_(layout == CHANNEL_LAYOUT_UNSUPPORTED
|
||||
? GuessChannelLayout(num_channels)
|
||||
: layout) {
|
||||
RTC_DCHECK_LE(num_channels_, kMaxConcurrentChannels);
|
||||
RTC_DCHECK_GT(sample_rate_hz_, 0);
|
||||
RTC_DCHECK_GT(samples_per_channel_, 0u);
|
||||
}
|
||||
|
||||
void AudioFrame::Reset() {
|
||||
ResetWithoutMuting();
|
||||
muted_ = true;
|
||||
}
|
||||
|
||||
void AudioFrame::ResetWithoutMuting() {
|
||||
// TODO(wu): Zero is a valid value for `timestamp_`. We should initialize
|
||||
// to an invalid value, or add a new member to indicate invalidity.
|
||||
timestamp_ = 0;
|
||||
elapsed_time_ms_ = -1;
|
||||
ntp_time_ms_ = -1;
|
||||
samples_per_channel_ = 0;
|
||||
sample_rate_hz_ = 0;
|
||||
num_channels_ = 0;
|
||||
channel_layout_ = CHANNEL_LAYOUT_NONE;
|
||||
speech_type_ = kUndefined;
|
||||
vad_activity_ = kVadUnknown;
|
||||
profile_timestamp_ms_ = 0;
|
||||
packet_infos_ = RtpPacketInfos();
|
||||
absolute_capture_timestamp_ms_ = std::nullopt;
|
||||
}
|
||||
|
||||
void AudioFrame::UpdateFrame(uint32_t timestamp,
|
||||
const int16_t* data,
|
||||
size_t samples_per_channel,
|
||||
int sample_rate_hz,
|
||||
SpeechType speech_type,
|
||||
VADActivity vad_activity,
|
||||
size_t num_channels) {
|
||||
RTC_CHECK_LE(num_channels, kMaxConcurrentChannels);
|
||||
timestamp_ = timestamp;
|
||||
samples_per_channel_ = samples_per_channel;
|
||||
sample_rate_hz_ = sample_rate_hz;
|
||||
speech_type_ = speech_type;
|
||||
vad_activity_ = vad_activity;
|
||||
num_channels_ = num_channels;
|
||||
channel_layout_ = GuessChannelLayout(num_channels);
|
||||
if (channel_layout_ != CHANNEL_LAYOUT_UNSUPPORTED) {
|
||||
RTC_DCHECK_EQ(num_channels, ChannelLayoutToChannelCount(channel_layout_));
|
||||
}
|
||||
|
||||
const size_t length = samples_per_channel * num_channels;
|
||||
RTC_CHECK_LE(length, data_.size());
|
||||
if (data != nullptr) {
|
||||
memcpy(data_.data(), data, sizeof(int16_t) * length);
|
||||
muted_ = false;
|
||||
} else {
|
||||
muted_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioFrame::CopyFrom(const AudioFrame& src) {
|
||||
if (this == &src)
|
||||
return;
|
||||
|
||||
if (muted_ && !src.muted()) {
|
||||
// TODO: bugs.webrtc.org/5647 - Since the default value for `muted_` is
|
||||
// false and `data_` may still be uninitialized (because we don't initialize
|
||||
// data_ as part of construction), we clear the full buffer here before
|
||||
// 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.
|
||||
ClearSamples(data_);
|
||||
}
|
||||
|
||||
timestamp_ = src.timestamp_;
|
||||
elapsed_time_ms_ = src.elapsed_time_ms_;
|
||||
ntp_time_ms_ = src.ntp_time_ms_;
|
||||
packet_infos_ = src.packet_infos_;
|
||||
muted_ = src.muted();
|
||||
samples_per_channel_ = src.samples_per_channel_;
|
||||
sample_rate_hz_ = src.sample_rate_hz_;
|
||||
speech_type_ = src.speech_type_;
|
||||
vad_activity_ = src.vad_activity_;
|
||||
num_channels_ = src.num_channels_;
|
||||
channel_layout_ = src.channel_layout_;
|
||||
absolute_capture_timestamp_ms_ = src.absolute_capture_timestamp_ms();
|
||||
|
||||
auto data = src.data_view();
|
||||
RTC_CHECK_LE(data.size(), data_.size());
|
||||
if (!muted_ && !data.empty()) {
|
||||
memcpy(&data_[0], &data[0], sizeof(int16_t) * data.size());
|
||||
}
|
||||
}
|
||||
|
||||
void AudioFrame::UpdateProfileTimeStamp() {
|
||||
profile_timestamp_ms_ = rtc::TimeMillis();
|
||||
}
|
||||
|
||||
int64_t AudioFrame::ElapsedProfileTimeMs() const {
|
||||
if (profile_timestamp_ms_ == 0) {
|
||||
// Profiling has not been activated.
|
||||
return -1;
|
||||
}
|
||||
return rtc::TimeSince(profile_timestamp_ms_);
|
||||
}
|
||||
|
||||
const int16_t* AudioFrame::data() const {
|
||||
return muted_ ? 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. Since `data_view()` returns an InterleavedView<> (which internally
|
||||
// uses rtc::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_);
|
||||
}
|
||||
|
||||
int16_t* AudioFrame::mutable_data() {
|
||||
// TODO: bugs.webrtc.org/5647 - Can we skip zeroing the buffer?
|
||||
// Consider instead if we should rather zero the buffer when `muted_` is set
|
||||
// to `true`.
|
||||
if (muted_) {
|
||||
ClearSamples(data_);
|
||||
muted_ = false;
|
||||
}
|
||||
return &data_[0];
|
||||
}
|
||||
|
||||
InterleavedView<int16_t> AudioFrame::mutable_data(size_t samples_per_channel,
|
||||
size_t num_channels) {
|
||||
const size_t total_samples = samples_per_channel * num_channels;
|
||||
RTC_CHECK_LE(total_samples, data_.size());
|
||||
RTC_CHECK_LE(num_channels, kMaxConcurrentChannels);
|
||||
// Sanity check for valid argument values during development.
|
||||
// If `samples_per_channel` is < `num_channels` but larger than 0,
|
||||
// then chances are the order of arguments is incorrect.
|
||||
RTC_DCHECK((samples_per_channel == 0 && num_channels == 0) ||
|
||||
num_channels <= samples_per_channel)
|
||||
<< "samples_per_channel=" << samples_per_channel
|
||||
<< "num_channels=" << num_channels;
|
||||
|
||||
// TODO: bugs.webrtc.org/5647 - Can we skip zeroing the buffer?
|
||||
// Consider instead if we should rather zero the whole buffer when `muted_` is
|
||||
// set to `true`.
|
||||
if (muted_) {
|
||||
ClearSamples(data_, total_samples);
|
||||
muted_ = false;
|
||||
}
|
||||
samples_per_channel_ = samples_per_channel;
|
||||
num_channels_ = num_channels;
|
||||
return InterleavedView<int16_t>(&data_[0], samples_per_channel, num_channels);
|
||||
}
|
||||
|
||||
void AudioFrame::Mute() {
|
||||
muted_ = true;
|
||||
}
|
||||
|
||||
bool AudioFrame::muted() const {
|
||||
return muted_;
|
||||
}
|
||||
|
||||
void AudioFrame::SetLayoutAndNumChannels(ChannelLayout layout,
|
||||
size_t num_channels) {
|
||||
channel_layout_ = layout;
|
||||
num_channels_ = num_channels;
|
||||
#if RTC_DCHECK_IS_ON
|
||||
// Do a sanity check that the layout and num_channels match.
|
||||
// If this lookup yield 0u, then the layout is likely CHANNEL_LAYOUT_DISCRETE.
|
||||
auto expected_num_channels = ChannelLayoutToChannelCount(layout);
|
||||
if (expected_num_channels) { // If expected_num_channels is 0
|
||||
RTC_DCHECK_EQ(expected_num_channels, num_channels_);
|
||||
}
|
||||
#endif
|
||||
RTC_CHECK_LE(samples_per_channel_ * num_channels_, data_.size());
|
||||
}
|
||||
|
||||
void AudioFrame::SetSampleRateAndChannelSize(int sample_rate) {
|
||||
sample_rate_hz_ = sample_rate;
|
||||
// We could call `AudioProcessing::GetFrameSize()` here, but that requires
|
||||
// adding a dependency on the ":audio_processing" build target, which can
|
||||
// complicate the dependency tree. Some refactoring is probably in order to
|
||||
// get some consistency around this since there are many places across the
|
||||
// code that assume this default buffer size.
|
||||
samples_per_channel_ = SampleRateToDefaultChannelSize(sample_rate_hz_);
|
||||
}
|
||||
|
||||
// static
|
||||
rtc::ArrayView<const int16_t> AudioFrame::zeroed_data() {
|
||||
static int16_t* null_data = new int16_t[kMaxDataSizeSamples]();
|
||||
return rtc::ArrayView<const int16_t>(null_data, kMaxDataSizeSamples);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
230
webrtc/api/audio/audio_frame.h
Normal file
230
webrtc/api/audio/audio_frame.h
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_AUDIO_FRAME_H_
|
||||
#define API_AUDIO_AUDIO_FRAME_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "api/audio/audio_view.h"
|
||||
#include "api/audio/channel_layout.h"
|
||||
#include "api/rtp_packet_infos.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Default webrtc buffer size in milliseconds.
|
||||
constexpr size_t kDefaultAudioBufferLengthMs = 10u;
|
||||
|
||||
// Default total number of audio buffers per second based on the default length.
|
||||
constexpr size_t kDefaultAudioBuffersPerSec =
|
||||
1000u / kDefaultAudioBufferLengthMs;
|
||||
|
||||
// Returns the number of samples a buffer needs to hold for ~10ms of a single
|
||||
// audio channel at a given sample rate.
|
||||
// See also `AudioProcessing::GetFrameSize()`.
|
||||
inline size_t SampleRateToDefaultChannelSize(size_t sample_rate) {
|
||||
// Basic sanity check. 192kHz is the highest supported input sample rate.
|
||||
RTC_DCHECK_LE(sample_rate, 192000);
|
||||
return sample_rate / kDefaultAudioBuffersPerSec;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* This class holds up to 120 ms of super-wideband (32 kHz) stereo audio. It
|
||||
* allows for adding and subtracting frames while keeping track of the resulting
|
||||
* states.
|
||||
*
|
||||
* Notes
|
||||
* - This is a de-facto api, not designed for external use. The AudioFrame class
|
||||
* is in need of overhaul or even replacement, and anyone depending on it
|
||||
* should be prepared for that.
|
||||
* - The total number of samples is samples_per_channel_ * num_channels_.
|
||||
* - Stereo data is interleaved starting with the left channel.
|
||||
*/
|
||||
class AudioFrame {
|
||||
public:
|
||||
// Using constexpr here causes linker errors unless the variable also has an
|
||||
// out-of-class definition, which is impractical in this header-only class.
|
||||
// (This makes no sense because it compiles as an enum value, which we most
|
||||
// certainly cannot take the address of, just fine.) C++17 introduces inline
|
||||
// variables which should allow us to switch to constexpr and keep this a
|
||||
// header-only class.
|
||||
enum : size_t {
|
||||
// Stereo, 32 kHz, 120 ms (2 * 32 * 120)
|
||||
// Stereo, 192 kHz, 20 ms (2 * 192 * 20)
|
||||
kMaxDataSizeSamples = 7680,
|
||||
kMaxDataSizeBytes = kMaxDataSizeSamples * sizeof(int16_t),
|
||||
};
|
||||
|
||||
enum VADActivity { kVadActive = 0, kVadPassive = 1, kVadUnknown = 2 };
|
||||
enum SpeechType {
|
||||
kNormalSpeech = 0,
|
||||
kPLC = 1,
|
||||
kCNG = 2,
|
||||
kPLCCNG = 3,
|
||||
kCodecPLC = 5,
|
||||
kUndefined = 4
|
||||
};
|
||||
|
||||
AudioFrame();
|
||||
|
||||
// Construct an audio frame with frame length properties and channel
|
||||
// information. `samples_per_channel()` will be initialized to a 10ms buffer
|
||||
// size and if `layout` is not specified (default value of
|
||||
// CHANNEL_LAYOUT_UNSUPPORTED is set), then the channel layout is derived
|
||||
// (guessed) from `num_channels`.
|
||||
AudioFrame(int sample_rate_hz,
|
||||
size_t num_channels,
|
||||
ChannelLayout layout = CHANNEL_LAYOUT_UNSUPPORTED);
|
||||
|
||||
AudioFrame(const AudioFrame&) = delete;
|
||||
AudioFrame& operator=(const AudioFrame&) = delete;
|
||||
|
||||
// Resets all members to their default state.
|
||||
void Reset();
|
||||
// Same as Reset(), but leaves mute state unchanged. Muting a frame requires
|
||||
// the buffer to be zeroed on the next call to mutable_data(). Callers
|
||||
// intending to write to the buffer immediately after Reset() can instead use
|
||||
// ResetWithoutMuting() to skip this wasteful zeroing.
|
||||
void ResetWithoutMuting();
|
||||
|
||||
// TODO: b/335805780 - Accept InterleavedView.
|
||||
void UpdateFrame(uint32_t timestamp,
|
||||
const int16_t* data,
|
||||
size_t samples_per_channel,
|
||||
int sample_rate_hz,
|
||||
SpeechType speech_type,
|
||||
VADActivity vad_activity,
|
||||
size_t num_channels = 1);
|
||||
|
||||
void CopyFrom(const AudioFrame& src);
|
||||
|
||||
// Sets a wall-time clock timestamp in milliseconds to be used for profiling
|
||||
// of time between two points in the audio chain.
|
||||
// Example:
|
||||
// t0: UpdateProfileTimeStamp()
|
||||
// t1: ElapsedProfileTimeMs() => t1 - t0 [msec]
|
||||
void UpdateProfileTimeStamp();
|
||||
// Returns the time difference between now and when UpdateProfileTimeStamp()
|
||||
// was last called. Returns -1 if UpdateProfileTimeStamp() has not yet been
|
||||
// called.
|
||||
int64_t ElapsedProfileTimeMs() const;
|
||||
|
||||
// data() returns a zeroed static buffer if the frame is muted.
|
||||
// TODO: b/335805780 - Return InterleavedView.
|
||||
const int16_t* data() const;
|
||||
|
||||
// Returns a read-only view of all the valid samples held by the AudioFrame.
|
||||
// For a muted AudioFrame, the samples will all be 0.
|
||||
InterleavedView<const int16_t> data_view() const;
|
||||
|
||||
// mutable_frame() always returns a non-static buffer; the first call to
|
||||
// mutable_frame() zeros the buffer and marks the frame as unmuted.
|
||||
// TODO: b/335805780 - Return an InterleavedView.
|
||||
int16_t* mutable_data();
|
||||
|
||||
// Grants write access to the audio buffer. The size of the returned writable
|
||||
// view is determined by the `samples_per_channel` and `num_channels`
|
||||
// dimensions which the function checks for correctness and stores in the
|
||||
// internal member variables; `samples_per_channel()` and `num_channels()`
|
||||
// respectively.
|
||||
// If the state is currently muted, the returned view will be zeroed out.
|
||||
InterleavedView<int16_t> mutable_data(size_t samples_per_channel,
|
||||
size_t num_channels);
|
||||
|
||||
// Prefer to mute frames using AudioFrameOperations::Mute.
|
||||
void Mute();
|
||||
// Frame is muted by default.
|
||||
bool muted() const;
|
||||
|
||||
size_t max_16bit_samples() const { return data_.size(); }
|
||||
size_t samples_per_channel() const { return samples_per_channel_; }
|
||||
size_t num_channels() const { return num_channels_; }
|
||||
|
||||
ChannelLayout channel_layout() const { return channel_layout_; }
|
||||
// Sets the `channel_layout` property as well as `num_channels`.
|
||||
void SetLayoutAndNumChannels(ChannelLayout layout, size_t num_channels);
|
||||
|
||||
int sample_rate_hz() const { return sample_rate_hz_; }
|
||||
|
||||
void set_absolute_capture_timestamp_ms(
|
||||
int64_t absolute_capture_time_stamp_ms) {
|
||||
absolute_capture_timestamp_ms_ = absolute_capture_time_stamp_ms;
|
||||
}
|
||||
|
||||
std::optional<int64_t> absolute_capture_timestamp_ms() const {
|
||||
return absolute_capture_timestamp_ms_;
|
||||
}
|
||||
|
||||
// Sets the sample_rate_hz and samples_per_channel properties based on a
|
||||
// given sample rate and calculates a default 10ms samples_per_channel value.
|
||||
void SetSampleRateAndChannelSize(int sample_rate);
|
||||
|
||||
// RTP timestamp of the first sample in the AudioFrame.
|
||||
uint32_t timestamp_ = 0;
|
||||
// Time since the first frame in milliseconds.
|
||||
// -1 represents an uninitialized value.
|
||||
int64_t elapsed_time_ms_ = -1;
|
||||
// NTP time of the estimated capture time in local timebase in milliseconds.
|
||||
// -1 represents an uninitialized value.
|
||||
int64_t ntp_time_ms_ = -1;
|
||||
size_t samples_per_channel_ = 0;
|
||||
int sample_rate_hz_ = 0;
|
||||
size_t num_channels_ = 0;
|
||||
SpeechType speech_type_ = kUndefined;
|
||||
VADActivity vad_activity_ = kVadUnknown;
|
||||
// Monotonically increasing timestamp intended for profiling of audio frames.
|
||||
// Typically used for measuring elapsed time between two different points in
|
||||
// the audio path. No lock is used to save resources and we are thread safe
|
||||
// by design.
|
||||
// TODO(nisse@webrtc.org): consider using std::optional.
|
||||
int64_t profile_timestamp_ms_ = 0;
|
||||
|
||||
// Information about packets used to assemble this audio frame. This is needed
|
||||
// by `SourceTracker` when the frame is delivered to the RTCRtpReceiver's
|
||||
// MediaStreamTrack, in order to implement getContributingSources(). See:
|
||||
// https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-getcontributingsources
|
||||
//
|
||||
// TODO(bugs.webrtc.org/10757):
|
||||
// Note that this information might not be fully accurate since we currently
|
||||
// don't have a proper way to track it across the audio sync buffer. The
|
||||
// sync buffer is the small sample-holding buffer located after the audio
|
||||
// decoder and before where samples are assembled into output frames.
|
||||
//
|
||||
// `RtpPacketInfos` may also be empty if the audio samples did not come from
|
||||
// RTP packets. E.g. if the audio were locally generated by packet loss
|
||||
// concealment, comfort noise generation, etc.
|
||||
RtpPacketInfos packet_infos_;
|
||||
|
||||
private:
|
||||
// A permanently zeroed out buffer to represent muted frames. This is a
|
||||
// header-only class, so the only way to avoid creating a separate zeroed
|
||||
// buffer per translation unit is to wrap a static in an inline function.
|
||||
static rtc::ArrayView<const int16_t> zeroed_data();
|
||||
|
||||
std::array<int16_t, kMaxDataSizeSamples> data_;
|
||||
bool muted_ = true;
|
||||
ChannelLayout channel_layout_ = CHANNEL_LAYOUT_NONE;
|
||||
|
||||
// Absolute capture timestamp when this audio frame was originally captured.
|
||||
// This is only valid for audio frames captured on this machine. The absolute
|
||||
// capture timestamp of a received frame is found in `packet_infos_`.
|
||||
// This timestamp MUST be based on the same clock as rtc::TimeMillis().
|
||||
std::optional<int64_t> absolute_capture_timestamp_ms_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_AUDIO_FRAME_H_
|
211
webrtc/api/audio/audio_processing.cc
Normal file
211
webrtc/api/audio/audio_processing.cc
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio/audio_processing.h"
|
||||
#include <string>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
using Agc1Config = AudioProcessing::Config::GainController1;
|
||||
using Agc2Config = AudioProcessing::Config::GainController2;
|
||||
|
||||
std::string NoiseSuppressionLevelToString(
|
||||
const AudioProcessing::Config::NoiseSuppression::Level& level) {
|
||||
switch (level) {
|
||||
case AudioProcessing::Config::NoiseSuppression::Level::kLow:
|
||||
return "Low";
|
||||
case AudioProcessing::Config::NoiseSuppression::Level::kModerate:
|
||||
return "Moderate";
|
||||
case AudioProcessing::Config::NoiseSuppression::Level::kHigh:
|
||||
return "High";
|
||||
case AudioProcessing::Config::NoiseSuppression::Level::kVeryHigh:
|
||||
return "VeryHigh";
|
||||
}
|
||||
RTC_CHECK_NOTREACHED();
|
||||
}
|
||||
|
||||
std::string GainController1ModeToString(const Agc1Config::Mode& mode) {
|
||||
switch (mode) {
|
||||
case Agc1Config::Mode::kAdaptiveAnalog:
|
||||
return "AdaptiveAnalog";
|
||||
case Agc1Config::Mode::kAdaptiveDigital:
|
||||
return "AdaptiveDigital";
|
||||
case Agc1Config::Mode::kFixedDigital:
|
||||
return "FixedDigital";
|
||||
}
|
||||
RTC_CHECK_NOTREACHED();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
constexpr int AudioProcessing::kNativeSampleRatesHz[];
|
||||
|
||||
void CustomProcessing::SetRuntimeSetting(
|
||||
AudioProcessing::RuntimeSetting setting) {}
|
||||
|
||||
bool Agc1Config::operator==(const Agc1Config& rhs) const {
|
||||
const auto& analog_lhs = analog_gain_controller;
|
||||
const auto& analog_rhs = rhs.analog_gain_controller;
|
||||
return enabled == rhs.enabled && mode == rhs.mode &&
|
||||
target_level_dbfs == rhs.target_level_dbfs &&
|
||||
compression_gain_db == rhs.compression_gain_db &&
|
||||
enable_limiter == rhs.enable_limiter &&
|
||||
analog_lhs.enabled == analog_rhs.enabled &&
|
||||
analog_lhs.startup_min_volume == analog_rhs.startup_min_volume &&
|
||||
analog_lhs.clipped_level_min == analog_rhs.clipped_level_min &&
|
||||
analog_lhs.enable_digital_adaptive ==
|
||||
analog_rhs.enable_digital_adaptive &&
|
||||
analog_lhs.clipped_level_step == analog_rhs.clipped_level_step &&
|
||||
analog_lhs.clipped_ratio_threshold ==
|
||||
analog_rhs.clipped_ratio_threshold &&
|
||||
analog_lhs.clipped_wait_frames == analog_rhs.clipped_wait_frames &&
|
||||
analog_lhs.clipping_predictor.mode ==
|
||||
analog_rhs.clipping_predictor.mode &&
|
||||
analog_lhs.clipping_predictor.window_length ==
|
||||
analog_rhs.clipping_predictor.window_length &&
|
||||
analog_lhs.clipping_predictor.reference_window_length ==
|
||||
analog_rhs.clipping_predictor.reference_window_length &&
|
||||
analog_lhs.clipping_predictor.reference_window_delay ==
|
||||
analog_rhs.clipping_predictor.reference_window_delay &&
|
||||
analog_lhs.clipping_predictor.clipping_threshold ==
|
||||
analog_rhs.clipping_predictor.clipping_threshold &&
|
||||
analog_lhs.clipping_predictor.crest_factor_margin ==
|
||||
analog_rhs.clipping_predictor.crest_factor_margin &&
|
||||
analog_lhs.clipping_predictor.use_predicted_step ==
|
||||
analog_rhs.clipping_predictor.use_predicted_step;
|
||||
}
|
||||
|
||||
bool Agc2Config::AdaptiveDigital::operator==(
|
||||
const Agc2Config::AdaptiveDigital& rhs) const {
|
||||
return enabled == rhs.enabled && headroom_db == rhs.headroom_db &&
|
||||
max_gain_db == rhs.max_gain_db &&
|
||||
initial_gain_db == rhs.initial_gain_db &&
|
||||
max_gain_change_db_per_second == rhs.max_gain_change_db_per_second &&
|
||||
max_output_noise_level_dbfs == rhs.max_output_noise_level_dbfs;
|
||||
}
|
||||
|
||||
bool Agc2Config::InputVolumeController::operator==(
|
||||
const Agc2Config::InputVolumeController& rhs) const {
|
||||
return enabled == rhs.enabled;
|
||||
}
|
||||
|
||||
bool Agc2Config::operator==(const Agc2Config& rhs) const {
|
||||
return enabled == rhs.enabled &&
|
||||
fixed_digital.gain_db == rhs.fixed_digital.gain_db &&
|
||||
adaptive_digital == rhs.adaptive_digital &&
|
||||
input_volume_controller == rhs.input_volume_controller;
|
||||
}
|
||||
|
||||
bool AudioProcessing::Config::CaptureLevelAdjustment::operator==(
|
||||
const AudioProcessing::Config::CaptureLevelAdjustment& rhs) const {
|
||||
return enabled == rhs.enabled && pre_gain_factor == rhs.pre_gain_factor &&
|
||||
post_gain_factor == rhs.post_gain_factor &&
|
||||
analog_mic_gain_emulation == rhs.analog_mic_gain_emulation;
|
||||
}
|
||||
|
||||
bool AudioProcessing::Config::CaptureLevelAdjustment::AnalogMicGainEmulation::
|
||||
operator==(const AudioProcessing::Config::CaptureLevelAdjustment::
|
||||
AnalogMicGainEmulation& rhs) const {
|
||||
return enabled == rhs.enabled && initial_level == rhs.initial_level;
|
||||
}
|
||||
|
||||
std::string AudioProcessing::Config::ToString() const {
|
||||
char buf[2048];
|
||||
rtc::SimpleStringBuilder builder(buf);
|
||||
builder << "AudioProcessing::Config{ "
|
||||
"pipeline: { "
|
||||
"maximum_internal_processing_rate: "
|
||||
<< pipeline.maximum_internal_processing_rate
|
||||
<< ", multi_channel_render: " << pipeline.multi_channel_render
|
||||
<< ", multi_channel_capture: " << pipeline.multi_channel_capture
|
||||
<< " }, pre_amplifier: { enabled: " << pre_amplifier.enabled
|
||||
<< ", fixed_gain_factor: " << pre_amplifier.fixed_gain_factor
|
||||
<< " },capture_level_adjustment: { enabled: "
|
||||
<< capture_level_adjustment.enabled
|
||||
<< ", pre_gain_factor: " << capture_level_adjustment.pre_gain_factor
|
||||
<< ", post_gain_factor: " << capture_level_adjustment.post_gain_factor
|
||||
<< ", analog_mic_gain_emulation: { enabled: "
|
||||
<< capture_level_adjustment.analog_mic_gain_emulation.enabled
|
||||
<< ", initial_level: "
|
||||
<< 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
|
||||
<< ", level: "
|
||||
<< NoiseSuppressionLevelToString(noise_suppression.level)
|
||||
<< " }, transient_suppression: { enabled: "
|
||||
<< transient_suppression.enabled
|
||||
<< " }, gain_controller1: { enabled: " << gain_controller1.enabled
|
||||
<< ", mode: " << GainController1ModeToString(gain_controller1.mode)
|
||||
<< ", target_level_dbfs: " << gain_controller1.target_level_dbfs
|
||||
<< ", compression_gain_db: " << gain_controller1.compression_gain_db
|
||||
<< ", enable_limiter: " << gain_controller1.enable_limiter
|
||||
<< ", analog_gain_controller { enabled: "
|
||||
<< gain_controller1.analog_gain_controller.enabled
|
||||
<< ", startup_min_volume: "
|
||||
<< gain_controller1.analog_gain_controller.startup_min_volume
|
||||
<< ", clipped_level_min: "
|
||||
<< gain_controller1.analog_gain_controller.clipped_level_min
|
||||
<< ", enable_digital_adaptive: "
|
||||
<< gain_controller1.analog_gain_controller.enable_digital_adaptive
|
||||
<< ", clipped_level_step: "
|
||||
<< gain_controller1.analog_gain_controller.clipped_level_step
|
||||
<< ", clipped_ratio_threshold: "
|
||||
<< gain_controller1.analog_gain_controller.clipped_ratio_threshold
|
||||
<< ", clipped_wait_frames: "
|
||||
<< gain_controller1.analog_gain_controller.clipped_wait_frames
|
||||
<< ", clipping_predictor: { enabled: "
|
||||
<< gain_controller1.analog_gain_controller.clipping_predictor.enabled
|
||||
<< ", mode: "
|
||||
<< gain_controller1.analog_gain_controller.clipping_predictor.mode
|
||||
<< ", window_length: "
|
||||
<< gain_controller1.analog_gain_controller.clipping_predictor
|
||||
.window_length
|
||||
<< ", reference_window_length: "
|
||||
<< gain_controller1.analog_gain_controller.clipping_predictor
|
||||
.reference_window_length
|
||||
<< ", reference_window_delay: "
|
||||
<< gain_controller1.analog_gain_controller.clipping_predictor
|
||||
.reference_window_delay
|
||||
<< ", clipping_threshold: "
|
||||
<< gain_controller1.analog_gain_controller.clipping_predictor
|
||||
.clipping_threshold
|
||||
<< ", crest_factor_margin: "
|
||||
<< gain_controller1.analog_gain_controller.clipping_predictor
|
||||
.crest_factor_margin
|
||||
<< ", use_predicted_step: "
|
||||
<< gain_controller1.analog_gain_controller.clipping_predictor
|
||||
.use_predicted_step
|
||||
<< " }}}, gain_controller2: { enabled: " << gain_controller2.enabled
|
||||
<< ", fixed_digital: { gain_db: "
|
||||
<< gain_controller2.fixed_digital.gain_db
|
||||
<< " }, adaptive_digital: { enabled: "
|
||||
<< gain_controller2.adaptive_digital.enabled
|
||||
<< ", headroom_db: " << gain_controller2.adaptive_digital.headroom_db
|
||||
<< ", max_gain_db: " << gain_controller2.adaptive_digital.max_gain_db
|
||||
<< ", initial_gain_db: "
|
||||
<< gain_controller2.adaptive_digital.initial_gain_db
|
||||
<< ", max_gain_change_db_per_second: "
|
||||
<< gain_controller2.adaptive_digital.max_gain_change_db_per_second
|
||||
<< ", max_output_noise_level_dbfs: "
|
||||
<< gain_controller2.adaptive_digital.max_output_noise_level_dbfs
|
||||
<< " }, input_volume_control : { enabled "
|
||||
<< gain_controller2.input_volume_controller.enabled << "}}";
|
||||
return builder.str();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
944
webrtc/api/audio/audio_processing.h
Normal file
944
webrtc/api/audio/audio_processing.h
Normal file
@ -0,0 +1,944 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_AUDIO_PROCESSING_H_
|
||||
#define API_AUDIO_AUDIO_PROCESSING_H_
|
||||
|
||||
// MSVC++ requires this to be set before any other includes to get M_PI.
|
||||
#ifndef _USE_MATH_DEFINES
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stddef.h> // size_t
|
||||
#include <stdio.h> // FILE
|
||||
#include <string.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#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/ref_count.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "api/task_queue/task_queue_base.h"
|
||||
#include "rtc_base/arraysize.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AecDump;
|
||||
class AudioBuffer;
|
||||
|
||||
class StreamConfig;
|
||||
class ProcessingConfig;
|
||||
|
||||
class EchoDetector;
|
||||
|
||||
// The Audio Processing Module (APM) provides a collection of voice processing
|
||||
// components designed for real-time communications software.
|
||||
//
|
||||
// APM operates on two audio streams on a frame-by-frame basis. Frames of the
|
||||
// primary stream, on which all processing is applied, are passed to
|
||||
// `ProcessStream()`. Frames of the reverse direction stream are passed to
|
||||
// `ProcessReverseStream()`. On the client-side, this will typically be the
|
||||
// near-end (capture) and far-end (render) streams, respectively. APM should be
|
||||
// placed in the signal chain as close to the audio hardware abstraction layer
|
||||
// (HAL) as possible.
|
||||
//
|
||||
// On the server-side, the reverse stream will normally not be used, with
|
||||
// processing occurring on each incoming stream.
|
||||
//
|
||||
// Component interfaces follow a similar pattern and are accessed through
|
||||
// corresponding getters in APM. All components are disabled at create-time,
|
||||
// with default settings that are recommended for most situations. New settings
|
||||
// can be applied without enabling a component. Enabling a component triggers
|
||||
// memory allocation and initialization to allow it to start processing the
|
||||
// streams.
|
||||
//
|
||||
// Thread safety is provided with the following assumptions to reduce locking
|
||||
// overhead:
|
||||
// 1. The stream getters and setters are called from the same thread as
|
||||
// ProcessStream(). More precisely, stream functions are never called
|
||||
// concurrently with ProcessStream().
|
||||
// 2. Parameter getters are never called concurrently with the corresponding
|
||||
// setter.
|
||||
//
|
||||
// APM accepts only linear PCM audio data in chunks of ~10 ms (see
|
||||
// AudioProcessing::GetFrameSize() for details) and sample rates ranging from
|
||||
// 8000 Hz to 384000 Hz. The int16 interfaces use interleaved data, while the
|
||||
// float interfaces use deinterleaved data.
|
||||
//
|
||||
// Usage example, omitting error checking:
|
||||
// rtc::scoped_refptr<AudioProcessing> apm = AudioProcessingBuilder().Create();
|
||||
//
|
||||
// AudioProcessing::Config config;
|
||||
// config.echo_canceller.enabled = true;
|
||||
// config.echo_canceller.mobile_mode = false;
|
||||
//
|
||||
// config.gain_controller1.enabled = true;
|
||||
// config.gain_controller1.mode =
|
||||
// AudioProcessing::Config::GainController1::kAdaptiveAnalog;
|
||||
// config.gain_controller1.analog_level_minimum = 0;
|
||||
// config.gain_controller1.analog_level_maximum = 255;
|
||||
//
|
||||
// config.gain_controller2.enabled = true;
|
||||
//
|
||||
// config.high_pass_filter.enabled = true;
|
||||
//
|
||||
// apm->ApplyConfig(config)
|
||||
//
|
||||
// // Start a voice call...
|
||||
//
|
||||
// // ... Render frame arrives bound for the audio HAL ...
|
||||
// apm->ProcessReverseStream(render_frame);
|
||||
//
|
||||
// // ... Capture frame arrives from the audio HAL ...
|
||||
// // Call required set_stream_ functions.
|
||||
// apm->set_stream_delay_ms(delay_ms);
|
||||
// apm->set_stream_analog_level(analog_level);
|
||||
//
|
||||
// apm->ProcessStream(capture_frame);
|
||||
//
|
||||
// // Call required stream_ functions.
|
||||
// analog_level = apm->recommended_stream_analog_level();
|
||||
// has_voice = apm->stream_has_voice();
|
||||
//
|
||||
// // Repeat render and capture processing for the duration of the call...
|
||||
// // Start a new call...
|
||||
// apm->Initialize();
|
||||
//
|
||||
// // Close the application...
|
||||
// apm.reset();
|
||||
//
|
||||
class RTC_EXPORT AudioProcessing : public RefCountInterface {
|
||||
public:
|
||||
// The struct below constitutes the new parameter scheme for the audio
|
||||
// processing. It is being introduced gradually and until it is fully
|
||||
// introduced, it is prone to change.
|
||||
// TODO(peah): Remove this comment once the new config scheme is fully rolled
|
||||
// out.
|
||||
//
|
||||
// The parameters and behavior of the audio processing module are controlled
|
||||
// by changing the default values in the AudioProcessing::Config struct.
|
||||
// The config is applied by passing the struct to the ApplyConfig method.
|
||||
//
|
||||
// This config is intended to be used during setup, and to enable/disable
|
||||
// top-level processing effects. Use during processing may cause undesired
|
||||
// submodule resets, affecting the audio quality. Use the RuntimeSetting
|
||||
// construct for runtime configuration.
|
||||
struct RTC_EXPORT Config {
|
||||
// Sets the properties of the audio processing pipeline.
|
||||
struct RTC_EXPORT Pipeline {
|
||||
// Ways to downmix a multi-channel track to mono.
|
||||
enum class DownmixMethod {
|
||||
kAverageChannels, // Average across channels.
|
||||
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 = 48000;
|
||||
// Allow multi-channel processing of render audio.
|
||||
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 = false;
|
||||
// Indicates how to downmix multi-channel capture audio to mono (when
|
||||
// needed).
|
||||
DownmixMethod capture_downmix_method = DownmixMethod::kAverageChannels;
|
||||
} pipeline;
|
||||
|
||||
// Enabled the pre-amplifier. It amplifies the capture signal
|
||||
// before any other processing is done.
|
||||
// TODO(webrtc:5298): Deprecate and use the pre-gain functionality in
|
||||
// capture_level_adjustment instead.
|
||||
struct PreAmplifier {
|
||||
bool enabled = false;
|
||||
float fixed_gain_factor = 1.0f;
|
||||
} pre_amplifier;
|
||||
|
||||
// Functionality for general level adjustment in the capture pipeline. This
|
||||
// should not be used together with the legacy PreAmplifier functionality.
|
||||
struct CaptureLevelAdjustment {
|
||||
bool operator==(const CaptureLevelAdjustment& rhs) const;
|
||||
bool operator!=(const CaptureLevelAdjustment& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
bool enabled = false;
|
||||
// The `pre_gain_factor` scales the signal before any processing is done.
|
||||
float pre_gain_factor = 1.0f;
|
||||
// The `post_gain_factor` scales the signal after all processing is done.
|
||||
float post_gain_factor = 1.0f;
|
||||
struct AnalogMicGainEmulation {
|
||||
bool operator==(const AnalogMicGainEmulation& rhs) const;
|
||||
bool operator!=(const AnalogMicGainEmulation& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
bool enabled = false;
|
||||
// Initial analog gain level to use for the emulated analog gain. Must
|
||||
// be in the range [0...255].
|
||||
int initial_level = 255;
|
||||
} analog_mic_gain_emulation;
|
||||
} capture_level_adjustment;
|
||||
|
||||
struct HighPassFilter {
|
||||
bool enabled = false;
|
||||
bool apply_in_full_band = true;
|
||||
} high_pass_filter;
|
||||
|
||||
struct EchoCanceller {
|
||||
bool enabled = false;
|
||||
bool mobile_mode = false;
|
||||
bool export_linear_aec_output = false;
|
||||
// Enforce the highpass filter to be on (has no effect for the mobile
|
||||
// mode).
|
||||
bool enforce_high_pass_filtering = true;
|
||||
} echo_canceller;
|
||||
|
||||
// Enables background noise suppression.
|
||||
struct NoiseSuppression {
|
||||
bool enabled = false;
|
||||
enum Level { kLow, kModerate, kHigh, kVeryHigh };
|
||||
Level level = kModerate;
|
||||
bool analyze_linear_aec_output_when_available = false;
|
||||
} noise_suppression;
|
||||
|
||||
// TODO(bugs.webrtc.org/357281131): Deprecated. Stop using and remove.
|
||||
// Enables transient suppression.
|
||||
struct TransientSuppression {
|
||||
bool enabled = false;
|
||||
} transient_suppression;
|
||||
|
||||
// Enables automatic gain control (AGC) functionality.
|
||||
// The automatic gain control (AGC) component brings the signal to an
|
||||
// appropriate range. This is done by applying a digital gain directly and,
|
||||
// in the analog mode, prescribing an analog gain to be applied at the audio
|
||||
// HAL.
|
||||
// Recommended to be enabled on the client-side.
|
||||
struct RTC_EXPORT GainController1 {
|
||||
bool operator==(const GainController1& rhs) const;
|
||||
bool operator!=(const GainController1& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
bool enabled = false;
|
||||
enum Mode {
|
||||
// Adaptive mode intended for use if an analog volume control is
|
||||
// available on the capture device. It will require the user to provide
|
||||
// coupling between the OS mixer controls and AGC through the
|
||||
// stream_analog_level() functions.
|
||||
// It consists of an analog gain prescription for the audio device and a
|
||||
// digital compression stage.
|
||||
kAdaptiveAnalog,
|
||||
// Adaptive mode intended for situations in which an analog volume
|
||||
// control is unavailable. It operates in a similar fashion to the
|
||||
// adaptive analog mode, but with scaling instead applied in the digital
|
||||
// domain. As with the analog mode, it additionally uses a digital
|
||||
// compression stage.
|
||||
kAdaptiveDigital,
|
||||
// Fixed mode which enables only the digital compression stage also used
|
||||
// by the two adaptive modes.
|
||||
// It is distinguished from the adaptive modes by considering only a
|
||||
// short time-window of the input signal. It applies a fixed gain
|
||||
// through most of the input level range, and compresses (gradually
|
||||
// reduces gain with increasing level) the input signal at higher
|
||||
// levels. This mode is preferred on embedded devices where the capture
|
||||
// signal level is predictable, so that a known gain can be applied.
|
||||
kFixedDigital
|
||||
};
|
||||
Mode mode = kAdaptiveAnalog;
|
||||
// Sets the target peak level (or envelope) of the AGC in dBFs (decibels
|
||||
// from digital full-scale). The convention is to use positive values. For
|
||||
// instance, passing in a value of 3 corresponds to -3 dBFs, or a target
|
||||
// level 3 dB below full-scale. Limited to [0, 31].
|
||||
int target_level_dbfs = 3;
|
||||
// Sets the maximum gain the digital compression stage may apply, in dB. A
|
||||
// higher number corresponds to greater compression, while a value of 0
|
||||
// will leave the signal uncompressed. Limited to [0, 90].
|
||||
// For updates after APM setup, use a RuntimeSetting instead.
|
||||
int compression_gain_db = 9;
|
||||
// When enabled, the compression stage will hard limit the signal to the
|
||||
// target level. Otherwise, the signal will be compressed but not limited
|
||||
// above the target level.
|
||||
bool enable_limiter = true;
|
||||
|
||||
// Enables the analog gain controller functionality.
|
||||
struct AnalogGainController {
|
||||
bool enabled = true;
|
||||
// TODO(bugs.webrtc.org/7494): Deprecated. Stop using and remove.
|
||||
int startup_min_volume = 0;
|
||||
// Lowest analog microphone level that will be applied in response to
|
||||
// clipping.
|
||||
int clipped_level_min = 70;
|
||||
// If true, an adaptive digital gain is applied.
|
||||
bool enable_digital_adaptive = true;
|
||||
// Amount the microphone level is lowered with every clipping event.
|
||||
// Limited to (0, 255].
|
||||
int clipped_level_step = 15;
|
||||
// Proportion of clipped samples required to declare a clipping event.
|
||||
// Limited to (0.f, 1.f).
|
||||
float clipped_ratio_threshold = 0.1f;
|
||||
// Time in frames to wait after a clipping event before checking again.
|
||||
// Limited to values higher than 0.
|
||||
int clipped_wait_frames = 300;
|
||||
|
||||
// Enables clipping prediction functionality.
|
||||
struct ClippingPredictor {
|
||||
bool enabled = false;
|
||||
enum Mode {
|
||||
// Clipping event prediction mode with fixed step estimation.
|
||||
kClippingEventPrediction,
|
||||
// Clipped peak estimation mode with adaptive step estimation.
|
||||
kAdaptiveStepClippingPeakPrediction,
|
||||
// Clipped peak estimation mode with fixed step estimation.
|
||||
kFixedStepClippingPeakPrediction,
|
||||
};
|
||||
Mode mode = kClippingEventPrediction;
|
||||
// Number of frames in the sliding analysis window.
|
||||
int window_length = 5;
|
||||
// Number of frames in the sliding reference window.
|
||||
int reference_window_length = 5;
|
||||
// Reference window delay (unit: number of frames).
|
||||
int reference_window_delay = 5;
|
||||
// Clipping prediction threshold (dBFS).
|
||||
float clipping_threshold = -1.0f;
|
||||
// Crest factor drop threshold (dB).
|
||||
float crest_factor_margin = 3.0f;
|
||||
// If true, the recommended clipped level step is used to modify the
|
||||
// analog gain. Otherwise, the predictor runs without affecting the
|
||||
// analog gain.
|
||||
bool use_predicted_step = true;
|
||||
} clipping_predictor;
|
||||
} analog_gain_controller;
|
||||
} gain_controller1;
|
||||
|
||||
// Parameters for AGC2, an Automatic Gain Control (AGC) sub-module which
|
||||
// replaces the AGC sub-module parametrized by `gain_controller1`.
|
||||
// AGC2 brings the captured audio signal to the desired level by combining
|
||||
// three different controllers (namely, input volume controller, adapative
|
||||
// digital controller and fixed digital controller) and a limiter.
|
||||
// TODO(bugs.webrtc.org:7494): Name `GainController` when AGC1 removed.
|
||||
struct RTC_EXPORT GainController2 {
|
||||
bool operator==(const GainController2& rhs) const;
|
||||
bool operator!=(const GainController2& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
// AGC2 must be created if and only if `enabled` is true.
|
||||
bool enabled = false;
|
||||
|
||||
// Parameters for the input volume controller, which adjusts the input
|
||||
// volume applied when the audio is captured (e.g., microphone volume on
|
||||
// a soundcard, input volume on HAL).
|
||||
struct InputVolumeController {
|
||||
bool operator==(const InputVolumeController& rhs) const;
|
||||
bool operator!=(const InputVolumeController& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
bool enabled = false;
|
||||
} input_volume_controller;
|
||||
|
||||
// Parameters for the adaptive digital controller, which adjusts and
|
||||
// applies a digital gain after echo cancellation and after noise
|
||||
// suppression.
|
||||
struct RTC_EXPORT AdaptiveDigital {
|
||||
bool operator==(const AdaptiveDigital& rhs) const;
|
||||
bool operator!=(const AdaptiveDigital& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
bool enabled = false;
|
||||
float headroom_db = 5.0f;
|
||||
float max_gain_db = 50.0f;
|
||||
float initial_gain_db = 15.0f;
|
||||
float max_gain_change_db_per_second = 6.0f;
|
||||
float max_output_noise_level_dbfs = -50.0f;
|
||||
} adaptive_digital;
|
||||
|
||||
// Parameters for the fixed digital controller, which applies a fixed
|
||||
// digital gain after the adaptive digital controller and before the
|
||||
// limiter.
|
||||
struct FixedDigital {
|
||||
// By setting `gain_db` to a value greater than zero, the limiter can be
|
||||
// turned into a compressor that first applies a fixed gain.
|
||||
float gain_db = 0.0f;
|
||||
} fixed_digital;
|
||||
} gain_controller2;
|
||||
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
// Specifies the properties of a setting to be passed to AudioProcessing at
|
||||
// runtime.
|
||||
class RuntimeSetting {
|
||||
public:
|
||||
enum class Type {
|
||||
kNotSpecified,
|
||||
kCapturePreGain,
|
||||
kCaptureCompressionGain,
|
||||
kCaptureFixedPostGain,
|
||||
kPlayoutVolumeChange,
|
||||
kCustomRenderProcessingRuntimeSetting,
|
||||
kPlayoutAudioDeviceChange,
|
||||
kCapturePostGain,
|
||||
kCaptureOutputUsed
|
||||
};
|
||||
|
||||
// Play-out audio device properties.
|
||||
struct PlayoutAudioDeviceInfo {
|
||||
int id; // Identifies the audio device.
|
||||
int max_volume; // Maximum play-out volume.
|
||||
};
|
||||
|
||||
RuntimeSetting() : type_(Type::kNotSpecified), value_(0.0f) {}
|
||||
~RuntimeSetting() = default;
|
||||
|
||||
static RuntimeSetting CreateCapturePreGain(float gain) {
|
||||
return {Type::kCapturePreGain, gain};
|
||||
}
|
||||
|
||||
static RuntimeSetting CreateCapturePostGain(float gain) {
|
||||
return {Type::kCapturePostGain, gain};
|
||||
}
|
||||
|
||||
// Corresponds to Config::GainController1::compression_gain_db, but for
|
||||
// runtime configuration.
|
||||
static RuntimeSetting CreateCompressionGainDb(int gain_db) {
|
||||
RTC_DCHECK_GE(gain_db, 0);
|
||||
RTC_DCHECK_LE(gain_db, 90);
|
||||
return {Type::kCaptureCompressionGain, static_cast<float>(gain_db)};
|
||||
}
|
||||
|
||||
// Corresponds to Config::GainController2::fixed_digital::gain_db, but for
|
||||
// runtime configuration.
|
||||
static RuntimeSetting CreateCaptureFixedPostGain(float gain_db) {
|
||||
RTC_DCHECK_GE(gain_db, 0.0f);
|
||||
RTC_DCHECK_LE(gain_db, 90.0f);
|
||||
return {Type::kCaptureFixedPostGain, gain_db};
|
||||
}
|
||||
|
||||
// Creates a runtime setting to notify play-out (aka render) audio device
|
||||
// changes.
|
||||
static RuntimeSetting CreatePlayoutAudioDeviceChange(
|
||||
PlayoutAudioDeviceInfo audio_device) {
|
||||
return {Type::kPlayoutAudioDeviceChange, audio_device};
|
||||
}
|
||||
|
||||
// Creates a runtime setting to notify play-out (aka render) volume changes.
|
||||
// `volume` is the unnormalized volume, the maximum of which
|
||||
static RuntimeSetting CreatePlayoutVolumeChange(int volume) {
|
||||
return {Type::kPlayoutVolumeChange, volume};
|
||||
}
|
||||
|
||||
static RuntimeSetting CreateCustomRenderSetting(float payload) {
|
||||
return {Type::kCustomRenderProcessingRuntimeSetting, payload};
|
||||
}
|
||||
|
||||
static RuntimeSetting CreateCaptureOutputUsedSetting(
|
||||
bool capture_output_used) {
|
||||
return {Type::kCaptureOutputUsed, capture_output_used};
|
||||
}
|
||||
|
||||
Type type() const { return type_; }
|
||||
// Getters do not return a value but instead modify the argument to protect
|
||||
// from implicit casting.
|
||||
void GetFloat(float* value) const {
|
||||
RTC_DCHECK(value);
|
||||
*value = value_.float_value;
|
||||
}
|
||||
void GetInt(int* value) const {
|
||||
RTC_DCHECK(value);
|
||||
*value = value_.int_value;
|
||||
}
|
||||
void GetBool(bool* value) const {
|
||||
RTC_DCHECK(value);
|
||||
*value = value_.bool_value;
|
||||
}
|
||||
void GetPlayoutAudioDeviceInfo(PlayoutAudioDeviceInfo* value) const {
|
||||
RTC_DCHECK(value);
|
||||
*value = value_.playout_audio_device_info;
|
||||
}
|
||||
|
||||
private:
|
||||
RuntimeSetting(Type id, float value) : type_(id), value_(value) {}
|
||||
RuntimeSetting(Type id, int value) : type_(id), value_(value) {}
|
||||
RuntimeSetting(Type id, PlayoutAudioDeviceInfo value)
|
||||
: type_(id), value_(value) {}
|
||||
Type type_;
|
||||
union U {
|
||||
U() {}
|
||||
U(int value) : int_value(value) {}
|
||||
U(float value) : float_value(value) {}
|
||||
U(PlayoutAudioDeviceInfo value) : playout_audio_device_info(value) {}
|
||||
float float_value;
|
||||
int int_value;
|
||||
bool bool_value;
|
||||
PlayoutAudioDeviceInfo playout_audio_device_info;
|
||||
} value_;
|
||||
};
|
||||
|
||||
~AudioProcessing() override {}
|
||||
|
||||
// Initializes internal states, while retaining all user settings. This
|
||||
// should be called before beginning to process a new audio stream. However,
|
||||
// it is not necessary to call before processing the first stream after
|
||||
// creation.
|
||||
//
|
||||
// It is also not necessary to call if the audio parameters (sample
|
||||
// rate and number of channels) have changed. Passing updated parameters
|
||||
// directly to `ProcessStream()` and `ProcessReverseStream()` is permissible.
|
||||
// If the parameters are known at init-time though, they may be provided.
|
||||
// TODO(webrtc:5298): Change to return void.
|
||||
virtual int Initialize() = 0;
|
||||
|
||||
// The int16 interfaces require:
|
||||
// - only `NativeRate`s be used
|
||||
// - that the input, output and reverse rates must match
|
||||
// - that `processing_config.output_stream()` matches
|
||||
// `processing_config.input_stream()`.
|
||||
//
|
||||
// The float interfaces accept arbitrary rates and support differing input and
|
||||
// output layouts, but the output must have either one channel or the same
|
||||
// number of channels as the input.
|
||||
virtual int Initialize(const ProcessingConfig& processing_config) = 0;
|
||||
|
||||
// TODO(peah): This method is a temporary solution used to take control
|
||||
// over the parameters in the audio processing module and is likely to change.
|
||||
virtual void ApplyConfig(const Config& config) = 0;
|
||||
|
||||
// TODO(ajm): Only intended for internal use. Make private and friend the
|
||||
// necessary classes?
|
||||
virtual int proc_sample_rate_hz() const = 0;
|
||||
virtual int proc_split_sample_rate_hz() const = 0;
|
||||
virtual size_t num_input_channels() const = 0;
|
||||
virtual size_t num_proc_channels() const = 0;
|
||||
virtual size_t num_output_channels() const = 0;
|
||||
virtual size_t num_reverse_channels() const = 0;
|
||||
|
||||
// Set to true when the output of AudioProcessing will be muted or in some
|
||||
// other way not used. Ideally, the captured audio would still be processed,
|
||||
// but some components may change behavior based on this information.
|
||||
// Default false. This method takes a lock. To achieve this in a lock-less
|
||||
// manner the PostRuntimeSetting can instead be used.
|
||||
virtual void set_output_will_be_muted(bool muted) = 0;
|
||||
|
||||
// Enqueues a runtime setting.
|
||||
virtual void SetRuntimeSetting(RuntimeSetting setting) = 0;
|
||||
|
||||
// Enqueues a runtime setting. Returns a bool indicating whether the
|
||||
// enqueueing was successfull.
|
||||
virtual bool PostRuntimeSetting(RuntimeSetting setting) = 0;
|
||||
|
||||
// Accepts and produces a ~10 ms frame of interleaved 16 bit integer audio as
|
||||
// specified in `input_config` and `output_config`. `src` and `dest` may use
|
||||
// the same memory, if desired.
|
||||
virtual int ProcessStream(const int16_t* const src,
|
||||
const StreamConfig& input_config,
|
||||
const StreamConfig& output_config,
|
||||
int16_t* const dest) = 0;
|
||||
|
||||
// Accepts deinterleaved float audio with the range [-1, 1]. Each element of
|
||||
// `src` points to a channel buffer, arranged according to `input_stream`. At
|
||||
// output, the channels will be arranged according to `output_stream` in
|
||||
// `dest`.
|
||||
//
|
||||
// The output must have one channel or as many channels as the input. `src`
|
||||
// and `dest` may use the same memory, if desired.
|
||||
virtual int ProcessStream(const float* const* src,
|
||||
const StreamConfig& input_config,
|
||||
const StreamConfig& output_config,
|
||||
float* const* dest) = 0;
|
||||
|
||||
// Accepts and produces a ~10 ms frame of interleaved 16 bit integer audio for
|
||||
// the reverse direction audio stream as specified in `input_config` and
|
||||
// `output_config`. `src` and `dest` may use the same memory, if desired.
|
||||
virtual int ProcessReverseStream(const int16_t* const src,
|
||||
const StreamConfig& input_config,
|
||||
const StreamConfig& output_config,
|
||||
int16_t* const dest) = 0;
|
||||
|
||||
// Accepts deinterleaved float audio with the range [-1, 1]. Each element of
|
||||
// `data` points to a channel buffer, arranged according to `reverse_config`.
|
||||
virtual int ProcessReverseStream(const float* const* src,
|
||||
const StreamConfig& input_config,
|
||||
const StreamConfig& output_config,
|
||||
float* const* dest) = 0;
|
||||
|
||||
// Accepts deinterleaved float audio with the range [-1, 1]. Each element
|
||||
// of `data` points to a channel buffer, arranged according to
|
||||
// `reverse_config`.
|
||||
virtual int AnalyzeReverseStream(const float* const* data,
|
||||
const StreamConfig& reverse_config) = 0;
|
||||
|
||||
// Returns the most recently produced ~10 ms of the linear AEC output at a
|
||||
// rate of 16 kHz. If there is more than one capture channel, a mono
|
||||
// representation of the input is returned. Returns true/false to indicate
|
||||
// whether an output returned.
|
||||
virtual bool GetLinearAecOutput(
|
||||
rtc::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
|
||||
// HAL. Must be within the range [0, 255].
|
||||
virtual void set_stream_analog_level(int level) = 0;
|
||||
|
||||
// When an analog mode is set, this should be called after
|
||||
// `set_stream_analog_level()` and `ProcessStream()` to obtain the recommended
|
||||
// new analog level for the audio HAL. It is the user's responsibility to
|
||||
// apply this level.
|
||||
virtual int recommended_stream_analog_level() const = 0;
|
||||
|
||||
// This must be called if and only if echo processing is enabled.
|
||||
//
|
||||
// Sets the `delay` in ms between ProcessReverseStream() receiving a far-end
|
||||
// frame and ProcessStream() receiving a near-end frame containing the
|
||||
// corresponding echo. On the client-side this can be expressed as
|
||||
// delay = (t_render - t_analyze) + (t_process - t_capture)
|
||||
// where,
|
||||
// - t_analyze is the time a frame is passed to ProcessReverseStream() and
|
||||
// t_render is the time the first sample of the same frame is rendered by
|
||||
// the audio hardware.
|
||||
// - t_capture is the time the first sample of a frame is captured by the
|
||||
// audio hardware and t_process is the time the same frame is passed to
|
||||
// ProcessStream().
|
||||
virtual int set_stream_delay_ms(int delay) = 0;
|
||||
virtual int stream_delay_ms() const = 0;
|
||||
|
||||
// Call to signal that a key press occurred (true) or did not occur (false)
|
||||
// with this chunk of audio.
|
||||
virtual void set_stream_key_pressed(bool key_pressed) = 0;
|
||||
|
||||
// Creates and attaches an webrtc::AecDump for recording debugging
|
||||
// information.
|
||||
// The `worker_queue` may not be null and must outlive the created
|
||||
// AecDump instance. |max_log_size_bytes == -1| means the log size
|
||||
// will be unlimited. `handle` may not be null. The AecDump takes
|
||||
// responsibility for `handle` and closes it in the destructor. A
|
||||
// return value of true indicates that the file has been
|
||||
// sucessfully opened, while a value of false indicates that
|
||||
// opening the file failed.
|
||||
virtual bool CreateAndAttachAecDump(
|
||||
absl::string_view file_name,
|
||||
int64_t max_log_size_bytes,
|
||||
absl::Nonnull<TaskQueueBase*> worker_queue) = 0;
|
||||
virtual bool CreateAndAttachAecDump(
|
||||
absl::Nonnull<FILE*> handle,
|
||||
int64_t max_log_size_bytes,
|
||||
absl::Nonnull<TaskQueueBase*> worker_queue) = 0;
|
||||
|
||||
// TODO(webrtc:5298) Deprecated variant.
|
||||
// Attaches provided webrtc::AecDump for recording debugging
|
||||
// information. Log file and maximum file size logic is supposed to
|
||||
// be handled by implementing instance of AecDump. Calling this
|
||||
// method when another AecDump is attached resets the active AecDump
|
||||
// with a new one. This causes the d-tor of the earlier AecDump to
|
||||
// be called. The d-tor call may block until all pending logging
|
||||
// tasks are completed.
|
||||
virtual void AttachAecDump(std::unique_ptr<AecDump> aec_dump) = 0;
|
||||
|
||||
// If no AecDump is attached, this has no effect. If an AecDump is
|
||||
// attached, it's destructor is called. The d-tor may block until
|
||||
// all pending logging tasks are completed.
|
||||
virtual void DetachAecDump() = 0;
|
||||
|
||||
// Get audio processing statistics.
|
||||
virtual AudioProcessingStats GetStatistics() = 0;
|
||||
// TODO(webrtc:5298) Deprecated variant. The `has_remote_tracks` argument
|
||||
// should be set if there are active remote tracks (this would usually be true
|
||||
// during a call). If there are no remote tracks some of the stats will not be
|
||||
// set by AudioProcessing, because they only make sense if there is at least
|
||||
// one remote track.
|
||||
virtual AudioProcessingStats GetStatistics(bool has_remote_tracks) = 0;
|
||||
|
||||
// Returns the last applied configuration.
|
||||
virtual AudioProcessing::Config GetConfig() const = 0;
|
||||
|
||||
enum Error {
|
||||
// Fatal errors.
|
||||
kNoError = 0,
|
||||
kUnspecifiedError = -1,
|
||||
kCreationFailedError = -2,
|
||||
kUnsupportedComponentError = -3,
|
||||
kUnsupportedFunctionError = -4,
|
||||
kNullPointerError = -5,
|
||||
kBadParameterError = -6,
|
||||
kBadSampleRateError = -7,
|
||||
kBadDataLengthError = -8,
|
||||
kBadNumberChannelsError = -9,
|
||||
kFileError = -10,
|
||||
kStreamParameterNotSetError = -11,
|
||||
kNotEnabledError = -12,
|
||||
|
||||
// Warnings are non-fatal.
|
||||
// This results when a set_stream_ parameter is out of range. Processing
|
||||
// will continue, but the parameter may have been truncated.
|
||||
kBadStreamParameterWarning = -13
|
||||
};
|
||||
|
||||
// Native rates supported by the integer interfaces.
|
||||
enum NativeRate {
|
||||
kSampleRate8kHz = 8000,
|
||||
kSampleRate16kHz = 16000,
|
||||
kSampleRate32kHz = 32000,
|
||||
kSampleRate48kHz = 48000
|
||||
};
|
||||
|
||||
// TODO(kwiberg): We currently need to support a compiler (Visual C++) that
|
||||
// complains if we don't explicitly state the size of the array here. Remove
|
||||
// the size when that's no longer the case.
|
||||
static constexpr int kNativeSampleRatesHz[4] = {
|
||||
kSampleRate8kHz, kSampleRate16kHz, kSampleRate32kHz, kSampleRate48kHz};
|
||||
static constexpr size_t kNumNativeSampleRates =
|
||||
arraysize(kNativeSampleRatesHz);
|
||||
static constexpr int kMaxNativeSampleRateHz =
|
||||
kNativeSampleRatesHz[kNumNativeSampleRates - 1];
|
||||
|
||||
// APM processes audio in chunks of about 10 ms. See GetFrameSize() for
|
||||
// details.
|
||||
static constexpr int kChunkSizeMs = 10;
|
||||
|
||||
// Returns floor(sample_rate_hz/100): the number of samples per channel used
|
||||
// as input and output to the audio processing module in calls to
|
||||
// ProcessStream, ProcessReverseStream, AnalyzeReverseStream, and
|
||||
// GetLinearAecOutput.
|
||||
//
|
||||
// This is exactly 10 ms for sample rates divisible by 100. For example:
|
||||
// - 48000 Hz (480 samples per channel),
|
||||
// - 44100 Hz (441 samples per channel),
|
||||
// - 16000 Hz (160 samples per channel).
|
||||
//
|
||||
// Sample rates not divisible by 100 are received/produced in frames of
|
||||
// approximately 10 ms. For example:
|
||||
// - 22050 Hz (220 samples per channel, or ~9.98 ms per frame),
|
||||
// - 11025 Hz (110 samples per channel, or ~9.98 ms per frame).
|
||||
// These nondivisible sample rates yield lower audio quality compared to
|
||||
// multiples of 100. Internal resampling to 10 ms frames causes a simulated
|
||||
// clock drift effect which impacts the performance of (for example) echo
|
||||
// cancellation.
|
||||
static int GetFrameSize(int sample_rate_hz) { return sample_rate_hz / 100; }
|
||||
};
|
||||
|
||||
// Experimental interface for a custom analysis submodule.
|
||||
class CustomAudioAnalyzer {
|
||||
public:
|
||||
// (Re-) Initializes the submodule.
|
||||
virtual void Initialize(int sample_rate_hz, int num_channels) = 0;
|
||||
// Analyzes the given capture or render signal.
|
||||
virtual void Analyze(const AudioBuffer* audio) = 0;
|
||||
// Returns a string representation of the module state.
|
||||
virtual std::string ToString() const = 0;
|
||||
|
||||
virtual ~CustomAudioAnalyzer() {}
|
||||
};
|
||||
|
||||
// Interface for a custom processing submodule.
|
||||
class CustomProcessing {
|
||||
public:
|
||||
// (Re-)Initializes the submodule.
|
||||
virtual void Initialize(int sample_rate_hz, int num_channels) = 0;
|
||||
// Processes the given capture or render signal.
|
||||
virtual void Process(AudioBuffer* audio) = 0;
|
||||
// Returns a string representation of the module state.
|
||||
virtual std::string ToString() const = 0;
|
||||
// Handles RuntimeSettings. TODO(webrtc:9262): make pure virtual
|
||||
// after updating dependencies.
|
||||
virtual void SetRuntimeSetting(AudioProcessing::RuntimeSetting setting);
|
||||
|
||||
virtual ~CustomProcessing() {}
|
||||
};
|
||||
|
||||
class RTC_EXPORT AudioProcessingBuilder {
|
||||
public:
|
||||
AudioProcessingBuilder();
|
||||
AudioProcessingBuilder(const AudioProcessingBuilder&) = delete;
|
||||
AudioProcessingBuilder& operator=(const AudioProcessingBuilder&) = delete;
|
||||
~AudioProcessingBuilder();
|
||||
|
||||
// Sets the APM configuration.
|
||||
AudioProcessingBuilder& SetConfig(const AudioProcessing::Config& config) {
|
||||
config_ = config;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the echo controller factory to inject when APM is created.
|
||||
AudioProcessingBuilder& SetEchoControlFactory(
|
||||
std::unique_ptr<EchoControlFactory> echo_control_factory) {
|
||||
echo_control_factory_ = std::move(echo_control_factory);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the capture post-processing sub-module to inject when APM is created.
|
||||
AudioProcessingBuilder& SetCapturePostProcessing(
|
||||
std::unique_ptr<CustomProcessing> capture_post_processing) {
|
||||
capture_post_processing_ = std::move(capture_post_processing);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the render pre-processing sub-module to inject when APM is created.
|
||||
AudioProcessingBuilder& SetRenderPreProcessing(
|
||||
std::unique_ptr<CustomProcessing> render_pre_processing) {
|
||||
render_pre_processing_ = std::move(render_pre_processing);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the echo detector to inject when APM is created.
|
||||
AudioProcessingBuilder& SetEchoDetector(
|
||||
rtc::scoped_refptr<EchoDetector> echo_detector) {
|
||||
echo_detector_ = std::move(echo_detector);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the capture analyzer sub-module to inject when APM is created.
|
||||
AudioProcessingBuilder& SetCaptureAnalyzer(
|
||||
std::unique_ptr<CustomAudioAnalyzer> capture_analyzer) {
|
||||
capture_analyzer_ = std::move(capture_analyzer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Creates an APM instance with the specified config or the default one if
|
||||
// unspecified. Injects the specified components transferring the ownership
|
||||
// to the newly created APM instance - i.e., except for the config, the
|
||||
// builder is reset to its initial state.
|
||||
rtc::scoped_refptr<AudioProcessing> Create();
|
||||
|
||||
private:
|
||||
AudioProcessing::Config config_;
|
||||
std::unique_ptr<EchoControlFactory> echo_control_factory_;
|
||||
std::unique_ptr<CustomProcessing> capture_post_processing_;
|
||||
std::unique_ptr<CustomProcessing> render_pre_processing_;
|
||||
rtc::scoped_refptr<EchoDetector> echo_detector_;
|
||||
std::unique_ptr<CustomAudioAnalyzer> capture_analyzer_;
|
||||
};
|
||||
|
||||
class StreamConfig {
|
||||
public:
|
||||
// sample_rate_hz: The sampling rate of the stream.
|
||||
// num_channels: The number of audio channels in the stream.
|
||||
StreamConfig(int sample_rate_hz = 0,
|
||||
size_t num_channels = 0) // NOLINT(runtime/explicit)
|
||||
: sample_rate_hz_(sample_rate_hz),
|
||||
num_channels_(num_channels),
|
||||
num_frames_(calculate_frames(sample_rate_hz)) {}
|
||||
|
||||
void set_sample_rate_hz(int value) {
|
||||
sample_rate_hz_ = value;
|
||||
num_frames_ = calculate_frames(value);
|
||||
}
|
||||
void set_num_channels(size_t value) { num_channels_ = value; }
|
||||
|
||||
int sample_rate_hz() const { return sample_rate_hz_; }
|
||||
|
||||
// The number of channels in the stream.
|
||||
size_t num_channels() const { return num_channels_; }
|
||||
|
||||
size_t num_frames() const { return num_frames_; }
|
||||
size_t num_samples() const { return num_channels_ * num_frames_; }
|
||||
|
||||
bool operator==(const StreamConfig& other) const {
|
||||
return sample_rate_hz_ == other.sample_rate_hz_ &&
|
||||
num_channels_ == other.num_channels_;
|
||||
}
|
||||
|
||||
bool operator!=(const StreamConfig& other) const { return !(*this == other); }
|
||||
|
||||
private:
|
||||
static size_t calculate_frames(int sample_rate_hz) {
|
||||
return static_cast<size_t>(AudioProcessing::GetFrameSize(sample_rate_hz));
|
||||
}
|
||||
|
||||
int sample_rate_hz_;
|
||||
size_t num_channels_;
|
||||
size_t num_frames_;
|
||||
};
|
||||
|
||||
class ProcessingConfig {
|
||||
public:
|
||||
enum StreamName {
|
||||
kInputStream,
|
||||
kOutputStream,
|
||||
kReverseInputStream,
|
||||
kReverseOutputStream,
|
||||
kNumStreamNames,
|
||||
};
|
||||
|
||||
const StreamConfig& input_stream() const {
|
||||
return streams[StreamName::kInputStream];
|
||||
}
|
||||
const StreamConfig& output_stream() const {
|
||||
return streams[StreamName::kOutputStream];
|
||||
}
|
||||
const StreamConfig& reverse_input_stream() const {
|
||||
return streams[StreamName::kReverseInputStream];
|
||||
}
|
||||
const StreamConfig& reverse_output_stream() const {
|
||||
return streams[StreamName::kReverseOutputStream];
|
||||
}
|
||||
|
||||
StreamConfig& input_stream() { return streams[StreamName::kInputStream]; }
|
||||
StreamConfig& output_stream() { return streams[StreamName::kOutputStream]; }
|
||||
StreamConfig& reverse_input_stream() {
|
||||
return streams[StreamName::kReverseInputStream];
|
||||
}
|
||||
StreamConfig& reverse_output_stream() {
|
||||
return streams[StreamName::kReverseOutputStream];
|
||||
}
|
||||
|
||||
bool operator==(const ProcessingConfig& other) const {
|
||||
for (int i = 0; i < StreamName::kNumStreamNames; ++i) {
|
||||
if (this->streams[i] != other.streams[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const ProcessingConfig& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
StreamConfig streams[StreamName::kNumStreamNames];
|
||||
};
|
||||
|
||||
// Interface for an echo detector submodule.
|
||||
class EchoDetector : public RefCountInterface {
|
||||
public:
|
||||
// (Re-)Initializes the submodule.
|
||||
virtual void Initialize(int capture_sample_rate_hz,
|
||||
int num_capture_channels,
|
||||
int render_sample_rate_hz,
|
||||
int num_render_channels) = 0;
|
||||
|
||||
// Analysis (not changing) of the first channel of the render signal.
|
||||
virtual void AnalyzeRenderAudio(rtc::ArrayView<const float> render_audio) = 0;
|
||||
|
||||
// Analysis (not changing) of the capture signal.
|
||||
virtual void AnalyzeCaptureAudio(
|
||||
rtc::ArrayView<const float> capture_audio) = 0;
|
||||
|
||||
struct Metrics {
|
||||
std::optional<double> echo_likelihood;
|
||||
std::optional<double> echo_likelihood_recent_max;
|
||||
};
|
||||
|
||||
// Collect current metrics from the echo detector.
|
||||
virtual Metrics GetMetrics() const = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_AUDIO_PROCESSING_H_
|
22
webrtc/api/audio/audio_processing_statistics.cc
Normal file
22
webrtc/api/audio/audio_processing_statistics.cc
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio/audio_processing_statistics.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
AudioProcessingStats::AudioProcessingStats() = default;
|
||||
|
||||
AudioProcessingStats::AudioProcessingStats(const AudioProcessingStats& other) =
|
||||
default;
|
||||
|
||||
AudioProcessingStats::~AudioProcessingStats() = default;
|
||||
|
||||
} // namespace webrtc
|
68
webrtc/api/audio/audio_processing_statistics.h
Normal file
68
webrtc/api/audio/audio_processing_statistics.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_AUDIO_PROCESSING_STATISTICS_H_
|
||||
#define API_AUDIO_AUDIO_PROCESSING_STATISTICS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
// This version of the stats uses Optionals, it will replace the regular
|
||||
// AudioProcessingStatistics struct.
|
||||
struct RTC_EXPORT AudioProcessingStats {
|
||||
AudioProcessingStats();
|
||||
AudioProcessingStats(const AudioProcessingStats& other);
|
||||
~AudioProcessingStats();
|
||||
|
||||
// Deprecated.
|
||||
// TODO(bugs.webrtc.org/11226): Remove.
|
||||
// True if voice is detected in the last capture frame, after processing.
|
||||
// It is conservative in flagging audio as speech, with low likelihood of
|
||||
// incorrectly flagging a frame as voice.
|
||||
// Only reported if voice detection is enabled in AudioProcessing::Config.
|
||||
std::optional<bool> voice_detected;
|
||||
|
||||
// AEC Statistics.
|
||||
// ERL = 10log_10(P_far / P_echo)
|
||||
std::optional<double> echo_return_loss;
|
||||
// ERLE = 10log_10(P_echo / P_out)
|
||||
std::optional<double> echo_return_loss_enhancement;
|
||||
// Fraction of time that the AEC linear filter is divergent, in a 1-second
|
||||
// non-overlapped aggregation window.
|
||||
std::optional<double> divergent_filter_fraction;
|
||||
|
||||
// The delay metrics consists of the delay median and standard deviation. It
|
||||
// also consists of the fraction of delay estimates that can make the echo
|
||||
// cancellation perform poorly. The values are aggregated until the first
|
||||
// call to `GetStatistics()` and afterwards aggregated and updated every
|
||||
// second. Note that if there are several clients pulling metrics from
|
||||
// `GetStatistics()` during a session the first call from any of them will
|
||||
// change to one second aggregation window for all.
|
||||
std::optional<int32_t> delay_median_ms;
|
||||
std::optional<int32_t> delay_standard_deviation_ms;
|
||||
|
||||
// Residual echo detector likelihood.
|
||||
std::optional<double> residual_echo_likelihood;
|
||||
// Maximum residual echo likelihood from the last time period.
|
||||
std::optional<double> residual_echo_likelihood_recent_max;
|
||||
|
||||
// The instantaneous delay estimate produced in the AEC. The unit is in
|
||||
// milliseconds and the value is the instantaneous value at the time of the
|
||||
// call to `GetStatistics()`.
|
||||
std::optional<int32_t> delay_ms;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_AUDIO_PROCESSING_STATISTICS_H_
|
269
webrtc/api/audio/audio_view.h
Normal file
269
webrtc/api/audio/audio_view.h
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_AUDIO_VIEW_H_
|
||||
#define API_AUDIO_AUDIO_VIEW_H_
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "api/audio/channel_layout.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// This file contains 3 types of view classes:
|
||||
//
|
||||
// * MonoView<>: A single channel contiguous buffer of samples.
|
||||
//
|
||||
// * InterleavedView<>: Channel samples are interleaved (side-by-side) in
|
||||
// the buffer. A single channel InterleavedView<> is the same thing as a
|
||||
// MonoView<>
|
||||
//
|
||||
// * DeinterleavedView<>: Each channel's samples are contiguous within the
|
||||
// buffer. Channels can be enumerated and accessing the individual channel
|
||||
// data is done via MonoView<>.
|
||||
//
|
||||
// The views are comparable to and built on rtc::ArrayView<> but add
|
||||
// audio specific properties for the dimensions of the buffer and the above
|
||||
// specialized [de]interleaved support.
|
||||
//
|
||||
// There are also a few generic utility functions that can simplify
|
||||
// generic code for supporting more than one type of view.
|
||||
|
||||
// MonoView<> represents a view over a single contiguous, audio buffer. This
|
||||
// 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 = rtc::ArrayView<T>;
|
||||
|
||||
// InterleavedView<> is a view over an interleaved audio buffer (e.g. from
|
||||
// AudioFrame).
|
||||
template <typename T>
|
||||
class InterleavedView {
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
InterleavedView() = default;
|
||||
|
||||
template <typename U>
|
||||
InterleavedView(U* data, size_t samples_per_channel, size_t num_channels)
|
||||
: num_channels_(num_channels),
|
||||
samples_per_channel_(samples_per_channel),
|
||||
data_(data, num_channels * samples_per_channel) {
|
||||
RTC_DCHECK_LE(num_channels_, kMaxConcurrentChannels);
|
||||
RTC_DCHECK(num_channels_ == 0u || samples_per_channel_ != 0u);
|
||||
}
|
||||
|
||||
// Construct an InterleavedView from a C-style array. Samples per channels
|
||||
// is calculated based on the array size / num_channels.
|
||||
template <typename U, size_t N>
|
||||
InterleavedView(U (&array)[N], // NOLINT
|
||||
size_t num_channels)
|
||||
: InterleavedView(array, N / num_channels, num_channels) {
|
||||
RTC_DCHECK_EQ(N % num_channels, 0u);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
InterleavedView(const InterleavedView<U>& other)
|
||||
: num_channels_(other.num_channels()),
|
||||
samples_per_channel_(other.samples_per_channel()),
|
||||
data_(other.data()) {}
|
||||
|
||||
size_t num_channels() const { return num_channels_; }
|
||||
size_t samples_per_channel() const { return samples_per_channel_; }
|
||||
rtc::ArrayView<T> data() const { return data_; }
|
||||
bool empty() const { return data_.empty(); }
|
||||
size_t size() const { return data_.size(); }
|
||||
|
||||
MonoView<T> AsMono() const {
|
||||
RTC_DCHECK_EQ(num_channels(), 1u);
|
||||
RTC_DCHECK_EQ(data_.size(), samples_per_channel_);
|
||||
return data_;
|
||||
}
|
||||
|
||||
// A simple wrapper around memcpy that includes checks for properties.
|
||||
// TODO(tommi): Consider if this can be utility function for both interleaved
|
||||
// and deinterleaved views.
|
||||
template <typename U>
|
||||
void CopyFrom(const InterleavedView<U>& source) {
|
||||
static_assert(sizeof(T) == sizeof(U), "");
|
||||
RTC_DCHECK_EQ(num_channels(), source.num_channels());
|
||||
RTC_DCHECK_EQ(samples_per_channel(), source.samples_per_channel());
|
||||
RTC_DCHECK_GE(data_.size(), source.data().size());
|
||||
const auto data = source.data();
|
||||
memcpy(&data_[0], &data[0], data.size() * sizeof(U));
|
||||
}
|
||||
|
||||
T& operator[](size_t idx) const { return data_[idx]; }
|
||||
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
|
||||
// save a few bytes per view. Use `dchecked_cast` to support size_t during
|
||||
// construction.
|
||||
size_t num_channels_ = 0u;
|
||||
size_t samples_per_channel_ = 0u;
|
||||
rtc::ArrayView<T> data_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class DeinterleavedView {
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
DeinterleavedView() = default;
|
||||
|
||||
template <typename U>
|
||||
DeinterleavedView(U* data, size_t samples_per_channel, size_t num_channels)
|
||||
: num_channels_(num_channels),
|
||||
samples_per_channel_(samples_per_channel),
|
||||
data_(data, num_channels * samples_per_channel_) {}
|
||||
|
||||
template <typename U>
|
||||
DeinterleavedView(const DeinterleavedView<U>& other)
|
||||
: num_channels_(other.num_channels()),
|
||||
samples_per_channel_(other.samples_per_channel()),
|
||||
data_(other.data()) {}
|
||||
|
||||
// Returns a deinterleaved channel where `idx` is the zero based index,
|
||||
// in the range [0 .. num_channels()-1].
|
||||
MonoView<T> operator[](size_t idx) const {
|
||||
RTC_DCHECK_LT(idx, num_channels_);
|
||||
return MonoView<T>(&data_[idx * samples_per_channel_],
|
||||
samples_per_channel_);
|
||||
}
|
||||
|
||||
size_t num_channels() const { return num_channels_; }
|
||||
size_t samples_per_channel() const { return samples_per_channel_; }
|
||||
rtc::ArrayView<T> data() const { return data_; }
|
||||
bool empty() const { return data_.empty(); }
|
||||
size_t size() const { return data_.size(); }
|
||||
|
||||
// Returns the first (and possibly only) channel.
|
||||
MonoView<T> AsMono() const {
|
||||
RTC_DCHECK_GE(num_channels(), 1u);
|
||||
return (*this)[0];
|
||||
}
|
||||
|
||||
private:
|
||||
// TODO(tommi): Consider having these be stored as uint16_t to save a few
|
||||
// bytes per view. Use `dchecked_cast` to support size_t during construction.
|
||||
size_t num_channels_ = 0u;
|
||||
size_t samples_per_channel_ = 0u;
|
||||
rtc::ArrayView<T> data_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr size_t NumChannels(const MonoView<T>& view) {
|
||||
return 1u;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t NumChannels(const InterleavedView<T>& view) {
|
||||
return view.num_channels();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t NumChannels(const DeinterleavedView<T>& view) {
|
||||
return view.num_channels();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool IsMono(const MonoView<T>& view) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool IsInterleavedView(const MonoView<T>& view) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool IsInterleavedView(const InterleavedView<T>& view) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool IsInterleavedView(const DeinterleavedView<const T>& view) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool IsMono(const InterleavedView<T>& view) {
|
||||
return NumChannels(view) == 1u;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool IsMono(const DeinterleavedView<T>& view) {
|
||||
return NumChannels(view) == 1u;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t SamplesPerChannel(const MonoView<T>& view) {
|
||||
return view.size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t SamplesPerChannel(const InterleavedView<T>& view) {
|
||||
return view.samples_per_channel();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t SamplesPerChannel(const DeinterleavedView<T>& view) {
|
||||
return view.samples_per_channel();
|
||||
}
|
||||
// A simple wrapper around memcpy that includes checks for properties.
|
||||
// The parameter order is the same as for memcpy(), first destination then
|
||||
// source.
|
||||
template <typename D, typename S>
|
||||
void CopySamples(D& destination, const S& source) {
|
||||
static_assert(
|
||||
sizeof(typename D::value_type) == sizeof(typename S::value_type), "");
|
||||
// Here we'd really like to do
|
||||
// static_assert(IsInterleavedView(destination) == IsInterleavedView(source),
|
||||
// "");
|
||||
// but the compiler doesn't like it inside this template function for
|
||||
// some reason. The following check is an approximation but unfortunately
|
||||
// means that copying between a MonoView and single channel interleaved or
|
||||
// deinterleaved views wouldn't work.
|
||||
// static_assert(sizeof(destination) == sizeof(source),
|
||||
// "Incompatible view types");
|
||||
RTC_DCHECK_EQ(NumChannels(destination), NumChannels(source));
|
||||
RTC_DCHECK_EQ(SamplesPerChannel(destination), SamplesPerChannel(source));
|
||||
RTC_DCHECK_GE(destination.size(), source.size());
|
||||
memcpy(&destination[0], &source[0],
|
||||
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_
|
282
webrtc/api/audio/channel_layout.cc
Normal file
282
webrtc/api/audio/channel_layout.cc
Normal file
@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio/channel_layout.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "rtc_base/arraysize.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
static const int kLayoutToChannels[] = {
|
||||
0, // CHANNEL_LAYOUT_NONE
|
||||
0, // CHANNEL_LAYOUT_UNSUPPORTED
|
||||
1, // CHANNEL_LAYOUT_MONO
|
||||
2, // CHANNEL_LAYOUT_STEREO
|
||||
3, // CHANNEL_LAYOUT_2_1
|
||||
3, // CHANNEL_LAYOUT_SURROUND
|
||||
4, // CHANNEL_LAYOUT_4_0
|
||||
4, // CHANNEL_LAYOUT_2_2
|
||||
4, // CHANNEL_LAYOUT_QUAD
|
||||
5, // CHANNEL_LAYOUT_5_0
|
||||
6, // CHANNEL_LAYOUT_5_1
|
||||
5, // CHANNEL_LAYOUT_5_0_BACK
|
||||
6, // CHANNEL_LAYOUT_5_1_BACK
|
||||
7, // CHANNEL_LAYOUT_7_0
|
||||
8, // CHANNEL_LAYOUT_7_1
|
||||
8, // CHANNEL_LAYOUT_7_1_WIDE
|
||||
2, // CHANNEL_LAYOUT_STEREO_DOWNMIX
|
||||
3, // CHANNEL_LAYOUT_2POINT1
|
||||
4, // CHANNEL_LAYOUT_3_1
|
||||
5, // CHANNEL_LAYOUT_4_1
|
||||
6, // CHANNEL_LAYOUT_6_0
|
||||
6, // CHANNEL_LAYOUT_6_0_FRONT
|
||||
6, // CHANNEL_LAYOUT_HEXAGONAL
|
||||
7, // CHANNEL_LAYOUT_6_1
|
||||
7, // CHANNEL_LAYOUT_6_1_BACK
|
||||
7, // CHANNEL_LAYOUT_6_1_FRONT
|
||||
7, // CHANNEL_LAYOUT_7_0_FRONT
|
||||
8, // CHANNEL_LAYOUT_7_1_WIDE_BACK
|
||||
8, // CHANNEL_LAYOUT_OCTAGONAL
|
||||
0, // CHANNEL_LAYOUT_DISCRETE
|
||||
3, // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC
|
||||
5, // CHANNEL_LAYOUT_4_1_QUAD_SIDE
|
||||
0, // CHANNEL_LAYOUT_BITSTREAM
|
||||
};
|
||||
|
||||
// The channel orderings for each layout as specified by FFmpeg. Each value
|
||||
// represents the index of each channel in each layout. Values of -1 mean the
|
||||
// channel at that index is not used for that layout. For example, the left side
|
||||
// surround sound channel in FFmpeg's 5.1 layout is in the 5th position (because
|
||||
// the order is L, R, C, LFE, LS, RS), so
|
||||
// kChannelOrderings[CHANNEL_LAYOUT_5_1][SIDE_LEFT] = 4;
|
||||
static const int kChannelOrderings[CHANNEL_LAYOUT_MAX + 1][CHANNELS_MAX + 1] = {
|
||||
// FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
|
||||
|
||||
// CHANNEL_LAYOUT_NONE
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_UNSUPPORTED
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_MONO
|
||||
{-1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_STEREO
|
||||
{0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_2_1
|
||||
{0, 1, -1, -1, -1, -1, -1, -1, 2, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_SURROUND
|
||||
{0, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_4_0
|
||||
{0, 1, 2, -1, -1, -1, -1, -1, 3, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_2_2
|
||||
{0, 1, -1, -1, -1, -1, -1, -1, -1, 2, 3},
|
||||
|
||||
// CHANNEL_LAYOUT_QUAD
|
||||
{0, 1, -1, -1, 2, 3, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_5_0
|
||||
{0, 1, 2, -1, -1, -1, -1, -1, -1, 3, 4},
|
||||
|
||||
// CHANNEL_LAYOUT_5_1
|
||||
{0, 1, 2, 3, -1, -1, -1, -1, -1, 4, 5},
|
||||
|
||||
// FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
|
||||
|
||||
// CHANNEL_LAYOUT_5_0_BACK
|
||||
{0, 1, 2, -1, 3, 4, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_5_1_BACK
|
||||
{0, 1, 2, 3, 4, 5, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_7_0
|
||||
{0, 1, 2, -1, 5, 6, -1, -1, -1, 3, 4},
|
||||
|
||||
// CHANNEL_LAYOUT_7_1
|
||||
{0, 1, 2, 3, 6, 7, -1, -1, -1, 4, 5},
|
||||
|
||||
// CHANNEL_LAYOUT_7_1_WIDE
|
||||
{0, 1, 2, 3, -1, -1, 6, 7, -1, 4, 5},
|
||||
|
||||
// CHANNEL_LAYOUT_STEREO_DOWNMIX
|
||||
{0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_2POINT1
|
||||
{0, 1, -1, 2, -1, -1, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_3_1
|
||||
{0, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_4_1
|
||||
{0, 1, 2, 4, -1, -1, -1, -1, 3, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_6_0
|
||||
{0, 1, 2, -1, -1, -1, -1, -1, 5, 3, 4},
|
||||
|
||||
// CHANNEL_LAYOUT_6_0_FRONT
|
||||
{0, 1, -1, -1, -1, -1, 4, 5, -1, 2, 3},
|
||||
|
||||
// FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
|
||||
|
||||
// CHANNEL_LAYOUT_HEXAGONAL
|
||||
{0, 1, 2, -1, 3, 4, -1, -1, 5, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_6_1
|
||||
{0, 1, 2, 3, -1, -1, -1, -1, 6, 4, 5},
|
||||
|
||||
// CHANNEL_LAYOUT_6_1_BACK
|
||||
{0, 1, 2, 3, 4, 5, -1, -1, 6, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_6_1_FRONT
|
||||
{0, 1, -1, 6, -1, -1, 4, 5, -1, 2, 3},
|
||||
|
||||
// CHANNEL_LAYOUT_7_0_FRONT
|
||||
{0, 1, 2, -1, -1, -1, 5, 6, -1, 3, 4},
|
||||
|
||||
// CHANNEL_LAYOUT_7_1_WIDE_BACK
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_OCTAGONAL
|
||||
{0, 1, 2, -1, 5, 6, -1, -1, 7, 3, 4},
|
||||
|
||||
// CHANNEL_LAYOUT_DISCRETE
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC
|
||||
{0, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
|
||||
// CHANNEL_LAYOUT_4_1_QUAD_SIDE
|
||||
{0, 1, -1, 4, -1, -1, -1, -1, -1, 2, 3},
|
||||
|
||||
// CHANNEL_LAYOUT_BITSTREAM
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
|
||||
// FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
|
||||
};
|
||||
|
||||
int ChannelLayoutToChannelCount(ChannelLayout layout) {
|
||||
RTC_DCHECK_LT(static_cast<size_t>(layout), arraysize(kLayoutToChannels));
|
||||
RTC_DCHECK_LE(kLayoutToChannels[layout], kMaxConcurrentChannels);
|
||||
return kLayoutToChannels[layout];
|
||||
}
|
||||
|
||||
// Converts a channel count into a channel layout.
|
||||
ChannelLayout GuessChannelLayout(int channels) {
|
||||
switch (channels) {
|
||||
case 1:
|
||||
return CHANNEL_LAYOUT_MONO;
|
||||
case 2:
|
||||
return CHANNEL_LAYOUT_STEREO;
|
||||
case 3:
|
||||
return CHANNEL_LAYOUT_SURROUND;
|
||||
case 4:
|
||||
return CHANNEL_LAYOUT_QUAD;
|
||||
case 5:
|
||||
return CHANNEL_LAYOUT_5_0;
|
||||
case 6:
|
||||
return CHANNEL_LAYOUT_5_1;
|
||||
case 7:
|
||||
return CHANNEL_LAYOUT_6_1;
|
||||
case 8:
|
||||
return CHANNEL_LAYOUT_7_1;
|
||||
default:
|
||||
RTC_DLOG(LS_WARNING) << "Unsupported channel count: " << channels;
|
||||
}
|
||||
return CHANNEL_LAYOUT_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int ChannelOrder(ChannelLayout layout, Channels channel) {
|
||||
RTC_DCHECK_LT(static_cast<size_t>(layout), arraysize(kChannelOrderings));
|
||||
RTC_DCHECK_LT(static_cast<size_t>(channel), arraysize(kChannelOrderings[0]));
|
||||
return kChannelOrderings[layout][channel];
|
||||
}
|
||||
|
||||
const char* ChannelLayoutToString(ChannelLayout layout) {
|
||||
switch (layout) {
|
||||
case CHANNEL_LAYOUT_NONE:
|
||||
return "NONE";
|
||||
case CHANNEL_LAYOUT_UNSUPPORTED:
|
||||
return "UNSUPPORTED";
|
||||
case CHANNEL_LAYOUT_MONO:
|
||||
return "MONO";
|
||||
case CHANNEL_LAYOUT_STEREO:
|
||||
return "STEREO";
|
||||
case CHANNEL_LAYOUT_2_1:
|
||||
return "2.1";
|
||||
case CHANNEL_LAYOUT_SURROUND:
|
||||
return "SURROUND";
|
||||
case CHANNEL_LAYOUT_4_0:
|
||||
return "4.0";
|
||||
case CHANNEL_LAYOUT_2_2:
|
||||
return "QUAD_SIDE";
|
||||
case CHANNEL_LAYOUT_QUAD:
|
||||
return "QUAD";
|
||||
case CHANNEL_LAYOUT_5_0:
|
||||
return "5.0";
|
||||
case CHANNEL_LAYOUT_5_1:
|
||||
return "5.1";
|
||||
case CHANNEL_LAYOUT_5_0_BACK:
|
||||
return "5.0_BACK";
|
||||
case CHANNEL_LAYOUT_5_1_BACK:
|
||||
return "5.1_BACK";
|
||||
case CHANNEL_LAYOUT_7_0:
|
||||
return "7.0";
|
||||
case CHANNEL_LAYOUT_7_1:
|
||||
return "7.1";
|
||||
case CHANNEL_LAYOUT_7_1_WIDE:
|
||||
return "7.1_WIDE";
|
||||
case CHANNEL_LAYOUT_STEREO_DOWNMIX:
|
||||
return "STEREO_DOWNMIX";
|
||||
case CHANNEL_LAYOUT_2POINT1:
|
||||
return "2POINT1";
|
||||
case CHANNEL_LAYOUT_3_1:
|
||||
return "3.1";
|
||||
case CHANNEL_LAYOUT_4_1:
|
||||
return "4.1";
|
||||
case CHANNEL_LAYOUT_6_0:
|
||||
return "6.0";
|
||||
case CHANNEL_LAYOUT_6_0_FRONT:
|
||||
return "6.0_FRONT";
|
||||
case CHANNEL_LAYOUT_HEXAGONAL:
|
||||
return "HEXAGONAL";
|
||||
case CHANNEL_LAYOUT_6_1:
|
||||
return "6.1";
|
||||
case CHANNEL_LAYOUT_6_1_BACK:
|
||||
return "6.1_BACK";
|
||||
case CHANNEL_LAYOUT_6_1_FRONT:
|
||||
return "6.1_FRONT";
|
||||
case CHANNEL_LAYOUT_7_0_FRONT:
|
||||
return "7.0_FRONT";
|
||||
case CHANNEL_LAYOUT_7_1_WIDE_BACK:
|
||||
return "7.1_WIDE_BACK";
|
||||
case CHANNEL_LAYOUT_OCTAGONAL:
|
||||
return "OCTAGONAL";
|
||||
case CHANNEL_LAYOUT_DISCRETE:
|
||||
return "DISCRETE";
|
||||
case CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC:
|
||||
return "STEREO_AND_KEYBOARD_MIC";
|
||||
case CHANNEL_LAYOUT_4_1_QUAD_SIDE:
|
||||
return "4.1_QUAD_SIDE";
|
||||
case CHANNEL_LAYOUT_BITSTREAM:
|
||||
return "BITSTREAM";
|
||||
}
|
||||
RTC_DCHECK_NOTREACHED() << "Invalid channel layout provided: " << layout;
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
165
webrtc/api/audio/channel_layout.h
Normal file
165
webrtc/api/audio/channel_layout.h
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CHANNEL_LAYOUT_H_
|
||||
#define API_AUDIO_CHANNEL_LAYOUT_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// This file is derived from Chromium's base/channel_layout.h.
|
||||
|
||||
// Enumerates the various representations of the ordering of audio channels.
|
||||
// Logged to UMA, so never reuse a value, always add new/greater ones!
|
||||
enum ChannelLayout {
|
||||
CHANNEL_LAYOUT_NONE = 0,
|
||||
CHANNEL_LAYOUT_UNSUPPORTED = 1,
|
||||
|
||||
// Front C
|
||||
CHANNEL_LAYOUT_MONO = 2,
|
||||
|
||||
// Front L, Front R
|
||||
CHANNEL_LAYOUT_STEREO = 3,
|
||||
|
||||
// Front L, Front R, Back C
|
||||
CHANNEL_LAYOUT_2_1 = 4,
|
||||
|
||||
// Front L, Front R, Front C
|
||||
CHANNEL_LAYOUT_SURROUND = 5,
|
||||
|
||||
// Front L, Front R, Front C, Back C
|
||||
CHANNEL_LAYOUT_4_0 = 6,
|
||||
|
||||
// Front L, Front R, Side L, Side R
|
||||
CHANNEL_LAYOUT_2_2 = 7,
|
||||
|
||||
// Front L, Front R, Back L, Back R
|
||||
CHANNEL_LAYOUT_QUAD = 8,
|
||||
|
||||
// Front L, Front R, Front C, Side L, Side R
|
||||
CHANNEL_LAYOUT_5_0 = 9,
|
||||
|
||||
// Front L, Front R, Front C, LFE, Side L, Side R
|
||||
CHANNEL_LAYOUT_5_1 = 10,
|
||||
|
||||
// Front L, Front R, Front C, Back L, Back R
|
||||
CHANNEL_LAYOUT_5_0_BACK = 11,
|
||||
|
||||
// Front L, Front R, Front C, LFE, Back L, Back R
|
||||
CHANNEL_LAYOUT_5_1_BACK = 12,
|
||||
|
||||
// Front L, Front R, Front C, Side L, Side R, Back L, Back R
|
||||
CHANNEL_LAYOUT_7_0 = 13,
|
||||
|
||||
// Front L, Front R, Front C, LFE, Side L, Side R, Back L, Back R
|
||||
CHANNEL_LAYOUT_7_1 = 14,
|
||||
|
||||
// Front L, Front R, Front C, LFE, Side L, Side R, Front LofC, Front RofC
|
||||
CHANNEL_LAYOUT_7_1_WIDE = 15,
|
||||
|
||||
// Stereo L, Stereo R
|
||||
CHANNEL_LAYOUT_STEREO_DOWNMIX = 16,
|
||||
|
||||
// Stereo L, Stereo R, LFE
|
||||
CHANNEL_LAYOUT_2POINT1 = 17,
|
||||
|
||||
// Stereo L, Stereo R, Front C, LFE
|
||||
CHANNEL_LAYOUT_3_1 = 18,
|
||||
|
||||
// Stereo L, Stereo R, Front C, Rear C, LFE
|
||||
CHANNEL_LAYOUT_4_1 = 19,
|
||||
|
||||
// Stereo L, Stereo R, Front C, Side L, Side R, Back C
|
||||
CHANNEL_LAYOUT_6_0 = 20,
|
||||
|
||||
// Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC
|
||||
CHANNEL_LAYOUT_6_0_FRONT = 21,
|
||||
|
||||
// Stereo L, Stereo R, Front C, Rear L, Rear R, Rear C
|
||||
CHANNEL_LAYOUT_HEXAGONAL = 22,
|
||||
|
||||
// Stereo L, Stereo R, Front C, LFE, Side L, Side R, Rear Center
|
||||
CHANNEL_LAYOUT_6_1 = 23,
|
||||
|
||||
// Stereo L, Stereo R, Front C, LFE, Back L, Back R, Rear Center
|
||||
CHANNEL_LAYOUT_6_1_BACK = 24,
|
||||
|
||||
// Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC, LFE
|
||||
CHANNEL_LAYOUT_6_1_FRONT = 25,
|
||||
|
||||
// Front L, Front R, Front C, Side L, Side R, Front LofC, Front RofC
|
||||
CHANNEL_LAYOUT_7_0_FRONT = 26,
|
||||
|
||||
// Front L, Front R, Front C, LFE, Back L, Back R, Front LofC, Front RofC
|
||||
CHANNEL_LAYOUT_7_1_WIDE_BACK = 27,
|
||||
|
||||
// Front L, Front R, Front C, Side L, Side R, Rear L, Back R, Back C.
|
||||
CHANNEL_LAYOUT_OCTAGONAL = 28,
|
||||
|
||||
// Channels are not explicitly mapped to speakers.
|
||||
CHANNEL_LAYOUT_DISCRETE = 29,
|
||||
|
||||
// Front L, Front R, Front C. Front C contains the keyboard mic audio. This
|
||||
// layout is only intended for input for WebRTC. The Front C channel
|
||||
// is stripped away in the WebRTC audio input pipeline and never seen outside
|
||||
// of that.
|
||||
CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC = 30,
|
||||
|
||||
// Front L, Front R, Side L, Side R, LFE
|
||||
CHANNEL_LAYOUT_4_1_QUAD_SIDE = 31,
|
||||
|
||||
// Actual channel layout is specified in the bitstream and the actual channel
|
||||
// count is unknown at Chromium media pipeline level (useful for audio
|
||||
// pass-through mode).
|
||||
CHANNEL_LAYOUT_BITSTREAM = 32,
|
||||
|
||||
// Max value, must always equal the largest entry ever logged.
|
||||
CHANNEL_LAYOUT_MAX = CHANNEL_LAYOUT_BITSTREAM
|
||||
};
|
||||
|
||||
// Note: Do not reorder or reassign these values; other code depends on their
|
||||
// ordering to operate correctly. E.g., CoreAudio channel layout computations.
|
||||
enum Channels {
|
||||
LEFT = 0,
|
||||
RIGHT,
|
||||
CENTER,
|
||||
LFE,
|
||||
BACK_LEFT,
|
||||
BACK_RIGHT,
|
||||
LEFT_OF_CENTER,
|
||||
RIGHT_OF_CENTER,
|
||||
BACK_CENTER,
|
||||
SIDE_LEFT,
|
||||
SIDE_RIGHT,
|
||||
CHANNELS_MAX =
|
||||
SIDE_RIGHT, // Must always equal the largest value ever logged.
|
||||
};
|
||||
|
||||
// The maximum number of concurrently active channels for all possible layouts.
|
||||
// ChannelLayoutToChannelCount() will never return a value higher than this.
|
||||
constexpr int kMaxConcurrentChannels = 8;
|
||||
|
||||
// Returns the expected channel position in an interleaved stream. Values of -1
|
||||
// mean the channel at that index is not used for that layout. Values range
|
||||
// from 0 to ChannelLayoutToChannelCount(layout) - 1.
|
||||
int ChannelOrder(ChannelLayout layout, Channels channel);
|
||||
|
||||
// Returns the number of channels in a given ChannelLayout.
|
||||
int ChannelLayoutToChannelCount(ChannelLayout layout);
|
||||
|
||||
// Given the number of channels, return the best layout,
|
||||
// or return CHANNEL_LAYOUT_UNSUPPORTED if there is no good match.
|
||||
ChannelLayout GuessChannelLayout(int channels);
|
||||
|
||||
// Returns a string representation of the channel layout.
|
||||
const char* ChannelLayoutToString(ChannelLayout layout);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CHANNEL_LAYOUT_H_
|
278
webrtc/api/audio/echo_canceller3_config.cc
Normal file
278
webrtc/api/audio/echo_canceller3_config.cc
Normal file
@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include "api/audio/echo_canceller3_config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/numerics/safe_minmax.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
bool Limit(float* value, float min, float max) {
|
||||
float clamped = rtc::SafeClamp(*value, min, max);
|
||||
clamped = std::isfinite(clamped) ? clamped : min;
|
||||
bool res = *value == clamped;
|
||||
*value = clamped;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Limit(size_t* value, size_t min, size_t max) {
|
||||
size_t clamped = rtc::SafeClamp(*value, min, max);
|
||||
bool res = *value == clamped;
|
||||
*value = clamped;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Limit(int* value, int min, int max) {
|
||||
int clamped = rtc::SafeClamp(*value, min, max);
|
||||
bool res = *value == clamped;
|
||||
*value = clamped;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool FloorLimit(size_t* value, size_t min) {
|
||||
size_t clamped = *value >= min ? *value : min;
|
||||
bool res = *value == clamped;
|
||||
*value = clamped;
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EchoCanceller3Config::EchoCanceller3Config() = default;
|
||||
EchoCanceller3Config::EchoCanceller3Config(const EchoCanceller3Config& e) =
|
||||
default;
|
||||
EchoCanceller3Config& EchoCanceller3Config::operator=(
|
||||
const EchoCanceller3Config& e) = default;
|
||||
EchoCanceller3Config::Delay::Delay() = default;
|
||||
EchoCanceller3Config::Delay::Delay(const EchoCanceller3Config::Delay& e) =
|
||||
default;
|
||||
EchoCanceller3Config::Delay& EchoCanceller3Config::Delay::operator=(
|
||||
const Delay& e) = default;
|
||||
|
||||
EchoCanceller3Config::EchoModel::EchoModel() = default;
|
||||
EchoCanceller3Config::EchoModel::EchoModel(
|
||||
const EchoCanceller3Config::EchoModel& e) = default;
|
||||
EchoCanceller3Config::EchoModel& EchoCanceller3Config::EchoModel::operator=(
|
||||
const EchoModel& e) = default;
|
||||
|
||||
EchoCanceller3Config::Suppressor::Suppressor() = default;
|
||||
EchoCanceller3Config::Suppressor::Suppressor(
|
||||
const EchoCanceller3Config::Suppressor& e) = default;
|
||||
EchoCanceller3Config::Suppressor& EchoCanceller3Config::Suppressor::operator=(
|
||||
const Suppressor& e) = default;
|
||||
|
||||
EchoCanceller3Config::Suppressor::MaskingThresholds::MaskingThresholds(
|
||||
float enr_transparent,
|
||||
float enr_suppress,
|
||||
float emr_transparent)
|
||||
: enr_transparent(enr_transparent),
|
||||
enr_suppress(enr_suppress),
|
||||
emr_transparent(emr_transparent) {}
|
||||
EchoCanceller3Config::Suppressor::MaskingThresholds::MaskingThresholds(
|
||||
const EchoCanceller3Config::Suppressor::MaskingThresholds& e) = default;
|
||||
EchoCanceller3Config::Suppressor::MaskingThresholds&
|
||||
EchoCanceller3Config::Suppressor::MaskingThresholds::operator=(
|
||||
const MaskingThresholds& e) = default;
|
||||
|
||||
EchoCanceller3Config::Suppressor::Tuning::Tuning(MaskingThresholds mask_lf,
|
||||
MaskingThresholds mask_hf,
|
||||
float max_inc_factor,
|
||||
float max_dec_factor_lf)
|
||||
: mask_lf(mask_lf),
|
||||
mask_hf(mask_hf),
|
||||
max_inc_factor(max_inc_factor),
|
||||
max_dec_factor_lf(max_dec_factor_lf) {}
|
||||
EchoCanceller3Config::Suppressor::Tuning::Tuning(
|
||||
const EchoCanceller3Config::Suppressor::Tuning& e) = default;
|
||||
EchoCanceller3Config::Suppressor::Tuning&
|
||||
EchoCanceller3Config::Suppressor::Tuning::operator=(const Tuning& e) = default;
|
||||
|
||||
bool EchoCanceller3Config::Validate(EchoCanceller3Config* config) {
|
||||
RTC_DCHECK(config);
|
||||
EchoCanceller3Config* c = config;
|
||||
bool res = true;
|
||||
|
||||
if (c->delay.down_sampling_factor != 4 &&
|
||||
c->delay.down_sampling_factor != 8) {
|
||||
c->delay.down_sampling_factor = 4;
|
||||
res = false;
|
||||
}
|
||||
|
||||
res = res & Limit(&c->delay.default_delay, 0, 5000);
|
||||
res = res & Limit(&c->delay.num_filters, 0, 5000);
|
||||
res = res & Limit(&c->delay.delay_headroom_samples, 0, 5000);
|
||||
res = res & Limit(&c->delay.hysteresis_limit_blocks, 0, 5000);
|
||||
res = res & Limit(&c->delay.fixed_capture_delay_samples, 0, 5000);
|
||||
res = res & Limit(&c->delay.delay_estimate_smoothing, 0.f, 1.f);
|
||||
res = res & Limit(&c->delay.delay_candidate_detection_threshold, 0.f, 1.f);
|
||||
res = res & Limit(&c->delay.delay_selection_thresholds.initial, 1, 250);
|
||||
res = res & Limit(&c->delay.delay_selection_thresholds.converged, 1, 250);
|
||||
|
||||
res = res & FloorLimit(&c->filter.refined.length_blocks, 1);
|
||||
res = res & Limit(&c->filter.refined.leakage_converged, 0.f, 1000.f);
|
||||
res = res & Limit(&c->filter.refined.leakage_diverged, 0.f, 1000.f);
|
||||
res = res & Limit(&c->filter.refined.error_floor, 0.f, 1000.f);
|
||||
res = res & Limit(&c->filter.refined.error_ceil, 0.f, 100000000.f);
|
||||
res = res & Limit(&c->filter.refined.noise_gate, 0.f, 100000000.f);
|
||||
|
||||
res = res & FloorLimit(&c->filter.refined_initial.length_blocks, 1);
|
||||
res = res & Limit(&c->filter.refined_initial.leakage_converged, 0.f, 1000.f);
|
||||
res = res & Limit(&c->filter.refined_initial.leakage_diverged, 0.f, 1000.f);
|
||||
res = res & Limit(&c->filter.refined_initial.error_floor, 0.f, 1000.f);
|
||||
res = res & Limit(&c->filter.refined_initial.error_ceil, 0.f, 100000000.f);
|
||||
res = res & Limit(&c->filter.refined_initial.noise_gate, 0.f, 100000000.f);
|
||||
|
||||
if (c->filter.refined.length_blocks <
|
||||
c->filter.refined_initial.length_blocks) {
|
||||
c->filter.refined_initial.length_blocks = c->filter.refined.length_blocks;
|
||||
res = false;
|
||||
}
|
||||
|
||||
res = res & FloorLimit(&c->filter.coarse.length_blocks, 1);
|
||||
res = res & Limit(&c->filter.coarse.rate, 0.f, 1.f);
|
||||
res = res & Limit(&c->filter.coarse.noise_gate, 0.f, 100000000.f);
|
||||
|
||||
res = res & FloorLimit(&c->filter.coarse_initial.length_blocks, 1);
|
||||
res = res & Limit(&c->filter.coarse_initial.rate, 0.f, 1.f);
|
||||
res = res & Limit(&c->filter.coarse_initial.noise_gate, 0.f, 100000000.f);
|
||||
|
||||
if (c->filter.coarse.length_blocks < c->filter.coarse_initial.length_blocks) {
|
||||
c->filter.coarse_initial.length_blocks = c->filter.coarse.length_blocks;
|
||||
res = false;
|
||||
}
|
||||
|
||||
res = res & Limit(&c->filter.config_change_duration_blocks, 0, 100000);
|
||||
res = res & Limit(&c->filter.initial_state_seconds, 0.f, 100.f);
|
||||
res = res & Limit(&c->filter.coarse_reset_hangover_blocks, 0, 250000);
|
||||
|
||||
res = res & Limit(&c->erle.min, 1.f, 100000.f);
|
||||
res = res & Limit(&c->erle.max_l, 1.f, 100000.f);
|
||||
res = res & Limit(&c->erle.max_h, 1.f, 100000.f);
|
||||
if (c->erle.min > c->erle.max_l || c->erle.min > c->erle.max_h) {
|
||||
c->erle.min = std::min(c->erle.max_l, c->erle.max_h);
|
||||
res = false;
|
||||
}
|
||||
res = res & Limit(&c->erle.num_sections, 1, c->filter.refined.length_blocks);
|
||||
|
||||
res = res & Limit(&c->ep_strength.default_gain, 0.f, 1000000.f);
|
||||
res = res & Limit(&c->ep_strength.default_len, -1.f, 1.f);
|
||||
res = res & Limit(&c->ep_strength.nearend_len, -1.0f, 1.0f);
|
||||
|
||||
res =
|
||||
res & Limit(&c->echo_audibility.low_render_limit, 0.f, 32768.f * 32768.f);
|
||||
res = res &
|
||||
Limit(&c->echo_audibility.normal_render_limit, 0.f, 32768.f * 32768.f);
|
||||
res = res & Limit(&c->echo_audibility.floor_power, 0.f, 32768.f * 32768.f);
|
||||
res = res & Limit(&c->echo_audibility.audibility_threshold_lf, 0.f,
|
||||
32768.f * 32768.f);
|
||||
res = res & Limit(&c->echo_audibility.audibility_threshold_mf, 0.f,
|
||||
32768.f * 32768.f);
|
||||
res = res & Limit(&c->echo_audibility.audibility_threshold_hf, 0.f,
|
||||
32768.f * 32768.f);
|
||||
|
||||
res = res &
|
||||
Limit(&c->render_levels.active_render_limit, 0.f, 32768.f * 32768.f);
|
||||
res = res & Limit(&c->render_levels.poor_excitation_render_limit, 0.f,
|
||||
32768.f * 32768.f);
|
||||
res = res & Limit(&c->render_levels.poor_excitation_render_limit_ds8, 0.f,
|
||||
32768.f * 32768.f);
|
||||
|
||||
res = res & Limit(&c->echo_model.noise_floor_hold, 0, 1000);
|
||||
res = res & Limit(&c->echo_model.min_noise_floor_power, 0, 2000000.f);
|
||||
res = res & Limit(&c->echo_model.stationary_gate_slope, 0, 1000000.f);
|
||||
res = res & Limit(&c->echo_model.noise_gate_power, 0, 1000000.f);
|
||||
res = res & Limit(&c->echo_model.noise_gate_slope, 0, 1000000.f);
|
||||
res = res & Limit(&c->echo_model.render_pre_window_size, 0, 100);
|
||||
res = res & Limit(&c->echo_model.render_post_window_size, 0, 100);
|
||||
|
||||
res = res & Limit(&c->comfort_noise.noise_floor_dbfs, -200.f, 0.f);
|
||||
|
||||
res = res & Limit(&c->suppressor.nearend_average_blocks, 1, 5000);
|
||||
|
||||
res = res &
|
||||
Limit(&c->suppressor.normal_tuning.mask_lf.enr_transparent, 0.f, 100.f);
|
||||
res = res &
|
||||
Limit(&c->suppressor.normal_tuning.mask_lf.enr_suppress, 0.f, 100.f);
|
||||
res = res &
|
||||
Limit(&c->suppressor.normal_tuning.mask_lf.emr_transparent, 0.f, 100.f);
|
||||
res = res &
|
||||
Limit(&c->suppressor.normal_tuning.mask_hf.enr_transparent, 0.f, 100.f);
|
||||
res = res &
|
||||
Limit(&c->suppressor.normal_tuning.mask_hf.enr_suppress, 0.f, 100.f);
|
||||
res = res &
|
||||
Limit(&c->suppressor.normal_tuning.mask_hf.emr_transparent, 0.f, 100.f);
|
||||
res = res & Limit(&c->suppressor.normal_tuning.max_inc_factor, 0.f, 100.f);
|
||||
res = res & Limit(&c->suppressor.normal_tuning.max_dec_factor_lf, 0.f, 100.f);
|
||||
|
||||
res = res & Limit(&c->suppressor.nearend_tuning.mask_lf.enr_transparent, 0.f,
|
||||
100.f);
|
||||
res = res &
|
||||
Limit(&c->suppressor.nearend_tuning.mask_lf.enr_suppress, 0.f, 100.f);
|
||||
res = res & Limit(&c->suppressor.nearend_tuning.mask_lf.emr_transparent, 0.f,
|
||||
100.f);
|
||||
res = res & Limit(&c->suppressor.nearend_tuning.mask_hf.enr_transparent, 0.f,
|
||||
100.f);
|
||||
res = res &
|
||||
Limit(&c->suppressor.nearend_tuning.mask_hf.enr_suppress, 0.f, 100.f);
|
||||
res = res & Limit(&c->suppressor.nearend_tuning.mask_hf.emr_transparent, 0.f,
|
||||
100.f);
|
||||
res = res & Limit(&c->suppressor.nearend_tuning.max_inc_factor, 0.f, 100.f);
|
||||
res =
|
||||
res & Limit(&c->suppressor.nearend_tuning.max_dec_factor_lf, 0.f, 100.f);
|
||||
|
||||
res = res & Limit(&c->suppressor.last_permanent_lf_smoothing_band, 0, 64);
|
||||
res = res & Limit(&c->suppressor.last_lf_smoothing_band, 0, 64);
|
||||
res = res & Limit(&c->suppressor.last_lf_band, 0, 63);
|
||||
res = res &
|
||||
Limit(&c->suppressor.first_hf_band, c->suppressor.last_lf_band + 1, 64);
|
||||
|
||||
res = res & Limit(&c->suppressor.dominant_nearend_detection.enr_threshold,
|
||||
0.f, 1000000.f);
|
||||
res = res & Limit(&c->suppressor.dominant_nearend_detection.snr_threshold,
|
||||
0.f, 1000000.f);
|
||||
res = res & Limit(&c->suppressor.dominant_nearend_detection.hold_duration, 0,
|
||||
10000);
|
||||
res = res & Limit(&c->suppressor.dominant_nearend_detection.trigger_threshold,
|
||||
0, 10000);
|
||||
|
||||
res = res &
|
||||
Limit(&c->suppressor.subband_nearend_detection.nearend_average_blocks,
|
||||
1, 1024);
|
||||
res =
|
||||
res & Limit(&c->suppressor.subband_nearend_detection.subband1.low, 0, 65);
|
||||
res = res & Limit(&c->suppressor.subband_nearend_detection.subband1.high,
|
||||
c->suppressor.subband_nearend_detection.subband1.low, 65);
|
||||
res =
|
||||
res & Limit(&c->suppressor.subband_nearend_detection.subband2.low, 0, 65);
|
||||
res = res & Limit(&c->suppressor.subband_nearend_detection.subband2.high,
|
||||
c->suppressor.subband_nearend_detection.subband2.low, 65);
|
||||
res = res & Limit(&c->suppressor.subband_nearend_detection.nearend_threshold,
|
||||
0.f, 1.e24f);
|
||||
res = res & Limit(&c->suppressor.subband_nearend_detection.snr_threshold, 0.f,
|
||||
1.e24f);
|
||||
|
||||
res = res & Limit(&c->suppressor.high_bands_suppression.enr_threshold, 0.f,
|
||||
1000000.f);
|
||||
res = res & Limit(&c->suppressor.high_bands_suppression.max_gain_during_echo,
|
||||
0.f, 1.f);
|
||||
res = res & Limit(&c->suppressor.high_bands_suppression
|
||||
.anti_howling_activation_threshold,
|
||||
0.f, 32768.f * 32768.f);
|
||||
res = res & Limit(&c->suppressor.high_bands_suppression.anti_howling_gain,
|
||||
0.f, 1.f);
|
||||
|
||||
res = res & Limit(&c->suppressor.floor_first_increase, 0.f, 1000000.f);
|
||||
|
||||
return res;
|
||||
}
|
||||
} // namespace webrtc
|
250
webrtc/api/audio/echo_canceller3_config.h
Normal file
250
webrtc/api/audio/echo_canceller3_config.h
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_ECHO_CANCELLER3_CONFIG_H_
|
||||
#define API_AUDIO_ECHO_CANCELLER3_CONFIG_H_
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Configuration struct for EchoCanceller3
|
||||
struct RTC_EXPORT EchoCanceller3Config {
|
||||
// Checks and updates the config parameters to lie within (mostly) reasonable
|
||||
// ranges. Returns true if and only of the config did not need to be changed.
|
||||
static bool Validate(EchoCanceller3Config* config);
|
||||
|
||||
EchoCanceller3Config();
|
||||
EchoCanceller3Config(const EchoCanceller3Config& e);
|
||||
EchoCanceller3Config& operator=(const EchoCanceller3Config& other);
|
||||
|
||||
struct Buffering {
|
||||
size_t excess_render_detection_interval_blocks = 250;
|
||||
size_t max_allowed_excess_render_blocks = 8;
|
||||
} buffering;
|
||||
|
||||
struct Delay {
|
||||
Delay();
|
||||
Delay(const Delay& e);
|
||||
Delay& operator=(const Delay& e);
|
||||
size_t default_delay = 5;
|
||||
size_t down_sampling_factor = 4;
|
||||
size_t num_filters = 5;
|
||||
size_t delay_headroom_samples = 32;
|
||||
size_t hysteresis_limit_blocks = 1;
|
||||
size_t fixed_capture_delay_samples = 0;
|
||||
float delay_estimate_smoothing = 0.7f;
|
||||
float delay_estimate_smoothing_delay_found = 0.7f;
|
||||
float delay_candidate_detection_threshold = 0.2f;
|
||||
struct DelaySelectionThresholds {
|
||||
int initial;
|
||||
int converged;
|
||||
} delay_selection_thresholds = {5, 20};
|
||||
bool use_external_delay_estimator = false;
|
||||
bool log_warning_on_delay_changes = false;
|
||||
struct AlignmentMixing {
|
||||
bool downmix;
|
||||
bool adaptive_selection;
|
||||
float activity_power_threshold;
|
||||
bool prefer_first_two_channels;
|
||||
};
|
||||
AlignmentMixing render_alignment_mixing = {false, true, 10000.f, true};
|
||||
AlignmentMixing capture_alignment_mixing = {false, true, 10000.f, false};
|
||||
bool detect_pre_echo = true;
|
||||
} delay;
|
||||
|
||||
struct Filter {
|
||||
struct RefinedConfiguration {
|
||||
size_t length_blocks;
|
||||
float leakage_converged;
|
||||
float leakage_diverged;
|
||||
float error_floor;
|
||||
float error_ceil;
|
||||
float noise_gate;
|
||||
};
|
||||
|
||||
struct CoarseConfiguration {
|
||||
size_t length_blocks;
|
||||
float rate;
|
||||
float noise_gate;
|
||||
};
|
||||
|
||||
RefinedConfiguration refined = {13, 0.00005f, 0.05f,
|
||||
0.001f, 2.f, 20075344.f};
|
||||
CoarseConfiguration coarse = {13, 0.7f, 20075344.f};
|
||||
|
||||
RefinedConfiguration refined_initial = {12, 0.005f, 0.5f,
|
||||
0.001f, 2.f, 20075344.f};
|
||||
CoarseConfiguration coarse_initial = {12, 0.9f, 20075344.f};
|
||||
|
||||
size_t config_change_duration_blocks = 250;
|
||||
float initial_state_seconds = 2.5f;
|
||||
int coarse_reset_hangover_blocks = 25;
|
||||
bool conservative_initial_phase = false;
|
||||
bool enable_coarse_filter_output_usage = true;
|
||||
bool use_linear_filter = true;
|
||||
bool high_pass_filter_echo_reference = false;
|
||||
bool export_linear_aec_output = false;
|
||||
} filter;
|
||||
|
||||
struct Erle {
|
||||
float min = 1.f;
|
||||
float max_l = 4.f;
|
||||
float max_h = 1.5f;
|
||||
bool onset_detection = true;
|
||||
size_t num_sections = 1;
|
||||
bool clamp_quality_estimate_to_zero = true;
|
||||
bool clamp_quality_estimate_to_one = true;
|
||||
} erle;
|
||||
|
||||
struct EpStrength {
|
||||
float default_gain = 1.f;
|
||||
float default_len = 0.83f;
|
||||
float nearend_len = 0.83f;
|
||||
bool echo_can_saturate = true;
|
||||
bool bounded_erl = false;
|
||||
bool erle_onset_compensation_in_dominant_nearend = false;
|
||||
bool use_conservative_tail_frequency_response = true;
|
||||
} ep_strength;
|
||||
|
||||
struct EchoAudibility {
|
||||
float low_render_limit = 4 * 64.f;
|
||||
float normal_render_limit = 64.f;
|
||||
float floor_power = 2 * 64.f;
|
||||
float audibility_threshold_lf = 10;
|
||||
float audibility_threshold_mf = 10;
|
||||
float audibility_threshold_hf = 10;
|
||||
bool use_stationarity_properties = false;
|
||||
bool use_stationarity_properties_at_init = false;
|
||||
} echo_audibility;
|
||||
|
||||
struct RenderLevels {
|
||||
float active_render_limit = 100.f;
|
||||
float poor_excitation_render_limit = 150.f;
|
||||
float poor_excitation_render_limit_ds8 = 20.f;
|
||||
float render_power_gain_db = 0.f;
|
||||
} render_levels;
|
||||
|
||||
struct EchoRemovalControl {
|
||||
bool has_clock_drift = false;
|
||||
bool linear_and_stable_echo_path = false;
|
||||
} echo_removal_control;
|
||||
|
||||
struct EchoModel {
|
||||
EchoModel();
|
||||
EchoModel(const EchoModel& e);
|
||||
EchoModel& operator=(const EchoModel& e);
|
||||
size_t noise_floor_hold = 50;
|
||||
float min_noise_floor_power = 1638400.f;
|
||||
float stationary_gate_slope = 10.f;
|
||||
float noise_gate_power = 27509.42f;
|
||||
float noise_gate_slope = 0.3f;
|
||||
size_t render_pre_window_size = 1;
|
||||
size_t render_post_window_size = 1;
|
||||
bool model_reverb_in_nonlinear_mode = true;
|
||||
} echo_model;
|
||||
|
||||
struct ComfortNoise {
|
||||
float noise_floor_dbfs = -96.03406f;
|
||||
} comfort_noise;
|
||||
|
||||
struct Suppressor {
|
||||
Suppressor();
|
||||
Suppressor(const Suppressor& e);
|
||||
Suppressor& operator=(const Suppressor& e);
|
||||
|
||||
size_t nearend_average_blocks = 4;
|
||||
|
||||
struct MaskingThresholds {
|
||||
MaskingThresholds(float enr_transparent,
|
||||
float enr_suppress,
|
||||
float emr_transparent);
|
||||
MaskingThresholds(const MaskingThresholds& e);
|
||||
MaskingThresholds& operator=(const MaskingThresholds& e);
|
||||
float enr_transparent;
|
||||
float enr_suppress;
|
||||
float emr_transparent;
|
||||
};
|
||||
|
||||
struct Tuning {
|
||||
Tuning(MaskingThresholds mask_lf,
|
||||
MaskingThresholds mask_hf,
|
||||
float max_inc_factor,
|
||||
float max_dec_factor_lf);
|
||||
Tuning(const Tuning& e);
|
||||
Tuning& operator=(const Tuning& e);
|
||||
MaskingThresholds mask_lf;
|
||||
MaskingThresholds mask_hf;
|
||||
float max_inc_factor;
|
||||
float max_dec_factor_lf;
|
||||
};
|
||||
|
||||
Tuning normal_tuning = Tuning(MaskingThresholds(.3f, .4f, .3f),
|
||||
MaskingThresholds(.07f, .1f, .3f),
|
||||
2.0f,
|
||||
0.25f);
|
||||
Tuning nearend_tuning = Tuning(MaskingThresholds(1.09f, 1.1f, .3f),
|
||||
MaskingThresholds(.1f, .3f, .3f),
|
||||
2.0f,
|
||||
0.25f);
|
||||
|
||||
bool lf_smoothing_during_initial_phase = true;
|
||||
int last_permanent_lf_smoothing_band = 0;
|
||||
int last_lf_smoothing_band = 5;
|
||||
int last_lf_band = 5;
|
||||
int first_hf_band = 8;
|
||||
|
||||
struct DominantNearendDetection {
|
||||
float enr_threshold = .25f;
|
||||
float enr_exit_threshold = 10.f;
|
||||
float snr_threshold = 30.f;
|
||||
int hold_duration = 50;
|
||||
int trigger_threshold = 12;
|
||||
bool use_during_initial_phase = true;
|
||||
bool use_unbounded_echo_spectrum = true;
|
||||
} dominant_nearend_detection;
|
||||
|
||||
struct SubbandNearendDetection {
|
||||
size_t nearend_average_blocks = 1;
|
||||
struct SubbandRegion {
|
||||
size_t low;
|
||||
size_t high;
|
||||
};
|
||||
SubbandRegion subband1 = {1, 1};
|
||||
SubbandRegion subband2 = {1, 1};
|
||||
float nearend_threshold = 1.f;
|
||||
float snr_threshold = 1.f;
|
||||
} subband_nearend_detection;
|
||||
|
||||
bool use_subband_nearend_detection = false;
|
||||
|
||||
struct HighBandsSuppression {
|
||||
float enr_threshold = 1.f;
|
||||
float max_gain_during_echo = 1.f;
|
||||
float anti_howling_activation_threshold = 400.f;
|
||||
float anti_howling_gain = 1.f;
|
||||
} high_bands_suppression;
|
||||
|
||||
float floor_first_increase = 0.00001f;
|
||||
bool conservative_hf_suppression = false;
|
||||
} suppressor;
|
||||
|
||||
struct MultiChannel {
|
||||
bool detect_stereo_content = true;
|
||||
float stereo_detection_threshold = 0.0f;
|
||||
int stereo_detection_timeout_threshold_seconds = 300;
|
||||
float stereo_detection_hysteresis_seconds = 2.0f;
|
||||
} multi_channel;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_ECHO_CANCELLER3_CONFIG_H_
|
75
webrtc/api/audio/echo_control.h
Normal file
75
webrtc/api/audio/echo_control.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_ECHO_CONTROL_H_
|
||||
#define API_AUDIO_ECHO_CONTROL_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioBuffer;
|
||||
|
||||
// Interface for an acoustic echo cancellation (AEC) submodule.
|
||||
class EchoControl {
|
||||
public:
|
||||
// Analysis (not changing) of the render signal.
|
||||
virtual void AnalyzeRender(AudioBuffer* render) = 0;
|
||||
|
||||
// Analysis (not changing) of the capture signal.
|
||||
virtual void AnalyzeCapture(AudioBuffer* capture) = 0;
|
||||
|
||||
// Processes the capture signal in order to remove the echo.
|
||||
virtual void ProcessCapture(AudioBuffer* capture, bool level_change) = 0;
|
||||
|
||||
// As above, but also returns the linear filter output.
|
||||
virtual void ProcessCapture(AudioBuffer* capture,
|
||||
AudioBuffer* linear_output,
|
||||
bool level_change) = 0;
|
||||
|
||||
struct Metrics {
|
||||
double echo_return_loss;
|
||||
double echo_return_loss_enhancement;
|
||||
int delay_ms;
|
||||
};
|
||||
|
||||
// Collect current metrics from the echo controller.
|
||||
virtual Metrics GetMetrics() const = 0;
|
||||
|
||||
// Provides an optional external estimate of the audio buffer delay.
|
||||
virtual void SetAudioBufferDelay(int delay_ms) = 0;
|
||||
|
||||
// Specifies whether the capture output will be used. The purpose of this is
|
||||
// to allow the echo controller to deactivate some of the processing when the
|
||||
// resulting output is anyway not used, for instance when the endpoint is
|
||||
// muted.
|
||||
// TODO(b/177830919): Make pure virtual.
|
||||
virtual void SetCaptureOutputUsage(bool capture_output_used) {}
|
||||
|
||||
// Returns wheter the signal is altered.
|
||||
virtual bool ActiveProcessing() const = 0;
|
||||
|
||||
virtual ~EchoControl() {}
|
||||
};
|
||||
|
||||
// Interface for a factory that creates EchoControllers.
|
||||
class EchoControlFactory {
|
||||
public:
|
||||
virtual std::unique_ptr<EchoControl> Create(int sample_rate_hz,
|
||||
int num_render_channels,
|
||||
int num_capture_channels) = 0;
|
||||
|
||||
virtual ~EchoControlFactory() = default;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_ECHO_CONTROL_H_
|
131
webrtc/api/function_view.h
Normal file
131
webrtc/api/function_view.h
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2016 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_FUNCTION_VIEW_H_
|
||||
#define API_FUNCTION_VIEW_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
// Just like std::function, FunctionView will wrap any callable and hide its
|
||||
// actual type, exposing only its signature. But unlike std::function,
|
||||
// FunctionView doesn't own its callable---it just points to it. Thus, it's a
|
||||
// good choice mainly as a function argument when the callable argument will
|
||||
// not be called again once the function has returned.
|
||||
//
|
||||
// Its constructors are implicit, so that callers won't have to convert lambdas
|
||||
// and other callables to FunctionView<Blah(Blah, Blah)> explicitly. This is
|
||||
// safe because FunctionView is only a reference to the real callable.
|
||||
//
|
||||
// Example use:
|
||||
//
|
||||
// void SomeFunction(rtc::FunctionView<int(int)> index_transform);
|
||||
// ...
|
||||
// SomeFunction([](int i) { return 2 * i + 1; });
|
||||
//
|
||||
// Note: FunctionView is tiny (essentially just two pointers) and trivially
|
||||
// copyable, so it's probably cheaper to pass it by value than by const
|
||||
// reference.
|
||||
|
||||
namespace rtc {
|
||||
|
||||
template <typename T>
|
||||
class FunctionView; // Undefined.
|
||||
|
||||
template <typename RetT, typename... ArgT>
|
||||
class FunctionView<RetT(ArgT...)> final {
|
||||
public:
|
||||
// Constructor for lambdas and other callables; it accepts every type of
|
||||
// argument except those noted in its enable_if call.
|
||||
template <
|
||||
typename F,
|
||||
typename std::enable_if<
|
||||
// Not for function pointers; we have another constructor for that
|
||||
// below.
|
||||
!std::is_function<typename std::remove_pointer<
|
||||
typename std::remove_reference<F>::type>::type>::value &&
|
||||
|
||||
// Not for nullptr; we have another constructor for that below.
|
||||
!std::is_same<std::nullptr_t,
|
||||
typename std::remove_cv<F>::type>::value &&
|
||||
|
||||
// Not for FunctionView objects; we have another constructor for that
|
||||
// (the implicitly declared copy constructor).
|
||||
!std::is_same<FunctionView,
|
||||
typename std::remove_cv<typename std::remove_reference<
|
||||
F>::type>::type>::value>::type* = nullptr>
|
||||
FunctionView(F&& f)
|
||||
: call_(CallVoidPtr<typename std::remove_reference<F>::type>) {
|
||||
f_.void_ptr = &f;
|
||||
}
|
||||
|
||||
// Constructor that accepts function pointers. If the argument is null, the
|
||||
// result is an empty FunctionView.
|
||||
template <
|
||||
typename F,
|
||||
typename std::enable_if<std::is_function<typename std::remove_pointer<
|
||||
typename std::remove_reference<F>::type>::type>::value>::type* =
|
||||
nullptr>
|
||||
FunctionView(F&& f)
|
||||
: call_(f ? CallFunPtr<typename std::remove_pointer<F>::type> : nullptr) {
|
||||
f_.fun_ptr = reinterpret_cast<void (*)()>(f);
|
||||
}
|
||||
|
||||
// Constructor that accepts nullptr. It creates an empty FunctionView.
|
||||
template <typename F,
|
||||
typename std::enable_if<std::is_same<
|
||||
std::nullptr_t,
|
||||
typename std::remove_cv<F>::type>::value>::type* = nullptr>
|
||||
FunctionView(F&& f) : call_(nullptr) {}
|
||||
|
||||
// Default constructor. Creates an empty FunctionView.
|
||||
FunctionView() : call_(nullptr) {}
|
||||
|
||||
RetT operator()(ArgT... args) const {
|
||||
RTC_DCHECK(call_);
|
||||
return call_(f_, std::forward<ArgT>(args)...);
|
||||
}
|
||||
|
||||
// Returns true if we have a function, false if we don't (i.e., we're null).
|
||||
explicit operator bool() const { return !!call_; }
|
||||
|
||||
private:
|
||||
union VoidUnion {
|
||||
void* void_ptr;
|
||||
void (*fun_ptr)();
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
static RetT CallVoidPtr(VoidUnion vu, ArgT... args) {
|
||||
return (*static_cast<F*>(vu.void_ptr))(std::forward<ArgT>(args)...);
|
||||
}
|
||||
template <typename F>
|
||||
static RetT CallFunPtr(VoidUnion vu, ArgT... args) {
|
||||
return (reinterpret_cast<typename std::add_pointer<F>::type>(vu.fun_ptr))(
|
||||
std::forward<ArgT>(args)...);
|
||||
}
|
||||
|
||||
// A pointer to the callable thing, with type information erased. It's a
|
||||
// union because we have to use separate types depending on if the callable
|
||||
// thing is a function pointer or something else.
|
||||
VoidUnion f_;
|
||||
|
||||
// Pointer to a dispatch function that knows the type of the callable thing
|
||||
// that's stored in f_, and how to call it. A FunctionView object is empty
|
||||
// (null) iff call_ is null.
|
||||
RetT (*call_)(VoidUnion, ArgT...);
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // API_FUNCTION_VIEW_H_
|
31
webrtc/api/location.h
Normal file
31
webrtc/api/location.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2023 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_LOCATION_H_
|
||||
#define API_LOCATION_H_
|
||||
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Location provides basic info where of an object was constructed, or was
|
||||
// significantly brought to life. This is a stripped down version of
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:base/location.h
|
||||
// that only specifies an interface compatible to how base::Location is
|
||||
// supposed to be used.
|
||||
// The declaration is overriden inside the Chromium build.
|
||||
class RTC_EXPORT Location {
|
||||
public:
|
||||
static Location Current() { return Location(); }
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_LOCATION_H_
|
130
webrtc/api/make_ref_counted.h
Normal file
130
webrtc/api/make_ref_counted.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2022 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef API_MAKE_REF_COUNTED_H_
|
||||
#define API_MAKE_REF_COUNTED_H_
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/nullability.h"
|
||||
#include "api/ref_count.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "rtc_base/ref_counted_object.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace webrtc_make_ref_counted_internal {
|
||||
// Determines if the given class has AddRef and Release methods.
|
||||
template <typename T>
|
||||
class HasAddRefAndRelease {
|
||||
private:
|
||||
template <typename C,
|
||||
decltype(std::declval<C>().AddRef())* = nullptr,
|
||||
decltype(std::declval<C>().Release())* = nullptr>
|
||||
static int Test(int);
|
||||
template <typename>
|
||||
static char Test(...);
|
||||
|
||||
public:
|
||||
static constexpr bool value = std::is_same_v<decltype(Test<T>(0)), int>;
|
||||
};
|
||||
} // namespace webrtc_make_ref_counted_internal
|
||||
|
||||
// General utilities for constructing a reference counted class and the
|
||||
// appropriate reference count implementation for that class.
|
||||
//
|
||||
// These utilities select either the `RefCountedObject` implementation or
|
||||
// `FinalRefCountedObject` depending on whether the to-be-shared class is
|
||||
// derived from the RefCountInterface interface or not (respectively).
|
||||
|
||||
// `make_ref_counted`:
|
||||
//
|
||||
// Use this when you want to construct a reference counted object of type T and
|
||||
// get a `scoped_refptr<>` back. Example:
|
||||
//
|
||||
// auto p = make_ref_counted<Foo>("bar", 123);
|
||||
//
|
||||
// For a class that inherits from RefCountInterface, this is equivalent to:
|
||||
//
|
||||
// auto p = scoped_refptr<Foo>(new RefCountedObject<Foo>("bar", 123));
|
||||
//
|
||||
// If the class does not inherit from RefCountInterface, but does have
|
||||
// AddRef/Release methods (so a T* is convertible to rtc::scoped_refptr), this
|
||||
// is equivalent to just
|
||||
//
|
||||
// auto p = scoped_refptr<Foo>(new Foo("bar", 123));
|
||||
//
|
||||
// Otherwise, the example is equivalent to:
|
||||
//
|
||||
// auto p = scoped_refptr<FinalRefCountedObject<Foo>>(
|
||||
// new FinalRefCountedObject<Foo>("bar", 123));
|
||||
//
|
||||
// In these cases, `make_ref_counted` reduces the amount of boilerplate code but
|
||||
// also helps with the most commonly intended usage of RefCountedObject whereby
|
||||
// methods for reference counting, are virtual and designed to satisfy the need
|
||||
// of an interface. When such a need does not exist, it is more efficient to use
|
||||
// the `FinalRefCountedObject` template, which does not add the vtable overhead.
|
||||
//
|
||||
// Note that in some cases, using RefCountedObject directly may still be what's
|
||||
// needed.
|
||||
|
||||
// `make_ref_counted` for abstract classes that are convertible to
|
||||
// RefCountInterface. The is_abstract requirement rejects classes that inherit
|
||||
// both RefCountInterface and RefCounted object, which is a a discouraged
|
||||
// pattern, and would result in double inheritance of RefCountedObject if this
|
||||
// template was applied.
|
||||
template <
|
||||
typename T,
|
||||
typename... Args,
|
||||
typename std::enable_if<std::is_convertible_v<T*, RefCountInterface*> &&
|
||||
std::is_abstract_v<T>,
|
||||
T>::type* = nullptr>
|
||||
absl::Nonnull<scoped_refptr<T>> make_ref_counted(Args&&... args) {
|
||||
return scoped_refptr<T>(new RefCountedObject<T>(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
// `make_ref_counted` for complete classes that are not convertible to
|
||||
// RefCountInterface and already carry a ref count.
|
||||
template <
|
||||
typename T,
|
||||
typename... Args,
|
||||
typename std::enable_if<
|
||||
!std::is_convertible_v<T*, RefCountInterface*> &&
|
||||
webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value,
|
||||
T>::type* = nullptr>
|
||||
absl::Nonnull<scoped_refptr<T>> make_ref_counted(Args&&... args) {
|
||||
return scoped_refptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
// `make_ref_counted` for complete classes that are not convertible to
|
||||
// RefCountInterface and have no ref count of their own.
|
||||
template <
|
||||
typename T,
|
||||
typename... Args,
|
||||
typename std::enable_if<
|
||||
!std::is_convertible_v<T*, RefCountInterface*> &&
|
||||
!webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value,
|
||||
|
||||
T>::type* = nullptr>
|
||||
absl::Nonnull<scoped_refptr<FinalRefCountedObject<T>>> make_ref_counted(
|
||||
Args&&... args) {
|
||||
return scoped_refptr<FinalRefCountedObject<T>>(
|
||||
new FinalRefCountedObject<T>(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
namespace rtc {
|
||||
// Backwards compatibe alias.
|
||||
// TODO: bugs.webrtc.org/42225969 - deprecate and remove.
|
||||
using ::webrtc::make_ref_counted;
|
||||
} // namespace rtc
|
||||
|
||||
#endif // API_MAKE_REF_COUNTED_H_
|
50
webrtc/api/meson.build
Normal file
50
webrtc/api/meson.build
Normal file
@ -0,0 +1,50 @@
|
||||
api_sources = [
|
||||
'audio/audio_frame.cc',
|
||||
'audio/audio_processing.cc',
|
||||
'audio/audio_processing_statistics.cc',
|
||||
'audio/channel_layout.cc',
|
||||
'audio/echo_canceller3_config.cc',
|
||||
'rtp_headers.cc',
|
||||
'rtp_packet_info.cc',
|
||||
'task_queue/task_queue_base.cc',
|
||||
'units/frequency.cc',
|
||||
'units/time_delta.cc',
|
||||
'units/timestamp.cc',
|
||||
'video/color_space.cc',
|
||||
'video/hdr_metadata.cc',
|
||||
'video/video_content_type.cc',
|
||||
'video/video_timing.cc',
|
||||
]
|
||||
|
||||
api_headers = [
|
||||
['', 'array_view.h'],
|
||||
['', 'location.h'],
|
||||
['', 'ref_count.h'],
|
||||
['', 'scoped_refptr.h'],
|
||||
['audio', 'audio_processing.h'],
|
||||
['audio', 'audio_processing_statistics.h'],
|
||||
['audio', 'echo_canceller3_config.h'],
|
||||
['audio', 'echo_control.h'],
|
||||
['task_queue', 'task_queue_base.h'],
|
||||
['units', 'time_delta.h'],
|
||||
]
|
||||
|
||||
foreach h : api_headers
|
||||
install_headers(
|
||||
join_paths(h[0], h[1]),
|
||||
subdir: join_paths(include_subdir, 'api', h[0])
|
||||
)
|
||||
endforeach
|
||||
|
||||
|
||||
libapi = static_library('libapi',
|
||||
api_sources,
|
||||
dependencies: common_deps,
|
||||
include_directories: webrtc_inc,
|
||||
cpp_args : common_cxxflags
|
||||
)
|
||||
|
||||
api_dep = declare_dependency(
|
||||
link_with: libapi
|
||||
)
|
||||
|
67
webrtc/api/ref_count.h
Normal file
67
webrtc/api/ref_count.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef API_REF_COUNT_H_
|
||||
#define API_REF_COUNT_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Refcounted objects should implement the following informal interface:
|
||||
//
|
||||
// void AddRef() const ;
|
||||
// RefCountReleaseStatus Release() const;
|
||||
//
|
||||
// You may access members of a reference-counted object, including the AddRef()
|
||||
// and Release() methods, only if you already own a reference to it, or if
|
||||
// you're borrowing someone else's reference. (A newly created object is a
|
||||
// special case: the reference count is zero on construction, and the code that
|
||||
// creates the object should immediately call AddRef(), bringing the reference
|
||||
// count from zero to one, e.g., by constructing an rtc::scoped_refptr).
|
||||
//
|
||||
// AddRef() creates a new reference to the object.
|
||||
//
|
||||
// Release() releases a reference to the object; the caller now has one less
|
||||
// reference than before the call. Returns kDroppedLastRef if the number of
|
||||
// references dropped to zero because of this (in which case the object destroys
|
||||
// itself). Otherwise, returns kOtherRefsRemained, to signal that at the precise
|
||||
// time the caller's reference was dropped, other references still remained (but
|
||||
// if other threads own references, this may of course have changed by the time
|
||||
// Release() returns).
|
||||
//
|
||||
// The caller of Release() must treat it in the same way as a delete operation:
|
||||
// Regardless of the return value from Release(), the caller mustn't access the
|
||||
// object. The object might still be alive, due to references held by other
|
||||
// users of the object, but the object can go away at any time, e.g., as the
|
||||
// result of another thread calling Release().
|
||||
//
|
||||
// Calling AddRef() and Release() manually is discouraged. It's recommended to
|
||||
// use rtc::scoped_refptr to manage all pointers to reference counted objects.
|
||||
// Note that rtc::scoped_refptr depends on compile-time duck-typing; formally
|
||||
// implementing the below RefCountInterface is not required.
|
||||
|
||||
enum class RefCountReleaseStatus { kDroppedLastRef, kOtherRefsRemained };
|
||||
|
||||
// Interfaces where refcounting is part of the public api should
|
||||
// inherit this abstract interface. The implementation of these
|
||||
// methods is usually provided by the RefCountedObject template class,
|
||||
// applied as a leaf in the inheritance tree.
|
||||
class RefCountInterface {
|
||||
public:
|
||||
virtual void AddRef() const = 0;
|
||||
virtual RefCountReleaseStatus Release() const = 0;
|
||||
|
||||
// Non-public destructor, because Release() has exclusive responsibility for
|
||||
// destroying the object.
|
||||
protected:
|
||||
virtual ~RefCountInterface() {}
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_REF_COUNT_H_
|
107
webrtc/api/ref_counted_base.h
Normal file
107
webrtc/api/ref_counted_base.h
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef API_REF_COUNTED_BASE_H_
|
||||
#define API_REF_COUNTED_BASE_H_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "api/ref_count.h"
|
||||
#include "rtc_base/ref_counter.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RefCountedBase {
|
||||
public:
|
||||
RefCountedBase() = default;
|
||||
|
||||
RefCountedBase(const RefCountedBase&) = delete;
|
||||
RefCountedBase& operator=(const RefCountedBase&) = delete;
|
||||
|
||||
void AddRef() const { ref_count_.IncRef(); }
|
||||
RefCountReleaseStatus Release() const {
|
||||
const auto status = ref_count_.DecRef();
|
||||
if (status == RefCountReleaseStatus::kDroppedLastRef) {
|
||||
delete this;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Provided for internal webrtc subclasses for corner cases where it's
|
||||
// necessary to know whether or not a reference is exclusively held.
|
||||
bool HasOneRef() const { return ref_count_.HasOneRef(); }
|
||||
|
||||
virtual ~RefCountedBase() = default;
|
||||
|
||||
private:
|
||||
mutable webrtc::webrtc_impl::RefCounter ref_count_{0};
|
||||
};
|
||||
|
||||
// Template based version of `RefCountedBase` for simple implementations that do
|
||||
// not need (or want) destruction via virtual destructor or the overhead of a
|
||||
// vtable.
|
||||
//
|
||||
// To use:
|
||||
// struct MyInt : public rtc::RefCountedNonVirtual<MyInt> {
|
||||
// int foo_ = 0;
|
||||
// };
|
||||
//
|
||||
// rtc::scoped_refptr<MyInt> my_int(new MyInt());
|
||||
//
|
||||
// sizeof(MyInt) on a 32 bit system would then be 8, int + refcount and no
|
||||
// vtable generated.
|
||||
template <typename T>
|
||||
class RefCountedNonVirtual {
|
||||
public:
|
||||
RefCountedNonVirtual() = default;
|
||||
|
||||
RefCountedNonVirtual(const RefCountedNonVirtual&) = delete;
|
||||
RefCountedNonVirtual& operator=(const RefCountedNonVirtual&) = delete;
|
||||
|
||||
void AddRef() const { ref_count_.IncRef(); }
|
||||
RefCountReleaseStatus Release() const {
|
||||
// If you run into this assert, T has virtual methods. There are two
|
||||
// options:
|
||||
// 1) The class doesn't actually need virtual methods, the type is complete
|
||||
// so the virtual attribute(s) can be removed.
|
||||
// 2) The virtual methods are a part of the design of the class. In this
|
||||
// case you can consider using `RefCountedBase` instead or alternatively
|
||||
// use `rtc::RefCountedObject`.
|
||||
static_assert(!std::is_polymorphic<T>::value,
|
||||
"T has virtual methods. RefCountedBase is a better fit.");
|
||||
const auto status = ref_count_.DecRef();
|
||||
if (status == RefCountReleaseStatus::kDroppedLastRef) {
|
||||
delete static_cast<const T*>(this);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Provided for internal webrtc subclasses for corner cases where it's
|
||||
// necessary to know whether or not a reference is exclusively held.
|
||||
bool HasOneRef() const { return ref_count_.HasOneRef(); }
|
||||
|
||||
~RefCountedNonVirtual() = default;
|
||||
|
||||
private:
|
||||
mutable webrtc::webrtc_impl::RefCounter ref_count_{0};
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
// Backwards compatibe aliases.
|
||||
// TODO: https://issues.webrtc.org/42225969 - deprecate and remove.
|
||||
namespace rtc {
|
||||
using RefCountedBase = webrtc::RefCountedBase;
|
||||
template <typename T>
|
||||
using RefCountedNonVirtual = webrtc::RefCountedNonVirtual<T>;
|
||||
} // namespace rtc
|
||||
|
||||
#endif // API_REF_COUNTED_BASE_H_
|
62
webrtc/api/rtp_headers.cc
Normal file
62
webrtc/api/rtp_headers.cc
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/rtp_headers.h"
|
||||
|
||||
#include "api/video/video_content_type.h"
|
||||
#include "api/video/video_rotation.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
AudioLevel::AudioLevel() : voice_activity_(false), audio_level_(0) {}
|
||||
|
||||
AudioLevel::AudioLevel(bool voice_activity, int audio_level)
|
||||
: voice_activity_(voice_activity), audio_level_(audio_level) {
|
||||
RTC_CHECK_GE(audio_level, 0);
|
||||
RTC_CHECK_LE(audio_level, 127);
|
||||
}
|
||||
|
||||
RTPHeaderExtension::RTPHeaderExtension()
|
||||
: hasTransmissionTimeOffset(false),
|
||||
transmissionTimeOffset(0),
|
||||
hasAbsoluteSendTime(false),
|
||||
absoluteSendTime(0),
|
||||
hasTransportSequenceNumber(false),
|
||||
transportSequenceNumber(0),
|
||||
hasVideoRotation(false),
|
||||
videoRotation(kVideoRotation_0),
|
||||
hasVideoContentType(false),
|
||||
videoContentType(VideoContentType::UNSPECIFIED),
|
||||
has_video_timing(false) {}
|
||||
|
||||
RTPHeaderExtension::RTPHeaderExtension(const RTPHeaderExtension& other) =
|
||||
default;
|
||||
|
||||
RTPHeaderExtension& RTPHeaderExtension::operator=(
|
||||
const RTPHeaderExtension& other) = default;
|
||||
|
||||
RTPHeader::RTPHeader()
|
||||
: markerBit(false),
|
||||
payloadType(0),
|
||||
sequenceNumber(0),
|
||||
timestamp(0),
|
||||
ssrc(0),
|
||||
numCSRCs(0),
|
||||
arrOfCSRCs(),
|
||||
paddingLength(0),
|
||||
headerLength(0),
|
||||
extension() {}
|
||||
|
||||
RTPHeader::RTPHeader(const RTPHeader& other) = default;
|
||||
|
||||
RTPHeader& RTPHeader::operator=(const RTPHeader& other) = default;
|
||||
|
||||
} // namespace webrtc
|
208
webrtc/api/rtp_headers.h
Normal file
208
webrtc/api/rtp_headers.h
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_RTP_HEADERS_H_
|
||||
#define API_RTP_HEADERS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "api/units/timestamp.h"
|
||||
#include "api/video/color_space.h"
|
||||
#include "api/video/video_content_type.h"
|
||||
#include "api/video/video_rotation.h"
|
||||
#include "api/video/video_timing.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
struct FeedbackRequest {
|
||||
// Determines whether the recv delta as specified in
|
||||
// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01
|
||||
// should be included.
|
||||
bool include_timestamps;
|
||||
// Include feedback of received packets in the range [sequence_number -
|
||||
// sequence_count + 1, sequence_number]. That is, no feedback will be sent if
|
||||
// sequence_count is zero.
|
||||
int sequence_count;
|
||||
};
|
||||
|
||||
// The Absolute Capture Time extension is used to stamp RTP packets with a NTP
|
||||
// timestamp showing when the first audio or video frame in a packet was
|
||||
// originally captured. The intent of this extension is to provide a way to
|
||||
// accomplish audio-to-video synchronization when RTCP-terminating intermediate
|
||||
// systems (e.g. mixers) are involved. See:
|
||||
// http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time
|
||||
struct AbsoluteCaptureTime {
|
||||
// Absolute capture timestamp is the NTP timestamp of when the first frame in
|
||||
// a packet was originally captured. This timestamp MUST be based on the same
|
||||
// clock as the clock used to generate NTP timestamps for RTCP sender reports
|
||||
// on the capture system.
|
||||
//
|
||||
// It’s not always possible to do an NTP clock readout at the exact moment of
|
||||
// when a media frame is captured. A capture system MAY postpone the readout
|
||||
// until a more convenient time. A capture system SHOULD have known delays
|
||||
// (e.g. from hardware buffers) subtracted from the readout to make the final
|
||||
// timestamp as close to the actual capture time as possible.
|
||||
//
|
||||
// This field is encoded as a 64-bit unsigned fixed-point number with the high
|
||||
// 32 bits for the timestamp in seconds and low 32 bits for the fractional
|
||||
// part. This is also known as the UQ32.32 format and is what the RTP
|
||||
// specification defines as the canonical format to represent NTP timestamps.
|
||||
uint64_t absolute_capture_timestamp;
|
||||
|
||||
// Estimated capture clock offset is the sender’s estimate of the offset
|
||||
// between its own NTP clock and the capture system’s NTP clock. The sender is
|
||||
// here defined as the system that owns the NTP clock used to generate the NTP
|
||||
// timestamps for the RTCP sender reports on this stream. The sender system is
|
||||
// typically either the capture system or a mixer.
|
||||
//
|
||||
// This field is encoded as a 64-bit two’s complement signed fixed-point
|
||||
// number with the high 32 bits for the seconds and low 32 bits for the
|
||||
// fractional part. It’s intended to make it easy for a receiver, that knows
|
||||
// how to estimate the sender system’s NTP clock, to also estimate the capture
|
||||
// system’s NTP clock:
|
||||
//
|
||||
// Capture NTP Clock = Sender NTP Clock + Capture Clock Offset
|
||||
std::optional<int64_t> estimated_capture_clock_offset;
|
||||
};
|
||||
|
||||
// The audio level extension is used to indicate the voice activity and the
|
||||
// audio level of the payload in the RTP stream. See:
|
||||
// https://tools.ietf.org/html/rfc6464#section-3.
|
||||
class AudioLevel {
|
||||
public:
|
||||
AudioLevel();
|
||||
AudioLevel(bool voice_activity, int audio_level);
|
||||
AudioLevel(const AudioLevel& other) = default;
|
||||
AudioLevel& operator=(const AudioLevel& other) = default;
|
||||
|
||||
// Flag indicating whether the encoder believes the audio packet contains
|
||||
// voice activity.
|
||||
bool voice_activity() const { return voice_activity_; }
|
||||
|
||||
// Audio level in -dBov. Values range from 0 to 127, representing 0 to -127
|
||||
// dBov. 127 represents digital silence.
|
||||
int level() const { return audio_level_; }
|
||||
|
||||
private:
|
||||
bool voice_activity_;
|
||||
int audio_level_;
|
||||
};
|
||||
|
||||
inline bool operator==(const AbsoluteCaptureTime& lhs,
|
||||
const AbsoluteCaptureTime& rhs) {
|
||||
return (lhs.absolute_capture_timestamp == rhs.absolute_capture_timestamp) &&
|
||||
(lhs.estimated_capture_clock_offset ==
|
||||
rhs.estimated_capture_clock_offset);
|
||||
}
|
||||
|
||||
inline bool operator!=(const AbsoluteCaptureTime& lhs,
|
||||
const AbsoluteCaptureTime& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
struct RTPHeaderExtension {
|
||||
RTPHeaderExtension();
|
||||
RTPHeaderExtension(const RTPHeaderExtension& other);
|
||||
RTPHeaderExtension& operator=(const RTPHeaderExtension& other);
|
||||
|
||||
static constexpr int kAbsSendTimeFraction = 18;
|
||||
|
||||
Timestamp GetAbsoluteSendTimestamp() const {
|
||||
RTC_DCHECK(hasAbsoluteSendTime);
|
||||
RTC_DCHECK(absoluteSendTime < (1ul << 24));
|
||||
return Timestamp::Micros((absoluteSendTime * 1000000ll) /
|
||||
(1 << kAbsSendTimeFraction));
|
||||
}
|
||||
|
||||
bool hasTransmissionTimeOffset;
|
||||
int32_t transmissionTimeOffset;
|
||||
bool hasAbsoluteSendTime;
|
||||
uint32_t absoluteSendTime;
|
||||
std::optional<AbsoluteCaptureTime> absolute_capture_time;
|
||||
bool hasTransportSequenceNumber;
|
||||
uint16_t transportSequenceNumber;
|
||||
std::optional<FeedbackRequest> feedback_request;
|
||||
|
||||
// Audio Level includes both level in dBov and voiced/unvoiced bit. See:
|
||||
// https://tools.ietf.org/html/rfc6464#section-3
|
||||
std::optional<AudioLevel> audio_level() const { return audio_level_; }
|
||||
|
||||
void set_audio_level(std::optional<AudioLevel> audio_level) {
|
||||
audio_level_ = audio_level;
|
||||
}
|
||||
|
||||
// For Coordination of Video Orientation. See
|
||||
// http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/
|
||||
// ts_126114v120700p.pdf
|
||||
bool hasVideoRotation;
|
||||
VideoRotation videoRotation;
|
||||
|
||||
// TODO(ilnik): Refactor this and one above to be std::optional() and remove
|
||||
// a corresponding bool flag.
|
||||
bool hasVideoContentType;
|
||||
VideoContentType videoContentType;
|
||||
|
||||
bool has_video_timing;
|
||||
VideoSendTiming video_timing;
|
||||
|
||||
VideoPlayoutDelay playout_delay;
|
||||
|
||||
// For identification of a stream when ssrc is not signaled. See
|
||||
// https://tools.ietf.org/html/rfc8852
|
||||
std::string stream_id;
|
||||
std::string repaired_stream_id;
|
||||
|
||||
// For identifying the media section used to interpret this RTP packet. See
|
||||
// https://tools.ietf.org/html/rfc8843
|
||||
std::string mid;
|
||||
|
||||
std::optional<ColorSpace> color_space;
|
||||
|
||||
private:
|
||||
std::optional<AudioLevel> audio_level_;
|
||||
};
|
||||
|
||||
enum { kRtpCsrcSize = 15 }; // RFC 3550 page 13
|
||||
|
||||
struct RTC_EXPORT RTPHeader {
|
||||
RTPHeader();
|
||||
RTPHeader(const RTPHeader& other);
|
||||
RTPHeader& operator=(const RTPHeader& other);
|
||||
|
||||
bool markerBit;
|
||||
uint8_t payloadType;
|
||||
uint16_t sequenceNumber;
|
||||
uint32_t timestamp;
|
||||
uint32_t ssrc;
|
||||
uint8_t numCSRCs;
|
||||
uint32_t arrOfCSRCs[kRtpCsrcSize];
|
||||
size_t paddingLength;
|
||||
size_t headerLength;
|
||||
RTPHeaderExtension extension;
|
||||
};
|
||||
|
||||
// RTCP mode to use. Compound mode is described by RFC 4585 and reduced-size
|
||||
// RTCP mode is described by RFC 5506.
|
||||
enum class RtcpMode { kOff, kCompound, kReducedSize };
|
||||
|
||||
enum NetworkState {
|
||||
kNetworkUp,
|
||||
kNetworkDown,
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_RTP_HEADERS_H_
|
63
webrtc/api/rtp_packet_info.cc
Normal file
63
webrtc/api/rtp_packet_info.cc
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/rtp_packet_info.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "api/rtp_headers.h"
|
||||
#include "api/units/timestamp.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
RtpPacketInfo::RtpPacketInfo()
|
||||
: ssrc_(0), rtp_timestamp_(0), receive_time_(Timestamp::MinusInfinity()) {}
|
||||
|
||||
RtpPacketInfo::RtpPacketInfo(uint32_t ssrc,
|
||||
std::vector<uint32_t> csrcs,
|
||||
uint32_t rtp_timestamp,
|
||||
Timestamp receive_time)
|
||||
: ssrc_(ssrc),
|
||||
csrcs_(std::move(csrcs)),
|
||||
rtp_timestamp_(rtp_timestamp),
|
||||
receive_time_(receive_time) {}
|
||||
|
||||
RtpPacketInfo::RtpPacketInfo(const RTPHeader& rtp_header,
|
||||
Timestamp receive_time)
|
||||
: ssrc_(rtp_header.ssrc),
|
||||
rtp_timestamp_(rtp_header.timestamp),
|
||||
receive_time_(receive_time) {
|
||||
const auto& extension = rtp_header.extension;
|
||||
const auto csrcs_count = std::min<size_t>(rtp_header.numCSRCs, kRtpCsrcSize);
|
||||
|
||||
csrcs_.assign(&rtp_header.arrOfCSRCs[0], &rtp_header.arrOfCSRCs[csrcs_count]);
|
||||
|
||||
if (extension.audio_level()) {
|
||||
audio_level_ = extension.audio_level()->level();
|
||||
}
|
||||
|
||||
absolute_capture_time_ = extension.absolute_capture_time;
|
||||
}
|
||||
|
||||
bool operator==(const RtpPacketInfo& lhs, const RtpPacketInfo& rhs) {
|
||||
return (lhs.ssrc() == rhs.ssrc()) && (lhs.csrcs() == rhs.csrcs()) &&
|
||||
(lhs.rtp_timestamp() == rhs.rtp_timestamp()) &&
|
||||
(lhs.receive_time() == rhs.receive_time()) &&
|
||||
(lhs.audio_level() == rhs.audio_level()) &&
|
||||
(lhs.absolute_capture_time() == rhs.absolute_capture_time()) &&
|
||||
(lhs.local_capture_clock_offset() == rhs.local_capture_clock_offset());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
117
webrtc/api/rtp_packet_info.h
Normal file
117
webrtc/api/rtp_packet_info.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_RTP_PACKET_INFO_H_
|
||||
#define API_RTP_PACKET_INFO_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "api/rtp_headers.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
//
|
||||
// Structure to hold information about a received `RtpPacket`. It is primarily
|
||||
// used to carry per-packet information from when a packet is received until
|
||||
// the information is passed to `SourceTracker`.
|
||||
//
|
||||
class RTC_EXPORT RtpPacketInfo {
|
||||
public:
|
||||
RtpPacketInfo();
|
||||
|
||||
RtpPacketInfo(uint32_t ssrc,
|
||||
std::vector<uint32_t> csrcs,
|
||||
uint32_t rtp_timestamp,
|
||||
Timestamp receive_time);
|
||||
|
||||
RtpPacketInfo(const RTPHeader& rtp_header, Timestamp receive_time);
|
||||
|
||||
RtpPacketInfo(const RtpPacketInfo& other) = default;
|
||||
RtpPacketInfo(RtpPacketInfo&& other) = default;
|
||||
RtpPacketInfo& operator=(const RtpPacketInfo& other) = default;
|
||||
RtpPacketInfo& operator=(RtpPacketInfo&& other) = default;
|
||||
|
||||
uint32_t ssrc() const { return ssrc_; }
|
||||
void set_ssrc(uint32_t value) { ssrc_ = value; }
|
||||
|
||||
const std::vector<uint32_t>& csrcs() const { return csrcs_; }
|
||||
void set_csrcs(std::vector<uint32_t> value) { csrcs_ = std::move(value); }
|
||||
|
||||
uint32_t rtp_timestamp() const { return rtp_timestamp_; }
|
||||
void set_rtp_timestamp(uint32_t value) { rtp_timestamp_ = value; }
|
||||
|
||||
Timestamp receive_time() const { return receive_time_; }
|
||||
void set_receive_time(Timestamp value) { receive_time_ = value; }
|
||||
|
||||
std::optional<uint8_t> audio_level() const { return audio_level_; }
|
||||
RtpPacketInfo& set_audio_level(std::optional<uint8_t> value) {
|
||||
audio_level_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const std::optional<AbsoluteCaptureTime>& absolute_capture_time() const {
|
||||
return absolute_capture_time_;
|
||||
}
|
||||
RtpPacketInfo& set_absolute_capture_time(
|
||||
const std::optional<AbsoluteCaptureTime>& value) {
|
||||
absolute_capture_time_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const std::optional<TimeDelta>& local_capture_clock_offset() const {
|
||||
return local_capture_clock_offset_;
|
||||
}
|
||||
RtpPacketInfo& set_local_capture_clock_offset(
|
||||
std::optional<TimeDelta> value) {
|
||||
local_capture_clock_offset_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
// Fields from the RTP header:
|
||||
// https://tools.ietf.org/html/rfc3550#section-5.1
|
||||
uint32_t ssrc_;
|
||||
std::vector<uint32_t> csrcs_;
|
||||
uint32_t rtp_timestamp_;
|
||||
|
||||
// Local `webrtc::Clock`-based timestamp of when the packet was received.
|
||||
Timestamp receive_time_;
|
||||
|
||||
// Fields from the Audio Level header extension:
|
||||
// https://tools.ietf.org/html/rfc6464#section-3
|
||||
std::optional<uint8_t> audio_level_;
|
||||
|
||||
// Fields from the Absolute Capture Time header extension:
|
||||
// http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time
|
||||
std::optional<AbsoluteCaptureTime> absolute_capture_time_;
|
||||
|
||||
// Clock offset between the local clock and the capturer's clock.
|
||||
// Do not confuse with `AbsoluteCaptureTime::estimated_capture_clock_offset`
|
||||
// which instead represents the clock offset between a remote sender and the
|
||||
// capturer. The following holds:
|
||||
// Capture's NTP Clock = Local NTP Clock + Local-Capture Clock Offset
|
||||
std::optional<TimeDelta> local_capture_clock_offset_;
|
||||
};
|
||||
|
||||
bool operator==(const RtpPacketInfo& lhs, const RtpPacketInfo& rhs);
|
||||
|
||||
inline bool operator!=(const RtpPacketInfo& lhs, const RtpPacketInfo& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_RTP_PACKET_INFO_H_
|
130
webrtc/api/rtp_packet_infos.h
Normal file
130
webrtc/api/rtp_packet_infos.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_RTP_PACKET_INFOS_H_
|
||||
#define API_RTP_PACKET_INFOS_H_
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "api/make_ref_counted.h"
|
||||
#include "api/ref_counted_base.h"
|
||||
#include "api/rtp_packet_info.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Semi-immutable structure to hold information about packets used to assemble
|
||||
// an audio or video frame. Uses internal reference counting to make it very
|
||||
// cheap to copy.
|
||||
//
|
||||
// We should ideally just use `std::vector<RtpPacketInfo>` and have it
|
||||
// `std::move()`-ed as the per-packet information is transferred from one object
|
||||
// to another. But moving the info, instead of copying it, is not easily done
|
||||
// for the current video code.
|
||||
class RTC_EXPORT RtpPacketInfos {
|
||||
public:
|
||||
using vector_type = std::vector<RtpPacketInfo>;
|
||||
|
||||
using value_type = vector_type::value_type;
|
||||
using size_type = vector_type::size_type;
|
||||
using difference_type = vector_type::difference_type;
|
||||
using const_reference = vector_type::const_reference;
|
||||
using const_pointer = vector_type::const_pointer;
|
||||
using const_iterator = vector_type::const_iterator;
|
||||
using const_reverse_iterator = vector_type::const_reverse_iterator;
|
||||
|
||||
using reference = const_reference;
|
||||
using pointer = const_pointer;
|
||||
using iterator = const_iterator;
|
||||
using reverse_iterator = const_reverse_iterator;
|
||||
|
||||
RtpPacketInfos() {}
|
||||
explicit RtpPacketInfos(const vector_type& entries)
|
||||
: data_(Data::Create(entries)) {}
|
||||
|
||||
explicit RtpPacketInfos(vector_type&& entries)
|
||||
: data_(Data::Create(std::move(entries))) {}
|
||||
|
||||
RtpPacketInfos(const RtpPacketInfos& other) = default;
|
||||
RtpPacketInfos(RtpPacketInfos&& other) = default;
|
||||
RtpPacketInfos& operator=(const RtpPacketInfos& other) = default;
|
||||
RtpPacketInfos& operator=(RtpPacketInfos&& other) = default;
|
||||
|
||||
const_reference operator[](size_type pos) const { return entries()[pos]; }
|
||||
|
||||
const_reference at(size_type pos) const { return entries().at(pos); }
|
||||
const_reference front() const { return entries().front(); }
|
||||
const_reference back() const { return entries().back(); }
|
||||
|
||||
const_iterator begin() const { return entries().begin(); }
|
||||
const_iterator end() const { return entries().end(); }
|
||||
const_reverse_iterator rbegin() const { return entries().rbegin(); }
|
||||
const_reverse_iterator rend() const { return entries().rend(); }
|
||||
|
||||
const_iterator cbegin() const { return entries().cbegin(); }
|
||||
const_iterator cend() const { return entries().cend(); }
|
||||
const_reverse_iterator crbegin() const { return entries().crbegin(); }
|
||||
const_reverse_iterator crend() const { return entries().crend(); }
|
||||
|
||||
bool empty() const { return entries().empty(); }
|
||||
size_type size() const { return entries().size(); }
|
||||
|
||||
private:
|
||||
class Data final : public rtc::RefCountedNonVirtual<Data> {
|
||||
public:
|
||||
static rtc::scoped_refptr<Data> Create(const vector_type& entries) {
|
||||
// Performance optimization for the empty case.
|
||||
if (entries.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return rtc::make_ref_counted<Data>(entries);
|
||||
}
|
||||
|
||||
static rtc::scoped_refptr<Data> Create(vector_type&& entries) {
|
||||
// Performance optimization for the empty case.
|
||||
if (entries.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return rtc::make_ref_counted<Data>(std::move(entries));
|
||||
}
|
||||
|
||||
const vector_type& entries() const { return entries_; }
|
||||
|
||||
explicit Data(const vector_type& entries) : entries_(entries) {}
|
||||
explicit Data(vector_type&& entries) : entries_(std::move(entries)) {}
|
||||
~Data() = default;
|
||||
|
||||
private:
|
||||
const vector_type entries_;
|
||||
};
|
||||
|
||||
static const vector_type& empty_entries() {
|
||||
static const vector_type& value = *new vector_type();
|
||||
return value;
|
||||
}
|
||||
|
||||
const vector_type& entries() const {
|
||||
if (data_ != nullptr) {
|
||||
return data_->entries();
|
||||
} else {
|
||||
return empty_entries();
|
||||
}
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<Data> data_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_RTP_PACKET_INFOS_H_
|
229
webrtc/api/scoped_refptr.h
Normal file
229
webrtc/api/scoped_refptr.h
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Originally these classes are from Chromium.
|
||||
// http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/ref_counted.h?view=markup
|
||||
|
||||
//
|
||||
// A smart pointer class for reference counted objects. Use this class instead
|
||||
// of calling AddRef and Release manually on a reference counted object to
|
||||
// avoid common memory leaks caused by forgetting to Release an object
|
||||
// reference. Sample usage:
|
||||
//
|
||||
// class MyFoo : public RefCounted<MyFoo> {
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
// void some_function() {
|
||||
// scoped_refptr<MyFoo> foo = make_ref_counted<MyFoo>();
|
||||
// foo->Method(param);
|
||||
// // `foo` is released when this function returns
|
||||
// }
|
||||
//
|
||||
// void some_other_function() {
|
||||
// scoped_refptr<MyFoo> foo = make_ref_counted<MyFoo>();
|
||||
// ...
|
||||
// foo = nullptr; // explicitly releases `foo`
|
||||
// ...
|
||||
// if (foo)
|
||||
// foo->Method(param);
|
||||
// }
|
||||
//
|
||||
// The above examples show how scoped_refptr<T> acts like a pointer to T.
|
||||
// Given two scoped_refptr<T> classes, it is also possible to exchange
|
||||
// references between the two objects, like so:
|
||||
//
|
||||
// {
|
||||
// scoped_refptr<MyFoo> a = make_ref_counted<MyFoo>();
|
||||
// scoped_refptr<MyFoo> b;
|
||||
//
|
||||
// b.swap(a);
|
||||
// // now, `b` references the MyFoo object, and `a` references null.
|
||||
// }
|
||||
//
|
||||
// To make both `a` and `b` in the above example reference the same MyFoo
|
||||
// object, simply use the assignment operator:
|
||||
//
|
||||
// {
|
||||
// scoped_refptr<MyFoo> a = make_ref_counted<MyFoo>();
|
||||
// scoped_refptr<MyFoo> b;
|
||||
//
|
||||
// b = a;
|
||||
// // now, `a` and `b` each own a reference to the same MyFoo object.
|
||||
// }
|
||||
//
|
||||
|
||||
#ifndef API_SCOPED_REFPTR_H_
|
||||
#define API_SCOPED_REFPTR_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/nullability.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
template <class T>
|
||||
class ABSL_NULLABILITY_COMPATIBLE scoped_refptr {
|
||||
public:
|
||||
using absl_nullability_compatible = void;
|
||||
using element_type = T;
|
||||
|
||||
scoped_refptr() : ptr_(nullptr) {}
|
||||
scoped_refptr(std::nullptr_t) : ptr_(nullptr) {} // NOLINT(runtime/explicit)
|
||||
|
||||
explicit scoped_refptr(absl::Nullable<T*> p) : ptr_(p) {
|
||||
if (ptr_)
|
||||
ptr_->AddRef();
|
||||
}
|
||||
|
||||
scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
|
||||
if (ptr_)
|
||||
ptr_->AddRef();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
|
||||
if (ptr_)
|
||||
ptr_->AddRef();
|
||||
}
|
||||
|
||||
// Move constructors.
|
||||
scoped_refptr(scoped_refptr<T>&& r) noexcept : ptr_(r.release()) {}
|
||||
|
||||
template <typename U>
|
||||
scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.release()) {}
|
||||
|
||||
~scoped_refptr() {
|
||||
if (ptr_)
|
||||
ptr_->Release();
|
||||
}
|
||||
|
||||
T* get() const { return ptr_; }
|
||||
explicit operator bool() const { return ptr_ != nullptr; }
|
||||
T& operator*() const { return *ptr_; }
|
||||
T* operator->() const { return ptr_; }
|
||||
|
||||
// Returns the (possibly null) raw pointer, and makes the scoped_refptr hold a
|
||||
// null pointer, all without touching the reference count of the underlying
|
||||
// pointed-to object. The object is still reference counted, and the caller of
|
||||
// release() is now the proud owner of one reference, so it is responsible for
|
||||
// calling Release() once on the object when no longer using it.
|
||||
T* release() {
|
||||
T* retVal = ptr_;
|
||||
ptr_ = nullptr;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
scoped_refptr<T>& operator=(absl::Nullable<T*> p) {
|
||||
// AddRef first so that self assignment should work
|
||||
if (p)
|
||||
p->AddRef();
|
||||
if (ptr_)
|
||||
ptr_->Release();
|
||||
ptr_ = p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
|
||||
return *this = r.ptr_;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
|
||||
return *this = r.get();
|
||||
}
|
||||
|
||||
scoped_refptr<T>& operator=(scoped_refptr<T>&& r) noexcept {
|
||||
scoped_refptr<T>(std::move(r)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
scoped_refptr<T>& operator=(scoped_refptr<U>&& r) noexcept {
|
||||
scoped_refptr<T>(std::move(r)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(absl::Nonnull<T**> pp) noexcept {
|
||||
T* p = ptr_;
|
||||
ptr_ = *pp;
|
||||
*pp = p;
|
||||
}
|
||||
|
||||
void swap(scoped_refptr<T>& r) noexcept { swap(&r.ptr_); }
|
||||
|
||||
protected:
|
||||
T* ptr_;
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const scoped_refptr<T>& a, const scoped_refptr<U>& b) {
|
||||
return a.get() == b.get();
|
||||
}
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const scoped_refptr<T>& a, const scoped_refptr<U>& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator==(const scoped_refptr<T>& a, std::nullptr_t) {
|
||||
return a.get() == nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator!=(const scoped_refptr<T>& a, std::nullptr_t) {
|
||||
return !(a == nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator==(std::nullptr_t, const scoped_refptr<T>& a) {
|
||||
return a.get() == nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator!=(std::nullptr_t, const scoped_refptr<T>& a) {
|
||||
return !(a == nullptr);
|
||||
}
|
||||
|
||||
// Comparison with raw pointer.
|
||||
template <typename T, typename U>
|
||||
bool operator==(const scoped_refptr<T>& a, const U* b) {
|
||||
return a.get() == b;
|
||||
}
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const scoped_refptr<T>& a, const U* b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const T* a, const scoped_refptr<U>& b) {
|
||||
return a == b.get();
|
||||
}
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const T* a, const scoped_refptr<U>& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
// Ordered comparison, needed for use as a std::map key.
|
||||
template <typename T, typename U>
|
||||
bool operator<(const scoped_refptr<T>& a, const scoped_refptr<U>& b) {
|
||||
return a.get() < b.get();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
namespace rtc {
|
||||
// Backwards compatible alias.
|
||||
// TODO: bugs.webrtc.org/42225969 - Deprecate and remove.
|
||||
using ::webrtc::scoped_refptr;
|
||||
} // namespace rtc
|
||||
|
||||
#endif // API_SCOPED_REFPTR_H_
|
141
webrtc/api/sequence_checker.h
Normal file
141
webrtc/api/sequence_checker.h
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef API_SEQUENCE_CHECKER_H_
|
||||
#define API_SEQUENCE_CHECKER_H_
|
||||
|
||||
#include "api/task_queue/task_queue_base.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/synchronization/sequence_checker_internal.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// SequenceChecker is a helper class used to help verify that some methods
|
||||
// of a class are called on the same task queue or thread. A
|
||||
// SequenceChecker is bound to a a task queue if the object is
|
||||
// created on a task queue, or a thread otherwise.
|
||||
//
|
||||
//
|
||||
// Example:
|
||||
// class MyClass {
|
||||
// public:
|
||||
// void Foo() {
|
||||
// RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||
// ... (do stuff) ...
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// SequenceChecker sequence_checker_;
|
||||
// }
|
||||
//
|
||||
// In Release mode, IsCurrent will always return true.
|
||||
class RTC_LOCKABLE SequenceChecker
|
||||
#if RTC_DCHECK_IS_ON
|
||||
: public webrtc_sequence_checker_internal::SequenceCheckerImpl {
|
||||
using Impl = webrtc_sequence_checker_internal::SequenceCheckerImpl;
|
||||
#else
|
||||
: public webrtc_sequence_checker_internal::SequenceCheckerDoNothing {
|
||||
using Impl = webrtc_sequence_checker_internal::SequenceCheckerDoNothing;
|
||||
#endif
|
||||
public:
|
||||
enum InitialState : bool { kDetached = false, kAttached = true };
|
||||
|
||||
// TODO(tommi): We could maybe join these two ctors and have fewer factory
|
||||
// functions. At the moment they're separate to minimize code changes when
|
||||
// we added the second ctor as well as avoiding to have unnecessary code at
|
||||
// the SequenceChecker which much only run for the SequenceCheckerImpl
|
||||
// implementation.
|
||||
// In theory we could have something like:
|
||||
//
|
||||
// SequenceChecker(InitialState initial_state = kAttached,
|
||||
// TaskQueueBase* attached_queue = TaskQueueBase::Current());
|
||||
//
|
||||
// But the problem with that is having the call to `Current()` exist for
|
||||
// `SequenceCheckerDoNothing`.
|
||||
explicit SequenceChecker(InitialState initial_state = kAttached)
|
||||
: Impl(initial_state) {}
|
||||
explicit SequenceChecker(TaskQueueBase* attached_queue)
|
||||
: Impl(attached_queue) {}
|
||||
|
||||
// Returns true if sequence checker is attached to the current sequence.
|
||||
bool IsCurrent() const { return Impl::IsCurrent(); }
|
||||
// Detaches checker from sequence to which it is attached. Next attempt
|
||||
// to do a check with this checker will result in attaching this checker
|
||||
// to the sequence on which check was performed.
|
||||
void Detach() { Impl::Detach(); }
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
// RTC_RUN_ON/RTC_GUARDED_BY/RTC_DCHECK_RUN_ON macros allows to annotate
|
||||
// variables are accessed from same thread/task queue.
|
||||
// Using tools designed to check mutexes, it checks at compile time everywhere
|
||||
// variable is access, there is a run-time dcheck thread/task queue is correct.
|
||||
//
|
||||
// class SequenceCheckerExample {
|
||||
// public:
|
||||
// int CalledFromPacer() RTC_RUN_ON(pacer_sequence_checker_) {
|
||||
// return var2_;
|
||||
// }
|
||||
//
|
||||
// void CallMeFromPacer() {
|
||||
// RTC_DCHECK_RUN_ON(&pacer_sequence_checker_)
|
||||
// << "Should be called from pacer";
|
||||
// CalledFromPacer();
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// int pacer_var_ RTC_GUARDED_BY(pacer_sequence_checker_);
|
||||
// SequenceChecker pacer_sequence_checker_;
|
||||
// };
|
||||
//
|
||||
// class TaskQueueExample {
|
||||
// public:
|
||||
// class Encoder {
|
||||
// public:
|
||||
// rtc::TaskQueueBase& Queue() { return encoder_queue_; }
|
||||
// void Encode() {
|
||||
// RTC_DCHECK_RUN_ON(&encoder_queue_);
|
||||
// DoSomething(var_);
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// rtc::TaskQueueBase& encoder_queue_;
|
||||
// Frame var_ RTC_GUARDED_BY(encoder_queue_);
|
||||
// };
|
||||
//
|
||||
// void Encode() {
|
||||
// // Will fail at runtime when DCHECK is enabled:
|
||||
// // encoder_->Encode();
|
||||
// // Will work:
|
||||
// rtc::scoped_refptr<Encoder> encoder = encoder_;
|
||||
// encoder_->Queue().PostTask([encoder] { encoder->Encode(); });
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// rtc::scoped_refptr<Encoder> encoder_;
|
||||
// }
|
||||
|
||||
// Document if a function expected to be called from same thread/task queue.
|
||||
#define RTC_RUN_ON(x) \
|
||||
RTC_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x))
|
||||
|
||||
// Checks current code is running on the desired sequence.
|
||||
//
|
||||
// First statement validates it is running on the sequence `x`.
|
||||
// Second statement annotates for the thread safety analyzer the check was done.
|
||||
// Such annotation has to be attached to a function, and that function has to be
|
||||
// called. Thus current implementation creates a noop lambda and calls it.
|
||||
#define RTC_DCHECK_RUN_ON(x) \
|
||||
RTC_DCHECK((x)->IsCurrent()) \
|
||||
<< webrtc::webrtc_sequence_checker_internal::ExpectationToString(x); \
|
||||
[]() RTC_ASSERT_EXCLUSIVE_LOCK(x) {}()
|
||||
|
||||
#endif // API_SEQUENCE_CHECKER_H_
|
78
webrtc/api/task_queue/task_queue_base.cc
Normal file
78
webrtc/api/task_queue/task_queue_base.cc
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2019 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include "api/task_queue/task_queue_base.h"
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
|
||||
#if defined(ABSL_HAVE_THREAD_LOCAL)
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
ABSL_CONST_INIT thread_local TaskQueueBase* current = nullptr;
|
||||
|
||||
} // namespace
|
||||
|
||||
TaskQueueBase* TaskQueueBase::Current() {
|
||||
return current;
|
||||
}
|
||||
|
||||
TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(
|
||||
TaskQueueBase* task_queue)
|
||||
: previous_(current) {
|
||||
current = task_queue;
|
||||
}
|
||||
|
||||
TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() {
|
||||
current = previous_;
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
ABSL_CONST_INIT pthread_key_t g_queue_ptr_tls = 0;
|
||||
|
||||
void InitializeTls() {
|
||||
RTC_CHECK(pthread_key_create(&g_queue_ptr_tls, nullptr) == 0);
|
||||
}
|
||||
|
||||
pthread_key_t GetQueuePtrTls() {
|
||||
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
|
||||
RTC_CHECK(pthread_once(&init_once, &InitializeTls) == 0);
|
||||
return g_queue_ptr_tls;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TaskQueueBase* TaskQueueBase::Current() {
|
||||
return static_cast<TaskQueueBase*>(pthread_getspecific(GetQueuePtrTls()));
|
||||
}
|
||||
|
||||
TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(
|
||||
TaskQueueBase* task_queue)
|
||||
: previous_(TaskQueueBase::Current()) {
|
||||
pthread_setspecific(GetQueuePtrTls(), task_queue);
|
||||
}
|
||||
|
||||
TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() {
|
||||
pthread_setspecific(GetQueuePtrTls(), previous_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#else
|
||||
#error Unsupported platform
|
||||
#endif
|
197
webrtc/api/task_queue/task_queue_base.h
Normal file
197
webrtc/api/task_queue/task_queue_base.h
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright 2019 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef API_TASK_QUEUE_TASK_QUEUE_BASE_H_
|
||||
#define API_TASK_QUEUE_TASK_QUEUE_BASE_H_
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "api/location.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Asynchronously executes tasks in a way that guarantees that they're executed
|
||||
// in FIFO order and that tasks never overlap. Tasks may always execute on the
|
||||
// same worker thread and they may not. To DCHECK that tasks are executing on a
|
||||
// known task queue, use IsCurrent().
|
||||
class RTC_LOCKABLE RTC_EXPORT TaskQueueBase {
|
||||
public:
|
||||
enum class DelayPrecision {
|
||||
// This may include up to a 17 ms leeway in addition to OS timer precision.
|
||||
// See PostDelayedTask() for more information.
|
||||
kLow,
|
||||
// This does not have the additional delay that kLow has, but it is still
|
||||
// limited by OS timer precision. See PostDelayedHighPrecisionTask() for
|
||||
// more information.
|
||||
kHigh,
|
||||
};
|
||||
|
||||
// Starts destruction of the task queue.
|
||||
// On return ensures no task are running and no new tasks are able to start
|
||||
// on the task queue.
|
||||
// Responsible for deallocation. Deallocation may happen synchronously during
|
||||
// Delete or asynchronously after Delete returns.
|
||||
// Code not running on the TaskQueue should not make any assumption when
|
||||
// TaskQueue is deallocated and thus should not call any methods after Delete.
|
||||
// Code running on the TaskQueue should not call Delete, but can assume
|
||||
// TaskQueue still exists and may call other methods, e.g. PostTask.
|
||||
// Should be called on the same task queue or thread that this task queue
|
||||
// was created on.
|
||||
virtual void Delete() = 0;
|
||||
|
||||
// Schedules a `task` to execute. Tasks are executed in FIFO order.
|
||||
// When a TaskQueue is deleted, pending tasks will not be executed but they
|
||||
// will be deleted.
|
||||
//
|
||||
// As long as tasks are not posted from task destruction, posted tasks are
|
||||
// guaranteed to be destroyed with Current() pointing to the task queue they
|
||||
// were posted to, whether they're executed or not. That means SequenceChecker
|
||||
// works during task destruction, a fact that can be used to guarantee
|
||||
// thread-compatible object deletion happening on a particular task queue
|
||||
// which can simplify class design.
|
||||
// Note that this guarantee does not apply to delayed tasks.
|
||||
//
|
||||
// May be called on any thread or task queue, including this task queue.
|
||||
void PostTask(absl::AnyInvocable<void() &&> task,
|
||||
const Location& location = Location::Current()) {
|
||||
PostTaskImpl(std::move(task), PostTaskTraits{}, location);
|
||||
}
|
||||
|
||||
// Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever
|
||||
// possible.
|
||||
//
|
||||
// Schedules a `task` to execute a specified `delay` from when the call is
|
||||
// made, using "low" precision. All scheduling is affected by OS-specific
|
||||
// leeway and current workloads which means that in terms of precision there
|
||||
// are no hard guarantees, but in addition to the OS induced leeway, "low"
|
||||
// precision adds up to a 17 ms additional leeway. The purpose of this leeway
|
||||
// is to achieve more efficient CPU scheduling and reduce Idle Wake Up
|
||||
// frequency.
|
||||
//
|
||||
// The task may execute with [-1, 17 + OS induced leeway) ms additional delay.
|
||||
//
|
||||
// Avoid making assumptions about the precision of the OS scheduler. On macOS,
|
||||
// the OS induced leeway may be 10% of sleep interval. On Windows, 1 ms
|
||||
// precision timers may be used but there are cases, such as when running on
|
||||
// battery, when the timer precision can be as poor as 15 ms.
|
||||
//
|
||||
// "Low" precision is not implemented everywhere yet. Where not yet
|
||||
// implemented, PostDelayedTask() has "high" precision. See
|
||||
// https://crbug.com/webrtc/13583 for more information.
|
||||
//
|
||||
// May be called on any thread or task queue, including this task queue.
|
||||
void PostDelayedTask(absl::AnyInvocable<void() &&> task,
|
||||
TimeDelta delay,
|
||||
const Location& location = Location::Current()) {
|
||||
PostDelayedTaskImpl(std::move(task), delay, PostDelayedTaskTraits{},
|
||||
location);
|
||||
}
|
||||
|
||||
// Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever
|
||||
// possible.
|
||||
//
|
||||
// Schedules a `task` to execute a specified `delay` from when the call is
|
||||
// made, using "high" precision. All scheduling is affected by OS-specific
|
||||
// leeway and current workloads which means that in terms of precision there
|
||||
// are no hard guarantees.
|
||||
//
|
||||
// The task may execute with [-1, OS induced leeway] ms additional delay.
|
||||
//
|
||||
// Avoid making assumptions about the precision of the OS scheduler. On macOS,
|
||||
// the OS induced leeway may be 10% of sleep interval. On Windows, 1 ms
|
||||
// precision timers may be used but there are cases, such as when running on
|
||||
// battery, when the timer precision can be as poor as 15 ms.
|
||||
//
|
||||
// May be called on any thread or task queue, including this task queue.
|
||||
void PostDelayedHighPrecisionTask(
|
||||
absl::AnyInvocable<void() &&> task,
|
||||
TimeDelta delay,
|
||||
const Location& location = Location::Current()) {
|
||||
PostDelayedTaskTraits traits;
|
||||
traits.high_precision = true;
|
||||
PostDelayedTaskImpl(std::move(task), delay, traits, location);
|
||||
}
|
||||
|
||||
// As specified by `precision`, calls either PostDelayedTask() or
|
||||
// PostDelayedHighPrecisionTask().
|
||||
void PostDelayedTaskWithPrecision(
|
||||
DelayPrecision precision,
|
||||
absl::AnyInvocable<void() &&> task,
|
||||
TimeDelta delay,
|
||||
const Location& location = Location::Current()) {
|
||||
switch (precision) {
|
||||
case DelayPrecision::kLow:
|
||||
PostDelayedTask(std::move(task), delay, location);
|
||||
break;
|
||||
case DelayPrecision::kHigh:
|
||||
PostDelayedHighPrecisionTask(std::move(task), delay, location);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the task queue that is running the current thread.
|
||||
// Returns nullptr if this thread is not associated with any task queue.
|
||||
// May be called on any thread or task queue, including this task queue.
|
||||
static TaskQueueBase* Current();
|
||||
bool IsCurrent() const { return Current() == this; }
|
||||
|
||||
protected:
|
||||
// This is currently only present here to simplify introduction of future
|
||||
// planned task queue changes.
|
||||
struct PostTaskTraits {};
|
||||
|
||||
struct PostDelayedTaskTraits {
|
||||
// If `high_precision` is false, tasks may execute within up to a 17 ms
|
||||
// leeway in addition to OS timer precision. Otherwise the task should be
|
||||
// limited to OS timer precision. See PostDelayedTask() and
|
||||
// PostDelayedHighPrecisionTask() for more information.
|
||||
bool high_precision = false;
|
||||
};
|
||||
|
||||
class RTC_EXPORT CurrentTaskQueueSetter {
|
||||
public:
|
||||
explicit CurrentTaskQueueSetter(TaskQueueBase* task_queue);
|
||||
CurrentTaskQueueSetter(const CurrentTaskQueueSetter&) = delete;
|
||||
CurrentTaskQueueSetter& operator=(const CurrentTaskQueueSetter&) = delete;
|
||||
~CurrentTaskQueueSetter();
|
||||
|
||||
private:
|
||||
TaskQueueBase* const previous_;
|
||||
};
|
||||
|
||||
// Subclasses should implement this method to support the behavior defined in
|
||||
// the PostTask and PostTaskTraits docs above.
|
||||
virtual void PostTaskImpl(absl::AnyInvocable<void() &&> task,
|
||||
const PostTaskTraits& traits,
|
||||
const Location& location) = 0;
|
||||
|
||||
// Subclasses should implement this method to support the behavior defined in
|
||||
// the PostDelayedTask/PostHighPrecisionDelayedTask and PostDelayedTaskTraits
|
||||
// docs above.
|
||||
virtual void PostDelayedTaskImpl(absl::AnyInvocable<void() &&> task,
|
||||
TimeDelta delay,
|
||||
const PostDelayedTaskTraits& traits,
|
||||
const Location& location) = 0;
|
||||
|
||||
// Users of the TaskQueue should call Delete instead of directly deleting
|
||||
// this object.
|
||||
virtual ~TaskQueueBase() = default;
|
||||
};
|
||||
|
||||
struct TaskQueueDeleter {
|
||||
void operator()(TaskQueueBase* task_queue) const { task_queue->Delete(); }
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_TASK_QUEUE_TASK_QUEUE_BASE_H_
|
32
webrtc/api/units/frequency.cc
Normal file
32
webrtc/api/units/frequency.cc
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include "api/units/frequency.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
|
||||
namespace webrtc {
|
||||
std::string ToString(Frequency value) {
|
||||
char buf[64];
|
||||
rtc::SimpleStringBuilder sb(buf);
|
||||
if (value.IsPlusInfinity()) {
|
||||
sb << "+inf Hz";
|
||||
} else if (value.IsMinusInfinity()) {
|
||||
sb << "-inf Hz";
|
||||
} else if (value.millihertz<int64_t>() % 1000 != 0) {
|
||||
sb.AppendFormat("%.3f Hz", value.hertz<double>());
|
||||
} else {
|
||||
sb << value.hertz<int64_t>() << " Hz";
|
||||
}
|
||||
return sb.str();
|
||||
}
|
||||
} // namespace webrtc
|
100
webrtc/api/units/frequency.h
Normal file
100
webrtc/api/units/frequency.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef API_UNITS_FREQUENCY_H_
|
||||
#define API_UNITS_FREQUENCY_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "api/units/time_delta.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
#include "rtc_base/units/unit_base.h" // IWYU pragma: export
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class Frequency final : public rtc_units_impl::RelativeUnit<Frequency> {
|
||||
public:
|
||||
template <typename T>
|
||||
static constexpr Frequency MilliHertz(T value) {
|
||||
static_assert(std::is_arithmetic<T>::value, "");
|
||||
return FromValue(value);
|
||||
}
|
||||
template <typename T>
|
||||
static constexpr Frequency Hertz(T value) {
|
||||
static_assert(std::is_arithmetic<T>::value, "");
|
||||
return FromFraction(1'000, value);
|
||||
}
|
||||
template <typename T>
|
||||
static constexpr Frequency KiloHertz(T value) {
|
||||
static_assert(std::is_arithmetic<T>::value, "");
|
||||
return FromFraction(1'000'000, value);
|
||||
}
|
||||
|
||||
Frequency() = delete;
|
||||
|
||||
template <typename Sink>
|
||||
friend void AbslStringify(Sink& sink, Frequency value);
|
||||
|
||||
template <typename T = int64_t>
|
||||
constexpr T hertz() const {
|
||||
return ToFraction<1000, T>();
|
||||
}
|
||||
template <typename T = int64_t>
|
||||
constexpr T millihertz() const {
|
||||
return ToValue<T>();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class rtc_units_impl::UnitBase<Frequency>;
|
||||
using RelativeUnit::RelativeUnit;
|
||||
static constexpr bool one_sided = true;
|
||||
};
|
||||
|
||||
inline constexpr Frequency operator/(int64_t nominator,
|
||||
const TimeDelta& interval) {
|
||||
constexpr int64_t kKiloPerMicro = 1000 * 1000000;
|
||||
RTC_DCHECK_LE(nominator, std::numeric_limits<int64_t>::max() / kKiloPerMicro);
|
||||
RTC_CHECK(interval.IsFinite());
|
||||
RTC_CHECK(!interval.IsZero());
|
||||
return Frequency::MilliHertz(nominator * kKiloPerMicro / interval.us());
|
||||
}
|
||||
|
||||
inline constexpr TimeDelta operator/(int64_t nominator,
|
||||
const Frequency& frequency) {
|
||||
constexpr int64_t kMegaPerMilli = 1000000 * 1000;
|
||||
RTC_DCHECK_LE(nominator, std::numeric_limits<int64_t>::max() / kMegaPerMilli);
|
||||
RTC_CHECK(frequency.IsFinite());
|
||||
RTC_CHECK(!frequency.IsZero());
|
||||
return TimeDelta::Micros(nominator * kMegaPerMilli / frequency.millihertz());
|
||||
}
|
||||
|
||||
inline constexpr double operator*(Frequency frequency, TimeDelta time_delta) {
|
||||
return frequency.hertz<double>() * time_delta.seconds<double>();
|
||||
}
|
||||
inline constexpr double operator*(TimeDelta time_delta, Frequency frequency) {
|
||||
return frequency * time_delta;
|
||||
}
|
||||
|
||||
RTC_EXPORT std::string ToString(Frequency value);
|
||||
inline std::string ToLogString(Frequency value) {
|
||||
return ToString(value);
|
||||
}
|
||||
|
||||
template <typename Sink>
|
||||
void AbslStringify(Sink& sink, Frequency value) {
|
||||
sink.Append(ToString(value));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // API_UNITS_FREQUENCY_H_
|
38
webrtc/api/units/time_delta.cc
Normal file
38
webrtc/api/units/time_delta.cc
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/units/time_delta.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
std::string ToString(TimeDelta value) {
|
||||
char buf[64];
|
||||
rtc::SimpleStringBuilder sb(buf);
|
||||
if (value.IsPlusInfinity()) {
|
||||
sb << "+inf ms";
|
||||
} else if (value.IsMinusInfinity()) {
|
||||
sb << "-inf ms";
|
||||
} else {
|
||||
if (value.us() == 0 || (value.us() % 1000) != 0)
|
||||
sb << value.us() << " us";
|
||||
else if (value.ms() % 1000 != 0)
|
||||
sb << value.ms() << " ms";
|
||||
else
|
||||
sb << value.seconds() << " s";
|
||||
}
|
||||
return sb.str();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
108
webrtc/api/units/time_delta.h
Normal file
108
webrtc/api/units/time_delta.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_UNITS_TIME_DELTA_H_
|
||||
#define API_UNITS_TIME_DELTA_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
#include "rtc_base/units/unit_base.h" // IWYU pragma: export
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// TimeDelta represents the difference between two timestamps. Commonly this can
|
||||
// be a duration. However since two Timestamps are not guaranteed to have the
|
||||
// same epoch (they might come from different computers, making exact
|
||||
// synchronisation infeasible), the duration covered by a TimeDelta can be
|
||||
// undefined. To simplify usage, it can be constructed and converted to
|
||||
// different units, specifically seconds (s), milliseconds (ms) and
|
||||
// microseconds (us).
|
||||
class TimeDelta final : public rtc_units_impl::RelativeUnit<TimeDelta> {
|
||||
public:
|
||||
template <typename T>
|
||||
static constexpr TimeDelta Minutes(T value) {
|
||||
static_assert(std::is_arithmetic<T>::value, "");
|
||||
return Seconds(value * 60);
|
||||
}
|
||||
template <typename T>
|
||||
static constexpr TimeDelta Seconds(T value) {
|
||||
static_assert(std::is_arithmetic<T>::value, "");
|
||||
return FromFraction(1'000'000, value);
|
||||
}
|
||||
template <typename T>
|
||||
static constexpr TimeDelta Millis(T value) {
|
||||
static_assert(std::is_arithmetic<T>::value, "");
|
||||
return FromFraction(1'000, value);
|
||||
}
|
||||
template <typename T>
|
||||
static constexpr TimeDelta Micros(T value) {
|
||||
static_assert(std::is_arithmetic<T>::value, "");
|
||||
return FromValue(value);
|
||||
}
|
||||
|
||||
TimeDelta() = delete;
|
||||
|
||||
template <typename Sink>
|
||||
friend void AbslStringify(Sink& sink, TimeDelta value);
|
||||
|
||||
template <typename T = int64_t>
|
||||
constexpr T seconds() const {
|
||||
return ToFraction<1000000, T>();
|
||||
}
|
||||
template <typename T = int64_t>
|
||||
constexpr T ms() const {
|
||||
return ToFraction<1000, T>();
|
||||
}
|
||||
template <typename T = int64_t>
|
||||
constexpr T us() const {
|
||||
return ToValue<T>();
|
||||
}
|
||||
template <typename T = int64_t>
|
||||
constexpr T ns() const {
|
||||
return ToMultiple<1000, T>();
|
||||
}
|
||||
|
||||
constexpr int64_t seconds_or(int64_t fallback_value) const {
|
||||
return ToFractionOr<1000000>(fallback_value);
|
||||
}
|
||||
constexpr int64_t ms_or(int64_t fallback_value) const {
|
||||
return ToFractionOr<1000>(fallback_value);
|
||||
}
|
||||
constexpr int64_t us_or(int64_t fallback_value) const {
|
||||
return ToValueOr(fallback_value);
|
||||
}
|
||||
|
||||
constexpr TimeDelta Abs() const {
|
||||
return us() < 0 ? TimeDelta::Micros(-us()) : *this;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class rtc_units_impl::UnitBase<TimeDelta>;
|
||||
using RelativeUnit::RelativeUnit;
|
||||
static constexpr bool one_sided = false;
|
||||
};
|
||||
|
||||
RTC_EXPORT std::string ToString(TimeDelta value);
|
||||
inline std::string ToLogString(TimeDelta value) {
|
||||
return ToString(value);
|
||||
}
|
||||
|
||||
template <typename Sink>
|
||||
void AbslStringify(Sink& sink, TimeDelta value) {
|
||||
sink.Append(ToString(value));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_UNITS_TIME_DELTA_H_
|
36
webrtc/api/units/timestamp.cc
Normal file
36
webrtc/api/units/timestamp.cc
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/units/timestamp.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
|
||||
namespace webrtc {
|
||||
std::string ToString(Timestamp value) {
|
||||
char buf[64];
|
||||
rtc::SimpleStringBuilder sb(buf);
|
||||
if (value.IsPlusInfinity()) {
|
||||
sb << "+inf ms";
|
||||
} else if (value.IsMinusInfinity()) {
|
||||
sb << "-inf ms";
|
||||
} else {
|
||||
if (value.us() == 0 || (value.us() % 1000) != 0)
|
||||
sb << value.us() << " us";
|
||||
else if (value.ms() % 1000 != 0)
|
||||
sb << value.ms() << " ms";
|
||||
else
|
||||
sb << value.seconds() << " s";
|
||||
}
|
||||
return sb.str();
|
||||
}
|
||||
} // namespace webrtc
|
137
webrtc/api/units/timestamp.h
Normal file
137
webrtc/api/units/timestamp.h
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_UNITS_TIMESTAMP_H_
|
||||
#define API_UNITS_TIMESTAMP_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "api/units/time_delta.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
#include "rtc_base/units/unit_base.h" // IWYU pragma: export
|
||||
|
||||
namespace webrtc {
|
||||
// Timestamp represents the time that has passed since some unspecified epoch.
|
||||
// The epoch is assumed to be before any represented timestamps, this means that
|
||||
// negative values are not valid. The most notable feature is that the
|
||||
// difference of two Timestamps results in a TimeDelta.
|
||||
class Timestamp final : public rtc_units_impl::UnitBase<Timestamp> {
|
||||
public:
|
||||
template <typename T>
|
||||
static constexpr Timestamp Seconds(T value) {
|
||||
static_assert(std::is_arithmetic<T>::value, "");
|
||||
return FromFraction(1'000'000, value);
|
||||
}
|
||||
template <typename T>
|
||||
static constexpr Timestamp Millis(T value) {
|
||||
static_assert(std::is_arithmetic<T>::value, "");
|
||||
return FromFraction(1'000, value);
|
||||
}
|
||||
template <typename T>
|
||||
static constexpr Timestamp Micros(T value) {
|
||||
static_assert(std::is_arithmetic<T>::value, "");
|
||||
return FromValue(value);
|
||||
}
|
||||
|
||||
Timestamp() = delete;
|
||||
|
||||
template <typename Sink>
|
||||
friend void AbslStringify(Sink& sink, Timestamp value);
|
||||
|
||||
template <typename T = int64_t>
|
||||
constexpr T seconds() const {
|
||||
return ToFraction<1000000, T>();
|
||||
}
|
||||
template <typename T = int64_t>
|
||||
constexpr T ms() const {
|
||||
return ToFraction<1000, T>();
|
||||
}
|
||||
template <typename T = int64_t>
|
||||
constexpr T us() const {
|
||||
return ToValue<T>();
|
||||
}
|
||||
|
||||
constexpr int64_t seconds_or(int64_t fallback_value) const {
|
||||
return ToFractionOr<1000000>(fallback_value);
|
||||
}
|
||||
constexpr int64_t ms_or(int64_t fallback_value) const {
|
||||
return ToFractionOr<1000>(fallback_value);
|
||||
}
|
||||
constexpr int64_t us_or(int64_t fallback_value) const {
|
||||
return ToValueOr(fallback_value);
|
||||
}
|
||||
|
||||
constexpr Timestamp operator+(const TimeDelta delta) const {
|
||||
if (IsPlusInfinity() || delta.IsPlusInfinity()) {
|
||||
RTC_DCHECK(!IsMinusInfinity());
|
||||
RTC_DCHECK(!delta.IsMinusInfinity());
|
||||
return PlusInfinity();
|
||||
} else if (IsMinusInfinity() || delta.IsMinusInfinity()) {
|
||||
RTC_DCHECK(!IsPlusInfinity());
|
||||
RTC_DCHECK(!delta.IsPlusInfinity());
|
||||
return MinusInfinity();
|
||||
}
|
||||
return Timestamp::Micros(us() + delta.us());
|
||||
}
|
||||
constexpr Timestamp operator-(const TimeDelta delta) const {
|
||||
if (IsPlusInfinity() || delta.IsMinusInfinity()) {
|
||||
RTC_DCHECK(!IsMinusInfinity());
|
||||
RTC_DCHECK(!delta.IsPlusInfinity());
|
||||
return PlusInfinity();
|
||||
} else if (IsMinusInfinity() || delta.IsPlusInfinity()) {
|
||||
RTC_DCHECK(!IsPlusInfinity());
|
||||
RTC_DCHECK(!delta.IsMinusInfinity());
|
||||
return MinusInfinity();
|
||||
}
|
||||
return Timestamp::Micros(us() - delta.us());
|
||||
}
|
||||
constexpr TimeDelta operator-(const Timestamp other) const {
|
||||
if (IsPlusInfinity() || other.IsMinusInfinity()) {
|
||||
RTC_DCHECK(!IsMinusInfinity());
|
||||
RTC_DCHECK(!other.IsPlusInfinity());
|
||||
return TimeDelta::PlusInfinity();
|
||||
} else if (IsMinusInfinity() || other.IsPlusInfinity()) {
|
||||
RTC_DCHECK(!IsPlusInfinity());
|
||||
RTC_DCHECK(!other.IsMinusInfinity());
|
||||
return TimeDelta::MinusInfinity();
|
||||
}
|
||||
return TimeDelta::Micros(us() - other.us());
|
||||
}
|
||||
constexpr Timestamp& operator-=(const TimeDelta delta) {
|
||||
*this = *this - delta;
|
||||
return *this;
|
||||
}
|
||||
constexpr Timestamp& operator+=(const TimeDelta delta) {
|
||||
*this = *this + delta;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class rtc_units_impl::UnitBase<Timestamp>;
|
||||
using UnitBase::UnitBase;
|
||||
static constexpr bool one_sided = true;
|
||||
};
|
||||
|
||||
RTC_EXPORT std::string ToString(Timestamp value);
|
||||
inline std::string ToLogString(Timestamp value) {
|
||||
return ToString(value);
|
||||
}
|
||||
|
||||
template <typename Sink>
|
||||
void AbslStringify(Sink& sink, Timestamp value) {
|
||||
sink.Append(ToString(value));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_UNITS_TIMESTAMP_H_
|
269
webrtc/api/video/color_space.cc
Normal file
269
webrtc/api/video/color_space.cc
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/video/color_space.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "api/video/hdr_metadata.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
// Try to convert `enum_value` into the enum class T. `enum_bitmask` is created
|
||||
// by the funciton below. Returns true if conversion was successful, false
|
||||
// otherwise.
|
||||
template <typename T>
|
||||
bool SetFromUint8(uint8_t enum_value, uint64_t enum_bitmask, T* out) {
|
||||
if ((enum_value < 64) && ((enum_bitmask >> enum_value) & 1)) {
|
||||
*out = static_cast<T>(enum_value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function serves as an assert for the constexpr function below. It's on
|
||||
// purpose not declared as constexpr so that it causes a build problem if enum
|
||||
// values of 64 or above are used. The bitmask and the code generating it would
|
||||
// have to be extended if the standard is updated to include enum values >= 64.
|
||||
int EnumMustBeLessThan64() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
constexpr int MakeMask(const int index, const int length, T (&values)[N]) {
|
||||
return length > 1
|
||||
? (MakeMask(index, 1, values) +
|
||||
MakeMask(index + 1, length - 1, values))
|
||||
: (static_cast<uint8_t>(values[index]) < 64
|
||||
? (uint64_t{1} << static_cast<uint8_t>(values[index]))
|
||||
: EnumMustBeLessThan64());
|
||||
}
|
||||
|
||||
// Create a bitmask where each bit corresponds to one potential enum value.
|
||||
// `values` should be an array listing all possible enum values. The bit is set
|
||||
// to one if the corresponding enum exists. Only works for enums with values
|
||||
// less than 64.
|
||||
template <typename T, size_t N>
|
||||
constexpr uint64_t CreateEnumBitmask(T (&values)[N]) {
|
||||
return MakeMask(0, N, values);
|
||||
}
|
||||
|
||||
bool SetChromaSitingFromUint8(uint8_t enum_value,
|
||||
ColorSpace::ChromaSiting* chroma_siting) {
|
||||
constexpr ColorSpace::ChromaSiting kChromaSitings[] = {
|
||||
ColorSpace::ChromaSiting::kUnspecified,
|
||||
ColorSpace::ChromaSiting::kCollocated, ColorSpace::ChromaSiting::kHalf};
|
||||
constexpr uint64_t enum_bitmask = CreateEnumBitmask(kChromaSitings);
|
||||
|
||||
return SetFromUint8(enum_value, enum_bitmask, chroma_siting);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ColorSpace::ColorSpace() = default;
|
||||
ColorSpace::ColorSpace(const ColorSpace& other) = default;
|
||||
ColorSpace::ColorSpace(ColorSpace&& other) = default;
|
||||
ColorSpace& ColorSpace::operator=(const ColorSpace& other) = default;
|
||||
|
||||
ColorSpace::ColorSpace(PrimaryID primaries,
|
||||
TransferID transfer,
|
||||
MatrixID matrix,
|
||||
RangeID range)
|
||||
: ColorSpace(primaries,
|
||||
transfer,
|
||||
matrix,
|
||||
range,
|
||||
ChromaSiting::kUnspecified,
|
||||
ChromaSiting::kUnspecified,
|
||||
nullptr) {}
|
||||
|
||||
ColorSpace::ColorSpace(PrimaryID primaries,
|
||||
TransferID transfer,
|
||||
MatrixID matrix,
|
||||
RangeID range,
|
||||
ChromaSiting chroma_siting_horz,
|
||||
ChromaSiting chroma_siting_vert,
|
||||
const HdrMetadata* hdr_metadata)
|
||||
: primaries_(primaries),
|
||||
transfer_(transfer),
|
||||
matrix_(matrix),
|
||||
range_(range),
|
||||
chroma_siting_horizontal_(chroma_siting_horz),
|
||||
chroma_siting_vertical_(chroma_siting_vert),
|
||||
hdr_metadata_(hdr_metadata ? std::make_optional(*hdr_metadata)
|
||||
: std::nullopt) {}
|
||||
|
||||
ColorSpace::PrimaryID ColorSpace::primaries() const {
|
||||
return primaries_;
|
||||
}
|
||||
|
||||
ColorSpace::TransferID ColorSpace::transfer() const {
|
||||
return transfer_;
|
||||
}
|
||||
|
||||
ColorSpace::MatrixID ColorSpace::matrix() const {
|
||||
return matrix_;
|
||||
}
|
||||
|
||||
ColorSpace::RangeID ColorSpace::range() const {
|
||||
return range_;
|
||||
}
|
||||
|
||||
ColorSpace::ChromaSiting ColorSpace::chroma_siting_horizontal() const {
|
||||
return chroma_siting_horizontal_;
|
||||
}
|
||||
|
||||
ColorSpace::ChromaSiting ColorSpace::chroma_siting_vertical() const {
|
||||
return chroma_siting_vertical_;
|
||||
}
|
||||
|
||||
const HdrMetadata* ColorSpace::hdr_metadata() const {
|
||||
return hdr_metadata_ ? &*hdr_metadata_ : nullptr;
|
||||
}
|
||||
|
||||
#define PRINT_ENUM_CASE(TYPE, NAME) \
|
||||
case TYPE::NAME: \
|
||||
ss << #NAME; \
|
||||
break;
|
||||
|
||||
std::string ColorSpace::AsString() const {
|
||||
char buf[1024];
|
||||
rtc::SimpleStringBuilder ss(buf);
|
||||
ss << "{primaries:";
|
||||
switch (primaries_) {
|
||||
PRINT_ENUM_CASE(PrimaryID, kBT709)
|
||||
PRINT_ENUM_CASE(PrimaryID, kUnspecified)
|
||||
PRINT_ENUM_CASE(PrimaryID, kBT470M)
|
||||
PRINT_ENUM_CASE(PrimaryID, kBT470BG)
|
||||
PRINT_ENUM_CASE(PrimaryID, kSMPTE170M)
|
||||
PRINT_ENUM_CASE(PrimaryID, kSMPTE240M)
|
||||
PRINT_ENUM_CASE(PrimaryID, kFILM)
|
||||
PRINT_ENUM_CASE(PrimaryID, kBT2020)
|
||||
PRINT_ENUM_CASE(PrimaryID, kSMPTEST428)
|
||||
PRINT_ENUM_CASE(PrimaryID, kSMPTEST431)
|
||||
PRINT_ENUM_CASE(PrimaryID, kSMPTEST432)
|
||||
PRINT_ENUM_CASE(PrimaryID, kJEDECP22)
|
||||
}
|
||||
ss << ", transfer:";
|
||||
switch (transfer_) {
|
||||
PRINT_ENUM_CASE(TransferID, kBT709)
|
||||
PRINT_ENUM_CASE(TransferID, kUnspecified)
|
||||
PRINT_ENUM_CASE(TransferID, kGAMMA22)
|
||||
PRINT_ENUM_CASE(TransferID, kGAMMA28)
|
||||
PRINT_ENUM_CASE(TransferID, kSMPTE170M)
|
||||
PRINT_ENUM_CASE(TransferID, kSMPTE240M)
|
||||
PRINT_ENUM_CASE(TransferID, kLINEAR)
|
||||
PRINT_ENUM_CASE(TransferID, kLOG)
|
||||
PRINT_ENUM_CASE(TransferID, kLOG_SQRT)
|
||||
PRINT_ENUM_CASE(TransferID, kIEC61966_2_4)
|
||||
PRINT_ENUM_CASE(TransferID, kBT1361_ECG)
|
||||
PRINT_ENUM_CASE(TransferID, kIEC61966_2_1)
|
||||
PRINT_ENUM_CASE(TransferID, kBT2020_10)
|
||||
PRINT_ENUM_CASE(TransferID, kBT2020_12)
|
||||
PRINT_ENUM_CASE(TransferID, kSMPTEST2084)
|
||||
PRINT_ENUM_CASE(TransferID, kSMPTEST428)
|
||||
PRINT_ENUM_CASE(TransferID, kARIB_STD_B67)
|
||||
}
|
||||
ss << ", matrix:";
|
||||
switch (matrix_) {
|
||||
PRINT_ENUM_CASE(MatrixID, kRGB)
|
||||
PRINT_ENUM_CASE(MatrixID, kBT709)
|
||||
PRINT_ENUM_CASE(MatrixID, kUnspecified)
|
||||
PRINT_ENUM_CASE(MatrixID, kFCC)
|
||||
PRINT_ENUM_CASE(MatrixID, kBT470BG)
|
||||
PRINT_ENUM_CASE(MatrixID, kSMPTE170M)
|
||||
PRINT_ENUM_CASE(MatrixID, kSMPTE240M)
|
||||
PRINT_ENUM_CASE(MatrixID, kYCOCG)
|
||||
PRINT_ENUM_CASE(MatrixID, kBT2020_NCL)
|
||||
PRINT_ENUM_CASE(MatrixID, kBT2020_CL)
|
||||
PRINT_ENUM_CASE(MatrixID, kSMPTE2085)
|
||||
PRINT_ENUM_CASE(MatrixID, kCDNCLS)
|
||||
PRINT_ENUM_CASE(MatrixID, kCDCLS)
|
||||
PRINT_ENUM_CASE(MatrixID, kBT2100_ICTCP)
|
||||
}
|
||||
|
||||
ss << ", range:";
|
||||
switch (range_) {
|
||||
PRINT_ENUM_CASE(RangeID, kInvalid)
|
||||
PRINT_ENUM_CASE(RangeID, kLimited)
|
||||
PRINT_ENUM_CASE(RangeID, kFull)
|
||||
PRINT_ENUM_CASE(RangeID, kDerived)
|
||||
}
|
||||
ss << "}";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
#undef PRINT_ENUM_CASE
|
||||
|
||||
bool ColorSpace::set_primaries_from_uint8(uint8_t enum_value) {
|
||||
constexpr PrimaryID kPrimaryIds[] = {
|
||||
PrimaryID::kBT709, PrimaryID::kUnspecified, PrimaryID::kBT470M,
|
||||
PrimaryID::kBT470BG, PrimaryID::kSMPTE170M, PrimaryID::kSMPTE240M,
|
||||
PrimaryID::kFILM, PrimaryID::kBT2020, PrimaryID::kSMPTEST428,
|
||||
PrimaryID::kSMPTEST431, PrimaryID::kSMPTEST432, PrimaryID::kJEDECP22};
|
||||
constexpr uint64_t enum_bitmask = CreateEnumBitmask(kPrimaryIds);
|
||||
|
||||
return SetFromUint8(enum_value, enum_bitmask, &primaries_);
|
||||
}
|
||||
|
||||
bool ColorSpace::set_transfer_from_uint8(uint8_t enum_value) {
|
||||
constexpr TransferID kTransferIds[] = {
|
||||
TransferID::kBT709, TransferID::kUnspecified,
|
||||
TransferID::kGAMMA22, TransferID::kGAMMA28,
|
||||
TransferID::kSMPTE170M, TransferID::kSMPTE240M,
|
||||
TransferID::kLINEAR, TransferID::kLOG,
|
||||
TransferID::kLOG_SQRT, TransferID::kIEC61966_2_4,
|
||||
TransferID::kBT1361_ECG, TransferID::kIEC61966_2_1,
|
||||
TransferID::kBT2020_10, TransferID::kBT2020_12,
|
||||
TransferID::kSMPTEST2084, TransferID::kSMPTEST428,
|
||||
TransferID::kARIB_STD_B67};
|
||||
constexpr uint64_t enum_bitmask = CreateEnumBitmask(kTransferIds);
|
||||
|
||||
return SetFromUint8(enum_value, enum_bitmask, &transfer_);
|
||||
}
|
||||
|
||||
bool ColorSpace::set_matrix_from_uint8(uint8_t enum_value) {
|
||||
constexpr MatrixID kMatrixIds[] = {
|
||||
MatrixID::kRGB, MatrixID::kBT709, MatrixID::kUnspecified,
|
||||
MatrixID::kFCC, MatrixID::kBT470BG, MatrixID::kSMPTE170M,
|
||||
MatrixID::kSMPTE240M, MatrixID::kYCOCG, MatrixID::kBT2020_NCL,
|
||||
MatrixID::kBT2020_CL, MatrixID::kSMPTE2085, MatrixID::kCDNCLS,
|
||||
MatrixID::kCDCLS, MatrixID::kBT2100_ICTCP};
|
||||
constexpr uint64_t enum_bitmask = CreateEnumBitmask(kMatrixIds);
|
||||
|
||||
return SetFromUint8(enum_value, enum_bitmask, &matrix_);
|
||||
}
|
||||
|
||||
bool ColorSpace::set_range_from_uint8(uint8_t enum_value) {
|
||||
constexpr RangeID kRangeIds[] = {RangeID::kInvalid, RangeID::kLimited,
|
||||
RangeID::kFull, RangeID::kDerived};
|
||||
constexpr uint64_t enum_bitmask = CreateEnumBitmask(kRangeIds);
|
||||
|
||||
return SetFromUint8(enum_value, enum_bitmask, &range_);
|
||||
}
|
||||
|
||||
bool ColorSpace::set_chroma_siting_horizontal_from_uint8(uint8_t enum_value) {
|
||||
return SetChromaSitingFromUint8(enum_value, &chroma_siting_horizontal_);
|
||||
}
|
||||
|
||||
bool ColorSpace::set_chroma_siting_vertical_from_uint8(uint8_t enum_value) {
|
||||
return SetChromaSitingFromUint8(enum_value, &chroma_siting_vertical_);
|
||||
}
|
||||
|
||||
void ColorSpace::set_hdr_metadata(const HdrMetadata* hdr_metadata) {
|
||||
hdr_metadata_ =
|
||||
hdr_metadata ? std::make_optional(*hdr_metadata) : std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
181
webrtc/api/video/color_space.h
Normal file
181
webrtc/api/video/color_space.h
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_VIDEO_COLOR_SPACE_H_
|
||||
#define API_VIDEO_COLOR_SPACE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "api/video/hdr_metadata.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// This class represents color information as specified in T-REC H.273,
|
||||
// available from https://www.itu.int/rec/T-REC-H.273.
|
||||
//
|
||||
// WebRTC's supported codecs:
|
||||
// - VP9 supports color profiles, see VP9 Bitstream & Decoding Process
|
||||
// Specification Version 0.6 Section 7.2.2 "Color config semantics" available
|
||||
// from https://www.webmproject.org.
|
||||
// - VP8 only supports BT.601, see
|
||||
// https://tools.ietf.org/html/rfc6386#section-9.2
|
||||
// - H264 uses the exact same representation as T-REC H.273. See T-REC-H.264
|
||||
// E.2.1, "VUI parameters semantics", available from
|
||||
// https://www.itu.int/rec/T-REC-H.264.
|
||||
|
||||
class RTC_EXPORT ColorSpace {
|
||||
public:
|
||||
enum class PrimaryID : uint8_t {
|
||||
// The indices are equal to the values specified in T-REC H.273 Table 2.
|
||||
kBT709 = 1,
|
||||
kUnspecified = 2,
|
||||
kBT470M = 4,
|
||||
kBT470BG = 5,
|
||||
kSMPTE170M = 6, // Identical to BT601
|
||||
kSMPTE240M = 7,
|
||||
kFILM = 8,
|
||||
kBT2020 = 9,
|
||||
kSMPTEST428 = 10,
|
||||
kSMPTEST431 = 11,
|
||||
kSMPTEST432 = 12,
|
||||
kJEDECP22 = 22, // Identical to EBU3213-E
|
||||
// When adding/removing entries here, please make sure to do the
|
||||
// corresponding change to kPrimaryIds.
|
||||
};
|
||||
|
||||
enum class TransferID : uint8_t {
|
||||
// The indices are equal to the values specified in T-REC H.273 Table 3.
|
||||
kBT709 = 1,
|
||||
kUnspecified = 2,
|
||||
kGAMMA22 = 4,
|
||||
kGAMMA28 = 5,
|
||||
kSMPTE170M = 6,
|
||||
kSMPTE240M = 7,
|
||||
kLINEAR = 8,
|
||||
kLOG = 9,
|
||||
kLOG_SQRT = 10,
|
||||
kIEC61966_2_4 = 11,
|
||||
kBT1361_ECG = 12,
|
||||
kIEC61966_2_1 = 13,
|
||||
kBT2020_10 = 14,
|
||||
kBT2020_12 = 15,
|
||||
kSMPTEST2084 = 16,
|
||||
kSMPTEST428 = 17,
|
||||
kARIB_STD_B67 = 18,
|
||||
// When adding/removing entries here, please make sure to do the
|
||||
// corresponding change to kTransferIds.
|
||||
};
|
||||
|
||||
enum class MatrixID : uint8_t {
|
||||
// The indices are equal to the values specified in T-REC H.273 Table 4.
|
||||
kRGB = 0,
|
||||
kBT709 = 1,
|
||||
kUnspecified = 2,
|
||||
kFCC = 4,
|
||||
kBT470BG = 5,
|
||||
kSMPTE170M = 6,
|
||||
kSMPTE240M = 7,
|
||||
kYCOCG = 8,
|
||||
kBT2020_NCL = 9,
|
||||
kBT2020_CL = 10,
|
||||
kSMPTE2085 = 11,
|
||||
kCDNCLS = 12,
|
||||
kCDCLS = 13,
|
||||
kBT2100_ICTCP = 14,
|
||||
// When adding/removing entries here, please make sure to do the
|
||||
// corresponding change to kMatrixIds.
|
||||
};
|
||||
|
||||
enum class RangeID {
|
||||
// The indices are equal to the values specified at
|
||||
// https://www.webmproject.org/docs/container/#colour for the element Range.
|
||||
kInvalid = 0,
|
||||
// Limited Rec. 709 color range with RGB values ranging from 16 to 235.
|
||||
kLimited = 1,
|
||||
// Full RGB color range with RGB values from 0 to 255.
|
||||
kFull = 2,
|
||||
// Range is defined by MatrixCoefficients/TransferCharacteristics.
|
||||
kDerived = 3,
|
||||
// When adding/removing entries here, please make sure to do the
|
||||
// corresponding change to kRangeIds.
|
||||
};
|
||||
|
||||
enum class ChromaSiting {
|
||||
// Chroma siting specifies how chroma is subsampled relative to the luma
|
||||
// samples in a YUV video frame.
|
||||
// The indices are equal to the values specified at
|
||||
// https://www.webmproject.org/docs/container/#colour for the element
|
||||
// ChromaSitingVert and ChromaSitingHorz.
|
||||
kUnspecified = 0,
|
||||
kCollocated = 1,
|
||||
kHalf = 2,
|
||||
// When adding/removing entries here, please make sure to do the
|
||||
// corresponding change to kChromaSitings.
|
||||
};
|
||||
|
||||
ColorSpace();
|
||||
ColorSpace(const ColorSpace& other);
|
||||
ColorSpace(ColorSpace&& other);
|
||||
ColorSpace& operator=(const ColorSpace& other);
|
||||
ColorSpace(PrimaryID primaries,
|
||||
TransferID transfer,
|
||||
MatrixID matrix,
|
||||
RangeID range);
|
||||
ColorSpace(PrimaryID primaries,
|
||||
TransferID transfer,
|
||||
MatrixID matrix,
|
||||
RangeID range,
|
||||
ChromaSiting chroma_siting_horizontal,
|
||||
ChromaSiting chroma_siting_vertical,
|
||||
const HdrMetadata* hdr_metadata);
|
||||
friend bool operator==(const ColorSpace& lhs, const ColorSpace& rhs) {
|
||||
return lhs.primaries_ == rhs.primaries_ && lhs.transfer_ == rhs.transfer_ &&
|
||||
lhs.matrix_ == rhs.matrix_ && lhs.range_ == rhs.range_ &&
|
||||
lhs.chroma_siting_horizontal_ == rhs.chroma_siting_horizontal_ &&
|
||||
lhs.chroma_siting_vertical_ == rhs.chroma_siting_vertical_ &&
|
||||
lhs.hdr_metadata_ == rhs.hdr_metadata_;
|
||||
}
|
||||
friend bool operator!=(const ColorSpace& lhs, const ColorSpace& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
PrimaryID primaries() const;
|
||||
TransferID transfer() const;
|
||||
MatrixID matrix() const;
|
||||
RangeID range() const;
|
||||
ChromaSiting chroma_siting_horizontal() const;
|
||||
ChromaSiting chroma_siting_vertical() const;
|
||||
const HdrMetadata* hdr_metadata() const;
|
||||
std::string AsString() const;
|
||||
|
||||
bool set_primaries_from_uint8(uint8_t enum_value);
|
||||
bool set_transfer_from_uint8(uint8_t enum_value);
|
||||
bool set_matrix_from_uint8(uint8_t enum_value);
|
||||
bool set_range_from_uint8(uint8_t enum_value);
|
||||
bool set_chroma_siting_horizontal_from_uint8(uint8_t enum_value);
|
||||
bool set_chroma_siting_vertical_from_uint8(uint8_t enum_value);
|
||||
void set_hdr_metadata(const HdrMetadata* hdr_metadata);
|
||||
|
||||
private:
|
||||
PrimaryID primaries_ = PrimaryID::kUnspecified;
|
||||
TransferID transfer_ = TransferID::kUnspecified;
|
||||
MatrixID matrix_ = MatrixID::kUnspecified;
|
||||
RangeID range_ = RangeID::kInvalid;
|
||||
ChromaSiting chroma_siting_horizontal_ = ChromaSiting::kUnspecified;
|
||||
ChromaSiting chroma_siting_vertical_ = ChromaSiting::kUnspecified;
|
||||
std::optional<HdrMetadata> hdr_metadata_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // API_VIDEO_COLOR_SPACE_H_
|
21
webrtc/api/video/hdr_metadata.cc
Normal file
21
webrtc/api/video/hdr_metadata.cc
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/video/hdr_metadata.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
HdrMasteringMetadata::Chromaticity::Chromaticity() = default;
|
||||
|
||||
HdrMasteringMetadata::HdrMasteringMetadata() = default;
|
||||
|
||||
HdrMetadata::HdrMetadata() = default;
|
||||
|
||||
} // namespace webrtc
|
105
webrtc/api/video/hdr_metadata.h
Normal file
105
webrtc/api/video/hdr_metadata.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_VIDEO_HDR_METADATA_H_
|
||||
#define API_VIDEO_HDR_METADATA_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// SMPTE ST 2086 mastering metadata,
|
||||
// see https://ieeexplore.ieee.org/document/8353899.
|
||||
struct HdrMasteringMetadata {
|
||||
struct Chromaticity {
|
||||
Chromaticity();
|
||||
|
||||
bool operator==(const Chromaticity& rhs) const {
|
||||
return x == rhs.x && y == rhs.y;
|
||||
}
|
||||
|
||||
bool Validate() const {
|
||||
return x >= 0.0 && x <= 1.0 && y >= 0.0 && y <= 1.0;
|
||||
}
|
||||
|
||||
// xy chromaticity coordinates must be calculated as specified in ISO
|
||||
// 11664-3:2012 Section 7, and must be specified with four decimal places.
|
||||
// The x coordinate should be in the range [0.0001, 0.7400] and the y
|
||||
// coordinate should be in the range [0.0001, 0.8400]. Valid range [0.0000,
|
||||
// 1.0000].
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
};
|
||||
|
||||
HdrMasteringMetadata();
|
||||
|
||||
bool operator==(const HdrMasteringMetadata& rhs) const {
|
||||
return ((primary_r == rhs.primary_r) && (primary_g == rhs.primary_g) &&
|
||||
(primary_b == rhs.primary_b) && (white_point == rhs.white_point) &&
|
||||
(luminance_max == rhs.luminance_max) &&
|
||||
(luminance_min == rhs.luminance_min));
|
||||
}
|
||||
|
||||
bool Validate() const {
|
||||
return luminance_max >= 0.0 && luminance_max <= 20000.0 &&
|
||||
luminance_min >= 0.0 && luminance_min <= 5.0 &&
|
||||
primary_r.Validate() && primary_g.Validate() &&
|
||||
primary_b.Validate() && white_point.Validate();
|
||||
}
|
||||
|
||||
// The nominal primaries of the mastering display.
|
||||
Chromaticity primary_r;
|
||||
Chromaticity primary_g;
|
||||
Chromaticity primary_b;
|
||||
|
||||
// The nominal chromaticity of the white point of the mastering display.
|
||||
Chromaticity white_point;
|
||||
|
||||
// The nominal maximum display luminance of the mastering display. Specified
|
||||
// in the unit candela/m2. The value should be in the range [5, 10000] with
|
||||
// zero decimal places. Valid range [0, 20000].
|
||||
float luminance_max = 0.0f;
|
||||
|
||||
// The nominal minimum display luminance of the mastering display. Specified
|
||||
// in the unit candela/m2. The value should be in the range [0.0001, 5.0000]
|
||||
// with four decimal places. Valid range [0.0000, 5.0000].
|
||||
float luminance_min = 0.0f;
|
||||
};
|
||||
|
||||
// High dynamic range (HDR) metadata common for HDR10 and WebM/VP9-based HDR
|
||||
// formats. This struct replicates the HDRMetadata struct defined in
|
||||
// https://cs.chromium.org/chromium/src/media/base/hdr_metadata.h
|
||||
struct HdrMetadata {
|
||||
HdrMetadata();
|
||||
|
||||
bool operator==(const HdrMetadata& rhs) const {
|
||||
return (
|
||||
(max_content_light_level == rhs.max_content_light_level) &&
|
||||
(max_frame_average_light_level == rhs.max_frame_average_light_level) &&
|
||||
(mastering_metadata == rhs.mastering_metadata));
|
||||
}
|
||||
|
||||
bool Validate() const {
|
||||
return max_content_light_level >= 0 && max_content_light_level <= 20000 &&
|
||||
max_frame_average_light_level >= 0 &&
|
||||
max_frame_average_light_level <= 20000 &&
|
||||
mastering_metadata.Validate();
|
||||
}
|
||||
|
||||
HdrMasteringMetadata mastering_metadata;
|
||||
// Max content light level (CLL), i.e. maximum brightness level present in the
|
||||
// stream, in nits. 1 nit = 1 candela/m2. Valid range [0, 20000].
|
||||
int max_content_light_level = 0;
|
||||
// Max frame-average light level (FALL), i.e. maximum average brightness of
|
||||
// the brightest frame in the stream, in nits. Valid range [0, 20000].
|
||||
int max_frame_average_light_level = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_VIDEO_HDR_METADATA_H_
|
45
webrtc/api/video/video_content_type.cc
Normal file
45
webrtc/api/video/video_content_type.cc
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/video/video_content_type.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace videocontenttypehelpers {
|
||||
|
||||
namespace {
|
||||
static constexpr uint8_t kScreenshareBitsSize = 1;
|
||||
static constexpr uint8_t kScreenshareBitsMask =
|
||||
(1u << kScreenshareBitsSize) - 1;
|
||||
} // namespace
|
||||
|
||||
bool IsScreenshare(const VideoContentType& content_type) {
|
||||
// Ensure no bits apart from the screenshare bit is set.
|
||||
// This CHECK is a temporary measure to detect code that introduces
|
||||
// values according to old versions.
|
||||
RTC_CHECK((static_cast<uint8_t>(content_type) & !kScreenshareBitsMask) == 0);
|
||||
return (static_cast<uint8_t>(content_type) & kScreenshareBitsMask) > 0;
|
||||
}
|
||||
|
||||
bool IsValidContentType(uint8_t value) {
|
||||
// Only the screenshare bit is allowed.
|
||||
// However, due to previous usage of the next 5 bits, we allow
|
||||
// the lower 6 bits to be set.
|
||||
return value < (1 << 6);
|
||||
}
|
||||
|
||||
const char* ToString(const VideoContentType& content_type) {
|
||||
return IsScreenshare(content_type) ? "screen" : "realtime";
|
||||
}
|
||||
} // namespace videocontenttypehelpers
|
||||
} // namespace webrtc
|
36
webrtc/api/video/video_content_type.h
Normal file
36
webrtc/api/video/video_content_type.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_VIDEO_VIDEO_CONTENT_TYPE_H_
|
||||
#define API_VIDEO_VIDEO_CONTENT_TYPE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// VideoContentType stored as a single byte, which is sent over the network
|
||||
// in the rtp-hdrext/video-content-type extension.
|
||||
// Only the lowest bit is used, per the enum.
|
||||
enum class VideoContentType : uint8_t {
|
||||
UNSPECIFIED = 0,
|
||||
SCREENSHARE = 1,
|
||||
};
|
||||
|
||||
namespace videocontenttypehelpers {
|
||||
bool IsScreenshare(const VideoContentType& content_type);
|
||||
|
||||
bool IsValidContentType(uint8_t value);
|
||||
|
||||
const char* ToString(const VideoContentType& content_type);
|
||||
} // namespace videocontenttypehelpers
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_VIDEO_VIDEO_CONTENT_TYPE_H_
|
26
webrtc/api/video/video_rotation.h
Normal file
26
webrtc/api/video/video_rotation.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_VIDEO_VIDEO_ROTATION_H_
|
||||
#define API_VIDEO_VIDEO_ROTATION_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// enum for clockwise rotation.
|
||||
enum VideoRotation {
|
||||
kVideoRotation_0 = 0,
|
||||
kVideoRotation_90 = 90,
|
||||
kVideoRotation_180 = 180,
|
||||
kVideoRotation_270 = 270
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_VIDEO_VIDEO_ROTATION_H_
|
124
webrtc/api/video/video_timing.cc
Normal file
124
webrtc/api/video/video_timing.cc
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/video/video_timing.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
uint16_t VideoSendTiming::GetDeltaCappedMs(int64_t base_ms, int64_t time_ms) {
|
||||
if (time_ms < base_ms) {
|
||||
RTC_DLOG(LS_ERROR) << "Delta " << (time_ms - base_ms)
|
||||
<< "ms expected to be positive";
|
||||
}
|
||||
return rtc::saturated_cast<uint16_t>(time_ms - base_ms);
|
||||
}
|
||||
|
||||
uint16_t VideoSendTiming::GetDeltaCappedMs(TimeDelta delta) {
|
||||
if (delta < TimeDelta::Zero()) {
|
||||
RTC_DLOG(LS_ERROR) << "Delta " << delta.ms()
|
||||
<< "ms expected to be positive";
|
||||
}
|
||||
return rtc::saturated_cast<uint16_t>(delta.ms());
|
||||
}
|
||||
|
||||
TimingFrameInfo::TimingFrameInfo()
|
||||
: rtp_timestamp(0),
|
||||
capture_time_ms(-1),
|
||||
encode_start_ms(-1),
|
||||
encode_finish_ms(-1),
|
||||
packetization_finish_ms(-1),
|
||||
pacer_exit_ms(-1),
|
||||
network_timestamp_ms(-1),
|
||||
network2_timestamp_ms(-1),
|
||||
receive_start_ms(-1),
|
||||
receive_finish_ms(-1),
|
||||
decode_start_ms(-1),
|
||||
decode_finish_ms(-1),
|
||||
render_time_ms(-1),
|
||||
flags(VideoSendTiming::kNotTriggered) {}
|
||||
|
||||
int64_t TimingFrameInfo::EndToEndDelay() const {
|
||||
return capture_time_ms >= 0 ? decode_finish_ms - capture_time_ms : -1;
|
||||
}
|
||||
|
||||
bool TimingFrameInfo::IsLongerThan(const TimingFrameInfo& other) const {
|
||||
int64_t other_delay = other.EndToEndDelay();
|
||||
return other_delay == -1 || EndToEndDelay() > other_delay;
|
||||
}
|
||||
|
||||
bool TimingFrameInfo::operator<(const TimingFrameInfo& other) const {
|
||||
return other.IsLongerThan(*this);
|
||||
}
|
||||
|
||||
bool TimingFrameInfo::operator<=(const TimingFrameInfo& other) const {
|
||||
return !IsLongerThan(other);
|
||||
}
|
||||
|
||||
bool TimingFrameInfo::IsOutlier() const {
|
||||
return !IsInvalid() && (flags & VideoSendTiming::kTriggeredBySize);
|
||||
}
|
||||
|
||||
bool TimingFrameInfo::IsTimerTriggered() const {
|
||||
return !IsInvalid() && (flags & VideoSendTiming::kTriggeredByTimer);
|
||||
}
|
||||
|
||||
bool TimingFrameInfo::IsInvalid() const {
|
||||
return flags == VideoSendTiming::kInvalid;
|
||||
}
|
||||
|
||||
std::string TimingFrameInfo::ToString() const {
|
||||
if (IsInvalid()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
rtc::SimpleStringBuilder sb(buf);
|
||||
|
||||
sb << rtp_timestamp << ',' << capture_time_ms << ',' << encode_start_ms << ','
|
||||
<< encode_finish_ms << ',' << packetization_finish_ms << ','
|
||||
<< pacer_exit_ms << ',' << network_timestamp_ms << ','
|
||||
<< network2_timestamp_ms << ',' << receive_start_ms << ','
|
||||
<< receive_finish_ms << ',' << decode_start_ms << ',' << decode_finish_ms
|
||||
<< ',' << render_time_ms << ',' << IsOutlier() << ','
|
||||
<< IsTimerTriggered();
|
||||
|
||||
return sb.str();
|
||||
}
|
||||
|
||||
VideoPlayoutDelay::VideoPlayoutDelay(TimeDelta min, TimeDelta max)
|
||||
: min_(std::clamp(min, TimeDelta::Zero(), kMax)),
|
||||
max_(std::clamp(max, min_, kMax)) {
|
||||
if (!(TimeDelta::Zero() <= min && min <= max && max <= kMax)) {
|
||||
RTC_LOG(LS_ERROR) << "Invalid video playout delay: [" << min << "," << max
|
||||
<< "]. Clamped to [" << this->min() << "," << this->max()
|
||||
<< "]";
|
||||
}
|
||||
}
|
||||
|
||||
bool VideoPlayoutDelay::Set(TimeDelta min, TimeDelta max) {
|
||||
if (TimeDelta::Zero() <= min && min <= max && max <= kMax) {
|
||||
min_ = min;
|
||||
max_ = max;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
150
webrtc/api/video/video_timing.h
Normal file
150
webrtc/api/video/video_timing.h
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_VIDEO_VIDEO_TIMING_H_
|
||||
#define API_VIDEO_VIDEO_TIMING_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include "api/units/time_delta.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Video timing timestamps in ms counted from capture_time_ms of a frame.
|
||||
// This structure represents data sent in video-timing RTP header extension.
|
||||
struct RTC_EXPORT VideoSendTiming {
|
||||
enum TimingFrameFlags : uint8_t {
|
||||
kNotTriggered = 0, // Timing info valid, but not to be transmitted.
|
||||
// Used on send-side only.
|
||||
kTriggeredByTimer = 1 << 0, // Frame marked for tracing by periodic timer.
|
||||
kTriggeredBySize = 1 << 1, // Frame marked for tracing due to size.
|
||||
kInvalid = std::numeric_limits<uint8_t>::max() // Invalid, ignore!
|
||||
};
|
||||
|
||||
// Returns |time_ms - base_ms| capped at max 16-bit value.
|
||||
// Used to fill this data structure as per
|
||||
// https://webrtc.org/experiments/rtp-hdrext/video-timing/ extension stores
|
||||
// 16-bit deltas of timestamps from packet capture time.
|
||||
static uint16_t GetDeltaCappedMs(int64_t base_ms, int64_t time_ms);
|
||||
static uint16_t GetDeltaCappedMs(TimeDelta delta);
|
||||
|
||||
uint16_t encode_start_delta_ms;
|
||||
uint16_t encode_finish_delta_ms;
|
||||
uint16_t packetization_finish_delta_ms;
|
||||
uint16_t pacer_exit_delta_ms;
|
||||
uint16_t network_timestamp_delta_ms;
|
||||
uint16_t network2_timestamp_delta_ms;
|
||||
uint8_t flags = TimingFrameFlags::kInvalid;
|
||||
};
|
||||
|
||||
// Used to report precise timings of a 'timing frames'. Contains all important
|
||||
// timestamps for a lifetime of that specific frame. Reported as a string via
|
||||
// GetStats(). Only frame which took the longest between two GetStats calls is
|
||||
// reported.
|
||||
struct RTC_EXPORT TimingFrameInfo {
|
||||
TimingFrameInfo();
|
||||
|
||||
// Returns end-to-end delay of a frame, if sender and receiver timestamps are
|
||||
// synchronized, -1 otherwise.
|
||||
int64_t EndToEndDelay() const;
|
||||
|
||||
// Returns true if current frame took longer to process than `other` frame.
|
||||
// If other frame's clocks are not synchronized, current frame is always
|
||||
// preferred.
|
||||
bool IsLongerThan(const TimingFrameInfo& other) const;
|
||||
|
||||
// Returns true if flags are set to indicate this frame was marked for tracing
|
||||
// due to the size being outside some limit.
|
||||
bool IsOutlier() const;
|
||||
|
||||
// Returns true if flags are set to indicate this frame was marked fro tracing
|
||||
// due to cyclic timer.
|
||||
bool IsTimerTriggered() const;
|
||||
|
||||
// Returns true if the timing data is marked as invalid, in which case it
|
||||
// should be ignored.
|
||||
bool IsInvalid() const;
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
bool operator<(const TimingFrameInfo& other) const;
|
||||
|
||||
bool operator<=(const TimingFrameInfo& other) const;
|
||||
|
||||
uint32_t rtp_timestamp; // Identifier of a frame.
|
||||
// All timestamps below are in local monotonous clock of a receiver.
|
||||
// If sender clock is not yet estimated, sender timestamps
|
||||
// (capture_time_ms ... pacer_exit_ms) are negative values, still
|
||||
// relatively correct.
|
||||
int64_t capture_time_ms; // Captrue time of a frame.
|
||||
int64_t encode_start_ms; // Encode start time.
|
||||
int64_t encode_finish_ms; // Encode completion time.
|
||||
int64_t packetization_finish_ms; // Time when frame was passed to pacer.
|
||||
int64_t pacer_exit_ms; // Time when last packet was pushed out of pacer.
|
||||
// Two in-network RTP processor timestamps: meaning is application specific.
|
||||
int64_t network_timestamp_ms;
|
||||
int64_t network2_timestamp_ms;
|
||||
int64_t receive_start_ms; // First received packet time.
|
||||
int64_t receive_finish_ms; // Last received packet time.
|
||||
int64_t decode_start_ms; // Decode start time.
|
||||
int64_t decode_finish_ms; // Decode completion time.
|
||||
int64_t render_time_ms; // Proposed render time to insure smooth playback.
|
||||
|
||||
uint8_t flags; // Flags indicating validity and/or why tracing was triggered.
|
||||
};
|
||||
|
||||
// Minimum and maximum playout delay values from capture to render.
|
||||
// These are best effort values.
|
||||
//
|
||||
// min = max = 0 indicates that the receiver should try and render
|
||||
// frame as soon as possible.
|
||||
//
|
||||
// min = x, max = y indicates that the receiver is free to adapt
|
||||
// in the range (x, y) based on network jitter.
|
||||
// This class ensures invariant 0 <= min <= max <= kMax.
|
||||
class RTC_EXPORT VideoPlayoutDelay {
|
||||
public:
|
||||
// Maximum supported value for the delay limit.
|
||||
static constexpr TimeDelta kMax = TimeDelta::Millis(10) * 0xFFF;
|
||||
|
||||
// Creates delay limits that indicates receiver should try to render frame
|
||||
// as soon as possible.
|
||||
static VideoPlayoutDelay Minimal() {
|
||||
return VideoPlayoutDelay(TimeDelta::Zero(), TimeDelta::Zero());
|
||||
}
|
||||
|
||||
// Creates valid, but unspecified limits.
|
||||
VideoPlayoutDelay() = default;
|
||||
VideoPlayoutDelay(const VideoPlayoutDelay&) = default;
|
||||
VideoPlayoutDelay& operator=(const VideoPlayoutDelay&) = default;
|
||||
VideoPlayoutDelay(TimeDelta min, TimeDelta max);
|
||||
|
||||
bool Set(TimeDelta min, TimeDelta max);
|
||||
|
||||
TimeDelta min() const { return min_; }
|
||||
TimeDelta max() const { return max_; }
|
||||
|
||||
friend bool operator==(const VideoPlayoutDelay& lhs,
|
||||
const VideoPlayoutDelay& rhs) {
|
||||
return lhs.min_ == rhs.min_ && lhs.max_ == rhs.max_;
|
||||
}
|
||||
|
||||
private:
|
||||
TimeDelta min_ = TimeDelta::Zero();
|
||||
TimeDelta max_ = kMax;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_VIDEO_VIDEO_TIMING_H_
|
55
webrtc/audio/utility/BUILD.gn
Normal file
55
webrtc/audio/utility/BUILD.gn
Normal file
@ -0,0 +1,55 @@
|
||||
# Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
import("../../webrtc.gni")
|
||||
|
||||
group("utility") {
|
||||
deps = [ ":audio_frame_operations" ]
|
||||
}
|
||||
|
||||
rtc_library("audio_frame_operations") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"audio_frame_operations.cc",
|
||||
"audio_frame_operations.h",
|
||||
"channel_mixer.cc",
|
||||
"channel_mixer.h",
|
||||
"channel_mixing_matrix.cc",
|
||||
"channel_mixing_matrix.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../../api:array_view",
|
||||
"../../api/audio:audio_frame_api",
|
||||
"../../common_audio",
|
||||
"../../rtc_base:checks",
|
||||
"../../rtc_base:logging",
|
||||
"../../rtc_base:safe_conversions",
|
||||
"//third_party/abseil-cpp/absl/base:core_headers",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_include_tests) {
|
||||
rtc_library("utility_tests") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"audio_frame_operations_unittest.cc",
|
||||
"channel_mixer_unittest.cc",
|
||||
"channel_mixing_matrix_unittest.cc",
|
||||
]
|
||||
deps = [
|
||||
":audio_frame_operations",
|
||||
"../../api/audio:audio_frame_api",
|
||||
"../../rtc_base:checks",
|
||||
"../../rtc_base:logging",
|
||||
"../../rtc_base:macromagic",
|
||||
"../../rtc_base:stringutils",
|
||||
"../../test:test_support",
|
||||
"//testing/gtest",
|
||||
]
|
||||
}
|
||||
}
|
216
webrtc/audio/utility/audio_frame_operations.cc
Normal file
216
webrtc/audio/utility/audio_frame_operations.cc
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "audio/utility/audio_frame_operations.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
#include "common_audio/include/audio_util.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
// 2.7ms @ 48kHz, 4ms @ 32kHz, 8ms @ 16kHz.
|
||||
const size_t kMuteFadeFrames = 128;
|
||||
const float kMuteFadeInc = 1.0f / kMuteFadeFrames;
|
||||
|
||||
} // namespace
|
||||
|
||||
void AudioFrameOperations::QuadToStereo(
|
||||
InterleavedView<const int16_t> src_audio,
|
||||
InterleavedView<int16_t> dst_audio) {
|
||||
RTC_DCHECK_EQ(NumChannels(src_audio), 4);
|
||||
RTC_DCHECK_EQ(NumChannels(dst_audio), 2);
|
||||
RTC_DCHECK_EQ(SamplesPerChannel(src_audio), SamplesPerChannel(dst_audio));
|
||||
for (size_t i = 0; i < SamplesPerChannel(src_audio); ++i) {
|
||||
auto dst_frame = i * 2;
|
||||
dst_audio[dst_frame] =
|
||||
(static_cast<int32_t>(src_audio[4 * i]) + src_audio[4 * i + 1]) >> 1;
|
||||
dst_audio[dst_frame + 1] =
|
||||
(static_cast<int32_t>(src_audio[4 * i + 2]) + src_audio[4 * i + 3]) >>
|
||||
1;
|
||||
}
|
||||
}
|
||||
|
||||
int AudioFrameOperations::QuadToStereo(AudioFrame* frame) {
|
||||
if (frame->num_channels_ != 4) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
RTC_DCHECK_LE(frame->samples_per_channel_ * 4,
|
||||
AudioFrame::kMaxDataSizeSamples);
|
||||
|
||||
if (!frame->muted()) {
|
||||
// Note that `src` and `dst` will map in to the same buffer, but the call
|
||||
// to `mutable_data()` changes the layout of `frame`, so `src` and `dst`
|
||||
// will have different dimensions (important to call `data_view()` first).
|
||||
auto src = frame->data_view();
|
||||
auto dst = frame->mutable_data(frame->samples_per_channel_, 2);
|
||||
QuadToStereo(src, dst);
|
||||
} else {
|
||||
frame->num_channels_ = 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioFrameOperations::DownmixChannels(
|
||||
InterleavedView<const int16_t> src_audio,
|
||||
InterleavedView<int16_t> dst_audio) {
|
||||
RTC_DCHECK_EQ(SamplesPerChannel(src_audio), SamplesPerChannel(dst_audio));
|
||||
if (NumChannels(src_audio) > 1 && IsMono(dst_audio)) {
|
||||
// TODO(tommi): change DownmixInterleavedToMono to support InterleavedView
|
||||
// and MonoView.
|
||||
DownmixInterleavedToMono(&src_audio.data()[0], SamplesPerChannel(src_audio),
|
||||
NumChannels(src_audio), &dst_audio.data()[0]);
|
||||
} else if (NumChannels(src_audio) == 4 && NumChannels(dst_audio) == 2) {
|
||||
QuadToStereo(src_audio, dst_audio);
|
||||
} else {
|
||||
RTC_DCHECK_NOTREACHED() << "src_channels: " << NumChannels(src_audio)
|
||||
<< ", dst_channels: " << NumChannels(dst_audio);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioFrameOperations::DownmixChannels(size_t dst_channels,
|
||||
AudioFrame* frame) {
|
||||
RTC_DCHECK_LE(frame->samples_per_channel_ * frame->num_channels_,
|
||||
AudioFrame::kMaxDataSizeSamples);
|
||||
if (frame->num_channels_ > 1 && dst_channels == 1) {
|
||||
if (!frame->muted()) {
|
||||
DownmixInterleavedToMono(frame->data(), frame->samples_per_channel_,
|
||||
frame->num_channels_, frame->mutable_data());
|
||||
}
|
||||
frame->num_channels_ = 1;
|
||||
} else if (frame->num_channels_ == 4 && dst_channels == 2) {
|
||||
int err = QuadToStereo(frame);
|
||||
RTC_DCHECK_EQ(err, 0);
|
||||
} else {
|
||||
RTC_DCHECK_NOTREACHED() << "src_channels: " << frame->num_channels_
|
||||
<< ", dst_channels: " << dst_channels;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioFrameOperations::UpmixChannels(size_t target_number_of_channels,
|
||||
AudioFrame* frame) {
|
||||
RTC_DCHECK_EQ(frame->num_channels_, 1);
|
||||
RTC_DCHECK_LE(frame->samples_per_channel_ * target_number_of_channels,
|
||||
AudioFrame::kMaxDataSizeSamples);
|
||||
|
||||
if (frame->num_channels_ != 1 ||
|
||||
frame->samples_per_channel_ * target_number_of_channels >
|
||||
AudioFrame::kMaxDataSizeSamples) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!frame->muted()) {
|
||||
// Up-mixing done in place. Going backwards through the frame ensure nothing
|
||||
// is irrevocably overwritten.
|
||||
auto frame_data = frame->mutable_data(frame->samples_per_channel_,
|
||||
target_number_of_channels);
|
||||
for (int i = frame->samples_per_channel_ - 1; i >= 0; --i) {
|
||||
for (size_t j = 0; j < target_number_of_channels; ++j) {
|
||||
frame_data[target_number_of_channels * i + j] = frame_data[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
frame->num_channels_ = target_number_of_channels;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioFrameOperations::SwapStereoChannels(AudioFrame* frame) {
|
||||
RTC_DCHECK(frame);
|
||||
if (frame->num_channels_ != 2 || frame->muted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t* frame_data = frame->mutable_data();
|
||||
for (size_t i = 0; i < frame->samples_per_channel_ * 2; i += 2) {
|
||||
std::swap(frame_data[i], frame_data[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioFrameOperations::Mute(AudioFrame* frame,
|
||||
bool previous_frame_muted,
|
||||
bool current_frame_muted) {
|
||||
RTC_DCHECK(frame);
|
||||
if (!previous_frame_muted && !current_frame_muted) {
|
||||
// Not muted, don't touch.
|
||||
} else if (previous_frame_muted && current_frame_muted) {
|
||||
// Frame fully muted.
|
||||
size_t total_samples = frame->samples_per_channel_ * frame->num_channels_;
|
||||
RTC_DCHECK_GE(AudioFrame::kMaxDataSizeSamples, total_samples);
|
||||
frame->Mute();
|
||||
} else {
|
||||
// Fade is a no-op on a muted frame.
|
||||
if (frame->muted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Limit number of samples to fade, if frame isn't long enough.
|
||||
size_t count = kMuteFadeFrames;
|
||||
float inc = kMuteFadeInc;
|
||||
if (frame->samples_per_channel_ < kMuteFadeFrames) {
|
||||
count = frame->samples_per_channel_;
|
||||
if (count > 0) {
|
||||
inc = 1.0f / count;
|
||||
}
|
||||
}
|
||||
|
||||
size_t start = 0;
|
||||
size_t end = count;
|
||||
float start_g = 0.0f;
|
||||
if (current_frame_muted) {
|
||||
// Fade out the last `count` samples of frame.
|
||||
RTC_DCHECK(!previous_frame_muted);
|
||||
start = frame->samples_per_channel_ - count;
|
||||
end = frame->samples_per_channel_;
|
||||
start_g = 1.0f;
|
||||
inc = -inc;
|
||||
} else {
|
||||
// Fade in the first `count` samples of frame.
|
||||
RTC_DCHECK(previous_frame_muted);
|
||||
}
|
||||
|
||||
// Perform fade.
|
||||
int16_t* frame_data = frame->mutable_data();
|
||||
size_t channels = frame->num_channels_;
|
||||
for (size_t j = 0; j < channels; ++j) {
|
||||
float g = start_g;
|
||||
for (size_t i = start * channels; i < end * channels; i += channels) {
|
||||
g += inc;
|
||||
frame_data[i + j] *= g;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioFrameOperations::Mute(AudioFrame* frame) {
|
||||
Mute(frame, true, true);
|
||||
}
|
||||
|
||||
int AudioFrameOperations::ScaleWithSat(float scale, AudioFrame* frame) {
|
||||
if (frame->muted()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16_t* frame_data = frame->mutable_data();
|
||||
for (size_t i = 0; i < frame->samples_per_channel_ * frame->num_channels_;
|
||||
i++) {
|
||||
frame_data[i] = rtc::saturated_cast<int16_t>(scale * frame_data[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} // namespace webrtc
|
78
webrtc/audio/utility/audio_frame_operations.h
Normal file
78
webrtc/audio/utility/audio_frame_operations.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_UTILITY_AUDIO_FRAME_OPERATIONS_H_
|
||||
#define AUDIO_UTILITY_AUDIO_FRAME_OPERATIONS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "api/array_view.h"
|
||||
#include "api/audio/audio_frame.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// TODO(andrew): consolidate this with utility.h and audio_frame_manipulator.h.
|
||||
// Change reference parameters to pointers. Consider using a namespace rather
|
||||
// than a class.
|
||||
class AudioFrameOperations {
|
||||
public:
|
||||
// Downmixes 4 channels `src_audio` to stereo `dst_audio`. This is an in-place
|
||||
// operation, meaning `src_audio` and `dst_audio` may point to the same
|
||||
// buffer.
|
||||
static void QuadToStereo(InterleavedView<const int16_t> src_audio,
|
||||
InterleavedView<int16_t> dst_audio);
|
||||
|
||||
// `frame.num_channels_` will be updated. This version checks that
|
||||
// `num_channels_` is 4 channels.
|
||||
static int QuadToStereo(AudioFrame* frame);
|
||||
|
||||
// Downmixes `src_channels` `src_audio` to `dst_channels` `dst_audio`.
|
||||
// This is an in-place operation, meaning `src_audio` and `dst_audio`
|
||||
// may point to the same buffer. Supported channel combinations are
|
||||
// Stereo to Mono, Quad to Mono, and Quad to Stereo.
|
||||
static void DownmixChannels(InterleavedView<const int16_t> src_audio,
|
||||
InterleavedView<int16_t> dst_audio);
|
||||
|
||||
// `frame.num_channels_` will be updated. This version checks that
|
||||
// `num_channels_` and `dst_channels` are valid and performs relevant downmix.
|
||||
// Supported channel combinations are N channels to Mono, and Quad to Stereo.
|
||||
static void DownmixChannels(size_t dst_channels, AudioFrame* frame);
|
||||
|
||||
// `frame.num_channels_` will be updated. This version checks that
|
||||
// `num_channels_` and `dst_channels` are valid and performs relevant
|
||||
// downmix. Supported channel combinations are Mono to N
|
||||
// channels. The single channel is replicated.
|
||||
static void UpmixChannels(size_t target_number_of_channels,
|
||||
AudioFrame* frame);
|
||||
|
||||
// Swap the left and right channels of `frame`. Fails silently if `frame` is
|
||||
// not stereo.
|
||||
static void SwapStereoChannels(AudioFrame* frame);
|
||||
|
||||
// Conditionally zero out contents of `frame` for implementing audio mute:
|
||||
// `previous_frame_muted` && `current_frame_muted` - Zero out whole frame.
|
||||
// `previous_frame_muted` && !`current_frame_muted` - Fade-in at frame start.
|
||||
// !`previous_frame_muted` && `current_frame_muted` - Fade-out at frame end.
|
||||
// !`previous_frame_muted` && !`current_frame_muted` - Leave frame untouched.
|
||||
static void Mute(AudioFrame* frame,
|
||||
bool previous_frame_muted,
|
||||
bool current_frame_muted);
|
||||
|
||||
// Zero out contents of frame.
|
||||
static void Mute(AudioFrame* frame);
|
||||
|
||||
static int ScaleWithSat(float scale, AudioFrame* frame);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // AUDIO_UTILITY_AUDIO_FRAME_OPERATIONS_H_
|
@ -1,596 +0,0 @@
|
||||
# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("//build/config/crypto.gni")
|
||||
import("//build/config/ui.gni")
|
||||
import("../build/webrtc.gni")
|
||||
|
||||
config("rtc_base_config") {
|
||||
include_dirs = [
|
||||
"//third_party/jsoncpp/overrides/include",
|
||||
"//third_party/jsoncpp/source/include",
|
||||
]
|
||||
|
||||
defines = [
|
||||
"FEATURE_ENABLE_SSL",
|
||||
"LOGGING=1",
|
||||
]
|
||||
|
||||
if (is_posix) {
|
||||
# TODO(henrike): issue 3307, make rtc_base build without disabling
|
||||
# these flags.
|
||||
cflags_cc = [ "-Wno-non-virtual-dtor" ]
|
||||
}
|
||||
}
|
||||
|
||||
config("rtc_base_chromium_config") {
|
||||
defines = [ "NO_MAIN_THREAD_WRAPPING" ]
|
||||
}
|
||||
|
||||
config("openssl_config") {
|
||||
defines = [
|
||||
"SSL_USE_OPENSSL",
|
||||
"HAVE_OPENSSL_SSL_H",
|
||||
]
|
||||
}
|
||||
|
||||
config("ios_config") {
|
||||
libs = [
|
||||
"CFNetwork.framework",
|
||||
|
||||
#"Foundation.framework", # Already included in //build/config:default_libs.
|
||||
"Security.framework",
|
||||
"SystemConfiguration.framework",
|
||||
|
||||
#"UIKit.framework", # Already included in //build/config:default_libs.
|
||||
]
|
||||
}
|
||||
|
||||
config("mac_config") {
|
||||
libs = [
|
||||
"Cocoa.framework",
|
||||
|
||||
#"Foundation.framework", # Already included in //build/config:default_libs.
|
||||
#"IOKit.framework", # Already included in //build/config:default_libs.
|
||||
#"Security.framework", # Already included in //build/config:default_libs.
|
||||
"SystemConfiguration.framework",
|
||||
]
|
||||
}
|
||||
|
||||
config("mac_x86_config") {
|
||||
libs = [
|
||||
#"Carbon.framework", # Already included in //build/config:default_libs.
|
||||
]
|
||||
}
|
||||
|
||||
if (is_linux && !build_with_chromium) {
|
||||
# Provides the same functionality as the //crypto:platform target, which
|
||||
# WebRTC cannot use as we don't sync src/crypto from Chromium.
|
||||
group("linux_system_ssl") {
|
||||
if (use_openssl) {
|
||||
deps = [
|
||||
"//third_party/boringssl",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_build_ssl == 0) {
|
||||
config("external_ssl_library") {
|
||||
assert(rtc_ssl_root != "",
|
||||
"You must specify rtc_ssl_root when rtc_build_ssl==0.")
|
||||
include_dirs = [ rtc_ssl_root ]
|
||||
}
|
||||
}
|
||||
|
||||
# The subset of rtc_base approved for use outside of libjingle.
|
||||
static_library("rtc_base_approved") {
|
||||
configs += [ "..:common_config" ]
|
||||
public_configs = [ "..:common_inherited_config" ]
|
||||
|
||||
sources = [
|
||||
"array_view.h",
|
||||
"atomicops.h",
|
||||
"bitbuffer.cc",
|
||||
"bitbuffer.h",
|
||||
"buffer.cc",
|
||||
"buffer.h",
|
||||
"bufferqueue.cc",
|
||||
"bufferqueue.h",
|
||||
"bytebuffer.cc",
|
||||
"bytebuffer.h",
|
||||
"byteorder.h",
|
||||
"checks.cc",
|
||||
"checks.h",
|
||||
"criticalsection.cc",
|
||||
"criticalsection.h",
|
||||
"event.cc",
|
||||
"event.h",
|
||||
"event_tracer.cc",
|
||||
"event_tracer.h",
|
||||
"exp_filter.cc",
|
||||
"exp_filter.h",
|
||||
"maybe.h",
|
||||
"md5.cc",
|
||||
"md5.h",
|
||||
"md5digest.cc",
|
||||
"md5digest.h",
|
||||
"platform_file.cc",
|
||||
"platform_file.h",
|
||||
"platform_thread.cc",
|
||||
"platform_thread.h",
|
||||
"safe_conversions.h",
|
||||
"safe_conversions_impl.h",
|
||||
"scoped_ptr.h",
|
||||
"stringencode.cc",
|
||||
"stringencode.h",
|
||||
"stringutils.cc",
|
||||
"stringutils.h",
|
||||
"systeminfo.cc",
|
||||
"systeminfo.h",
|
||||
"template_util.h",
|
||||
"thread_annotations.h",
|
||||
"thread_checker.h",
|
||||
"thread_checker_impl.cc",
|
||||
"thread_checker_impl.h",
|
||||
"timeutils.cc",
|
||||
"timeutils.h",
|
||||
"trace_event.h",
|
||||
]
|
||||
|
||||
if (!build_with_chromium) {
|
||||
sources += [
|
||||
"basictypes.h",
|
||||
"constructormagic.h",
|
||||
"logging.cc",
|
||||
"logging.h",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
static_library("rtc_base") {
|
||||
cflags = []
|
||||
cflags_cc = []
|
||||
libs = []
|
||||
deps = [
|
||||
":rtc_base_approved",
|
||||
]
|
||||
|
||||
configs += [
|
||||
"..:common_config",
|
||||
":rtc_base_config",
|
||||
]
|
||||
|
||||
public_configs = [
|
||||
"..:common_inherited_config",
|
||||
":rtc_base_config",
|
||||
]
|
||||
|
||||
defines = [ "LOGGING=1" ]
|
||||
|
||||
sources = [
|
||||
"arraysize.h",
|
||||
"asyncfile.cc",
|
||||
"asyncfile.h",
|
||||
"asyncinvoker-inl.h",
|
||||
"asyncinvoker.cc",
|
||||
"asyncinvoker.h",
|
||||
"asyncpacketsocket.cc",
|
||||
"asyncpacketsocket.h",
|
||||
"asyncresolverinterface.cc",
|
||||
"asyncresolverinterface.h",
|
||||
"asyncsocket.cc",
|
||||
"asyncsocket.h",
|
||||
"asynctcpsocket.cc",
|
||||
"asynctcpsocket.h",
|
||||
"asyncudpsocket.cc",
|
||||
"asyncudpsocket.h",
|
||||
"autodetectproxy.cc",
|
||||
"autodetectproxy.h",
|
||||
"base64.cc",
|
||||
"base64.h",
|
||||
"basicdefs.h",
|
||||
"common.cc",
|
||||
"common.h",
|
||||
"crc32.cc",
|
||||
"crc32.h",
|
||||
"cryptstring.cc",
|
||||
"cryptstring.h",
|
||||
"diskcache.cc",
|
||||
"diskcache.h",
|
||||
"filerotatingstream.cc",
|
||||
"filerotatingstream.h",
|
||||
"fileutils.cc",
|
||||
"fileutils.h",
|
||||
"firewallsocketserver.cc",
|
||||
"firewallsocketserver.h",
|
||||
"flags.cc",
|
||||
"flags.h",
|
||||
"format_macros.h",
|
||||
"gunit_prod.h",
|
||||
"helpers.cc",
|
||||
"helpers.h",
|
||||
"httpbase.cc",
|
||||
"httpbase.h",
|
||||
"httpclient.cc",
|
||||
"httpclient.h",
|
||||
"httpcommon-inl.h",
|
||||
"httpcommon.cc",
|
||||
"httpcommon.h",
|
||||
"httprequest.cc",
|
||||
"httprequest.h",
|
||||
"iosfilesystem.mm",
|
||||
"ipaddress.cc",
|
||||
"ipaddress.h",
|
||||
"linked_ptr.h",
|
||||
"mathutils.h",
|
||||
"messagedigest.cc",
|
||||
"messagedigest.h",
|
||||
"messagehandler.cc",
|
||||
"messagehandler.h",
|
||||
"messagequeue.cc",
|
||||
"messagequeue.h",
|
||||
"nethelpers.cc",
|
||||
"nethelpers.h",
|
||||
"network.cc",
|
||||
"network.h",
|
||||
"networkmonitor.cc",
|
||||
"networkmonitor.h",
|
||||
"nullsocketserver.h",
|
||||
"pathutils.cc",
|
||||
"pathutils.h",
|
||||
"physicalsocketserver.cc",
|
||||
"physicalsocketserver.h",
|
||||
"proxydetect.cc",
|
||||
"proxydetect.h",
|
||||
"proxyinfo.cc",
|
||||
"proxyinfo.h",
|
||||
"ratelimiter.cc",
|
||||
"ratelimiter.h",
|
||||
"ratetracker.cc",
|
||||
"ratetracker.h",
|
||||
"rtccertificate.cc",
|
||||
"rtccertificate.h",
|
||||
"scoped_autorelease_pool.h",
|
||||
"scoped_autorelease_pool.mm",
|
||||
"sha1.cc",
|
||||
"sha1.h",
|
||||
"sha1digest.cc",
|
||||
"sha1digest.h",
|
||||
"signalthread.cc",
|
||||
"signalthread.h",
|
||||
"sigslot.cc",
|
||||
"sigslot.h",
|
||||
"sigslotrepeater.h",
|
||||
"socket.h",
|
||||
"socketadapters.cc",
|
||||
"socketadapters.h",
|
||||
"socketaddress.cc",
|
||||
"socketaddress.h",
|
||||
"socketaddresspair.cc",
|
||||
"socketaddresspair.h",
|
||||
"socketfactory.h",
|
||||
"socketpool.cc",
|
||||
"socketpool.h",
|
||||
"socketserver.h",
|
||||
"socketstream.cc",
|
||||
"socketstream.h",
|
||||
"ssladapter.cc",
|
||||
"ssladapter.h",
|
||||
"sslfingerprint.cc",
|
||||
"sslfingerprint.h",
|
||||
"sslidentity.cc",
|
||||
"sslidentity.h",
|
||||
"sslsocketfactory.cc",
|
||||
"sslsocketfactory.h",
|
||||
"sslstreamadapter.cc",
|
||||
"sslstreamadapter.h",
|
||||
"sslstreamadapterhelper.cc",
|
||||
"sslstreamadapterhelper.h",
|
||||
"stream.cc",
|
||||
"stream.h",
|
||||
"task.cc",
|
||||
"task.h",
|
||||
"taskparent.cc",
|
||||
"taskparent.h",
|
||||
"taskrunner.cc",
|
||||
"taskrunner.h",
|
||||
"thread.cc",
|
||||
"thread.h",
|
||||
"timing.cc",
|
||||
"timing.h",
|
||||
"urlencode.cc",
|
||||
"urlencode.h",
|
||||
"worker.cc",
|
||||
"worker.h",
|
||||
]
|
||||
|
||||
if (is_posix) {
|
||||
sources += [
|
||||
"unixfilesystem.cc",
|
||||
"unixfilesystem.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (build_with_chromium) {
|
||||
sources += [
|
||||
"../../webrtc_overrides/webrtc/base/logging.cc",
|
||||
"../../webrtc_overrides/webrtc/base/logging.h",
|
||||
]
|
||||
|
||||
deps += [ "..:webrtc_common" ]
|
||||
|
||||
if (is_win) {
|
||||
sources += [ "../../webrtc_overrides/webrtc/base/win32socketinit.cc" ]
|
||||
}
|
||||
|
||||
include_dirs = [
|
||||
"../../webrtc_overrides",
|
||||
"../../boringssl/src/include",
|
||||
]
|
||||
|
||||
public_configs += [ ":rtc_base_chromium_config" ]
|
||||
} else {
|
||||
sources += [
|
||||
"bandwidthsmoother.cc",
|
||||
"bandwidthsmoother.h",
|
||||
"bind.h",
|
||||
"bind.h.pump",
|
||||
"callback.h",
|
||||
"callback.h.pump",
|
||||
"fileutils_mock.h",
|
||||
"genericslot.h",
|
||||
"genericslot.h.pump",
|
||||
"httpserver.cc",
|
||||
"httpserver.h",
|
||||
"json.cc",
|
||||
"json.h",
|
||||
"logsinks.cc",
|
||||
"logsinks.h",
|
||||
"mathutils.h",
|
||||
"multipart.cc",
|
||||
"multipart.h",
|
||||
"natserver.cc",
|
||||
"natserver.h",
|
||||
"natsocketfactory.cc",
|
||||
"natsocketfactory.h",
|
||||
"nattypes.cc",
|
||||
"nattypes.h",
|
||||
"optionsfile.cc",
|
||||
"optionsfile.h",
|
||||
"profiler.cc",
|
||||
"profiler.h",
|
||||
"proxyserver.cc",
|
||||
"proxyserver.h",
|
||||
"refcount.h",
|
||||
"referencecountedsingletonfactory.h",
|
||||
"rollingaccumulator.h",
|
||||
"scoped_ref_ptr.h",
|
||||
"scopedptrcollection.h",
|
||||
"sec_buffer.h",
|
||||
"sharedexclusivelock.cc",
|
||||
"sharedexclusivelock.h",
|
||||
"sslconfig.h",
|
||||
"sslroots.h",
|
||||
"testclient.cc",
|
||||
"testclient.h",
|
||||
"transformadapter.cc",
|
||||
"transformadapter.h",
|
||||
"versionparsing.cc",
|
||||
"versionparsing.h",
|
||||
"virtualsocketserver.cc",
|
||||
"virtualsocketserver.h",
|
||||
"window.h",
|
||||
"windowpicker.h",
|
||||
"windowpickerfactory.h",
|
||||
]
|
||||
|
||||
deps += [ "..:webrtc_common" ]
|
||||
|
||||
if (is_posix) {
|
||||
sources += [
|
||||
"latebindingsymboltable.cc",
|
||||
"latebindingsymboltable.cc.def",
|
||||
"latebindingsymboltable.h",
|
||||
"latebindingsymboltable.h.def",
|
||||
"posix.cc",
|
||||
"posix.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
sources += [
|
||||
"dbus.cc",
|
||||
"dbus.h",
|
||||
"libdbusglibsymboltable.cc",
|
||||
"libdbusglibsymboltable.h",
|
||||
"linuxfdwalk.c",
|
||||
"linuxfdwalk.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
sources += [
|
||||
"macasyncsocket.cc",
|
||||
"macasyncsocket.h",
|
||||
"maccocoasocketserver.h",
|
||||
"maccocoasocketserver.mm",
|
||||
"macsocketserver.cc",
|
||||
"macsocketserver.h",
|
||||
"macwindowpicker.cc",
|
||||
"macwindowpicker.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
sources += [
|
||||
"diskcache_win32.cc",
|
||||
"diskcache_win32.h",
|
||||
"win32regkey.cc",
|
||||
"win32regkey.h",
|
||||
"win32socketinit.cc",
|
||||
"win32socketinit.h",
|
||||
"win32socketserver.cc",
|
||||
"win32socketserver.h",
|
||||
]
|
||||
}
|
||||
if (rtc_build_json) {
|
||||
deps += [ "//third_party/jsoncpp" ]
|
||||
} else {
|
||||
include_dirs += [ rtc_jsoncpp_root ]
|
||||
|
||||
# When defined changes the include path for json.h to where it is
|
||||
# expected to be when building json outside of the standalone build.
|
||||
defines += [ "WEBRTC_EXTERNAL_JSON" ]
|
||||
}
|
||||
} # !build_with_chromium
|
||||
|
||||
# TODO(henrike): issue 3307, make rtc_base build with the Chromium default
|
||||
# compiler settings.
|
||||
configs -= [ "//build/config/compiler:chromium_code" ]
|
||||
configs += [ "//build/config/compiler:no_chromium_code" ]
|
||||
if (!is_win) {
|
||||
cflags += [ "-Wno-uninitialized" ]
|
||||
cflags_cc += [ "-Wno-non-virtual-dtor" ]
|
||||
}
|
||||
|
||||
if (use_openssl) {
|
||||
public_configs += [ ":openssl_config" ]
|
||||
if (rtc_build_ssl) {
|
||||
deps += [ "//third_party/boringssl" ]
|
||||
} else {
|
||||
configs += [ "external_ssl_library" ]
|
||||
}
|
||||
sources += [
|
||||
"openssl.h",
|
||||
"openssladapter.cc",
|
||||
"openssladapter.h",
|
||||
"openssldigest.cc",
|
||||
"openssldigest.h",
|
||||
"opensslidentity.cc",
|
||||
"opensslidentity.h",
|
||||
"opensslstreamadapter.cc",
|
||||
"opensslstreamadapter.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_android) {
|
||||
sources += [
|
||||
"ifaddrs-android.cc",
|
||||
"ifaddrs-android.h",
|
||||
]
|
||||
|
||||
libs += [
|
||||
"log",
|
||||
"GLESv2",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_ios) {
|
||||
all_dependent_configs = [ ":ios_config" ]
|
||||
|
||||
sources += [
|
||||
"macconversion.cc",
|
||||
"macconversion.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (use_x11) {
|
||||
sources += [
|
||||
"x11windowpicker.cc",
|
||||
"x11windowpicker.h",
|
||||
]
|
||||
libs += [
|
||||
"dl",
|
||||
"rt",
|
||||
"Xext",
|
||||
"X11",
|
||||
"Xcomposite",
|
||||
"Xrender",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
libs += [
|
||||
"dl",
|
||||
"rt",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
sources += [
|
||||
"maccocoathreadhelper.h",
|
||||
"maccocoathreadhelper.mm",
|
||||
"macconversion.cc",
|
||||
"macconversion.h",
|
||||
"macutils.cc",
|
||||
"macutils.h",
|
||||
]
|
||||
|
||||
all_dependent_configs = [ ":mac_config" ]
|
||||
|
||||
if (current_cpu == "x86") {
|
||||
all_dependent_configs += [ ":mac_x86_config" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
sources += [
|
||||
"win32.cc",
|
||||
"win32.h",
|
||||
"win32filesystem.cc",
|
||||
"win32filesystem.h",
|
||||
"win32securityerrors.cc",
|
||||
"win32window.cc",
|
||||
"win32window.h",
|
||||
"win32windowpicker.cc",
|
||||
"win32windowpicker.h",
|
||||
"winfirewall.cc",
|
||||
"winfirewall.h",
|
||||
"winping.cc",
|
||||
"winping.h",
|
||||
]
|
||||
|
||||
libs += [
|
||||
"crypt32.lib",
|
||||
"iphlpapi.lib",
|
||||
"secur32.lib",
|
||||
]
|
||||
|
||||
cflags += [
|
||||
# Suppress warnings about WIN32_LEAN_AND_MEAN.
|
||||
"/wd4005",
|
||||
"/wd4703",
|
||||
]
|
||||
|
||||
defines += [ "_CRT_NONSTDC_NO_DEPRECATE" ]
|
||||
}
|
||||
|
||||
if (is_posix && is_debug) {
|
||||
# The Chromium build/common.gypi defines this for all posix
|
||||
# _except_ for ios & mac. We want it there as well, e.g.
|
||||
# because ASSERT and friends trigger off of it.
|
||||
defines += [ "_DEBUG" ]
|
||||
}
|
||||
|
||||
if (is_ios || (is_mac && current_cpu != "x86")) {
|
||||
defines += [ "CARBON_DEPRECATED=YES" ]
|
||||
}
|
||||
|
||||
if (is_linux || is_android) {
|
||||
sources += [
|
||||
"linux.cc",
|
||||
"linux.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_nacl) {
|
||||
deps += [ "//native_client_sdk/src/libraries/nacl_io" ]
|
||||
defines += [ "timezone=_timezone" ]
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
noinst_LTLIBRARIES = libbase.la
|
||||
|
||||
noinst_HEADERS = arraysize.h \
|
||||
atomicops.h \
|
||||
basictypes.h \
|
||||
constructormagic.h \
|
||||
safe_conversions.h \
|
||||
safe_conversions_impl.h \
|
||||
scoped_ptr.h \
|
||||
template_util.h \
|
||||
thread_annotations.h
|
||||
|
||||
libbase_la_SOURCES = criticalsection.cc \
|
||||
criticalsection.h \
|
||||
checks.cc \
|
||||
checks.h \
|
||||
event.cc \
|
||||
event.h \
|
||||
platform_thread.cc \
|
||||
platform_thread.h \
|
||||
platform_file.cc \
|
||||
platform_file.h \
|
||||
stringutils.cc \
|
||||
stringutils.h \
|
||||
thread_checker.h \
|
||||
thread_checker_impl.cc \
|
||||
thread_checker_impl.h
|
||||
|
||||
libbase_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS)
|
||||
|
||||
EXTRA_DIST = BUILD.gn
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_ATOMICOPS_H_
|
||||
#define WEBRTC_BASE_ATOMICOPS_H_
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
// Include winsock2.h before including <windows.h> to maintain consistency with
|
||||
// win32.h. We can't include win32.h directly here since it pulls in
|
||||
// headers such as basictypes.h which causes problems in Chromium where webrtc
|
||||
// exists as two separate projects, webrtc and libjingle.
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#endif // defined(WEBRTC_WIN)
|
||||
|
||||
namespace rtc {
|
||||
class AtomicOps {
|
||||
public:
|
||||
#if defined(WEBRTC_WIN)
|
||||
// Assumes sizeof(int) == sizeof(LONG), which it is on Win32 and Win64.
|
||||
static int Increment(volatile int* i) {
|
||||
return ::InterlockedIncrement(reinterpret_cast<volatile LONG*>(i));
|
||||
}
|
||||
static int Decrement(volatile int* i) {
|
||||
return ::InterlockedDecrement(reinterpret_cast<volatile LONG*>(i));
|
||||
}
|
||||
static int AcquireLoad(volatile const int* i) {
|
||||
return *i;
|
||||
}
|
||||
static void ReleaseStore(volatile int* i, int value) {
|
||||
*i = value;
|
||||
}
|
||||
static int CompareAndSwap(volatile int* i, int old_value, int new_value) {
|
||||
return ::InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(i),
|
||||
new_value,
|
||||
old_value);
|
||||
}
|
||||
#else
|
||||
static int Increment(volatile int* i) {
|
||||
return __sync_add_and_fetch(i, 1);
|
||||
}
|
||||
static int Decrement(volatile int* i) {
|
||||
return __sync_sub_and_fetch(i, 1);
|
||||
}
|
||||
static int AcquireLoad(volatile const int* i) {
|
||||
return __atomic_load_n(i, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
static void ReleaseStore(volatile int* i, int value) {
|
||||
__atomic_store_n(i, value, __ATOMIC_RELEASE);
|
||||
}
|
||||
static int CompareAndSwap(volatile int* i, int old_value, int new_value) {
|
||||
return __sync_val_compare_and_swap(i, old_value, new_value);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // WEBRTC_BASE_ATOMICOPS_H_
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_BASICTYPES_H_
|
||||
#define WEBRTC_BASE_BASICTYPES_H_
|
||||
|
||||
#include <stddef.h> // for NULL, size_t
|
||||
#include <stdint.h> // for uintptr_t and (u)int_t types.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h" // NOLINT
|
||||
#endif
|
||||
|
||||
// Detect compiler is for x86 or x64.
|
||||
#if defined(__x86_64__) || defined(_M_X64) || \
|
||||
defined(__i386__) || defined(_M_IX86)
|
||||
#define CPU_X86 1
|
||||
#endif
|
||||
|
||||
// Detect compiler is for arm.
|
||||
#if defined(__arm__) || defined(_M_ARM)
|
||||
#define CPU_ARM 1
|
||||
#endif
|
||||
|
||||
#if defined(CPU_X86) && defined(CPU_ARM)
|
||||
#error CPU_X86 and CPU_ARM both defined.
|
||||
#endif
|
||||
|
||||
#if !defined(RTC_ARCH_CPU_BIG_ENDIAN) && !defined(RTC_ARCH_CPU_LITTLE_ENDIAN)
|
||||
// x86, arm or GCC provided __BYTE_ORDER__ macros
|
||||
#if CPU_X86 || CPU_ARM || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
#define RTC_ARCH_CPU_LITTLE_ENDIAN
|
||||
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define RTC_ARCH_CPU_BIG_ENDIAN
|
||||
#else
|
||||
#error RTC_ARCH_CPU_BIG_ENDIAN or RTC_ARCH_CPU_LITTLE_ENDIAN should be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(RTC_ARCH_CPU_BIG_ENDIAN) && defined(RTC_ARCH_CPU_LITTLE_ENDIAN)
|
||||
#error RTC_ARCH_CPU_BIG_ENDIAN and RTC_ARCH_CPU_LITTLE_ENDIAN both defined.
|
||||
#endif
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
// The following only works for C++
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifndef ALIGNP
|
||||
#define ALIGNP(p, t) \
|
||||
(reinterpret_cast<uint8_t*>(((reinterpret_cast<uintptr_t>(p) + \
|
||||
((t) - 1)) & ~((t) - 1))))
|
||||
#endif
|
||||
|
||||
#define RTC_IS_ALIGNED(p, a) (!((uintptr_t)(p) & ((a) - 1)))
|
||||
|
||||
// Use these to declare and define a static local variable that gets leaked so
|
||||
// that its destructors are not called at exit.
|
||||
#define RTC_DEFINE_STATIC_LOCAL(type, name, arguments) \
|
||||
static type& name = *new type arguments
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // WEBRTC_BASE_BASICTYPES_H_
|
@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Most of this was borrowed (with minor modifications) from V8's and Chromium's
|
||||
// src/base/logging.cc.
|
||||
|
||||
// Use the C++ version to provide __GLIBCXX__.
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#if defined(__GLIBCXX__) && !defined(__UCLIBC__)
|
||||
#include <cxxabi.h>
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
||||
#if defined(WEBRTC_ANDROID)
|
||||
#define LOG_TAG "rtc"
|
||||
#include <android/log.h> // NOLINT
|
||||
#endif
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Warning C4722: destructor never returns, potential memory leak.
|
||||
// FatalMessage's dtor very intentionally aborts.
|
||||
#pragma warning(disable:4722)
|
||||
#endif
|
||||
|
||||
namespace rtc {
|
||||
|
||||
void VPrintError(const char* format, va_list args) {
|
||||
#if defined(WEBRTC_ANDROID)
|
||||
__android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args);
|
||||
#else
|
||||
vfprintf(stderr, format, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PrintError(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VPrintError(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// TODO(ajm): This works on Mac (although the parsing fails) but I don't seem
|
||||
// to get usable symbols on Linux. This is copied from V8. Chromium has a more
|
||||
// advanced stace trace system; also more difficult to copy.
|
||||
void DumpBacktrace() {
|
||||
#if defined(__GLIBCXX__) && !defined(__UCLIBC__)
|
||||
void* trace[100];
|
||||
int size = backtrace(trace, sizeof(trace) / sizeof(*trace));
|
||||
char** symbols = backtrace_symbols(trace, size);
|
||||
PrintError("\n==== C stack trace ===============================\n\n");
|
||||
if (size == 0) {
|
||||
PrintError("(empty)\n");
|
||||
} else if (symbols == NULL) {
|
||||
PrintError("(no symbols)\n");
|
||||
} else {
|
||||
for (int i = 1; i < size; ++i) {
|
||||
char mangled[201];
|
||||
if (sscanf(symbols[i], "%*[^(]%*[(]%200[^)+]", mangled) == 1) { // NOLINT
|
||||
PrintError("%2d: ", i);
|
||||
int status;
|
||||
size_t length;
|
||||
char* demangled = abi::__cxa_demangle(mangled, NULL, &length, &status);
|
||||
PrintError("%s\n", demangled != NULL ? demangled : mangled);
|
||||
free(demangled);
|
||||
} else {
|
||||
// If parsing failed, at least print the unparsed symbol.
|
||||
PrintError("%s\n", symbols[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(symbols);
|
||||
#endif
|
||||
}
|
||||
|
||||
FatalMessage::FatalMessage(const char* file, int line) {
|
||||
Init(file, line);
|
||||
}
|
||||
|
||||
FatalMessage::FatalMessage(const char* file, int line, std::string* result) {
|
||||
Init(file, line);
|
||||
stream_ << "Check failed: " << *result << std::endl << "# ";
|
||||
delete result;
|
||||
}
|
||||
|
||||
NO_RETURN FatalMessage::~FatalMessage() {
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
stream_ << std::endl << "#" << std::endl;
|
||||
PrintError(stream_.str().c_str());
|
||||
DumpBacktrace();
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
|
||||
void FatalMessage::Init(const char* file, int line) {
|
||||
stream_ << std::endl << std::endl << "#" << std::endl << "# Fatal error in "
|
||||
<< file << ", line " << line << std::endl << "# ";
|
||||
}
|
||||
|
||||
// MSVC doesn't like complex extern templates and DLLs.
|
||||
#if !defined(COMPILER_MSVC)
|
||||
// Explicit instantiations for commonly used comparisons.
|
||||
template std::string* MakeCheckOpString<int, int>(
|
||||
const int&, const int&, const char* names);
|
||||
template std::string* MakeCheckOpString<unsigned long, unsigned long>(
|
||||
const unsigned long&, const unsigned long&, const char* names);
|
||||
template std::string* MakeCheckOpString<unsigned long, unsigned int>(
|
||||
const unsigned long&, const unsigned int&, const char* names);
|
||||
template std::string* MakeCheckOpString<unsigned int, unsigned long>(
|
||||
const unsigned int&, const unsigned long&, const char* names);
|
||||
template std::string* MakeCheckOpString<std::string, std::string>(
|
||||
const std::string&, const std::string&, const char* name);
|
||||
#endif
|
||||
|
||||
} // namespace rtc
|
@ -1,229 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_CHECKS_H_
|
||||
#define WEBRTC_BASE_CHECKS_H_
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
// The macros here print a message to stderr and abort under various
|
||||
// conditions. All will accept additional stream messages. For example:
|
||||
// RTC_DCHECK_EQ(foo, bar) << "I'm printed when foo != bar.";
|
||||
//
|
||||
// - RTC_CHECK(x) is an assertion that x is always true, and that if it isn't,
|
||||
// it's better to terminate the process than to continue. During development,
|
||||
// the reason that it's better to terminate might simply be that the error
|
||||
// handling code isn't in place yet; in production, the reason might be that
|
||||
// the author of the code truly believes that x will always be true, but that
|
||||
// she recognizes that if she is wrong, abrupt and unpleasant process
|
||||
// termination is still better than carrying on with the assumption violated.
|
||||
//
|
||||
// RTC_CHECK always evaluates its argument, so it's OK for x to have side
|
||||
// effects.
|
||||
//
|
||||
// - RTC_DCHECK(x) is the same as RTC_CHECK(x)---an assertion that x is always
|
||||
// true---except that x will only be evaluated in debug builds; in production
|
||||
// builds, x is simply assumed to be true. This is useful if evaluating x is
|
||||
// expensive and the expected cost of failing to detect the violated
|
||||
// assumption is acceptable. You should not handle cases where a production
|
||||
// build fails to spot a violated condition, even those that would result in
|
||||
// crashes. If the code needs to cope with the error, make it cope, but don't
|
||||
// call RTC_DCHECK; if the condition really can't occur, but you'd sleep
|
||||
// better at night knowing that the process will suicide instead of carrying
|
||||
// on in case you were wrong, use RTC_CHECK instead of RTC_DCHECK.
|
||||
//
|
||||
// RTC_DCHECK only evaluates its argument in debug builds, so if x has visible
|
||||
// side effects, you need to write e.g.
|
||||
// bool w = x; RTC_DCHECK(w);
|
||||
//
|
||||
// - RTC_CHECK_EQ, _NE, _GT, ..., and RTC_DCHECK_EQ, _NE, _GT, ... are
|
||||
// specialized variants of RTC_CHECK and RTC_DCHECK that print prettier
|
||||
// messages if the condition doesn't hold. Prefer them to raw RTC_CHECK and
|
||||
// RTC_DCHECK.
|
||||
//
|
||||
// - FATAL() aborts unconditionally.
|
||||
//
|
||||
// TODO(ajm): Ideally, checks.h would be combined with logging.h, but
|
||||
// consolidation with system_wrappers/logging.h should happen first.
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// Helper macro which avoids evaluating the arguments to a stream if
|
||||
// the condition doesn't hold.
|
||||
#define RTC_LAZY_STREAM(stream, condition) \
|
||||
!(condition) ? static_cast<void>(0) : rtc::FatalMessageVoidify() & (stream)
|
||||
|
||||
// The actual stream used isn't important. We reference condition in the code
|
||||
// but don't evaluate it; this is to avoid "unused variable" warnings (we do so
|
||||
// in a particularly convoluted way with an extra ?: because that appears to be
|
||||
// the simplest construct that keeps Visual Studio from complaining about
|
||||
// condition being unused).
|
||||
#define RTC_EAT_STREAM_PARAMETERS(condition) \
|
||||
(true ? true : !(condition)) \
|
||||
? static_cast<void>(0) \
|
||||
: rtc::FatalMessageVoidify() & rtc::FatalMessage("", 0).stream()
|
||||
|
||||
// RTC_CHECK dies with a fatal error if condition is not true. It is *not*
|
||||
// controlled by NDEBUG, so the check will be executed regardless of
|
||||
// compilation mode.
|
||||
//
|
||||
// We make sure RTC_CHECK et al. always evaluates their arguments, as
|
||||
// doing RTC_CHECK(FunctionWithSideEffect()) is a common idiom.
|
||||
#define RTC_CHECK(condition) \
|
||||
RTC_LAZY_STREAM(rtc::FatalMessage(__FILE__, __LINE__).stream(), \
|
||||
!(condition)) \
|
||||
<< "Check failed: " #condition << std::endl << "# "
|
||||
|
||||
// Helper macro for binary operators.
|
||||
// Don't use this macro directly in your code, use RTC_CHECK_EQ et al below.
|
||||
//
|
||||
// TODO(akalin): Rewrite this so that constructs like if (...)
|
||||
// RTC_CHECK_EQ(...) else { ... } work properly.
|
||||
#define RTC_CHECK_OP(name, op, val1, val2) \
|
||||
if (std::string* _result = \
|
||||
rtc::Check##name##Impl((val1), (val2), #val1 " " #op " " #val2)) \
|
||||
rtc::FatalMessage(__FILE__, __LINE__, _result).stream()
|
||||
|
||||
// Build the error message string. This is separate from the "Impl"
|
||||
// function template because it is not performance critical and so can
|
||||
// be out of line, while the "Impl" code should be inline. Caller
|
||||
// takes ownership of the returned string.
|
||||
template<class t1, class t2>
|
||||
std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
|
||||
std::ostringstream ss;
|
||||
ss << names << " (" << v1 << " vs. " << v2 << ")";
|
||||
std::string* msg = new std::string(ss.str());
|
||||
return msg;
|
||||
}
|
||||
|
||||
// MSVC doesn't like complex extern templates and DLLs.
|
||||
#if !defined(COMPILER_MSVC)
|
||||
// Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated
|
||||
// in logging.cc.
|
||||
extern template std::string* MakeCheckOpString<int, int>(
|
||||
const int&, const int&, const char* names);
|
||||
extern template
|
||||
std::string* MakeCheckOpString<unsigned long, unsigned long>(
|
||||
const unsigned long&, const unsigned long&, const char* names);
|
||||
extern template
|
||||
std::string* MakeCheckOpString<unsigned long, unsigned int>(
|
||||
const unsigned long&, const unsigned int&, const char* names);
|
||||
extern template
|
||||
std::string* MakeCheckOpString<unsigned int, unsigned long>(
|
||||
const unsigned int&, const unsigned long&, const char* names);
|
||||
extern template
|
||||
std::string* MakeCheckOpString<std::string, std::string>(
|
||||
const std::string&, const std::string&, const char* name);
|
||||
#endif
|
||||
|
||||
// Helper functions for RTC_CHECK_OP macro.
|
||||
// The (int, int) specialization works around the issue that the compiler
|
||||
// will not instantiate the template version of the function on values of
|
||||
// unnamed enum type - see comment below.
|
||||
#define DEFINE_RTC_CHECK_OP_IMPL(name, op) \
|
||||
template <class t1, class t2> \
|
||||
inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
|
||||
const char* names) { \
|
||||
if (v1 op v2) \
|
||||
return NULL; \
|
||||
else \
|
||||
return rtc::MakeCheckOpString(v1, v2, names); \
|
||||
} \
|
||||
inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \
|
||||
if (v1 op v2) \
|
||||
return NULL; \
|
||||
else \
|
||||
return rtc::MakeCheckOpString(v1, v2, names); \
|
||||
}
|
||||
DEFINE_RTC_CHECK_OP_IMPL(EQ, ==)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(NE, !=)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(LE, <=)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(LT, < )
|
||||
DEFINE_RTC_CHECK_OP_IMPL(GE, >=)
|
||||
DEFINE_RTC_CHECK_OP_IMPL(GT, > )
|
||||
#undef DEFINE_RTC_CHECK_OP_IMPL
|
||||
|
||||
#define RTC_CHECK_EQ(val1, val2) RTC_CHECK_OP(EQ, ==, val1, val2)
|
||||
#define RTC_CHECK_NE(val1, val2) RTC_CHECK_OP(NE, !=, val1, val2)
|
||||
#define RTC_CHECK_LE(val1, val2) RTC_CHECK_OP(LE, <=, val1, val2)
|
||||
#define RTC_CHECK_LT(val1, val2) RTC_CHECK_OP(LT, < , val1, val2)
|
||||
#define RTC_CHECK_GE(val1, val2) RTC_CHECK_OP(GE, >=, val1, val2)
|
||||
#define RTC_CHECK_GT(val1, val2) RTC_CHECK_OP(GT, > , val1, val2)
|
||||
|
||||
// The RTC_DCHECK macro is equivalent to RTC_CHECK except that it only generates
|
||||
// code in debug builds. It does reference the condition parameter in all cases,
|
||||
// though, so callers won't risk getting warnings about unused variables.
|
||||
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
|
||||
#define RTC_DCHECK_IS_ON 1
|
||||
#define RTC_DCHECK(condition) RTC_CHECK(condition)
|
||||
#define RTC_DCHECK_EQ(v1, v2) RTC_CHECK_EQ(v1, v2)
|
||||
#define RTC_DCHECK_NE(v1, v2) RTC_CHECK_NE(v1, v2)
|
||||
#define RTC_DCHECK_LE(v1, v2) RTC_CHECK_LE(v1, v2)
|
||||
#define RTC_DCHECK_LT(v1, v2) RTC_CHECK_LT(v1, v2)
|
||||
#define RTC_DCHECK_GE(v1, v2) RTC_CHECK_GE(v1, v2)
|
||||
#define RTC_DCHECK_GT(v1, v2) RTC_CHECK_GT(v1, v2)
|
||||
#else
|
||||
#define RTC_DCHECK_IS_ON 0
|
||||
#define RTC_DCHECK(condition) RTC_EAT_STREAM_PARAMETERS(condition)
|
||||
#define RTC_DCHECK_EQ(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) == (v2))
|
||||
#define RTC_DCHECK_NE(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) != (v2))
|
||||
#define RTC_DCHECK_LE(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) <= (v2))
|
||||
#define RTC_DCHECK_LT(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) < (v2))
|
||||
#define RTC_DCHECK_GE(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) >= (v2))
|
||||
#define RTC_DCHECK_GT(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) > (v2))
|
||||
#endif
|
||||
|
||||
// This is identical to LogMessageVoidify but in name.
|
||||
class FatalMessageVoidify {
|
||||
public:
|
||||
FatalMessageVoidify() { }
|
||||
// This has to be an operator with a precedence lower than << but
|
||||
// higher than ?:
|
||||
void operator&(std::ostream&) { }
|
||||
};
|
||||
|
||||
#define RTC_UNREACHABLE_CODE_HIT false
|
||||
#define RTC_NOTREACHED() RTC_DCHECK(RTC_UNREACHABLE_CODE_HIT)
|
||||
|
||||
#define FATAL() rtc::FatalMessage(__FILE__, __LINE__).stream()
|
||||
// TODO(ajm): Consider adding RTC_NOTIMPLEMENTED macro when
|
||||
// base/logging.h and system_wrappers/logging.h are consolidated such that we
|
||||
// can match the Chromium behavior.
|
||||
|
||||
// Like a stripped-down LogMessage from logging.h, except that it aborts.
|
||||
class FatalMessage {
|
||||
public:
|
||||
FatalMessage(const char* file, int line);
|
||||
// Used for RTC_CHECK_EQ(), etc. Takes ownership of the given string.
|
||||
FatalMessage(const char* file, int line, std::string* result);
|
||||
NO_RETURN ~FatalMessage();
|
||||
|
||||
std::ostream& stream() { return stream_; }
|
||||
|
||||
private:
|
||||
void Init(const char* file, int line);
|
||||
|
||||
std::ostringstream stream_;
|
||||
};
|
||||
|
||||
// Performs the integer division a/b and returns the result. CHECKs that the
|
||||
// remainder is zero.
|
||||
template <typename T>
|
||||
inline T CheckedDivExact(T a, T b) {
|
||||
RTC_CHECK_EQ(a % b, static_cast<T>(0));
|
||||
return a / b;
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_CHECKS_H_
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_CONSTRUCTORMAGIC_H_
|
||||
#define WEBRTC_BASE_CONSTRUCTORMAGIC_H_
|
||||
|
||||
// Put this in the declarations for a class to be unassignable.
|
||||
#define RTC_DISALLOW_ASSIGN(TypeName) \
|
||||
void operator=(const TypeName&) = delete
|
||||
|
||||
// A macro to disallow the copy constructor and operator= functions. This should
|
||||
// be used in the declarations for a class.
|
||||
#define RTC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&) = delete; \
|
||||
RTC_DISALLOW_ASSIGN(TypeName)
|
||||
|
||||
// A macro to disallow all the implicit constructors, namely the default
|
||||
// constructor, copy constructor and operator= functions.
|
||||
//
|
||||
// This should be used in the declarations for a class that wants to prevent
|
||||
// anyone from instantiating it. This is especially useful for classes
|
||||
// containing only static methods.
|
||||
#define RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName() = delete; \
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
|
||||
#endif // WEBRTC_BASE_CONSTRUCTORMAGIC_H_
|
@ -1,169 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
CriticalSection::CriticalSection() {
|
||||
#if defined(WEBRTC_WIN)
|
||||
InitializeCriticalSection(&crit_);
|
||||
#else
|
||||
pthread_mutexattr_t mutex_attribute;
|
||||
pthread_mutexattr_init(&mutex_attribute);
|
||||
pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&mutex_, &mutex_attribute);
|
||||
pthread_mutexattr_destroy(&mutex_attribute);
|
||||
CS_DEBUG_CODE(thread_ = 0);
|
||||
CS_DEBUG_CODE(recursion_count_ = 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
CriticalSection::~CriticalSection() {
|
||||
#if defined(WEBRTC_WIN)
|
||||
DeleteCriticalSection(&crit_);
|
||||
#else
|
||||
pthread_mutex_destroy(&mutex_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CriticalSection::Enter() EXCLUSIVE_LOCK_FUNCTION() {
|
||||
#if defined(WEBRTC_WIN)
|
||||
EnterCriticalSection(&crit_);
|
||||
#else
|
||||
pthread_mutex_lock(&mutex_);
|
||||
#if CS_DEBUG_CHECKS
|
||||
if (!recursion_count_) {
|
||||
RTC_DCHECK(!thread_);
|
||||
thread_ = pthread_self();
|
||||
} else {
|
||||
RTC_DCHECK(CurrentThreadIsOwner());
|
||||
}
|
||||
++recursion_count_;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CriticalSection::TryEnter() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
|
||||
#if defined(WEBRTC_WIN)
|
||||
return TryEnterCriticalSection(&crit_) != FALSE;
|
||||
#else
|
||||
if (pthread_mutex_trylock(&mutex_) != 0)
|
||||
return false;
|
||||
#if CS_DEBUG_CHECKS
|
||||
if (!recursion_count_) {
|
||||
RTC_DCHECK(!thread_);
|
||||
thread_ = pthread_self();
|
||||
} else {
|
||||
RTC_DCHECK(CurrentThreadIsOwner());
|
||||
}
|
||||
++recursion_count_;
|
||||
#endif
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
void CriticalSection::Leave() UNLOCK_FUNCTION() {
|
||||
RTC_DCHECK(CurrentThreadIsOwner());
|
||||
#if defined(WEBRTC_WIN)
|
||||
LeaveCriticalSection(&crit_);
|
||||
#else
|
||||
#if CS_DEBUG_CHECKS
|
||||
--recursion_count_;
|
||||
RTC_DCHECK(recursion_count_ >= 0);
|
||||
if (!recursion_count_)
|
||||
thread_ = 0;
|
||||
#endif
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CriticalSection::CurrentThreadIsOwner() const {
|
||||
#if defined(WEBRTC_WIN)
|
||||
// OwningThread has type HANDLE but actually contains the Thread ID:
|
||||
// http://stackoverflow.com/questions/12675301/why-is-the-owningthread-member-of-critical-section-of-type-handle-when-it-is-de
|
||||
// Converting through size_t avoids the VS 2015 warning C4312: conversion from
|
||||
// 'type1' to 'type2' of greater size
|
||||
return crit_.OwningThread ==
|
||||
reinterpret_cast<HANDLE>(static_cast<size_t>(GetCurrentThreadId()));
|
||||
#else
|
||||
#if CS_DEBUG_CHECKS
|
||||
return pthread_equal(thread_, pthread_self());
|
||||
#else
|
||||
return true;
|
||||
#endif // CS_DEBUG_CHECKS
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CriticalSection::IsLocked() const {
|
||||
#if defined(WEBRTC_WIN)
|
||||
return crit_.LockCount != -1;
|
||||
#else
|
||||
#if CS_DEBUG_CHECKS
|
||||
return thread_ != 0;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
CritScope::CritScope(CriticalSection* cs) : cs_(cs) { cs_->Enter(); }
|
||||
CritScope::~CritScope() { cs_->Leave(); }
|
||||
|
||||
TryCritScope::TryCritScope(CriticalSection* cs)
|
||||
: cs_(cs), locked_(cs->TryEnter()) {
|
||||
CS_DEBUG_CODE(lock_was_called_ = false);
|
||||
}
|
||||
|
||||
TryCritScope::~TryCritScope() {
|
||||
CS_DEBUG_CODE(RTC_DCHECK(lock_was_called_));
|
||||
if (locked_)
|
||||
cs_->Leave();
|
||||
}
|
||||
|
||||
bool TryCritScope::locked() const {
|
||||
CS_DEBUG_CODE(lock_was_called_ = true);
|
||||
return locked_;
|
||||
}
|
||||
|
||||
void GlobalLockPod::Lock() {
|
||||
#if !defined(WEBRTC_WIN)
|
||||
const struct timespec ts_null = {0};
|
||||
#endif
|
||||
|
||||
while (AtomicOps::CompareAndSwap(&lock_acquired, 0, 1)) {
|
||||
#if defined(WEBRTC_WIN)
|
||||
::Sleep(0);
|
||||
#else
|
||||
nanosleep(&ts_null, nullptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalLockPod::Unlock() {
|
||||
int old_value = AtomicOps::CompareAndSwap(&lock_acquired, 1, 0);
|
||||
RTC_DCHECK_EQ(1, old_value) << "Unlock called without calling Lock first";
|
||||
}
|
||||
|
||||
GlobalLock::GlobalLock() {
|
||||
lock_acquired = 0;
|
||||
}
|
||||
|
||||
GlobalLockScope::GlobalLockScope(GlobalLockPod* lock)
|
||||
: lock_(lock) {
|
||||
lock_->Lock();
|
||||
}
|
||||
|
||||
GlobalLockScope::~GlobalLockScope() {
|
||||
lock_->Unlock();
|
||||
}
|
||||
|
||||
} // namespace rtc
|
@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_CRITICALSECTION_H_
|
||||
#define WEBRTC_BASE_CRITICALSECTION_H_
|
||||
|
||||
#include "webrtc/base/atomicops.h"
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/thread_annotations.h"
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
// Include winsock2.h before including <windows.h> to maintain consistency with
|
||||
// win32.h. We can't include win32.h directly here since it pulls in
|
||||
// headers such as basictypes.h which causes problems in Chromium where webrtc
|
||||
// exists as two separate projects, webrtc and libjingle.
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <sal.h> // must come after windows headers.
|
||||
#endif // defined(WEBRTC_WIN)
|
||||
|
||||
#if defined(WEBRTC_POSIX)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
|
||||
#define CS_DEBUG_CHECKS 1
|
||||
#endif
|
||||
|
||||
#if CS_DEBUG_CHECKS
|
||||
#define CS_DEBUG_CODE(x) x
|
||||
#else // !CS_DEBUG_CHECKS
|
||||
#define CS_DEBUG_CODE(x)
|
||||
#endif // !CS_DEBUG_CHECKS
|
||||
|
||||
namespace rtc {
|
||||
|
||||
class LOCKABLE CriticalSection {
|
||||
public:
|
||||
CriticalSection();
|
||||
~CriticalSection();
|
||||
|
||||
void Enter() EXCLUSIVE_LOCK_FUNCTION();
|
||||
bool TryEnter() EXCLUSIVE_TRYLOCK_FUNCTION(true);
|
||||
void Leave() UNLOCK_FUNCTION();
|
||||
|
||||
// Use only for RTC_DCHECKing.
|
||||
bool CurrentThreadIsOwner() const;
|
||||
// Use only for RTC_DCHECKing.
|
||||
bool IsLocked() const;
|
||||
|
||||
private:
|
||||
#if defined(WEBRTC_WIN)
|
||||
CRITICAL_SECTION crit_;
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
pthread_mutex_t mutex_;
|
||||
CS_DEBUG_CODE(pthread_t thread_);
|
||||
CS_DEBUG_CODE(int recursion_count_);
|
||||
#endif
|
||||
};
|
||||
|
||||
// CritScope, for serializing execution through a scope.
|
||||
class SCOPED_LOCKABLE CritScope {
|
||||
public:
|
||||
explicit CritScope(CriticalSection* cs) EXCLUSIVE_LOCK_FUNCTION(cs);
|
||||
~CritScope() UNLOCK_FUNCTION();
|
||||
private:
|
||||
CriticalSection* const cs_;
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(CritScope);
|
||||
};
|
||||
|
||||
// Tries to lock a critical section on construction via
|
||||
// CriticalSection::TryEnter, and unlocks on destruction if the
|
||||
// lock was taken. Never blocks.
|
||||
//
|
||||
// IMPORTANT: Unlike CritScope, the lock may not be owned by this thread in
|
||||
// subsequent code. Users *must* check locked() to determine if the
|
||||
// lock was taken. If you're not calling locked(), you're doing it wrong!
|
||||
class TryCritScope {
|
||||
public:
|
||||
explicit TryCritScope(CriticalSection* cs);
|
||||
~TryCritScope();
|
||||
#if defined(WEBRTC_WIN)
|
||||
_Check_return_ bool locked() const;
|
||||
#else
|
||||
bool locked() const __attribute__((warn_unused_result));
|
||||
#endif
|
||||
private:
|
||||
CriticalSection* const cs_;
|
||||
const bool locked_;
|
||||
CS_DEBUG_CODE(mutable bool lock_was_called_);
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(TryCritScope);
|
||||
};
|
||||
|
||||
// A POD lock used to protect global variables. Do NOT use for other purposes.
|
||||
// No custom constructor or private data member should be added.
|
||||
class LOCKABLE GlobalLockPod {
|
||||
public:
|
||||
void Lock() EXCLUSIVE_LOCK_FUNCTION();
|
||||
|
||||
void Unlock() UNLOCK_FUNCTION();
|
||||
|
||||
volatile int lock_acquired;
|
||||
};
|
||||
|
||||
class GlobalLock : public GlobalLockPod {
|
||||
public:
|
||||
GlobalLock();
|
||||
};
|
||||
|
||||
// GlobalLockScope, for serializing execution through a scope.
|
||||
class SCOPED_LOCKABLE GlobalLockScope {
|
||||
public:
|
||||
explicit GlobalLockScope(GlobalLockPod* lock) EXCLUSIVE_LOCK_FUNCTION(lock);
|
||||
~GlobalLockScope() UNLOCK_FUNCTION();
|
||||
private:
|
||||
GlobalLockPod* const lock_;
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(GlobalLockScope);
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_CRITICALSECTION_H_
|
@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/base/event.h"
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
#include <windows.h>
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#else
|
||||
#error "Must define either WEBRTC_WIN or WEBRTC_POSIX."
|
||||
#endif
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
|
||||
Event::Event(bool manual_reset, bool initially_signaled) {
|
||||
event_handle_ = ::CreateEvent(NULL, // Security attributes.
|
||||
manual_reset,
|
||||
initially_signaled,
|
||||
NULL); // Name.
|
||||
RTC_CHECK(event_handle_);
|
||||
}
|
||||
|
||||
Event::~Event() {
|
||||
CloseHandle(event_handle_);
|
||||
}
|
||||
|
||||
void Event::Set() {
|
||||
SetEvent(event_handle_);
|
||||
}
|
||||
|
||||
void Event::Reset() {
|
||||
ResetEvent(event_handle_);
|
||||
}
|
||||
|
||||
bool Event::Wait(int milliseconds) {
|
||||
DWORD ms = (milliseconds == kForever) ? INFINITE : milliseconds;
|
||||
return (WaitForSingleObject(event_handle_, ms) == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
|
||||
Event::Event(bool manual_reset, bool initially_signaled)
|
||||
: is_manual_reset_(manual_reset),
|
||||
event_status_(initially_signaled) {
|
||||
RTC_CHECK(pthread_mutex_init(&event_mutex_, NULL) == 0);
|
||||
RTC_CHECK(pthread_cond_init(&event_cond_, NULL) == 0);
|
||||
}
|
||||
|
||||
Event::~Event() {
|
||||
pthread_mutex_destroy(&event_mutex_);
|
||||
pthread_cond_destroy(&event_cond_);
|
||||
}
|
||||
|
||||
void Event::Set() {
|
||||
pthread_mutex_lock(&event_mutex_);
|
||||
event_status_ = true;
|
||||
pthread_cond_broadcast(&event_cond_);
|
||||
pthread_mutex_unlock(&event_mutex_);
|
||||
}
|
||||
|
||||
void Event::Reset() {
|
||||
pthread_mutex_lock(&event_mutex_);
|
||||
event_status_ = false;
|
||||
pthread_mutex_unlock(&event_mutex_);
|
||||
}
|
||||
|
||||
bool Event::Wait(int milliseconds) {
|
||||
pthread_mutex_lock(&event_mutex_);
|
||||
int error = 0;
|
||||
|
||||
if (milliseconds != kForever) {
|
||||
// Converting from seconds and microseconds (1e-6) plus
|
||||
// milliseconds (1e-3) to seconds and nanoseconds (1e-9).
|
||||
|
||||
struct timespec ts;
|
||||
#if HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
|
||||
// Use relative time version, which tends to be more efficient for
|
||||
// pthread implementations where provided (like on Android).
|
||||
ts.tv_sec = milliseconds / 1000;
|
||||
ts.tv_nsec = (milliseconds % 1000) * 1000000;
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
ts.tv_sec = tv.tv_sec + (milliseconds / 1000);
|
||||
ts.tv_nsec = tv.tv_usec * 1000 + (milliseconds % 1000) * 1000000;
|
||||
|
||||
// Handle overflow.
|
||||
if (ts.tv_nsec >= 1000000000) {
|
||||
ts.tv_sec++;
|
||||
ts.tv_nsec -= 1000000000;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (!event_status_ && error == 0) {
|
||||
#if HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
|
||||
error = pthread_cond_timedwait_relative_np(
|
||||
&event_cond_, &event_mutex_, &ts);
|
||||
#else
|
||||
error = pthread_cond_timedwait(&event_cond_, &event_mutex_, &ts);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
while (!event_status_ && error == 0)
|
||||
error = pthread_cond_wait(&event_cond_, &event_mutex_);
|
||||
}
|
||||
|
||||
// NOTE(liulk): Exactly one thread will auto-reset this event. All
|
||||
// the other threads will think it's unsignaled. This seems to be
|
||||
// consistent with auto-reset events in WEBRTC_WIN
|
||||
if (error == 0 && !is_manual_reset_)
|
||||
event_status_ = false;
|
||||
|
||||
pthread_mutex_unlock(&event_mutex_);
|
||||
|
||||
return (error == 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace rtc
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_EVENT_H__
|
||||
#define WEBRTC_BASE_EVENT_H__
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
#include "webrtc/base/win32.h" // NOLINT: consider this a system header.
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
#include <pthread.h>
|
||||
#else
|
||||
#error "Must define either WEBRTC_WIN or WEBRTC_POSIX."
|
||||
#endif
|
||||
|
||||
#include "webrtc/base/basictypes.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
class Event {
|
||||
public:
|
||||
static const int kForever = -1;
|
||||
|
||||
Event(bool manual_reset, bool initially_signaled);
|
||||
~Event();
|
||||
|
||||
void Set();
|
||||
void Reset();
|
||||
|
||||
// Wait for the event to become signaled, for the specified number of
|
||||
// |milliseconds|. To wait indefinetly, pass kForever.
|
||||
bool Wait(int milliseconds);
|
||||
|
||||
private:
|
||||
#if defined(WEBRTC_WIN)
|
||||
HANDLE event_handle_;
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
pthread_mutex_t event_mutex_;
|
||||
pthread_cond_t event_cond_;
|
||||
const bool is_manual_reset_;
|
||||
bool event_status_;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_EVENT_H__
|
@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_MAYBE_H_
|
||||
#define WEBRTC_BASE_MAYBE_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// Simple std::experimental::optional-wannabe. It either contains a T or not.
|
||||
// In order to keep the implementation simple and portable, this implementation
|
||||
// actually contains a (default-constructed) T even when it supposedly doesn't
|
||||
// contain a value; use e.g. rtc::scoped_ptr<T> instead if that's too
|
||||
// expensive.
|
||||
//
|
||||
// A moved-from Maybe<T> may only be destroyed, and assigned to if T allows
|
||||
// being assigned to after having been moved from. Specifically, you may not
|
||||
// assume that it just doesn't contain a value anymore.
|
||||
//
|
||||
// TODO(kwiberg): Get rid of this class when the standard library has
|
||||
// std::optional (and we're allowed to use it).
|
||||
template <typename T>
|
||||
class Maybe final {
|
||||
public:
|
||||
// Construct an empty Maybe.
|
||||
Maybe() : has_value_(false) {}
|
||||
|
||||
// Construct a Maybe that contains a value.
|
||||
explicit Maybe(const T& val) : value_(val), has_value_(true) {}
|
||||
explicit Maybe(T&& val) : value_(static_cast<T&&>(val)), has_value_(true) {}
|
||||
|
||||
// Copy and move constructors.
|
||||
// TODO(kwiberg): =default the move constructor when MSVC supports it.
|
||||
Maybe(const Maybe&) = default;
|
||||
Maybe(Maybe&& m)
|
||||
: value_(static_cast<T&&>(m.value_)), has_value_(m.has_value_) {}
|
||||
|
||||
// Assignment.
|
||||
// TODO(kwiberg): =default the move assignment op when MSVC supports it.
|
||||
Maybe& operator=(const Maybe&) = default;
|
||||
Maybe& operator=(Maybe&& m) {
|
||||
value_ = static_cast<T&&>(m.value_);
|
||||
has_value_ = m.has_value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend void swap(Maybe& m1, Maybe& m2) {
|
||||
using std::swap;
|
||||
swap(m1.value_, m2.value_);
|
||||
swap(m1.has_value_, m2.has_value_);
|
||||
}
|
||||
|
||||
// Conversion to bool to test if we have a value.
|
||||
explicit operator bool() const { return has_value_; }
|
||||
|
||||
// Dereferencing. Only allowed if we have a value.
|
||||
const T* operator->() const {
|
||||
RTC_DCHECK(has_value_);
|
||||
return &value_;
|
||||
}
|
||||
T* operator->() {
|
||||
RTC_DCHECK(has_value_);
|
||||
return &value_;
|
||||
}
|
||||
const T& operator*() const {
|
||||
RTC_DCHECK(has_value_);
|
||||
return value_;
|
||||
}
|
||||
T& operator*() {
|
||||
RTC_DCHECK(has_value_);
|
||||
return value_;
|
||||
}
|
||||
|
||||
// Dereference with a default value in case we don't have a value.
|
||||
const T& value_or(const T& default_val) const {
|
||||
return has_value_ ? value_ : default_val;
|
||||
}
|
||||
|
||||
// Equality tests. Two Maybes are equal if they contain equivalent values, or
|
||||
// if they're both empty.
|
||||
friend bool operator==(const Maybe& m1, const Maybe& m2) {
|
||||
return m1.has_value_ && m2.has_value_ ? m1.value_ == m2.value_
|
||||
: m1.has_value_ == m2.has_value_;
|
||||
}
|
||||
friend bool operator!=(const Maybe& m1, const Maybe& m2) {
|
||||
return m1.has_value_ && m2.has_value_ ? m1.value_ != m2.value_
|
||||
: m1.has_value_ != m2.has_value_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Invariant: Unless *this has been moved from, value_ is default-initialized
|
||||
// (or copied or moved from a default-initialized T) if !has_value_.
|
||||
T value_;
|
||||
bool has_value_;
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_MAYBE_H_
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/base/platform_file.h"
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace rtc {
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE;
|
||||
|
||||
FILE* FdopenPlatformFileForWriting(PlatformFile file) {
|
||||
if (file == kInvalidPlatformFileValue)
|
||||
return NULL;
|
||||
int fd = _open_osfhandle(reinterpret_cast<intptr_t>(file), 0);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
return _fdopen(fd, "w");
|
||||
}
|
||||
|
||||
bool ClosePlatformFile(PlatformFile file) {
|
||||
return CloseHandle(file) != 0;
|
||||
}
|
||||
#else
|
||||
const PlatformFile kInvalidPlatformFileValue = -1;
|
||||
|
||||
FILE* FdopenPlatformFileForWriting(PlatformFile file) {
|
||||
return fdopen(file, "w");
|
||||
}
|
||||
|
||||
bool ClosePlatformFile(PlatformFile file) {
|
||||
return close(file);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace rtc
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_PLATFORM_FILE_H_
|
||||
#define WEBRTC_BASE_PLATFORM_FILE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace rtc {
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
typedef HANDLE PlatformFile;
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
typedef int PlatformFile;
|
||||
#else
|
||||
#error Unsupported platform
|
||||
#endif
|
||||
|
||||
extern const PlatformFile kInvalidPlatformFileValue;
|
||||
|
||||
// Associates a standard FILE stream with an existing PlatformFile.
|
||||
// Note that after this function has returned a valid FILE stream,
|
||||
// the PlatformFile should no longer be used.
|
||||
FILE* FdopenPlatformFileForWriting(PlatformFile file);
|
||||
|
||||
// Closes a PlatformFile.
|
||||
// Don't use ClosePlatformFile to close a file opened with FdopenPlatformFile.
|
||||
// Use fclose instead.
|
||||
bool ClosePlatformFile(PlatformFile file);
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_PLATFORM_FILE_H_
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/base/platform_thread.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
#if defined(WEBRTC_LINUX)
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
namespace rtc {
|
||||
|
||||
PlatformThreadId CurrentThreadId() {
|
||||
PlatformThreadId ret;
|
||||
#if defined(WEBRTC_WIN)
|
||||
ret = GetCurrentThreadId();
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
#if defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
|
||||
ret = pthread_mach_thread_np(pthread_self());
|
||||
#elif defined(WEBRTC_LINUX)
|
||||
ret = syscall(__NR_gettid);
|
||||
#elif defined(WEBRTC_ANDROID)
|
||||
ret = gettid();
|
||||
#else
|
||||
// Default implementation for nacl and solaris.
|
||||
ret = reinterpret_cast<pid_t>(pthread_self());
|
||||
#endif
|
||||
#endif // defined(WEBRTC_POSIX)
|
||||
RTC_DCHECK(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PlatformThreadRef CurrentThreadRef() {
|
||||
#if defined(WEBRTC_WIN)
|
||||
return GetCurrentThreadId();
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
return pthread_self();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) {
|
||||
#if defined(WEBRTC_WIN)
|
||||
return a == b;
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
return pthread_equal(a, b);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetCurrentThreadName(const char* name) {
|
||||
RTC_DCHECK(strlen(name) < 64);
|
||||
#if defined(WEBRTC_WIN)
|
||||
struct {
|
||||
DWORD dwType;
|
||||
LPCSTR szName;
|
||||
DWORD dwThreadID;
|
||||
DWORD dwFlags;
|
||||
} threadname_info = {0x1000, name, static_cast<DWORD>(-1), 0};
|
||||
|
||||
__try {
|
||||
::RaiseException(0x406D1388, 0, sizeof(threadname_info) / sizeof(DWORD),
|
||||
reinterpret_cast<ULONG_PTR*>(&threadname_info));
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
}
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
|
||||
prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name));
|
||||
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
|
||||
pthread_setname_np(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace rtc
|
@ -1,636 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/memory/scoped_ptr.h.
|
||||
|
||||
// Scopers help you manage ownership of a pointer, helping you easily manage a
|
||||
// pointer within a scope, and automatically destroying the pointer at the end
|
||||
// of a scope. There are two main classes you will use, which correspond to the
|
||||
// operators new/delete and new[]/delete[].
|
||||
//
|
||||
// Example usage (scoped_ptr<T>):
|
||||
// {
|
||||
// scoped_ptr<Foo> foo(new Foo("wee"));
|
||||
// } // foo goes out of scope, releasing the pointer with it.
|
||||
//
|
||||
// {
|
||||
// scoped_ptr<Foo> foo; // No pointer managed.
|
||||
// foo.reset(new Foo("wee")); // Now a pointer is managed.
|
||||
// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
|
||||
// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
|
||||
// foo->Method(); // Foo::Method() called.
|
||||
// foo.get()->Method(); // Foo::Method() called.
|
||||
// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer
|
||||
// // manages a pointer.
|
||||
// foo.reset(new Foo("wee4")); // foo manages a pointer again.
|
||||
// foo.reset(); // Foo("wee4") destroyed, foo no longer
|
||||
// // manages a pointer.
|
||||
// } // foo wasn't managing a pointer, so nothing was destroyed.
|
||||
//
|
||||
// Example usage (scoped_ptr<T[]>):
|
||||
// {
|
||||
// scoped_ptr<Foo[]> foo(new Foo[100]);
|
||||
// foo.get()->Method(); // Foo::Method on the 0th element.
|
||||
// foo[10].Method(); // Foo::Method on the 10th element.
|
||||
// }
|
||||
//
|
||||
// These scopers also implement part of the functionality of C++11 unique_ptr
|
||||
// in that they are "movable but not copyable." You can use the scopers in
|
||||
// the parameter and return types of functions to signify ownership transfer
|
||||
// in to and out of a function. When calling a function that has a scoper
|
||||
// as the argument type, it must be called with the result of an analogous
|
||||
// scoper's Pass() function or another function that generates a temporary;
|
||||
// passing by copy will NOT work. Here is an example using scoped_ptr:
|
||||
//
|
||||
// void TakesOwnership(scoped_ptr<Foo> arg) {
|
||||
// // Do something with arg
|
||||
// }
|
||||
// scoped_ptr<Foo> CreateFoo() {
|
||||
// // No need for calling Pass() because we are constructing a temporary
|
||||
// // for the return value.
|
||||
// return scoped_ptr<Foo>(new Foo("new"));
|
||||
// }
|
||||
// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
|
||||
// return arg.Pass();
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay").
|
||||
// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay").
|
||||
// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo.
|
||||
// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2.
|
||||
// PassThru(ptr2.Pass()); // ptr2 is correspondingly nullptr.
|
||||
// }
|
||||
//
|
||||
// Notice that if you do not call Pass() when returning from PassThru(), or
|
||||
// when invoking TakesOwnership(), the code will not compile because scopers
|
||||
// are not copyable; they only implement move semantics which require calling
|
||||
// the Pass() function to signify a destructive transfer of state. CreateFoo()
|
||||
// is different though because we are constructing a temporary on the return
|
||||
// line and thus can avoid needing to call Pass().
|
||||
//
|
||||
// Pass() properly handles upcast in initialization, i.e. you can use a
|
||||
// scoped_ptr<Child> to initialize a scoped_ptr<Parent>:
|
||||
//
|
||||
// scoped_ptr<Foo> foo(new Foo());
|
||||
// scoped_ptr<FooParent> parent(foo.Pass());
|
||||
//
|
||||
// PassAs<>() should be used to upcast return value in return statement:
|
||||
//
|
||||
// scoped_ptr<Foo> CreateFoo() {
|
||||
// scoped_ptr<FooChild> result(new FooChild());
|
||||
// return result.PassAs<Foo>();
|
||||
// }
|
||||
//
|
||||
// Note that PassAs<>() is implemented only for scoped_ptr<T>, but not for
|
||||
// scoped_ptr<T[]>. This is because casting array pointers may not be safe.
|
||||
|
||||
#ifndef WEBRTC_BASE_SCOPED_PTR_H__
|
||||
#define WEBRTC_BASE_SCOPED_PTR_H__
|
||||
|
||||
// This is an implementation designed to match the anticipated future TR2
|
||||
// implementation of the scoped_ptr class.
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <algorithm> // For std::swap().
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/template_util.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// Function object which deletes its parameter, which must be a pointer.
|
||||
// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
|
||||
// invokes 'delete'. The default deleter for scoped_ptr<T>.
|
||||
template <class T>
|
||||
struct DefaultDeleter {
|
||||
DefaultDeleter() {}
|
||||
template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
|
||||
// IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
|
||||
// if U* is implicitly convertible to T* and U is not an array type.
|
||||
//
|
||||
// Correct implementation should use SFINAE to disable this
|
||||
// constructor. However, since there are no other 1-argument constructors,
|
||||
// using a static_assert based on is_convertible<> and requiring
|
||||
// complete types is simpler and will cause compile failures for equivalent
|
||||
// misuses.
|
||||
//
|
||||
// Note, the is_convertible<U*, T*> check also ensures that U is not an
|
||||
// array. T is guaranteed to be a non-array, so any U* where U is an array
|
||||
// cannot convert to T*.
|
||||
enum { T_must_be_complete = sizeof(T) };
|
||||
enum { U_must_be_complete = sizeof(U) };
|
||||
static_assert(rtc::is_convertible<U*, T*>::value,
|
||||
"U* must implicitly convert to T*");
|
||||
}
|
||||
inline void operator()(T* ptr) const {
|
||||
enum { type_must_be_complete = sizeof(T) };
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization of DefaultDeleter for array types.
|
||||
template <class T>
|
||||
struct DefaultDeleter<T[]> {
|
||||
inline void operator()(T* ptr) const {
|
||||
enum { type_must_be_complete = sizeof(T) };
|
||||
delete[] ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// Disable this operator for any U != T because it is undefined to execute
|
||||
// an array delete when the static type of the array mismatches the dynamic
|
||||
// type.
|
||||
//
|
||||
// References:
|
||||
// C++98 [expr.delete]p3
|
||||
// http://cplusplus.github.com/LWG/lwg-defects.html#938
|
||||
template <typename U> void operator()(U* array) const;
|
||||
};
|
||||
|
||||
template <class T, int n>
|
||||
struct DefaultDeleter<T[n]> {
|
||||
// Never allow someone to declare something like scoped_ptr<int[10]>.
|
||||
static_assert(sizeof(T) == -1, "do not use array with size as type");
|
||||
};
|
||||
|
||||
// Function object which invokes 'free' on its parameter, which must be
|
||||
// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
|
||||
//
|
||||
// scoped_ptr<int, rtc::FreeDeleter> foo_ptr(
|
||||
// static_cast<int*>(malloc(sizeof(int))));
|
||||
struct FreeDeleter {
|
||||
inline void operator()(void* ptr) const {
|
||||
free(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename T>
|
||||
struct ShouldAbortOnSelfReset {
|
||||
template <typename U>
|
||||
static rtc::internal::NoType Test(const typename U::AllowSelfReset*);
|
||||
|
||||
template <typename U>
|
||||
static rtc::internal::YesType Test(...);
|
||||
|
||||
static const bool value =
|
||||
sizeof(Test<T>(0)) == sizeof(rtc::internal::YesType);
|
||||
};
|
||||
|
||||
// Minimal implementation of the core logic of scoped_ptr, suitable for
|
||||
// reuse in both scoped_ptr and its specializations.
|
||||
template <class T, class D>
|
||||
class scoped_ptr_impl {
|
||||
public:
|
||||
explicit scoped_ptr_impl(T* p) : data_(p) {}
|
||||
|
||||
// Initializer for deleters that have data parameters.
|
||||
scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
|
||||
|
||||
// Templated constructor that destructively takes the value from another
|
||||
// scoped_ptr_impl.
|
||||
template <typename U, typename V>
|
||||
scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
|
||||
: data_(other->release(), other->get_deleter()) {
|
||||
// We do not support move-only deleters. We could modify our move
|
||||
// emulation to have rtc::subtle::move() and rtc::subtle::forward()
|
||||
// functions that are imperfect emulations of their C++11 equivalents,
|
||||
// but until there's a requirement, just assume deleters are copyable.
|
||||
}
|
||||
|
||||
template <typename U, typename V>
|
||||
void TakeState(scoped_ptr_impl<U, V>* other) {
|
||||
// See comment in templated constructor above regarding lack of support
|
||||
// for move-only deleters.
|
||||
reset(other->release());
|
||||
get_deleter() = other->get_deleter();
|
||||
}
|
||||
|
||||
~scoped_ptr_impl() {
|
||||
if (data_.ptr != nullptr) {
|
||||
// Not using get_deleter() saves one function call in non-optimized
|
||||
// builds.
|
||||
static_cast<D&>(data_)(data_.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void reset(T* p) {
|
||||
// This is a self-reset, which is no longer allowed for default deleters:
|
||||
// https://crbug.com/162971
|
||||
assert(!ShouldAbortOnSelfReset<D>::value || p == nullptr || p != data_.ptr);
|
||||
|
||||
// Note that running data_.ptr = p can lead to undefined behavior if
|
||||
// get_deleter()(get()) deletes this. In order to prevent this, reset()
|
||||
// should update the stored pointer before deleting its old value.
|
||||
//
|
||||
// However, changing reset() to use that behavior may cause current code to
|
||||
// break in unexpected ways. If the destruction of the owned object
|
||||
// dereferences the scoped_ptr when it is destroyed by a call to reset(),
|
||||
// then it will incorrectly dispatch calls to |p| rather than the original
|
||||
// value of |data_.ptr|.
|
||||
//
|
||||
// During the transition period, set the stored pointer to nullptr while
|
||||
// deleting the object. Eventually, this safety check will be removed to
|
||||
// prevent the scenario initially described from occurring and
|
||||
// http://crbug.com/176091 can be closed.
|
||||
T* old = data_.ptr;
|
||||
data_.ptr = nullptr;
|
||||
if (old != nullptr)
|
||||
static_cast<D&>(data_)(old);
|
||||
data_.ptr = p;
|
||||
}
|
||||
|
||||
T* get() const { return data_.ptr; }
|
||||
|
||||
D& get_deleter() { return data_; }
|
||||
const D& get_deleter() const { return data_; }
|
||||
|
||||
void swap(scoped_ptr_impl& p2) {
|
||||
// Standard swap idiom: 'using std::swap' ensures that std::swap is
|
||||
// present in the overload set, but we call swap unqualified so that
|
||||
// any more-specific overloads can be used, if available.
|
||||
using std::swap;
|
||||
swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
|
||||
swap(data_.ptr, p2.data_.ptr);
|
||||
}
|
||||
|
||||
T* release() {
|
||||
T* old_ptr = data_.ptr;
|
||||
data_.ptr = nullptr;
|
||||
return old_ptr;
|
||||
}
|
||||
|
||||
T** accept() {
|
||||
reset(nullptr);
|
||||
return &(data_.ptr);
|
||||
}
|
||||
|
||||
T** use() {
|
||||
return &(data_.ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
// Needed to allow type-converting constructor.
|
||||
template <typename U, typename V> friend class scoped_ptr_impl;
|
||||
|
||||
// Use the empty base class optimization to allow us to have a D
|
||||
// member, while avoiding any space overhead for it when D is an
|
||||
// empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
|
||||
// discussion of this technique.
|
||||
struct Data : public D {
|
||||
explicit Data(T* ptr_in) : ptr(ptr_in) {}
|
||||
Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
|
||||
T* ptr;
|
||||
};
|
||||
|
||||
Data data_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
|
||||
// automatically deletes the pointer it holds (if any).
|
||||
// That is, scoped_ptr<T> owns the T object that it points to.
|
||||
// Like a T*, a scoped_ptr<T> may hold either nullptr or a pointer to a T
|
||||
// object. Also like T*, scoped_ptr<T> is thread-compatible, and once you
|
||||
// dereference it, you get the thread safety guarantees of T.
|
||||
//
|
||||
// The size of scoped_ptr is small. On most compilers, when using the
|
||||
// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
|
||||
// increase the size proportional to whatever state they need to have. See
|
||||
// comments inside scoped_ptr_impl<> for details.
|
||||
//
|
||||
// Current implementation targets having a strict subset of C++11's
|
||||
// unique_ptr<> features. Known deficiencies include not supporting move-only
|
||||
// deleters, function pointers as deleters, and deleters with reference
|
||||
// types.
|
||||
template <class T, class D = rtc::DefaultDeleter<T> >
|
||||
class scoped_ptr {
|
||||
|
||||
// TODO(ajm): If we ever import RefCountedBase, this check needs to be
|
||||
// enabled.
|
||||
//static_assert(rtc::internal::IsNotRefCounted<T>::value,
|
||||
// "T is refcounted type and needs scoped refptr");
|
||||
|
||||
public:
|
||||
// The element and deleter types.
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
|
||||
// Constructor. Defaults to initializing with nullptr.
|
||||
scoped_ptr() : impl_(nullptr) {}
|
||||
|
||||
// Constructor. Takes ownership of p.
|
||||
explicit scoped_ptr(element_type* p) : impl_(p) {}
|
||||
|
||||
// Constructor. Allows initialization of a stateful deleter.
|
||||
scoped_ptr(element_type* p, const D& d) : impl_(p, d) {}
|
||||
|
||||
// Constructor. Allows construction from a nullptr.
|
||||
scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
|
||||
|
||||
// Constructor. Allows construction from a scoped_ptr rvalue for a
|
||||
// convertible type and deleter.
|
||||
//
|
||||
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
|
||||
// from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
|
||||
// has different post-conditions if D is a reference type. Since this
|
||||
// implementation does not support deleters with reference type,
|
||||
// we do not need a separate move constructor allowing us to avoid one
|
||||
// use of SFINAE. You only need to care about this if you modify the
|
||||
// implementation of scoped_ptr.
|
||||
template <typename U, typename V>
|
||||
scoped_ptr(scoped_ptr<U, V>&& other)
|
||||
: impl_(&other.impl_) {
|
||||
static_assert(!rtc::is_array<U>::value, "U cannot be an array");
|
||||
}
|
||||
|
||||
// operator=. Allows assignment from a scoped_ptr rvalue for a convertible
|
||||
// type and deleter.
|
||||
//
|
||||
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
|
||||
// the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
|
||||
// form has different requirements on for move-only Deleters. Since this
|
||||
// implementation does not support move-only Deleters, we do not need a
|
||||
// separate move assignment operator allowing us to avoid one use of SFINAE.
|
||||
// You only need to care about this if you modify the implementation of
|
||||
// scoped_ptr.
|
||||
template <typename U, typename V>
|
||||
scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) {
|
||||
static_assert(!rtc::is_array<U>::value, "U cannot be an array");
|
||||
impl_.TakeState(&rhs.impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// operator=. Allows assignment from a nullptr. Deletes the currently owned
|
||||
// object, if any.
|
||||
scoped_ptr& operator=(decltype(nullptr)) {
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Deleted copy constructor and copy assignment, to make the type move-only.
|
||||
scoped_ptr(const scoped_ptr& other) = delete;
|
||||
scoped_ptr& operator=(const scoped_ptr& other) = delete;
|
||||
|
||||
// Get an rvalue reference. (sp.Pass() does the same thing as std::move(sp).)
|
||||
scoped_ptr&& Pass() { return static_cast<scoped_ptr&&>(*this); }
|
||||
|
||||
// Reset. Deletes the currently owned object, if any.
|
||||
// Then takes ownership of a new object, if given.
|
||||
void reset(element_type* p = nullptr) { impl_.reset(p); }
|
||||
|
||||
// Accessors to get the owned object.
|
||||
// operator* and operator-> will assert() if there is no current object.
|
||||
element_type& operator*() const {
|
||||
assert(impl_.get() != nullptr);
|
||||
return *impl_.get();
|
||||
}
|
||||
element_type* operator->() const {
|
||||
assert(impl_.get() != nullptr);
|
||||
return impl_.get();
|
||||
}
|
||||
element_type* get() const { return impl_.get(); }
|
||||
|
||||
// Access to the deleter.
|
||||
deleter_type& get_deleter() { return impl_.get_deleter(); }
|
||||
const deleter_type& get_deleter() const { return impl_.get_deleter(); }
|
||||
|
||||
// Allow scoped_ptr<element_type> to be used in boolean expressions, but not
|
||||
// implicitly convertible to a real bool (which is dangerous).
|
||||
//
|
||||
// Note that this trick is only safe when the == and != operators
|
||||
// are declared explicitly, as otherwise "scoped_ptr1 ==
|
||||
// scoped_ptr2" will compile but do the wrong thing (i.e., convert
|
||||
// to Testable and then do the comparison).
|
||||
private:
|
||||
typedef rtc::internal::scoped_ptr_impl<element_type, deleter_type>
|
||||
scoped_ptr::*Testable;
|
||||
|
||||
public:
|
||||
operator Testable() const {
|
||||
return impl_.get() ? &scoped_ptr::impl_ : nullptr;
|
||||
}
|
||||
|
||||
// Comparison operators.
|
||||
// These return whether two scoped_ptr refer to the same object, not just to
|
||||
// two different but equal objects.
|
||||
bool operator==(const element_type* p) const { return impl_.get() == p; }
|
||||
bool operator!=(const element_type* p) const { return impl_.get() != p; }
|
||||
|
||||
// Swap two scoped pointers.
|
||||
void swap(scoped_ptr& p2) {
|
||||
impl_.swap(p2.impl_);
|
||||
}
|
||||
|
||||
// Release a pointer.
|
||||
// The return value is the current pointer held by this object. If this object
|
||||
// holds a nullptr, the return value is nullptr. After this operation, this
|
||||
// object will hold a nullptr, and will not own the object any more.
|
||||
element_type* release() WARN_UNUSED_RESULT {
|
||||
return impl_.release();
|
||||
}
|
||||
|
||||
// Delete the currently held pointer and return a pointer
|
||||
// to allow overwriting of the current pointer address.
|
||||
element_type** accept() WARN_UNUSED_RESULT {
|
||||
return impl_.accept();
|
||||
}
|
||||
|
||||
// Return a pointer to the current pointer address.
|
||||
element_type** use() WARN_UNUSED_RESULT {
|
||||
return impl_.use();
|
||||
}
|
||||
|
||||
private:
|
||||
// Needed to reach into |impl_| in the constructor.
|
||||
template <typename U, typename V> friend class scoped_ptr;
|
||||
rtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
|
||||
|
||||
// Forbidden for API compatibility with std::unique_ptr.
|
||||
explicit scoped_ptr(int disallow_construction_from_null);
|
||||
|
||||
// Forbid comparison of scoped_ptr types. If U != T, it totally
|
||||
// doesn't make sense, and if U == T, it still doesn't make sense
|
||||
// because you should never have the same object owned by two different
|
||||
// scoped_ptrs.
|
||||
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
|
||||
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
class scoped_ptr<T[], D> {
|
||||
public:
|
||||
// The element and deleter types.
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
|
||||
// Constructor. Defaults to initializing with nullptr.
|
||||
scoped_ptr() : impl_(nullptr) {}
|
||||
|
||||
// Constructor. Stores the given array. Note that the argument's type
|
||||
// must exactly match T*. In particular:
|
||||
// - it cannot be a pointer to a type derived from T, because it is
|
||||
// inherently unsafe in the general case to access an array through a
|
||||
// pointer whose dynamic type does not match its static type (eg., if
|
||||
// T and the derived types had different sizes access would be
|
||||
// incorrectly calculated). Deletion is also always undefined
|
||||
// (C++98 [expr.delete]p3). If you're doing this, fix your code.
|
||||
// - it cannot be const-qualified differently from T per unique_ptr spec
|
||||
// (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
|
||||
// to work around this may use implicit_cast<const T*>().
|
||||
// However, because of the first bullet in this comment, users MUST
|
||||
// NOT use implicit_cast<Base*>() to upcast the static type of the array.
|
||||
explicit scoped_ptr(element_type* array) : impl_(array) {}
|
||||
|
||||
// Constructor. Allows construction from a nullptr.
|
||||
scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
|
||||
|
||||
// Constructor. Allows construction from a scoped_ptr rvalue.
|
||||
scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {}
|
||||
|
||||
// operator=. Allows assignment from a scoped_ptr rvalue.
|
||||
scoped_ptr& operator=(scoped_ptr&& rhs) {
|
||||
impl_.TakeState(&rhs.impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// operator=. Allows assignment from a nullptr. Deletes the currently owned
|
||||
// array, if any.
|
||||
scoped_ptr& operator=(decltype(nullptr)) {
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Deleted copy constructor and copy assignment, to make the type move-only.
|
||||
scoped_ptr(const scoped_ptr& other) = delete;
|
||||
scoped_ptr& operator=(const scoped_ptr& other) = delete;
|
||||
|
||||
// Get an rvalue reference. (sp.Pass() does the same thing as std::move(sp).)
|
||||
scoped_ptr&& Pass() { return static_cast<scoped_ptr&&>(*this); }
|
||||
|
||||
// Reset. Deletes the currently owned array, if any.
|
||||
// Then takes ownership of a new object, if given.
|
||||
void reset(element_type* array = nullptr) { impl_.reset(array); }
|
||||
|
||||
// Accessors to get the owned array.
|
||||
element_type& operator[](size_t i) const {
|
||||
assert(impl_.get() != nullptr);
|
||||
return impl_.get()[i];
|
||||
}
|
||||
element_type* get() const { return impl_.get(); }
|
||||
|
||||
// Access to the deleter.
|
||||
deleter_type& get_deleter() { return impl_.get_deleter(); }
|
||||
const deleter_type& get_deleter() const { return impl_.get_deleter(); }
|
||||
|
||||
// Allow scoped_ptr<element_type> to be used in boolean expressions, but not
|
||||
// implicitly convertible to a real bool (which is dangerous).
|
||||
private:
|
||||
typedef rtc::internal::scoped_ptr_impl<element_type, deleter_type>
|
||||
scoped_ptr::*Testable;
|
||||
|
||||
public:
|
||||
operator Testable() const {
|
||||
return impl_.get() ? &scoped_ptr::impl_ : nullptr;
|
||||
}
|
||||
|
||||
// Comparison operators.
|
||||
// These return whether two scoped_ptr refer to the same object, not just to
|
||||
// two different but equal objects.
|
||||
bool operator==(element_type* array) const { return impl_.get() == array; }
|
||||
bool operator!=(element_type* array) const { return impl_.get() != array; }
|
||||
|
||||
// Swap two scoped pointers.
|
||||
void swap(scoped_ptr& p2) {
|
||||
impl_.swap(p2.impl_);
|
||||
}
|
||||
|
||||
// Release a pointer.
|
||||
// The return value is the current pointer held by this object. If this object
|
||||
// holds a nullptr, the return value is nullptr. After this operation, this
|
||||
// object will hold a nullptr, and will not own the object any more.
|
||||
element_type* release() WARN_UNUSED_RESULT {
|
||||
return impl_.release();
|
||||
}
|
||||
|
||||
// Delete the currently held pointer and return a pointer
|
||||
// to allow overwriting of the current pointer address.
|
||||
element_type** accept() WARN_UNUSED_RESULT {
|
||||
return impl_.accept();
|
||||
}
|
||||
|
||||
// Return a pointer to the current pointer address.
|
||||
element_type** use() WARN_UNUSED_RESULT {
|
||||
return impl_.use();
|
||||
}
|
||||
|
||||
private:
|
||||
// Force element_type to be a complete type.
|
||||
enum { type_must_be_complete = sizeof(element_type) };
|
||||
|
||||
// Actually hold the data.
|
||||
rtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
|
||||
|
||||
// Disable initialization from any type other than element_type*, by
|
||||
// providing a constructor that matches such an initialization, but is
|
||||
// private and has no definition. This is disabled because it is not safe to
|
||||
// call delete[] on an array whose static type does not match its dynamic
|
||||
// type.
|
||||
template <typename U> explicit scoped_ptr(U* array);
|
||||
explicit scoped_ptr(int disallow_construction_from_null);
|
||||
|
||||
// Disable reset() from any type other than element_type*, for the same
|
||||
// reasons as the constructor above.
|
||||
template <typename U> void reset(U* array);
|
||||
void reset(int disallow_reset_from_null);
|
||||
|
||||
// Forbid comparison of scoped_ptr types. If U != T, it totally
|
||||
// doesn't make sense, and if U == T, it still doesn't make sense
|
||||
// because you should never have the same object owned by two different
|
||||
// scoped_ptrs.
|
||||
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
|
||||
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
void swap(rtc::scoped_ptr<T, D>& p1, rtc::scoped_ptr<T, D>& p2) {
|
||||
p1.swap(p2);
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
template <class T, class D>
|
||||
bool operator==(T* p1, const rtc::scoped_ptr<T, D>& p2) {
|
||||
return p1 == p2.get();
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
bool operator!=(T* p1, const rtc::scoped_ptr<T, D>& p2) {
|
||||
return p1 != p2.get();
|
||||
}
|
||||
|
||||
// A function to convert T* into scoped_ptr<T>
|
||||
// Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
|
||||
// for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
|
||||
template <typename T>
|
||||
rtc::scoped_ptr<T> rtc_make_scoped_ptr(T* ptr) {
|
||||
return rtc::scoped_ptr<T>(ptr);
|
||||
}
|
||||
|
||||
#endif // #ifndef WEBRTC_BASE_SCOPED_PTR_H__
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/stringutils.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
bool memory_check(const void* memory, int c, size_t count) {
|
||||
const char* char_memory = static_cast<const char*>(memory);
|
||||
char char_c = static_cast<char>(c);
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
if (char_memory[i] != char_c) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool string_match(const char* target, const char* pattern) {
|
||||
while (*pattern) {
|
||||
if (*pattern == '*') {
|
||||
if (!*++pattern) {
|
||||
return true;
|
||||
}
|
||||
while (*target) {
|
||||
if ((toupper(*pattern) == toupper(*target))
|
||||
&& string_match(target + 1, pattern + 1)) {
|
||||
return true;
|
||||
}
|
||||
++target;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
if (toupper(*pattern) != toupper(*target)) {
|
||||
return false;
|
||||
}
|
||||
++target;
|
||||
++pattern;
|
||||
}
|
||||
}
|
||||
return !*target;
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n,
|
||||
CharacterTransformation transformation) {
|
||||
wchar_t c1, c2;
|
||||
while (true) {
|
||||
if (n-- == 0) return 0;
|
||||
c1 = transformation(*s1);
|
||||
// Double check that characters are not UTF-8
|
||||
RTC_DCHECK_LT(static_cast<unsigned char>(*s2), 128);
|
||||
// Note: *s2 gets implicitly promoted to wchar_t
|
||||
c2 = transformation(*s2);
|
||||
if (c1 != c2) return (c1 < c2) ? -1 : 1;
|
||||
if (!c1) return 0;
|
||||
++s1;
|
||||
++s2;
|
||||
}
|
||||
}
|
||||
|
||||
size_t asccpyn(wchar_t* buffer, size_t buflen,
|
||||
const char* source, size_t srclen) {
|
||||
if (buflen <= 0)
|
||||
return 0;
|
||||
|
||||
if (srclen == SIZE_UNKNOWN) {
|
||||
srclen = strlenn(source, buflen - 1);
|
||||
} else if (srclen >= buflen) {
|
||||
srclen = buflen - 1;
|
||||
}
|
||||
#if !defined(NDEBUG)
|
||||
// Double check that characters are not UTF-8
|
||||
for (size_t pos = 0; pos < srclen; ++pos)
|
||||
RTC_DCHECK_LT(static_cast<unsigned char>(source[pos]), 128);
|
||||
#endif
|
||||
std::copy(source, source + srclen, buffer);
|
||||
buffer[srclen] = 0;
|
||||
return srclen;
|
||||
}
|
||||
|
||||
#endif // WEBRTC_WIN
|
||||
|
||||
void replace_substrs(const char *search,
|
||||
size_t search_len,
|
||||
const char *replace,
|
||||
size_t replace_len,
|
||||
std::string *s) {
|
||||
size_t pos = 0;
|
||||
while ((pos = s->find(search, pos, search_len)) != std::string::npos) {
|
||||
s->replace(pos, search_len, replace, replace_len);
|
||||
pos += replace_len;
|
||||
}
|
||||
}
|
||||
|
||||
bool starts_with(const char *s1, const char *s2) {
|
||||
return strncmp(s1, s2, strlen(s2)) == 0;
|
||||
}
|
||||
|
||||
bool ends_with(const char *s1, const char *s2) {
|
||||
size_t s1_length = strlen(s1);
|
||||
size_t s2_length = strlen(s2);
|
||||
|
||||
if (s2_length > s1_length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* start = s1 + (s1_length - s2_length);
|
||||
return strncmp(start, s2, s2_length) == 0;
|
||||
}
|
||||
|
||||
static const char kWhitespace[] = " \n\r\t";
|
||||
|
||||
std::string string_trim(const std::string& s) {
|
||||
std::string::size_type first = s.find_first_not_of(kWhitespace);
|
||||
std::string::size_type last = s.find_last_not_of(kWhitespace);
|
||||
|
||||
if (first == std::string::npos || last == std::string::npos) {
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
return s.substr(first, last - first + 1);
|
||||
}
|
||||
|
||||
} // namespace rtc
|
@ -1,318 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_STRINGUTILS_H__
|
||||
#define WEBRTC_BASE_STRINGUTILS_H__
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
#include <malloc.h>
|
||||
#include <wchar.h>
|
||||
#define alloca _alloca
|
||||
#endif // WEBRTC_WIN
|
||||
|
||||
#if defined(WEBRTC_POSIX)
|
||||
#ifdef BSD
|
||||
#include <stdlib.h>
|
||||
#else // BSD
|
||||
#include <alloca.h>
|
||||
#endif // !BSD
|
||||
#endif // WEBRTC_POSIX
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/base/basictypes.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Generic string/memory utilities
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define STACK_ARRAY(TYPE, LEN) static_cast<TYPE*>(::alloca((LEN)*sizeof(TYPE)))
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// Complement to memset. Verifies memory consists of count bytes of value c.
|
||||
bool memory_check(const void* memory, int c, size_t count);
|
||||
|
||||
// Determines whether the simple wildcard pattern matches target.
|
||||
// Alpha characters in pattern match case-insensitively.
|
||||
// Asterisks in pattern match 0 or more characters.
|
||||
// Ex: string_match("www.TEST.GOOGLE.COM", "www.*.com") -> true
|
||||
bool string_match(const char* target, const char* pattern);
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Rename a bunch of common string functions so they are consistent across
|
||||
// platforms and between char and wchar_t variants.
|
||||
// Here is the full list of functions that are unified:
|
||||
// strlen, strcmp, stricmp, strncmp, strnicmp
|
||||
// strchr, vsnprintf, strtoul, tolowercase
|
||||
// tolowercase is like tolower, but not compatible with end-of-file value
|
||||
//
|
||||
// It's not clear if we will ever use wchar_t strings on unix. In theory,
|
||||
// all strings should be Utf8 all the time, except when interfacing with Win32
|
||||
// APIs that require Utf16.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline char tolowercase(char c) {
|
||||
return static_cast<char>(tolower(c));
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
|
||||
inline size_t strlen(const wchar_t* s) {
|
||||
return wcslen(s);
|
||||
}
|
||||
inline int strcmp(const wchar_t* s1, const wchar_t* s2) {
|
||||
return wcscmp(s1, s2);
|
||||
}
|
||||
inline int stricmp(const wchar_t* s1, const wchar_t* s2) {
|
||||
return _wcsicmp(s1, s2);
|
||||
}
|
||||
inline int strncmp(const wchar_t* s1, const wchar_t* s2, size_t n) {
|
||||
return wcsncmp(s1, s2, n);
|
||||
}
|
||||
inline int strnicmp(const wchar_t* s1, const wchar_t* s2, size_t n) {
|
||||
return _wcsnicmp(s1, s2, n);
|
||||
}
|
||||
inline const wchar_t* strchr(const wchar_t* s, wchar_t c) {
|
||||
return wcschr(s, c);
|
||||
}
|
||||
inline const wchar_t* strstr(const wchar_t* haystack, const wchar_t* needle) {
|
||||
return wcsstr(haystack, needle);
|
||||
}
|
||||
#ifndef vsnprintf
|
||||
inline int vsnprintf(wchar_t* buf, size_t n, const wchar_t* fmt, va_list args) {
|
||||
return _vsnwprintf(buf, n, fmt, args);
|
||||
}
|
||||
#endif // !vsnprintf
|
||||
inline unsigned long strtoul(const wchar_t* snum, wchar_t** end, int base) {
|
||||
return wcstoul(snum, end, base);
|
||||
}
|
||||
inline wchar_t tolowercase(wchar_t c) {
|
||||
return static_cast<wchar_t>(towlower(c));
|
||||
}
|
||||
|
||||
#endif // WEBRTC_WIN
|
||||
|
||||
#if defined(WEBRTC_POSIX)
|
||||
|
||||
inline int _stricmp(const char* s1, const char* s2) {
|
||||
return strcasecmp(s1, s2);
|
||||
}
|
||||
inline int _strnicmp(const char* s1, const char* s2, size_t n) {
|
||||
return strncasecmp(s1, s2, n);
|
||||
}
|
||||
|
||||
#endif // WEBRTC_POSIX
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Traits simplifies porting string functions to be CTYPE-agnostic
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace rtc {
|
||||
|
||||
const size_t SIZE_UNKNOWN = static_cast<size_t>(-1);
|
||||
|
||||
template<class CTYPE>
|
||||
struct Traits {
|
||||
// STL string type
|
||||
//typedef XXX string;
|
||||
// Null-terminated string
|
||||
//inline static const CTYPE* empty_str();
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// String utilities which work with char or wchar_t
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class CTYPE>
|
||||
inline const CTYPE* nonnull(const CTYPE* str, const CTYPE* def_str = NULL) {
|
||||
return str ? str : (def_str ? def_str : Traits<CTYPE>::empty_str());
|
||||
}
|
||||
|
||||
template<class CTYPE>
|
||||
const CTYPE* strchr(const CTYPE* str, const CTYPE* chs) {
|
||||
for (size_t i=0; str[i]; ++i) {
|
||||
for (size_t j=0; chs[j]; ++j) {
|
||||
if (str[i] == chs[j]) {
|
||||
return str + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class CTYPE>
|
||||
const CTYPE* strchrn(const CTYPE* str, size_t slen, CTYPE ch) {
|
||||
for (size_t i=0; i<slen && str[i]; ++i) {
|
||||
if (str[i] == ch) {
|
||||
return str + i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class CTYPE>
|
||||
size_t strlenn(const CTYPE* buffer, size_t buflen) {
|
||||
size_t bufpos = 0;
|
||||
while (buffer[bufpos] && (bufpos < buflen)) {
|
||||
++bufpos;
|
||||
}
|
||||
return bufpos;
|
||||
}
|
||||
|
||||
// Safe versions of strncpy, strncat, snprintf and vsnprintf that always
|
||||
// null-terminate.
|
||||
|
||||
template<class CTYPE>
|
||||
size_t strcpyn(CTYPE* buffer, size_t buflen,
|
||||
const CTYPE* source, size_t srclen = SIZE_UNKNOWN) {
|
||||
if (buflen <= 0)
|
||||
return 0;
|
||||
|
||||
if (srclen == SIZE_UNKNOWN) {
|
||||
srclen = strlenn(source, buflen - 1);
|
||||
} else if (srclen >= buflen) {
|
||||
srclen = buflen - 1;
|
||||
}
|
||||
memcpy(buffer, source, srclen * sizeof(CTYPE));
|
||||
buffer[srclen] = 0;
|
||||
return srclen;
|
||||
}
|
||||
|
||||
template<class CTYPE>
|
||||
size_t strcatn(CTYPE* buffer, size_t buflen,
|
||||
const CTYPE* source, size_t srclen = SIZE_UNKNOWN) {
|
||||
if (buflen <= 0)
|
||||
return 0;
|
||||
|
||||
size_t bufpos = strlenn(buffer, buflen - 1);
|
||||
return bufpos + strcpyn(buffer + bufpos, buflen - bufpos, source, srclen);
|
||||
}
|
||||
|
||||
// Some compilers (clang specifically) require vsprintfn be defined before
|
||||
// sprintfn.
|
||||
template<class CTYPE>
|
||||
size_t vsprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format,
|
||||
va_list args) {
|
||||
int len = vsnprintf(buffer, buflen, format, args);
|
||||
if ((len < 0) || (static_cast<size_t>(len) >= buflen)) {
|
||||
len = static_cast<int>(buflen - 1);
|
||||
buffer[len] = 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
template<class CTYPE>
|
||||
size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...);
|
||||
template<class CTYPE>
|
||||
size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
size_t len = vsprintfn(buffer, buflen, format, args);
|
||||
va_end(args);
|
||||
return len;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow safe comparing and copying ascii (not UTF-8) with both wide and
|
||||
// non-wide character strings.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline int asccmp(const char* s1, const char* s2) {
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
inline int ascicmp(const char* s1, const char* s2) {
|
||||
return _stricmp(s1, s2);
|
||||
}
|
||||
inline int ascncmp(const char* s1, const char* s2, size_t n) {
|
||||
return strncmp(s1, s2, n);
|
||||
}
|
||||
inline int ascnicmp(const char* s1, const char* s2, size_t n) {
|
||||
return _strnicmp(s1, s2, n);
|
||||
}
|
||||
inline size_t asccpyn(char* buffer, size_t buflen,
|
||||
const char* source, size_t srclen = SIZE_UNKNOWN) {
|
||||
return strcpyn(buffer, buflen, source, srclen);
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
|
||||
typedef wchar_t(*CharacterTransformation)(wchar_t);
|
||||
inline wchar_t identity(wchar_t c) { return c; }
|
||||
int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n,
|
||||
CharacterTransformation transformation);
|
||||
|
||||
inline int asccmp(const wchar_t* s1, const char* s2) {
|
||||
return ascii_string_compare(s1, s2, static_cast<size_t>(-1), identity);
|
||||
}
|
||||
inline int ascicmp(const wchar_t* s1, const char* s2) {
|
||||
return ascii_string_compare(s1, s2, static_cast<size_t>(-1), tolowercase);
|
||||
}
|
||||
inline int ascncmp(const wchar_t* s1, const char* s2, size_t n) {
|
||||
return ascii_string_compare(s1, s2, n, identity);
|
||||
}
|
||||
inline int ascnicmp(const wchar_t* s1, const char* s2, size_t n) {
|
||||
return ascii_string_compare(s1, s2, n, tolowercase);
|
||||
}
|
||||
size_t asccpyn(wchar_t* buffer, size_t buflen,
|
||||
const char* source, size_t srclen = SIZE_UNKNOWN);
|
||||
|
||||
#endif // WEBRTC_WIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Traits<char> specializations
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct Traits<char> {
|
||||
typedef std::string string;
|
||||
inline static const char* empty_str() { return ""; }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Traits<wchar_t> specializations (Windows only, currently)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
|
||||
template<>
|
||||
struct Traits<wchar_t> {
|
||||
typedef std::wstring string;
|
||||
inline static const wchar_t* empty_str() { return L""; }
|
||||
};
|
||||
|
||||
#endif // WEBRTC_WIN
|
||||
|
||||
// Replaces all occurrences of "search" with "replace".
|
||||
void replace_substrs(const char *search,
|
||||
size_t search_len,
|
||||
const char *replace,
|
||||
size_t replace_len,
|
||||
std::string *s);
|
||||
|
||||
// True iff s1 starts with s2.
|
||||
bool starts_with(const char *s1, const char *s2);
|
||||
|
||||
// True iff s1 ends with s2.
|
||||
bool ends_with(const char *s1, const char *s2);
|
||||
|
||||
// Remove leading and trailing whitespaces.
|
||||
std::string string_trim(const std::string& s);
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_STRINGUTILS_H__
|
@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/template_util.h.
|
||||
|
||||
#ifndef WEBRTC_BASE_TEMPLATE_UTIL_H_
|
||||
#define WEBRTC_BASE_TEMPLATE_UTIL_H_
|
||||
|
||||
#include <stddef.h> // For size_t.
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// Template definitions from tr1.
|
||||
|
||||
template<class T, T v>
|
||||
struct integral_constant {
|
||||
static const T value = v;
|
||||
typedef T value_type;
|
||||
typedef integral_constant<T, v> type;
|
||||
};
|
||||
|
||||
template <class T, T v> const T integral_constant<T, v>::value;
|
||||
|
||||
typedef integral_constant<bool, true> true_type;
|
||||
typedef integral_constant<bool, false> false_type;
|
||||
|
||||
template <class T> struct is_pointer : false_type {};
|
||||
template <class T> struct is_pointer<T*> : true_type {};
|
||||
|
||||
template <class T, class U> struct is_same : public false_type {};
|
||||
template <class T> struct is_same<T, T> : true_type {};
|
||||
|
||||
template<class> struct is_array : public false_type {};
|
||||
template<class T, size_t n> struct is_array<T[n]> : public true_type {};
|
||||
template<class T> struct is_array<T[]> : public true_type {};
|
||||
|
||||
template <class T> struct is_non_const_reference : false_type {};
|
||||
template <class T> struct is_non_const_reference<T&> : true_type {};
|
||||
template <class T> struct is_non_const_reference<const T&> : false_type {};
|
||||
|
||||
template <class T> struct is_void : false_type {};
|
||||
template <> struct is_void<void> : true_type {};
|
||||
|
||||
template <class T>
|
||||
struct remove_reference {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_reference<T&> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_reference<T&&> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Types YesType and NoType are guaranteed such that sizeof(YesType) <
|
||||
// sizeof(NoType).
|
||||
typedef char YesType;
|
||||
|
||||
struct NoType {
|
||||
YesType dummy[2];
|
||||
};
|
||||
|
||||
// This class is an implementation detail for is_convertible, and you
|
||||
// don't need to know how it works to use is_convertible. For those
|
||||
// who care: we declare two different functions, one whose argument is
|
||||
// of type To and one with a variadic argument list. We give them
|
||||
// return types of different size, so we can use sizeof to trick the
|
||||
// compiler into telling us which function it would have chosen if we
|
||||
// had called it with an argument of type From. See Alexandrescu's
|
||||
// _Modern C++ Design_ for more details on this sort of trick.
|
||||
|
||||
struct ConvertHelper {
|
||||
template <typename To>
|
||||
static YesType Test(To);
|
||||
|
||||
template <typename To>
|
||||
static NoType Test(...);
|
||||
|
||||
template <typename From>
|
||||
static From& Create();
|
||||
};
|
||||
|
||||
// Used to determine if a type is a struct/union/class. Inspired by Boost's
|
||||
// is_class type_trait implementation.
|
||||
struct IsClassHelper {
|
||||
template <typename C>
|
||||
static YesType Test(void(C::*)(void));
|
||||
|
||||
template <typename C>
|
||||
static NoType Test(...);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Inherits from true_type if From is convertible to To, false_type otherwise.
|
||||
//
|
||||
// Note that if the type is convertible, this will be a true_type REGARDLESS
|
||||
// of whether or not the conversion would emit a warning.
|
||||
template <typename From, typename To>
|
||||
struct is_convertible
|
||||
: integral_constant<bool,
|
||||
sizeof(internal::ConvertHelper::Test<To>(
|
||||
internal::ConvertHelper::Create<From>())) ==
|
||||
sizeof(internal::YesType)> {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_class
|
||||
: integral_constant<bool,
|
||||
sizeof(internal::IsClassHelper::Test<T>(0)) ==
|
||||
sizeof(internal::YesType)> {
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_TEMPLATE_UTIL_H_
|
@ -1,99 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
//
|
||||
// Borrowed from
|
||||
// https://code.google.com/p/gperftools/source/browse/src/base/thread_annotations.h
|
||||
// but adapted for clang attributes instead of the gcc.
|
||||
//
|
||||
// This header file contains the macro definitions for thread safety
|
||||
// annotations that allow the developers to document the locking policies
|
||||
// of their multi-threaded code. The annotations can also help program
|
||||
// analysis tools to identify potential thread safety issues.
|
||||
|
||||
#ifndef BASE_THREAD_ANNOTATIONS_H_
|
||||
#define BASE_THREAD_ANNOTATIONS_H_
|
||||
|
||||
#if defined(__clang__) && (!defined(SWIG))
|
||||
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
||||
#else
|
||||
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
|
||||
#endif
|
||||
|
||||
// Document if a shared variable/field needs to be protected by a lock.
|
||||
// GUARDED_BY allows the user to specify a particular lock that should be
|
||||
// held when accessing the annotated variable, while GUARDED_VAR only
|
||||
// indicates a shared variable should be guarded (by any lock). GUARDED_VAR
|
||||
// is primarily used when the client cannot express the name of the lock.
|
||||
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
|
||||
#define GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(guarded)
|
||||
|
||||
// Document if the memory location pointed to by a pointer should be guarded
|
||||
// by a lock when dereferencing the pointer. Similar to GUARDED_VAR,
|
||||
// PT_GUARDED_VAR is primarily used when the client cannot express the name
|
||||
// of the lock. Note that a pointer variable to a shared memory location
|
||||
// could itself be a shared variable. For example, if a shared global pointer
|
||||
// q, which is guarded by mu1, points to a shared memory location that is
|
||||
// guarded by mu2, q should be annotated as follows:
|
||||
// int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
|
||||
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded_by(x))
|
||||
#define PT_GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded)
|
||||
|
||||
// Document the acquisition order between locks that can be held
|
||||
// simultaneously by a thread. For any two locks that need to be annotated
|
||||
// to establish an acquisition order, only one of them needs the annotation.
|
||||
// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER
|
||||
// and ACQUIRED_BEFORE.)
|
||||
#define ACQUIRED_AFTER(x) THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(x))
|
||||
#define ACQUIRED_BEFORE(x) THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(x))
|
||||
|
||||
// The following three annotations document the lock requirements for
|
||||
// functions/methods.
|
||||
|
||||
// Document if a function expects certain locks to be held before it is called
|
||||
#define EXCLUSIVE_LOCKS_REQUIRED(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
|
||||
|
||||
#define SHARED_LOCKS_REQUIRED(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
|
||||
|
||||
// Document the locks acquired in the body of the function. These locks
|
||||
// cannot be held when calling this function (as google3's Mutex locks are
|
||||
// non-reentrant).
|
||||
#define LOCKS_EXCLUDED(x) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(x))
|
||||
|
||||
// Document the lock the annotated function returns without acquiring it.
|
||||
#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
||||
|
||||
// Document if a class/type is a lockable type (such as the Mutex class).
|
||||
#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable)
|
||||
|
||||
// Document if a class is a scoped lockable type (such as the MutexLock class).
|
||||
#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
||||
|
||||
// The following annotations specify lock and unlock primitives.
|
||||
#define EXCLUSIVE_LOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
|
||||
|
||||
#define SHARED_LOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
|
||||
|
||||
#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
|
||||
|
||||
#define SHARED_TRYLOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
|
||||
|
||||
#define UNLOCK_FUNCTION(...) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
|
||||
|
||||
// An escape hatch for thread safety analysis to ignore the annotated function.
|
||||
#define NO_THREAD_SAFETY_ANALYSIS \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
|
||||
|
||||
#endif // BASE_THREAD_ANNOTATIONS_H_
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/threading/thread_checker.h.
|
||||
|
||||
#ifndef WEBRTC_BASE_THREAD_CHECKER_H_
|
||||
#define WEBRTC_BASE_THREAD_CHECKER_H_
|
||||
|
||||
// Apart from debug builds, we also enable the thread checker in
|
||||
// builds with DCHECK_ALWAYS_ON so that trybots and waterfall bots
|
||||
// with this define will get the same level of thread checking as
|
||||
// debug bots.
|
||||
//
|
||||
// Note that this does not perfectly match situations where RTC_DCHECK is
|
||||
// enabled. For example a non-official release build may have
|
||||
// DCHECK_ALWAYS_ON undefined (and therefore ThreadChecker would be
|
||||
// disabled) but have RTC_DCHECKs enabled at runtime.
|
||||
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
|
||||
#define ENABLE_THREAD_CHECKER 1
|
||||
#else
|
||||
#define ENABLE_THREAD_CHECKER 0
|
||||
#endif
|
||||
|
||||
#include "webrtc/base/thread_checker_impl.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// Do nothing implementation, for use in release mode.
|
||||
//
|
||||
// Note: You should almost always use the ThreadChecker class to get the
|
||||
// right version for your build configuration.
|
||||
class ThreadCheckerDoNothing {
|
||||
public:
|
||||
bool CalledOnValidThread() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void DetachFromThread() {}
|
||||
};
|
||||
|
||||
// ThreadChecker is a helper class used to help verify that some methods of a
|
||||
// class are called from the same thread. It provides identical functionality to
|
||||
// base::NonThreadSafe, but it is meant to be held as a member variable, rather
|
||||
// than inherited from base::NonThreadSafe.
|
||||
//
|
||||
// While inheriting from base::NonThreadSafe may give a clear indication about
|
||||
// the thread-safety of a class, it may also lead to violations of the style
|
||||
// guide with regard to multiple inheritance. The choice between having a
|
||||
// ThreadChecker member and inheriting from base::NonThreadSafe should be based
|
||||
// on whether:
|
||||
// - Derived classes need to know the thread they belong to, as opposed to
|
||||
// having that functionality fully encapsulated in the base class.
|
||||
// - Derived classes should be able to reassign the base class to another
|
||||
// thread, via DetachFromThread.
|
||||
//
|
||||
// If neither of these are true, then having a ThreadChecker member and calling
|
||||
// CalledOnValidThread is the preferable solution.
|
||||
//
|
||||
// Example:
|
||||
// class MyClass {
|
||||
// public:
|
||||
// void Foo() {
|
||||
// RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
// ... (do stuff) ...
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// ThreadChecker thread_checker_;
|
||||
// }
|
||||
//
|
||||
// In Release mode, CalledOnValidThread will always return true.
|
||||
#if ENABLE_THREAD_CHECKER
|
||||
class ThreadChecker : public ThreadCheckerImpl {
|
||||
};
|
||||
#else
|
||||
class ThreadChecker : public ThreadCheckerDoNothing {
|
||||
};
|
||||
#endif // ENABLE_THREAD_CHECKER
|
||||
|
||||
#undef ENABLE_THREAD_CHECKER
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_THREAD_CHECKER_H_
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/threading/thread_checker_impl.cc.
|
||||
|
||||
#include "webrtc/base/thread_checker_impl.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
ThreadCheckerImpl::ThreadCheckerImpl() : valid_thread_(CurrentThreadRef()) {
|
||||
}
|
||||
|
||||
ThreadCheckerImpl::~ThreadCheckerImpl() {
|
||||
}
|
||||
|
||||
bool ThreadCheckerImpl::CalledOnValidThread() const {
|
||||
const PlatformThreadRef current_thread = CurrentThreadRef();
|
||||
CritScope scoped_lock(&lock_);
|
||||
if (!valid_thread_) // Set if previously detached.
|
||||
valid_thread_ = current_thread;
|
||||
return IsThreadRefEqual(valid_thread_, current_thread);
|
||||
}
|
||||
|
||||
void ThreadCheckerImpl::DetachFromThread() {
|
||||
CritScope scoped_lock(&lock_);
|
||||
valid_thread_ = 0;
|
||||
}
|
||||
|
||||
} // namespace rtc
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Borrowed from Chromium's src/base/threading/thread_checker_impl.h.
|
||||
|
||||
#ifndef WEBRTC_BASE_THREAD_CHECKER_IMPL_H_
|
||||
#define WEBRTC_BASE_THREAD_CHECKER_IMPL_H_
|
||||
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/base/platform_thread.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// Real implementation of ThreadChecker, for use in debug mode, or
|
||||
// for temporary use in release mode (e.g. to RTC_CHECK on a threading issue
|
||||
// seen only in the wild).
|
||||
//
|
||||
// Note: You should almost always use the ThreadChecker class to get the
|
||||
// right version for your build configuration.
|
||||
class ThreadCheckerImpl {
|
||||
public:
|
||||
ThreadCheckerImpl();
|
||||
~ThreadCheckerImpl();
|
||||
|
||||
bool CalledOnValidThread() const;
|
||||
|
||||
// Changes the thread that is checked for in CalledOnValidThread. This may
|
||||
// be useful when an object may be created on one thread and then used
|
||||
// exclusively on another thread.
|
||||
void DetachFromThread();
|
||||
|
||||
private:
|
||||
mutable CriticalSection lock_;
|
||||
// This is mutable so that CalledOnValidThread can set it.
|
||||
// It's guarded by |lock_|.
|
||||
mutable PlatformThreadRef valid_thread_;
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_THREAD_CHECKER_IMPL_H_
|
124
webrtc/common.h
124
webrtc/common.h
@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_H_
|
||||
#define WEBRTC_COMMON_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "webrtc/base/basictypes.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Class Config is designed to ease passing a set of options across webrtc code.
|
||||
// Options are identified by typename in order to avoid incorrect casts.
|
||||
//
|
||||
// Usage:
|
||||
// * declaring an option:
|
||||
// struct Algo1_CostFunction {
|
||||
// virtual float cost(int x) const { return x; }
|
||||
// virtual ~Algo1_CostFunction() {}
|
||||
// };
|
||||
//
|
||||
// * accessing an option:
|
||||
// config.Get<Algo1_CostFunction>().cost(value);
|
||||
//
|
||||
// * setting an option:
|
||||
// struct SqrCost : Algo1_CostFunction {
|
||||
// virtual float cost(int x) const { return x*x; }
|
||||
// };
|
||||
// config.Set<Algo1_CostFunction>(new SqrCost());
|
||||
//
|
||||
// Note: This class is thread-compatible (like STL containers).
|
||||
class Config {
|
||||
public:
|
||||
// Returns the option if set or a default constructed one.
|
||||
// Callers that access options too often are encouraged to cache the result.
|
||||
// Returned references are owned by this.
|
||||
//
|
||||
// Requires std::is_default_constructible<T>
|
||||
template<typename T> const T& Get() const;
|
||||
|
||||
// Set the option, deleting any previous instance of the same.
|
||||
// This instance gets ownership of the newly set value.
|
||||
template<typename T> void Set(T* value);
|
||||
|
||||
Config() {}
|
||||
~Config() {
|
||||
// Note: this method is inline so webrtc public API depends only
|
||||
// on the headers.
|
||||
for (OptionMap::iterator it = options_.begin();
|
||||
it != options_.end(); ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef void* OptionIdentifier;
|
||||
|
||||
struct BaseOption {
|
||||
virtual ~BaseOption() {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Option : BaseOption {
|
||||
explicit Option(T* v): value(v) {}
|
||||
~Option() {
|
||||
delete value;
|
||||
}
|
||||
T* value;
|
||||
};
|
||||
|
||||
// Own implementation of rtti-subset to avoid depending on rtti and its costs.
|
||||
template<typename T>
|
||||
static OptionIdentifier identifier() {
|
||||
static char id_placeholder;
|
||||
return &id_placeholder;
|
||||
}
|
||||
|
||||
// Used to instantiate a default constructed object that doesn't needs to be
|
||||
// owned. This allows Get<T> to be implemented without requiring explicitly
|
||||
// locks.
|
||||
template<typename T>
|
||||
static const T& default_value() {
|
||||
RTC_DEFINE_STATIC_LOCAL(const T, def, ());
|
||||
return def;
|
||||
}
|
||||
|
||||
typedef std::map<OptionIdentifier, BaseOption*> OptionMap;
|
||||
OptionMap options_;
|
||||
|
||||
// RTC_DISALLOW_COPY_AND_ASSIGN
|
||||
Config(const Config&);
|
||||
void operator=(const Config&);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
const T& Config::Get() const {
|
||||
OptionMap::const_iterator it = options_.find(identifier<T>());
|
||||
if (it != options_.end()) {
|
||||
const T* t = static_cast<Option<T>*>(it->second)->value;
|
||||
if (t) {
|
||||
return *t;
|
||||
}
|
||||
}
|
||||
return default_value<T>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Config::Set(T* value) {
|
||||
BaseOption*& it = options_[identifier<T>()];
|
||||
delete it;
|
||||
it = new Option<T>(value);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_H_
|
@ -6,37 +6,19 @@
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("//build/config/arm.gni")
|
||||
import("../build/webrtc.gni")
|
||||
import("../webrtc.gni")
|
||||
|
||||
config("common_audio_config") {
|
||||
include_dirs = [
|
||||
"resampler/include",
|
||||
"signal_processing/include",
|
||||
"vad/include",
|
||||
]
|
||||
}
|
||||
visibility = [ ":*" ]
|
||||
|
||||
source_set("common_audio") {
|
||||
rtc_library("common_audio") {
|
||||
visibility += [ "*" ]
|
||||
sources = [
|
||||
"audio_converter.cc",
|
||||
"audio_converter.h",
|
||||
"audio_ring_buffer.cc",
|
||||
"audio_ring_buffer.h",
|
||||
"audio_util.cc",
|
||||
"blocker.cc",
|
||||
"blocker.h",
|
||||
"channel_buffer.cc",
|
||||
"channel_buffer.h",
|
||||
"fft4g.c",
|
||||
"fft4g.h",
|
||||
"fir_filter.cc",
|
||||
"fir_filter.h",
|
||||
"fir_filter_neon.h",
|
||||
"fir_filter_sse.h",
|
||||
"include/audio_util.h",
|
||||
"lapped_transform.cc",
|
||||
"lapped_transform.h",
|
||||
"real_fourier.cc",
|
||||
"real_fourier.h",
|
||||
"real_fourier_ooura.cc",
|
||||
@ -48,7 +30,79 @@ source_set("common_audio") {
|
||||
"resampler/push_sinc_resampler.h",
|
||||
"resampler/resampler.cc",
|
||||
"resampler/sinc_resampler.cc",
|
||||
"resampler/sinc_resampler.h",
|
||||
"smoothing_filter.cc",
|
||||
"smoothing_filter.h",
|
||||
"vad/include/vad.h",
|
||||
"vad/vad.cc",
|
||||
"wav_file.cc",
|
||||
"wav_file.h",
|
||||
"wav_header.cc",
|
||||
"wav_header.h",
|
||||
"window_generator.cc",
|
||||
"window_generator.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":common_audio_c",
|
||||
":sinc_resampler",
|
||||
"../api:array_view",
|
||||
"../api/audio:audio_frame_api",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:gtest_prod",
|
||||
"../rtc_base:logging",
|
||||
"../rtc_base:safe_conversions",
|
||||
"../rtc_base:sanitizer",
|
||||
"../rtc_base:timeutils",
|
||||
"../rtc_base/memory:aligned_malloc",
|
||||
"../rtc_base/system:arch",
|
||||
"../rtc_base/system:file_wrapper",
|
||||
"../system_wrappers",
|
||||
"third_party/ooura:fft_size_256",
|
||||
]
|
||||
|
||||
defines = []
|
||||
|
||||
if (rtc_build_with_neon) {
|
||||
deps += [ ":common_audio_neon" ]
|
||||
}
|
||||
|
||||
if (current_cpu == "x86" || current_cpu == "x64") {
|
||||
deps += [ ":common_audio_sse2" ]
|
||||
deps += [ ":common_audio_avx2" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_source_set("mock_common_audio") {
|
||||
visibility += webrtc_default_visibility
|
||||
testonly = true
|
||||
sources = [
|
||||
"mocks/mock_smoothing_filter.h",
|
||||
"vad/mock/mock_vad.h",
|
||||
]
|
||||
deps = [
|
||||
":common_audio",
|
||||
"../test:test_support",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("common_audio_c_arm_asm") {
|
||||
sources = []
|
||||
deps = []
|
||||
if (current_cpu == "arm") {
|
||||
sources += [ "signal_processing/complex_bit_reverse_arm.S" ]
|
||||
|
||||
if (arm_version >= 7) {
|
||||
sources += [ "signal_processing/filter_ar_fast_q12_armv7.S" ]
|
||||
} else {
|
||||
sources += [ "signal_processing/filter_ar_fast_q12.c" ]
|
||||
}
|
||||
deps += [ "../rtc_base/system:asm_defines" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_library("common_audio_c") {
|
||||
visibility += webrtc_default_visibility
|
||||
sources = [
|
||||
"ring_buffer.c",
|
||||
"ring_buffer.h",
|
||||
"signal_processing/auto_corr_to_refl_coef.c",
|
||||
@ -57,7 +111,6 @@ source_set("common_audio") {
|
||||
"signal_processing/copy_set_operations.c",
|
||||
"signal_processing/cross_correlation.c",
|
||||
"signal_processing/division_operations.c",
|
||||
"signal_processing/dot_product_with_scale.c",
|
||||
"signal_processing/downsample_fast.c",
|
||||
"signal_processing/energy.c",
|
||||
"signal_processing/filter_ar.c",
|
||||
@ -68,6 +121,7 @@ source_set("common_audio") {
|
||||
"signal_processing/include/real_fft.h",
|
||||
"signal_processing/include/signal_processing_library.h",
|
||||
"signal_processing/include/spl_inl.h",
|
||||
"signal_processing/include/spl_inl_armv7.h",
|
||||
"signal_processing/levinson_durbin.c",
|
||||
"signal_processing/lpc_to_refl_coef.c",
|
||||
"signal_processing/min_max_operations.c",
|
||||
@ -81,15 +135,12 @@ source_set("common_audio") {
|
||||
"signal_processing/resample_by_2_internal.h",
|
||||
"signal_processing/resample_fractional.c",
|
||||
"signal_processing/spl_init.c",
|
||||
"signal_processing/spl_inl.c",
|
||||
"signal_processing/spl_sqrt.c",
|
||||
"signal_processing/splitting_filter.c",
|
||||
"signal_processing/sqrt_of_one_minus_x_squared.c",
|
||||
"signal_processing/vector_scaling_operations.c",
|
||||
"sparse_fir_filter.cc",
|
||||
"sparse_fir_filter.h",
|
||||
"vad/include/vad.h",
|
||||
"vad/include/webrtc_vad.h",
|
||||
"vad/vad.cc",
|
||||
"vad/vad_core.c",
|
||||
"vad/vad_core.h",
|
||||
"vad/vad_filterbank.c",
|
||||
@ -99,47 +150,8 @@ source_set("common_audio") {
|
||||
"vad/vad_sp.c",
|
||||
"vad/vad_sp.h",
|
||||
"vad/webrtc_vad.c",
|
||||
"wav_file.cc",
|
||||
"wav_file.h",
|
||||
"wav_header.cc",
|
||||
"wav_header.h",
|
||||
"window_generator.cc",
|
||||
"window_generator.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../system_wrappers",
|
||||
]
|
||||
|
||||
defines = []
|
||||
if (rtc_use_openmax_dl) {
|
||||
sources += [
|
||||
"real_fourier_openmax.cc",
|
||||
"real_fourier_openmax.h",
|
||||
]
|
||||
defines += [ "RTC_USE_OPENMAX_DL" ]
|
||||
if (rtc_build_openmax_dl) {
|
||||
deps += [ "//third_party/openmax_dl/dl" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (current_cpu == "arm") {
|
||||
sources += [
|
||||
"signal_processing/complex_bit_reverse_arm.S",
|
||||
"signal_processing/spl_sqrt_floor_arm.S",
|
||||
]
|
||||
|
||||
if (arm_version >= 7) {
|
||||
sources += [ "signal_processing/filter_ar_fast_q12_armv7.S" ]
|
||||
} else {
|
||||
sources += [ "signal_processing/filter_ar_fast_q12.c" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_build_with_neon) {
|
||||
deps += [ ":common_audio_neon" ]
|
||||
}
|
||||
|
||||
if (current_cpu == "mipsel") {
|
||||
sources += [
|
||||
"signal_processing/complex_bit_reverse_mips.c",
|
||||
@ -150,7 +162,6 @@ source_set("common_audio") {
|
||||
"signal_processing/include/spl_inl_mips.h",
|
||||
"signal_processing/min_max_operations_mips.c",
|
||||
"signal_processing/resample_by_2_mips.c",
|
||||
"signal_processing/spl_sqrt_floor_mips.c",
|
||||
]
|
||||
if (mips_dsp_rev > 0) {
|
||||
sources += [ "signal_processing/vector_scaling_operations_mips.c" ]
|
||||
@ -163,81 +174,222 @@ source_set("common_audio") {
|
||||
sources += [
|
||||
"signal_processing/complex_bit_reverse.c",
|
||||
"signal_processing/filter_ar_fast_q12.c",
|
||||
"signal_processing/spl_sqrt_floor.c",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
cflags = [ "/wd4334" ] # Ignore warning on shift operator promotion.
|
||||
deps = [
|
||||
":common_audio_c_arm_asm",
|
||||
":common_audio_cc",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:compile_assert_c",
|
||||
"../rtc_base:sanitizer",
|
||||
"../rtc_base/system:arch",
|
||||
"../system_wrappers",
|
||||
"third_party/ooura:fft_size_256",
|
||||
"third_party/spl_sqrt_floor",
|
||||
]
|
||||
}
|
||||
|
||||
configs += [ "..:common_config" ]
|
||||
|
||||
public_configs = [
|
||||
"..:common_inherited_config",
|
||||
":common_audio_config",
|
||||
rtc_library("common_audio_cc") {
|
||||
sources = [
|
||||
"signal_processing/dot_product_with_scale.cc",
|
||||
"signal_processing/dot_product_with_scale.h",
|
||||
]
|
||||
|
||||
if (is_clang) {
|
||||
# Suppress warnings from Chrome's Clang plugins.
|
||||
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
|
||||
configs -= [ "//build/config/clang:find_bad_constructs" ]
|
||||
deps = [
|
||||
"../rtc_base:safe_conversions",
|
||||
"../system_wrappers",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("sinc_resampler") {
|
||||
sources = [ "resampler/sinc_resampler.h" ]
|
||||
deps = [
|
||||
"../rtc_base:gtest_prod",
|
||||
"../rtc_base/memory:aligned_malloc",
|
||||
"../rtc_base/system:arch",
|
||||
"../system_wrappers",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("fir_filter") {
|
||||
visibility += webrtc_default_visibility
|
||||
sources = [ "fir_filter.h" ]
|
||||
}
|
||||
|
||||
rtc_library("fir_filter_factory") {
|
||||
visibility += webrtc_default_visibility
|
||||
sources = [
|
||||
"fir_filter_c.cc",
|
||||
"fir_filter_c.h",
|
||||
"fir_filter_factory.cc",
|
||||
"fir_filter_factory.h",
|
||||
]
|
||||
deps = [
|
||||
":fir_filter",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base/system:arch",
|
||||
"../system_wrappers",
|
||||
]
|
||||
if (current_cpu == "x86" || current_cpu == "x64") {
|
||||
deps += [ ":common_audio_sse2" ]
|
||||
deps += [ ":common_audio_avx2" ]
|
||||
}
|
||||
if (rtc_build_with_neon) {
|
||||
deps += [ ":common_audio_neon" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (current_cpu == "x86" || current_cpu == "x64") {
|
||||
source_set("common_audio_sse2") {
|
||||
rtc_library("common_audio_sse2") {
|
||||
sources = [
|
||||
"fir_filter_sse.cc",
|
||||
"fir_filter_sse.h",
|
||||
"resampler/sinc_resampler_sse.cc",
|
||||
]
|
||||
|
||||
if (is_posix) {
|
||||
if (is_posix || is_fuchsia) {
|
||||
cflags = [ "-msse2" ]
|
||||
}
|
||||
|
||||
configs += [ "..:common_inherited_config" ]
|
||||
|
||||
if (is_clang) {
|
||||
# Suppress warnings from Chrome's Clang plugins.
|
||||
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
|
||||
configs -= [ "//build/config/clang:find_bad_constructs" ]
|
||||
deps = [
|
||||
":fir_filter",
|
||||
":sinc_resampler",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base/memory:aligned_malloc",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("common_audio_avx2") {
|
||||
sources = [
|
||||
"fir_filter_avx2.cc",
|
||||
"fir_filter_avx2.h",
|
||||
"resampler/sinc_resampler_avx2.cc",
|
||||
]
|
||||
|
||||
if (is_win) {
|
||||
cflags = [ "/arch:AVX2" ]
|
||||
} else {
|
||||
cflags = [
|
||||
"-mavx2",
|
||||
"-mfma",
|
||||
]
|
||||
}
|
||||
|
||||
deps = [
|
||||
":fir_filter",
|
||||
":sinc_resampler",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base/memory:aligned_malloc",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc_build_with_neon) {
|
||||
source_set("common_audio_neon") {
|
||||
rtc_library("common_audio_neon") {
|
||||
sources = [
|
||||
"fir_filter_neon.cc",
|
||||
"fir_filter_neon.h",
|
||||
"resampler/sinc_resampler_neon.cc",
|
||||
]
|
||||
|
||||
if (current_cpu != "arm64") {
|
||||
# Enable compilation for the NEON instruction set.
|
||||
suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
|
||||
cflags = [ "-mfpu=neon" ]
|
||||
}
|
||||
|
||||
deps = [
|
||||
":common_audio_neon_c",
|
||||
":fir_filter",
|
||||
":sinc_resampler",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base/memory:aligned_malloc",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("common_audio_neon_c") {
|
||||
visibility += webrtc_default_visibility
|
||||
sources = [
|
||||
"signal_processing/cross_correlation_neon.c",
|
||||
"signal_processing/downsample_fast_neon.c",
|
||||
"signal_processing/min_max_operations_neon.c",
|
||||
]
|
||||
|
||||
if (current_cpu != "arm64") {
|
||||
# Enable compilation for the NEON instruction set. This is needed
|
||||
# since //build/config/arm.gni only enables NEON for iOS, not Android.
|
||||
# This provides the same functionality as webrtc/build/arm_neon.gypi.
|
||||
configs -= [ "//build/config/compiler:compiler_arm_fpu" ]
|
||||
# Enable compilation for the NEON instruction set.
|
||||
suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
|
||||
cflags = [ "-mfpu=neon" ]
|
||||
}
|
||||
|
||||
# Disable LTO on NEON targets due to compiler bug.
|
||||
# TODO(fdegans): Enable this. See crbug.com/408997.
|
||||
if (rtc_use_lto) {
|
||||
cflags -= [
|
||||
"-flto",
|
||||
"-ffat-lto-objects",
|
||||
deps = [
|
||||
":common_audio_c",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base/system:arch",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
configs += [ "..:common_config" ]
|
||||
public_configs = [ "..:common_inherited_config" ]
|
||||
if (rtc_include_tests && !build_with_chromium) {
|
||||
rtc_test("common_audio_unittests") {
|
||||
visibility += webrtc_default_visibility
|
||||
testonly = true
|
||||
|
||||
sources = [
|
||||
"audio_converter_unittest.cc",
|
||||
"audio_util_unittest.cc",
|
||||
"channel_buffer_unittest.cc",
|
||||
"fir_filter_unittest.cc",
|
||||
"real_fourier_unittest.cc",
|
||||
"resampler/push_resampler_unittest.cc",
|
||||
"resampler/push_sinc_resampler_unittest.cc",
|
||||
"resampler/resampler_unittest.cc",
|
||||
"resampler/sinusoidal_linear_chirp_source.cc",
|
||||
"resampler/sinusoidal_linear_chirp_source.h",
|
||||
"ring_buffer_unittest.cc",
|
||||
"signal_processing/real_fft_unittest.cc",
|
||||
"signal_processing/signal_processing_unittest.cc",
|
||||
"smoothing_filter_unittest.cc",
|
||||
"vad/vad_core_unittest.cc",
|
||||
"vad/vad_filterbank_unittest.cc",
|
||||
"vad/vad_gmm_unittest.cc",
|
||||
"vad/vad_sp_unittest.cc",
|
||||
"vad/vad_unittest.cc",
|
||||
"vad/vad_unittest.h",
|
||||
"wav_file_unittest.cc",
|
||||
"wav_header_unittest.cc",
|
||||
"window_generator_unittest.cc",
|
||||
]
|
||||
|
||||
# Does not compile on iOS for arm: webrtc:5544.
|
||||
if (!is_ios || target_cpu != "arm") {
|
||||
sources += [ "resampler/sinc_resampler_unittest.cc" ]
|
||||
}
|
||||
|
||||
deps = [
|
||||
":common_audio",
|
||||
":common_audio_c",
|
||||
":fir_filter",
|
||||
":fir_filter_factory",
|
||||
":sinc_resampler",
|
||||
"../rtc_base:checks",
|
||||
"../rtc_base:macromagic",
|
||||
"../rtc_base:rtc_base_tests_utils",
|
||||
"../rtc_base:stringutils",
|
||||
"../rtc_base:timeutils",
|
||||
"../rtc_base/system:arch",
|
||||
"../system_wrappers",
|
||||
"../test:fileutils",
|
||||
"../test:rtc_expect_death",
|
||||
"../test:test_main",
|
||||
"../test:test_support",
|
||||
"//testing/gtest",
|
||||
]
|
||||
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_support" ]
|
||||
|
||||
shard_timeout = 900
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,153 +0,0 @@
|
||||
noinst_LTLIBRARIES = libcommon_audio.la
|
||||
|
||||
noinst_HEADERS = include/audio_util.h
|
||||
|
||||
libcommon_audio_la_SOURCES = resampler/include/push_resampler.h \
|
||||
resampler/include/resampler.h \
|
||||
resampler/push_sinc_resampler.h \
|
||||
resampler/sinc_resampler.h \
|
||||
resampler/sinusoidal_linear_chirp_source.h \
|
||||
resampler/push_resampler.cc \
|
||||
resampler/push_sinc_resampler.cc \
|
||||
resampler/resampler.cc \
|
||||
resampler/sinc_resampler.cc \
|
||||
resampler/sinusoidal_linear_chirp_source.cc \
|
||||
signal_processing/include/real_fft.h \
|
||||
signal_processing/include/signal_processing_library.h \
|
||||
signal_processing/include/spl_inl.h \
|
||||
signal_processing/include/spl_inl_armv7.h \
|
||||
signal_processing/include/spl_inl_mips.h \
|
||||
signal_processing/auto_corr_to_refl_coef.c \
|
||||
signal_processing/auto_correlation.c \
|
||||
signal_processing/complex_fft.c \
|
||||
signal_processing/complex_fft_tables.h \
|
||||
signal_processing/copy_set_operations.c \
|
||||
signal_processing/cross_correlation.c \
|
||||
signal_processing/division_operations.c \
|
||||
signal_processing/dot_product_with_scale.c \
|
||||
signal_processing/downsample_fast.c \
|
||||
signal_processing/energy.c \
|
||||
signal_processing/filter_ar.c \
|
||||
signal_processing/filter_ma_fast_q12.c \
|
||||
signal_processing/get_hanning_window.c \
|
||||
signal_processing/get_scaling_square.c \
|
||||
signal_processing/ilbc_specific_functions.c \
|
||||
signal_processing/levinson_durbin.c \
|
||||
signal_processing/lpc_to_refl_coef.c \
|
||||
signal_processing/min_max_operations.c \
|
||||
signal_processing/randomization_functions.c \
|
||||
signal_processing/real_fft.c \
|
||||
signal_processing/refl_coef_to_lpc.c \
|
||||
signal_processing/resample.c \
|
||||
signal_processing/resample_48khz.c \
|
||||
signal_processing/resample_by_2.c \
|
||||
signal_processing/resample_by_2_internal.c \
|
||||
signal_processing/resample_by_2_internal.h \
|
||||
signal_processing/resample_fractional.c \
|
||||
signal_processing/spl_init.c \
|
||||
signal_processing/spl_sqrt.c \
|
||||
signal_processing/splitting_filter.c \
|
||||
signal_processing/sqrt_of_one_minus_x_squared.c \
|
||||
signal_processing/vector_scaling_operations.c \
|
||||
vad/include/vad.h \
|
||||
vad/include/webrtc_vad.h \
|
||||
vad/vad.cc \
|
||||
vad/vad_core.c \
|
||||
vad/vad_core.h \
|
||||
vad/vad_filterbank.c \
|
||||
vad/vad_filterbank.h \
|
||||
vad/vad_gmm.c \
|
||||
vad/vad_gmm.h \
|
||||
vad/vad_sp.c \
|
||||
vad/vad_sp.h \
|
||||
vad/webrtc_vad.c \
|
||||
audio_converter.cc \
|
||||
audio_converter.h \
|
||||
audio_ring_buffer.cc \
|
||||
audio_ring_buffer.h \
|
||||
audio_util.cc \
|
||||
blocker.cc \
|
||||
blocker.h \
|
||||
channel_buffer.cc \
|
||||
channel_buffer.h \
|
||||
fft4g.c \
|
||||
fft4g.h \
|
||||
fir_filter.cc \
|
||||
fir_filter.h \
|
||||
lapped_transform.cc \
|
||||
lapped_transform.h \
|
||||
real_fourier.cc \
|
||||
real_fourier.h \
|
||||
real_fourier_ooura.cc \
|
||||
real_fourier_ooura.h \
|
||||
real_fourier_openmax.h \
|
||||
ring_buffer.h \
|
||||
ring_buffer.c \
|
||||
sparse_fir_filter.cc \
|
||||
sparse_fir_filter.h \
|
||||
wav_file.h \
|
||||
wav_file.cc \
|
||||
wav_header.h \
|
||||
wav_header.cc \
|
||||
window_generator.h \
|
||||
window_generator.cc
|
||||
|
||||
if HAVE_X86
|
||||
noinst_LTLIBRARIES += libcommon_audio_sse2.la
|
||||
libcommon_audio_sse2_la_SOURCES = \
|
||||
resampler/sinc_resampler_sse.cc \
|
||||
fir_filter_sse.cc \
|
||||
fir_filter_sse.h
|
||||
|
||||
libcommon_audio_sse2_la_CFLAGS = $(AM_CFLAGS) $(COMMON_CFLAGS) -msse2
|
||||
libcommon_audio_sse2_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS) -msse2
|
||||
libcommon_audio_sse2_la_LDFLAGS = $(AM_LDFLAGS)
|
||||
|
||||
libcommon_audio_la_LIBADD = libcommon_audio_sse2.la
|
||||
endif
|
||||
|
||||
if HAVE_ARM
|
||||
libcommon_audio_la_SOURCES += \
|
||||
signal_processing/complex_bit_reverse_arm.S \
|
||||
signal_processing/spl_sqrt_floor_arm.S
|
||||
endif
|
||||
|
||||
if HAVE_ARMV7
|
||||
libcommon_audio_la_SOURCES += \
|
||||
signal_processing/filter_ar_fast_q12_armv7.S
|
||||
endif
|
||||
|
||||
if HAVE_NEON
|
||||
libcommon_audio_la_SOURCES += \
|
||||
resampler/sinc_resampler_neon.cc \
|
||||
signal_processing/cross_correlation_neon.c \
|
||||
signal_processing/downsample_fast_neon.c \
|
||||
signal_processing/min_max_operations_neon.c \
|
||||
fir_filter_neon.cc \
|
||||
fir_filter_neon.h
|
||||
endif
|
||||
|
||||
if !HAVE_ARM
|
||||
# FIXME: This condition will also hold for !HAVE_MIPS
|
||||
libcommon_audio_la_SOURCES += \
|
||||
signal_processing/complex_bit_reverse.c \
|
||||
signal_processing/filter_ar_fast_q12.c \
|
||||
signal_processing/spl_sqrt_floor.c
|
||||
endif
|
||||
|
||||
libcommon_audio_la_CCASFLAGS = $(AM_CCASFLAGS) $(COMMON_CFLAGS)
|
||||
libcommon_audio_la_CFLAGS = $(AM_CFLAGS) $(COMMON_CFLAGS)
|
||||
libcommon_audio_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS)
|
||||
|
||||
# FIXME: The MIPS optimisations need to be hooked up once we have the
|
||||
# autotools conditionals in place
|
||||
EXTRA_DIST = BUILD.gn \
|
||||
signal_processing/complex_bit_reverse_mips.c \
|
||||
signal_processing/complex_fft_mips.c \
|
||||
signal_processing/cross_correlation_mips.c \
|
||||
signal_processing/downsample_fast_mips.c \
|
||||
signal_processing/filter_ar_fast_q12_mips.c \
|
||||
signal_processing/min_max_operations_mips.c \
|
||||
signal_processing/resample_by_2_mips.c \
|
||||
signal_processing/spl_sqrt_floor_mips.c \
|
||||
signal_processing/vector_scaling_operations_mips.c
|
@ -8,32 +8,36 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/common_audio/audio_converter.h"
|
||||
#include "common_audio/audio_converter.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/safe_conversions.h"
|
||||
#include "webrtc/common_audio/channel_buffer.h"
|
||||
#include "webrtc/common_audio/resampler/push_sinc_resampler.h"
|
||||
#include "webrtc/system_wrappers/include/scoped_vector.h"
|
||||
|
||||
using rtc::checked_cast;
|
||||
#include "common_audio/channel_buffer.h"
|
||||
#include "common_audio/resampler/push_sinc_resampler.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CopyConverter : public AudioConverter {
|
||||
public:
|
||||
CopyConverter(int src_channels, size_t src_frames, int dst_channels,
|
||||
CopyConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames)
|
||||
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
|
||||
~CopyConverter() override {};
|
||||
~CopyConverter() override {}
|
||||
|
||||
void Convert(const float* const* src, size_t src_size, float* const* dst,
|
||||
void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) override {
|
||||
CheckSizes(src_size, dst_capacity);
|
||||
if (src != dst) {
|
||||
for (int i = 0; i < src_channels(); ++i)
|
||||
for (size_t i = 0; i < src_channels(); ++i)
|
||||
std::memcpy(dst[i], src[i], dst_frames() * sizeof(*dst[i]));
|
||||
}
|
||||
}
|
||||
@ -41,17 +45,21 @@ class CopyConverter : public AudioConverter {
|
||||
|
||||
class UpmixConverter : public AudioConverter {
|
||||
public:
|
||||
UpmixConverter(int src_channels, size_t src_frames, int dst_channels,
|
||||
UpmixConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames)
|
||||
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
|
||||
~UpmixConverter() override {};
|
||||
~UpmixConverter() override {}
|
||||
|
||||
void Convert(const float* const* src, size_t src_size, float* const* dst,
|
||||
void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) override {
|
||||
CheckSizes(src_size, dst_capacity);
|
||||
for (size_t i = 0; i < dst_frames(); ++i) {
|
||||
const float value = src[0][i];
|
||||
for (int j = 0; j < dst_channels(); ++j)
|
||||
for (size_t j = 0; j < dst_channels(); ++j)
|
||||
dst[j][i] = value;
|
||||
}
|
||||
}
|
||||
@ -59,19 +67,22 @@ class UpmixConverter : public AudioConverter {
|
||||
|
||||
class DownmixConverter : public AudioConverter {
|
||||
public:
|
||||
DownmixConverter(int src_channels, size_t src_frames, int dst_channels,
|
||||
DownmixConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames)
|
||||
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {
|
||||
}
|
||||
~DownmixConverter() override {};
|
||||
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
|
||||
~DownmixConverter() override {}
|
||||
|
||||
void Convert(const float* const* src, size_t src_size, float* const* dst,
|
||||
void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) override {
|
||||
CheckSizes(src_size, dst_capacity);
|
||||
float* dst_mono = dst[0];
|
||||
for (size_t i = 0; i < src_frames(); ++i) {
|
||||
float sum = 0;
|
||||
for (int j = 0; j < src_channels(); ++j)
|
||||
for (size_t j = 0; j < src_channels(); ++j)
|
||||
sum += src[j][i];
|
||||
dst_mono[i] = sum / src_channels();
|
||||
}
|
||||
@ -80,16 +91,21 @@ class DownmixConverter : public AudioConverter {
|
||||
|
||||
class ResampleConverter : public AudioConverter {
|
||||
public:
|
||||
ResampleConverter(int src_channels, size_t src_frames, int dst_channels,
|
||||
ResampleConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames)
|
||||
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {
|
||||
resamplers_.reserve(src_channels);
|
||||
for (int i = 0; i < src_channels; ++i)
|
||||
resamplers_.push_back(new PushSincResampler(src_frames, dst_frames));
|
||||
for (size_t i = 0; i < src_channels; ++i)
|
||||
resamplers_.push_back(std::unique_ptr<PushSincResampler>(
|
||||
new PushSincResampler(src_frames, dst_frames)));
|
||||
}
|
||||
~ResampleConverter() override {};
|
||||
~ResampleConverter() override {}
|
||||
|
||||
void Convert(const float* const* src, size_t src_size, float* const* dst,
|
||||
void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) override {
|
||||
CheckSizes(src_size, dst_capacity);
|
||||
for (size_t i = 0; i < resamplers_.size(); ++i)
|
||||
@ -97,69 +113,73 @@ class ResampleConverter : public AudioConverter {
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedVector<PushSincResampler> resamplers_;
|
||||
std::vector<std::unique_ptr<PushSincResampler>> resamplers_;
|
||||
};
|
||||
|
||||
// Apply a vector of converters in serial, in the order given. At least two
|
||||
// converters must be provided.
|
||||
class CompositionConverter : public AudioConverter {
|
||||
public:
|
||||
CompositionConverter(ScopedVector<AudioConverter> converters)
|
||||
: converters_(converters.Pass()) {
|
||||
RTC_CHECK_GE(converters_.size(), 2u);
|
||||
explicit CompositionConverter(
|
||||
std::vector<std::unique_ptr<AudioConverter>> converters)
|
||||
: converters_(std::move(converters)) {
|
||||
RTC_CHECK_GE(converters_.size(), 2);
|
||||
// We need an intermediate buffer after every converter.
|
||||
for (auto it = converters_.begin(); it != converters_.end() - 1; ++it)
|
||||
buffers_.push_back(new ChannelBuffer<float>((*it)->dst_frames(),
|
||||
(*it)->dst_channels()));
|
||||
buffers_.push_back(
|
||||
std::unique_ptr<ChannelBuffer<float>>(new ChannelBuffer<float>(
|
||||
(*it)->dst_frames(), (*it)->dst_channels())));
|
||||
}
|
||||
~CompositionConverter() override {};
|
||||
~CompositionConverter() override {}
|
||||
|
||||
void Convert(const float* const* src, size_t src_size, float* const* dst,
|
||||
void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) override {
|
||||
converters_.front()->Convert(src, src_size, buffers_.front()->channels(),
|
||||
buffers_.front()->size());
|
||||
for (size_t i = 2; i < converters_.size(); ++i) {
|
||||
auto src_buffer = buffers_[i - 2];
|
||||
auto dst_buffer = buffers_[i - 1];
|
||||
converters_[i]->Convert(src_buffer->channels(),
|
||||
src_buffer->size(),
|
||||
dst_buffer->channels(),
|
||||
dst_buffer->size());
|
||||
auto& src_buffer = buffers_[i - 2];
|
||||
auto& dst_buffer = buffers_[i - 1];
|
||||
converters_[i]->Convert(src_buffer->channels(), src_buffer->size(),
|
||||
dst_buffer->channels(), dst_buffer->size());
|
||||
}
|
||||
converters_.back()->Convert(buffers_.back()->channels(),
|
||||
buffers_.back()->size(), dst, dst_capacity);
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedVector<AudioConverter> converters_;
|
||||
ScopedVector<ChannelBuffer<float>> buffers_;
|
||||
std::vector<std::unique_ptr<AudioConverter>> converters_;
|
||||
std::vector<std::unique_ptr<ChannelBuffer<float>>> buffers_;
|
||||
};
|
||||
|
||||
rtc::scoped_ptr<AudioConverter> AudioConverter::Create(int src_channels,
|
||||
std::unique_ptr<AudioConverter> AudioConverter::Create(size_t src_channels,
|
||||
size_t src_frames,
|
||||
int dst_channels,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames) {
|
||||
rtc::scoped_ptr<AudioConverter> sp;
|
||||
std::unique_ptr<AudioConverter> sp;
|
||||
if (src_channels > dst_channels) {
|
||||
if (src_frames != dst_frames) {
|
||||
ScopedVector<AudioConverter> converters;
|
||||
converters.push_back(new DownmixConverter(src_channels, src_frames,
|
||||
dst_channels, src_frames));
|
||||
converters.push_back(new ResampleConverter(dst_channels, src_frames,
|
||||
dst_channels, dst_frames));
|
||||
sp.reset(new CompositionConverter(converters.Pass()));
|
||||
std::vector<std::unique_ptr<AudioConverter>> converters;
|
||||
converters.push_back(std::unique_ptr<AudioConverter>(new DownmixConverter(
|
||||
src_channels, src_frames, dst_channels, src_frames)));
|
||||
converters.push_back(
|
||||
std::unique_ptr<AudioConverter>(new ResampleConverter(
|
||||
dst_channels, src_frames, dst_channels, dst_frames)));
|
||||
sp.reset(new CompositionConverter(std::move(converters)));
|
||||
} else {
|
||||
sp.reset(new DownmixConverter(src_channels, src_frames, dst_channels,
|
||||
dst_frames));
|
||||
}
|
||||
} else if (src_channels < dst_channels) {
|
||||
if (src_frames != dst_frames) {
|
||||
ScopedVector<AudioConverter> converters;
|
||||
converters.push_back(new ResampleConverter(src_channels, src_frames,
|
||||
src_channels, dst_frames));
|
||||
converters.push_back(new UpmixConverter(src_channels, dst_frames,
|
||||
dst_channels, dst_frames));
|
||||
sp.reset(new CompositionConverter(converters.Pass()));
|
||||
std::vector<std::unique_ptr<AudioConverter>> converters;
|
||||
converters.push_back(
|
||||
std::unique_ptr<AudioConverter>(new ResampleConverter(
|
||||
src_channels, src_frames, src_channels, dst_frames)));
|
||||
converters.push_back(std::unique_ptr<AudioConverter>(new UpmixConverter(
|
||||
src_channels, dst_frames, dst_channels, dst_frames)));
|
||||
sp.reset(new CompositionConverter(std::move(converters)));
|
||||
} else {
|
||||
sp.reset(new UpmixConverter(src_channels, src_frames, dst_channels,
|
||||
dst_frames));
|
||||
@ -168,22 +188,21 @@ rtc::scoped_ptr<AudioConverter> AudioConverter::Create(int src_channels,
|
||||
sp.reset(new ResampleConverter(src_channels, src_frames, dst_channels,
|
||||
dst_frames));
|
||||
} else {
|
||||
sp.reset(new CopyConverter(src_channels, src_frames, dst_channels,
|
||||
dst_frames));
|
||||
sp.reset(
|
||||
new CopyConverter(src_channels, src_frames, dst_channels, dst_frames));
|
||||
}
|
||||
|
||||
return sp.Pass();
|
||||
return sp;
|
||||
}
|
||||
|
||||
// For CompositionConverter.
|
||||
AudioConverter::AudioConverter()
|
||||
: src_channels_(0),
|
||||
src_frames_(0),
|
||||
dst_channels_(0),
|
||||
dst_frames_(0) {}
|
||||
: src_channels_(0), src_frames_(0), dst_channels_(0), dst_frames_(0) {}
|
||||
|
||||
AudioConverter::AudioConverter(int src_channels, size_t src_frames,
|
||||
int dst_channels, size_t dst_frames)
|
||||
AudioConverter::AudioConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames)
|
||||
: src_channels_(src_channels),
|
||||
src_frames_(src_frames),
|
||||
dst_channels_(dst_channels),
|
||||
|
@ -8,16 +8,17 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
#define WEBRTC_COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
#ifndef COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
#define COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Format conversion (remixing and resampling) for audio. Only simple remixing
|
||||
// conversions are supported: downmix to mono (i.e. |dst_channels| == 1) or
|
||||
// conversions are supported: downmix to mono (i.e. `dst_channels` == 1) or
|
||||
// upmix from mono (i.e. |src_channels == 1|).
|
||||
//
|
||||
// The source and destination chunks have the same duration in time; specifying
|
||||
@ -26,41 +27,46 @@ class AudioConverter {
|
||||
public:
|
||||
// Returns a new AudioConverter, which will use the supplied format for its
|
||||
// lifetime. Caller is responsible for the memory.
|
||||
static rtc::scoped_ptr<AudioConverter> Create(int src_channels,
|
||||
static std::unique_ptr<AudioConverter> Create(size_t src_channels,
|
||||
size_t src_frames,
|
||||
int dst_channels,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames);
|
||||
virtual ~AudioConverter() {};
|
||||
virtual ~AudioConverter() {}
|
||||
|
||||
// Convert |src|, containing |src_size| samples, to |dst|, having a sample
|
||||
// capacity of |dst_capacity|. Both point to a series of buffers containing
|
||||
AudioConverter(const AudioConverter&) = delete;
|
||||
AudioConverter& operator=(const AudioConverter&) = delete;
|
||||
|
||||
// Convert `src`, containing `src_size` samples, to `dst`, having a sample
|
||||
// capacity of `dst_capacity`. Both point to a series of buffers containing
|
||||
// the samples for each channel. The sizes must correspond to the format
|
||||
// passed to Create().
|
||||
virtual void Convert(const float* const* src, size_t src_size,
|
||||
float* const* dst, size_t dst_capacity) = 0;
|
||||
virtual void Convert(const float* const* src,
|
||||
size_t src_size,
|
||||
float* const* dst,
|
||||
size_t dst_capacity) = 0;
|
||||
|
||||
int src_channels() const { return src_channels_; }
|
||||
size_t src_channels() const { return src_channels_; }
|
||||
size_t src_frames() const { return src_frames_; }
|
||||
int dst_channels() const { return dst_channels_; }
|
||||
size_t dst_channels() const { return dst_channels_; }
|
||||
size_t dst_frames() const { return dst_frames_; }
|
||||
|
||||
protected:
|
||||
AudioConverter();
|
||||
AudioConverter(int src_channels, size_t src_frames, int dst_channels,
|
||||
AudioConverter(size_t src_channels,
|
||||
size_t src_frames,
|
||||
size_t dst_channels,
|
||||
size_t dst_frames);
|
||||
|
||||
// Helper to RTC_CHECK that inputs are correctly sized.
|
||||
void CheckSizes(size_t src_size, size_t dst_capacity) const;
|
||||
|
||||
private:
|
||||
const int src_channels_;
|
||||
const size_t src_channels_;
|
||||
const size_t src_frames_;
|
||||
const int dst_channels_;
|
||||
const size_t dst_channels_;
|
||||
const size_t dst_frames_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(AudioConverter);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
#endif // COMMON_AUDIO_AUDIO_CONVERTER_H_
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user