Merge branch 'upstream-master'
Bug: 153469641 Test: none Change-Id: Ic33e363deb0d1ac4bb4d57c3c239eb2e45370802 Merged-In: Ic33e363deb0d1ac4bb4d57c3c239eb2e45370802
This commit is contained in:
@ -1,3 +1,21 @@
|
||||
# Defines the Chromium style for automatic reformatting.
|
||||
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
BasedOnStyle: Chromium
|
||||
---
|
||||
Language: Java
|
||||
BasedOnStyle: Google
|
||||
---
|
||||
Language: ObjC
|
||||
BasedOnStyle: Google
|
||||
BinPackParameters: false
|
||||
BinPackArguments: false
|
||||
ColumnLimit: 100
|
||||
ObjCBlockIndentWidth: 2
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AlignOperands: false
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
BreakBeforeTernaryOperators: false
|
||||
IndentWrappedFunctionNames: true
|
||||
ContinuationIndentWidth: 4
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
|
24
.git-blame-ignore-revs
Normal file
24
.git-blame-ignore-revs
Normal file
@ -0,0 +1,24 @@
|
||||
# git hyper-blame master ignore list.
|
||||
#
|
||||
# This file contains a list of git hashes of revisions to be ignored by git
|
||||
# hyper-blame (in depot_tools). These revisions are considered "unimportant" in
|
||||
# that they are unlikely to be what you are interested in when blaming.
|
||||
#
|
||||
# Instructions:
|
||||
# - Only large (generally automated) reformatting or renaming CLs should be
|
||||
# added to this list. Do not put things here just because you feel they are
|
||||
# trivial or unimportant. If in doubt, do not put it on this list.
|
||||
# - Precede each revision with a comment containing the first line of its log.
|
||||
# - Only put full 40-character hashes on this list (not short hashes or any
|
||||
# other revision reference).
|
||||
# - Append to the bottom of the file (revisions should be in chronological order
|
||||
# from oldest to newest).
|
||||
# - Because you must use a hash, you need to append to this list in a follow-up
|
||||
# CL to the actual reformatting CL that you are trying to ignore.
|
||||
|
||||
# Format all Java in WebRTC.
|
||||
b6760f9e4442410f2bcb6090b3b89bf709e2fce2
|
||||
# Format all C++ in WebRTC.
|
||||
665174fdbb4e0540eccb27cf7412348f1b65534c
|
||||
# Format almost all C++ in WebRTC. Again. Mostly #include reordering.
|
||||
a4d873786f10eedd72de25ad0d94ad7c53c1f68a
|
153
.gitignore
vendored
153
.gitignore
vendored
@ -21,10 +21,13 @@
|
||||
*.vpwhistu
|
||||
*.vtg
|
||||
*.xcodeproj
|
||||
*.xcworkspace
|
||||
*_proto.xml
|
||||
*_proto_cpp.xml
|
||||
*~
|
||||
.*.sw?
|
||||
.cipd
|
||||
.clangd
|
||||
.classpath
|
||||
.cproject
|
||||
.gdb_history
|
||||
@ -39,132 +42,32 @@
|
||||
/base
|
||||
/build
|
||||
/buildtools
|
||||
/chromium/.gclient.tmp
|
||||
/chromium/.gclient.tmp_entries
|
||||
/chromium/.last_sync_chromium
|
||||
/chromium/_bad_scm
|
||||
/chromium/src
|
||||
/gyp-mac-tool
|
||||
/links
|
||||
/links.db
|
||||
/ios
|
||||
/mojo
|
||||
/out
|
||||
/resources/**/*.aecdump
|
||||
/resources/**/*.bin
|
||||
/resources/**/*.chn
|
||||
/resources/**/*.dat
|
||||
/resources/**/*.gai
|
||||
/resources/**/*.jpg
|
||||
/resources/**/*.pcap
|
||||
/resources/**/*.pcm
|
||||
/resources/**/*.rtp
|
||||
/resources/**/*.rx
|
||||
/resources/**/*.wav
|
||||
/resources/**/*.yuv
|
||||
/resources/**/*.BIT*
|
||||
/resources/**/*.INP
|
||||
/resources/**/*.OUT*
|
||||
/talk/examples/android/bin
|
||||
/talk/examples/android/gen
|
||||
/talk/examples/android/libs
|
||||
/talk/examples/android/local.properties
|
||||
/talk/examples/android/obj
|
||||
/talk/examples/android/proguard-project.txt
|
||||
/talk/examples/androidtests/bin
|
||||
/talk/examples/androidtests/gen
|
||||
/talk/app/webrtc/androidtests/bin
|
||||
/talk/app/webrtc/androidtests/gen
|
||||
/talk/app/webrtc/androidtests/libs
|
||||
/testing
|
||||
/third_party/WebKit/Tools/Scripts
|
||||
/third_party/android_platform
|
||||
/third_party/android_tools
|
||||
/third_party/appurify-python
|
||||
/third_party/asan
|
||||
/third_party/ashmem
|
||||
/third_party/binutils
|
||||
/third_party/boringssl
|
||||
/third_party/BUILD.gn
|
||||
/third_party/catapult
|
||||
/third_party/clang_format
|
||||
/third_party/class-dump
|
||||
/third_party/colorama
|
||||
/third_party/cygwin
|
||||
/third_party/directxsdk
|
||||
/third_party/drmemory
|
||||
/third_party/expat
|
||||
/third_party/ffmpeg
|
||||
/third_party/gaeunit
|
||||
/third_party/gflags/src
|
||||
/third_party/google-visualization-python
|
||||
/third_party/icu
|
||||
/third_party/instrumented_libraries
|
||||
/third_party/ijar
|
||||
/third_party/jsoncpp
|
||||
/third_party/jsr-305
|
||||
/third_party/junit
|
||||
/third_party/junit-jar
|
||||
/third_party/libc++
|
||||
/third_party/libc++-static
|
||||
/third_party/libc++abi
|
||||
/third_party/libevent
|
||||
/third_party/libjingle
|
||||
/third_party/libjpeg
|
||||
/third_party/libjpeg_turbo
|
||||
/third_party/libsrtp
|
||||
/third_party/libvpx_new
|
||||
/third_party/libxml
|
||||
/third_party/libudev
|
||||
/third_party/libyuv
|
||||
/third_party/llvm
|
||||
/third_party/llvm-build
|
||||
/third_party/lss
|
||||
/third_party/mockito
|
||||
/third_party/modp_b64
|
||||
/third_party/nss
|
||||
/third_party/oauth2
|
||||
/third_party/ocmock
|
||||
/third_party/openh264
|
||||
/third_party/openmax_dl
|
||||
/third_party/opus
|
||||
/third_party/proguard
|
||||
/third_party/protobuf
|
||||
/third_party/requests
|
||||
/third_party/robolectric
|
||||
/third_party/sqlite
|
||||
/third_party/syzygy
|
||||
/third_party/usrsctp
|
||||
/third_party/valgrind
|
||||
/third_party/WebKit
|
||||
/third_party/winsdk_samples/src
|
||||
/third_party/yasm
|
||||
/third_party/zlib
|
||||
/tools/android
|
||||
/tools/clang
|
||||
/tools/generate_library_loader
|
||||
/tools/gn
|
||||
/tools/grit
|
||||
/tools/gyp
|
||||
/tools/isolate_driver.py
|
||||
/tools/memory
|
||||
/tools/protoc_wrapper
|
||||
/tools/python
|
||||
/tools/sanitizer_options
|
||||
/tools/swarming_client
|
||||
/tools/telemetry
|
||||
/tools/tsan_suppressions
|
||||
/tools/valgrind
|
||||
/tools/vim
|
||||
/tools/win
|
||||
/tools/xdisplaycheck
|
||||
/tools/whitespace.txt
|
||||
/webrtc/examples/android/opensl_loopback/bin
|
||||
/webrtc/examples/android/opensl_loopback/gen
|
||||
/webrtc/examples/android/opensl_loopback/libs
|
||||
/webrtc/examples/android/opensl_loopback/local.properties
|
||||
/webrtc/examples/android/opensl_loopback/obj
|
||||
/webrtc/examples/android/opensl_loopback/proguard-project.txt
|
||||
/webrtc/modules/audio_device/android/test/bin/
|
||||
/webrtc/modules/audio_device/android/test/gen/
|
||||
/webrtc/modules/audio_device/android/test/libs/
|
||||
/third_party
|
||||
/tools
|
||||
/tools_webrtc/android/profiling/flamegraph
|
||||
/tools_webrtc/android/profiling/simpleperf
|
||||
/tools_webrtc/audio_quality/linux/pesq
|
||||
/tools_webrtc/audio_quality/linux/PolqaOem64
|
||||
/tools_webrtc/audio_quality/mac/pesq
|
||||
/tools_webrtc/audio_quality/win/*.exe
|
||||
/tools_webrtc/audio_quality/win/*.dll
|
||||
/tools_webrtc/video_quality_toolchain/linux/ffmpeg
|
||||
/tools_webrtc/video_quality_toolchain/linux/zxing
|
||||
/tools_webrtc/video_quality_toolchain/mac/ffmpeg
|
||||
/tools_webrtc/video_quality_toolchain/mac/zxing
|
||||
/tools_webrtc/video_quality_toolchain/win/*.dll
|
||||
/tools_webrtc/video_quality_toolchain/win/*.exe
|
||||
/rtc_tools/testing/*.zip
|
||||
/rtc_tools/testing/*.gz
|
||||
/rtc_tools/testing/golang/*/*.gz
|
||||
/rtc_tools/testing/golang/*/*.zip
|
||||
/rtc_tools/testing/webrtc_apprtc_browsertest/*
|
||||
/rtc_tools/testing/browsertest/*
|
||||
/x86-generic_out/
|
||||
/xcodebuild
|
||||
/.vscode
|
||||
!webrtc/*
|
||||
|
79
.gn
79
.gn
@ -6,6 +6,8 @@
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("//build/dotfile_settings.gni")
|
||||
|
||||
# The location of the build configuration file.
|
||||
buildconfig = "//build/config/BUILDCONFIG.gn"
|
||||
|
||||
@ -18,32 +20,59 @@ secondary_source = "//build/secondary/"
|
||||
# matching these patterns (see "gn help label_pattern" for format) will have
|
||||
# their includes checked for proper dependencies when you run either
|
||||
# "gn check" or "gn gen --check".
|
||||
check_targets = [ "//webrtc/*" ]
|
||||
check_targets = [
|
||||
":webrtc_common",
|
||||
"//api/*",
|
||||
"//audio/*",
|
||||
"//backup/*",
|
||||
"//call/*",
|
||||
"//common_audio/*",
|
||||
"//common_video/*",
|
||||
"//examples/*",
|
||||
"//logging/*",
|
||||
"//media/*",
|
||||
"//modules/*",
|
||||
"//p2p/*",
|
||||
"//pc/*",
|
||||
"//rtc_base/*",
|
||||
"//rtc_tools/*",
|
||||
"//sdk/*",
|
||||
"//stats/*",
|
||||
"//system_wrappers/*",
|
||||
"//test/*",
|
||||
"//video/*",
|
||||
"//third_party/libyuv/*",
|
||||
]
|
||||
|
||||
# These are the list of GN files that run exec_script. This whitelist exists
|
||||
# to force additional review for new uses of exec_script, which is strongly
|
||||
# discouraged except for gypi_to_gn calls.
|
||||
exec_script_whitelist = [
|
||||
"//build/config/android/BUILD.gn",
|
||||
"//build/config/android/config.gni",
|
||||
"//build/config/android/internal_rules.gni",
|
||||
"//build/config/android/rules.gni",
|
||||
"//build/config/compiler/BUILD.gn",
|
||||
"//build/config/gcc/gcc_version.gni",
|
||||
"//build/config/ios/ios_sdk.gni",
|
||||
"//build/config/linux/BUILD.gn",
|
||||
"//build/config/linux/pkg_config.gni",
|
||||
"//build/config/mac/mac_sdk.gni",
|
||||
"//build/config/posix/BUILD.gn",
|
||||
"//build/config/sysroot.gni",
|
||||
"//build/config/win/visual_studio_version.gni",
|
||||
"//build/gn_helpers.py",
|
||||
"//build/gypi_to_gn.py",
|
||||
"//build/toolchain/gcc_toolchain.gni",
|
||||
"//build/toolchain/mac/BUILD.gn",
|
||||
"//build/toolchain/win/BUILD.gn",
|
||||
"//third_party/boringssl/BUILD.gn",
|
||||
"//third_party/openh264/BUILD.gn",
|
||||
"//third_party/opus/BUILD.gn",
|
||||
"//webrtc/modules/video_render/BUILD.gn",
|
||||
]
|
||||
exec_script_whitelist = build_dotfile_settings.exec_script_whitelist +
|
||||
[ "//build_overrides/build.gni" ]
|
||||
|
||||
default_args = {
|
||||
# Webrtc does not support component builds because we are not using the
|
||||
# template "component" but we rely directly on "rtc_static_library" and
|
||||
# "rtc_shared_library". This means that we cannot use the chromium default
|
||||
# value for this argument.
|
||||
# This also means that the user can override this value using --args or
|
||||
# the args.gn file but this setting will be ignored because we don't support
|
||||
# component builds.
|
||||
is_component_build = false
|
||||
|
||||
mac_sdk_min = "10.12"
|
||||
|
||||
ios_deployment_target = "10.0"
|
||||
|
||||
# The SDK API level, in contrast, is set by build/android/AndroidManifest.xml.
|
||||
android32_ndk_api_level = 16
|
||||
android64_ndk_api_level = 21
|
||||
|
||||
# WebRTC does not provide the gflags dependency. Because libyuv uses it only
|
||||
# for unittests, it can be disabled (see third_party/libyuv/BUILD.gn)
|
||||
libyuv_use_gflags = false
|
||||
|
||||
enable_libaom = true
|
||||
|
||||
gtest_enable_absl_printers = true
|
||||
}
|
||||
|
68
.vpython
Normal file
68
.vpython
Normal file
@ -0,0 +1,68 @@
|
||||
# This is a vpython "spec" file.
|
||||
#
|
||||
# It describes patterns for python wheel dependencies of the python scripts in
|
||||
# the chromium repo, particularly for dependencies that have compiled components
|
||||
# (since pure-python dependencies can be easily vendored into third_party).
|
||||
#
|
||||
# When vpython is invoked, it finds this file and builds a python VirtualEnv,
|
||||
# containing all of the dependencies described in this file, fetching them from
|
||||
# CIPD (the "Chrome Infrastructure Package Deployer" service). Unlike `pip`,
|
||||
# this never requires the end-user machine to have a working python extension
|
||||
# compilation environment. All of these packages are built using:
|
||||
# https://chromium.googlesource.com/infra/infra/+/master/infra/tools/dockerbuild/
|
||||
#
|
||||
# All python scripts in the repo share this same spec, to avoid dependency
|
||||
# fragmentation.
|
||||
#
|
||||
# If you have depot_tools installed in your $PATH, you can invoke python scripts
|
||||
# in this repo by running them as you normally would run them, except
|
||||
# substituting `vpython` instead of `python` on the command line, e.g.:
|
||||
# vpython path/to/script.py some --arguments
|
||||
#
|
||||
# Read more about `vpython` and how to modify this file here:
|
||||
# https://chromium.googlesource.com/infra/infra/+/master/doc/users/vpython.md
|
||||
|
||||
python_version: "2.7"
|
||||
|
||||
# Used by:
|
||||
# third_party/catapult
|
||||
wheel: <
|
||||
name: "infra/python/wheels/psutil/${platform}_${py_python}_${py_abi}"
|
||||
version: "version:5.2.2"
|
||||
>
|
||||
|
||||
# Used by tools_webrtc/perf/webrtc_dashboard_upload.py.
|
||||
wheel: <
|
||||
name: "infra/python/wheels/httplib2-py2_py3"
|
||||
version: "version:0.10.3"
|
||||
>
|
||||
|
||||
# Used by:
|
||||
# build/toolchain/win
|
||||
wheel: <
|
||||
name: "infra/python/wheels/pypiwin32/${vpython_platform}"
|
||||
version: "version:219"
|
||||
match_tag: <
|
||||
platform: "win32"
|
||||
>
|
||||
match_tag: <
|
||||
platform: "win_amd64"
|
||||
>
|
||||
>
|
||||
|
||||
wheel: <
|
||||
name: "infra/python/wheels/six-py2_py3"
|
||||
version: "version:1.10.0"
|
||||
>
|
||||
wheel: <
|
||||
name: "infra/python/wheels/pbr-py2_py3"
|
||||
version: "version:3.0.0"
|
||||
>
|
||||
wheel: <
|
||||
name: "infra/python/wheels/funcsigs-py2_py3"
|
||||
version: "version:1.0.2"
|
||||
>
|
||||
wheel: <
|
||||
name: "infra/python/wheels/mock-py2_py3"
|
||||
version: "version:2.0.0"
|
||||
>
|
106
AUTHORS
106
AUTHORS
@ -1,50 +1,126 @@
|
||||
# Names should be added to this file like so:
|
||||
# Name or Organization <email address>
|
||||
|
||||
Adam Fedor <adam.fedor@gmail.com>
|
||||
Akshay Shah <meetakshay99@gmail.com>
|
||||
Alex Henrie <alexhenrie24@gmail.com>
|
||||
Alexander Brauckmann <a.brauckmann@gmail.com>
|
||||
Alexandre Gouaillard <agouaillard@gmail.com>
|
||||
Andrew MacDonald <andrew@webrtc.org>
|
||||
Andrey Efremov <yoklmnprst@ya.ru>
|
||||
Anil Kumar <an1kumar@gmail.com>
|
||||
Ben Strong <bstrong@gmail.com>
|
||||
Bob Withers <bwit@pobox.com>
|
||||
Bridger Maxwell <bridgeyman@gmail.com>
|
||||
Chris Tserng <tserng@amazon.com>
|
||||
Christophe Dumez <ch.dumez@samsung.com>
|
||||
Cody Barnes <conceptgenesis@gmail.com>
|
||||
Colin Plumb
|
||||
Cyril Lashkevich <notorca@gmail.com>
|
||||
David Porter <david@porter.me>
|
||||
Dax Booysen <dax@younow.com>
|
||||
Danail Kirov <dkirovbroadsoft@gmail.com>
|
||||
Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
Dmitry Lizin <sdkdimon@gmail.com>
|
||||
Eric Rescorla, RTFM Inc. <ekr@rtfm.com>
|
||||
Frederik Riedel, Frogg GmbH <frederik.riedel@frogg.io>
|
||||
Giji Gangadharan <giji.g@samsung.com>
|
||||
Graham Yoakum <gyoakum@skobalt.com>
|
||||
Gustavo Garcia <gustavogb@gmail.com>
|
||||
Hugues Ekra <hekra01@gmail.com>
|
||||
Jake Hilton <jakehilton@gmail.com>
|
||||
James H. Brown <jbrown@burgoyne.com>
|
||||
Jan Kalab <pitlicek@gmail.com>
|
||||
Jens Nielsen <jens.nielsen@berotec.se>
|
||||
Jiawei Ou <jiawei.ou@gmail.com>
|
||||
Jie Mao <maojie0924@gmail.com>
|
||||
Jose Antonio Olivera Ortega <josea.olivera@gmail.com>
|
||||
Kiran Thind <kiran.thind@gmail.com>
|
||||
Luke Weber <luke.weber@gmail.com>
|
||||
Maksim Khobat <maksimkhobat@gmail.com>
|
||||
Mallikarjuna Rao V <vm.arjun@samsung.com>
|
||||
Manish Jethani <manish.jethani@gmail.com>
|
||||
Martin Storsjo <martin@martin.st>
|
||||
Matthias Liebig <matthias.gcode@gmail.com>
|
||||
Maxim Potapov <vopatop.skam@gmail.com>
|
||||
Michael Iedema <michael@kapsulate.com>
|
||||
Mike Gilbert <floppymaster@gmail.com>
|
||||
Mo Zanaty <mzanaty@cisco.com>
|
||||
Pali Rohar
|
||||
Paul Kapustin <pkapustin@gmail.com>
|
||||
Philipp Hancke <philipp.hancke@googlemail.com>
|
||||
Peng Yu <yupeng323@gmail.com>
|
||||
Rafael Lopez Diez <rafalopezdiez@gmail.com>
|
||||
Ralph Giles <giles@ghostscript.com>
|
||||
Riku Voipio <riku.voipio@linaro.org>
|
||||
Robert Bares <robert@bares.me>
|
||||
Robert Nagy <robert.nagy@gmail.com>
|
||||
Ryan Yoakum <ryoakum@skobalt.com>
|
||||
Satender Saroha <ssaroha@yahoo.com>
|
||||
Sarah Thompson <sarah@telergy.com>
|
||||
Saul Kravitz <Saul.Kravitz@celera.com>
|
||||
Silviu Caragea <silviu.cpp@gmail.com>
|
||||
Stefan Gula <steweg@gmail.com>
|
||||
Steve Reid <sreid@sea-to-sky.net>
|
||||
Tarun Chawla <trnkumarchawla@gmail.com>
|
||||
Trevor Hayes <trevor.axiom@gmail.com>
|
||||
Uladzislau Susha <landby@gmail.com>
|
||||
Vladimir Beloborodov <VladimirTechMan@gmail.com>
|
||||
Vicken Simonian <vsimon@gmail.com>
|
||||
Victor Costan <costan@gmail.com>
|
||||
Alexander Brauckmann <a.brauckmann@gmail.com>
|
||||
Xiaohong Xu <freemine@yeah.net>
|
||||
Xiaolei Yu <dreifachstein@gmail.com>
|
||||
Yura Yaroshevich <yura.yaroshevich@gmail.com>
|
||||
Yuriy Pavlyshak <yuriy@appear.in>
|
||||
Hans Knoechel <hans@hans-knoechel.de>
|
||||
Korniltsev Anatoly <korniltsev.anatoly@gmail.com>
|
||||
Todd Wong <todd.wong.ndq@gmail.com>
|
||||
Sergio Garcia Murillo <sergio.garcia.murillo@gmail.com>
|
||||
Maxim Pavlov <pavllovmax@gmail.com>
|
||||
Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
Piasy Xu <xz4215@gmail.com>
|
||||
Tomas Popela <tomas.popela@gmail.com>
|
||||
Jan Grulich <grulja@gmail.com>
|
||||
Jiwon Kim <jwkim0000@gmail.com>
|
||||
Eike Rathke <erathke@redhat.com>
|
||||
Michel Promonet <michel.promonet.1@gmail.com>
|
||||
Min Wang <mingewang@gmail.com>
|
||||
Ramprakash Jelari <ennajelari@gmail.com>
|
||||
CZ Theng <cz.theng@gmail.com>
|
||||
Miguel Paris <mparisdiaz@gmail.com>
|
||||
Raman Budny <budnyjj@gmail.com>
|
||||
Stephan Hartmann <stha09@googlemail.com>
|
||||
|
||||
&yet LLC
|
||||
Agora IO
|
||||
ARM Holdings
|
||||
BroadSoft Inc.
|
||||
Google Inc.
|
||||
Intel Corporation
|
||||
MIPS Technologies
|
||||
Mozilla Foundation
|
||||
Opera Software ASA
|
||||
Sinch AB
|
||||
struktur AG
|
||||
Telenor Digital AS
|
||||
Temasys Communications
|
||||
Vonage Holdings Corp.
|
||||
&yet LLC <*@andyet.com>
|
||||
Agora IO <*@agora.io>
|
||||
ARM Holdings <*@arm.com>
|
||||
BroadSoft Inc. <*@broadsoft.com>
|
||||
Facebook Inc. <*@fb.com>
|
||||
Google Inc. <*@google.com>
|
||||
HyperConnect Inc. <*@hpcnt.com>
|
||||
Life On Air Inc. <*@lifeonair.com>
|
||||
Intel Corporation <*@intel.com>
|
||||
Microsoft Corporation <*@microsoft.com>
|
||||
MIPS Technologies <*@mips.com>
|
||||
Mozilla Foundation <*@mozilla.com>
|
||||
NVIDIA Corporation <*@nvidia.com>
|
||||
Opera Software ASA <*@opera.com>
|
||||
Optical Tone Ltd <*@opticaltone.com>
|
||||
Pengutronix e.K. <*@pengutronix.de>
|
||||
RingCentral, Inc. <*@ringcentral.com>
|
||||
Sinch AB <*@sinch.com>
|
||||
struktur AG <*@struktur.de>
|
||||
Telenor Digital AS <*@telenor.com>
|
||||
Temasys Communications <*@temasys.io>
|
||||
The Chromium Authors <*@chromium.org>
|
||||
The WebRTC Authors <*@webrtc.org>
|
||||
Twilio, Inc. <*@twilio.com>
|
||||
Videxio AS <*@videxio.com>
|
||||
Vidyo, Inc. <*@vidyo.com>
|
||||
Vonage Holdings Corp. <*@vonage.com>
|
||||
Wire Swiss GmbH <*@wire.com>
|
||||
Vewd Software AS <*@vewd.com>
|
||||
Highfive, Inc. <*@highfive.com>
|
||||
CoSMo Software Consulting, Pte Ltd <*@cosmosoftware.io>
|
||||
Tuple, LLC <*@tuple.app>
|
||||
Videona Socialmedia <*@videona.com>
|
||||
|
167
Android.bp
167
Android.bp
@ -1,167 +0,0 @@
|
||||
// Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
// These defines will apply to all source files
|
||||
// Think again before changing it
|
||||
cc_defaults {
|
||||
name: "webrtc_flags",
|
||||
vendor: true,
|
||||
|
||||
cflags: [
|
||||
"-DWEBRTC_POSIX",
|
||||
"-DWEBRTC_LINUX",
|
||||
"-DWEBRTC_THREAD_RR",
|
||||
"-DWEBRTC_CLOCK_TYPE_REALTIME",
|
||||
"-DWEBRTC_ANDROID",
|
||||
|
||||
// The following macros are used by modules,
|
||||
// we might need to re-organize them
|
||||
// "-DWEBRTC_ANDROID_OPENSLES", // [module audio_device]
|
||||
// "-DNETEQ_VOICEENGINE_CODECS", // [module audio_coding neteq]
|
||||
// "-DWEBRTC_MODULE_UTILITY_VIDEO", // [module media_file] [module utility]
|
||||
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
// The following warnings are disabled in most webrtc modules,
|
||||
// until we upgrade to newer cleaner upstream webrtc.
|
||||
"-Wno-missing-braces",
|
||||
"-Wno-missing-field-initializers",
|
||||
"-Wno-unused-parameter",
|
||||
],
|
||||
|
||||
header_libs: ["libwebrtc_headers"],
|
||||
|
||||
arch: {
|
||||
arm: {
|
||||
instruction_set: "arm",
|
||||
|
||||
cflags: [
|
||||
"-DWEBRTC_ARCH_ARM",
|
||||
// "-DWEBRTC_DETECT_ARM_NEON", // only used in a build configuration without Neon
|
||||
// TODO(kma): figure out if the above define could be moved to NDK build only.
|
||||
|
||||
// The following upstram ARM_NEON and ARMV7A defintions do not work on AOSP yet.
|
||||
// They should be fixed in the next merge from upstream.
|
||||
//# TODO(kma): test if the code under next two macros works with generic GCC compilers
|
||||
// "-DWEBRTC_ARCH_ARM_NEON",
|
||||
// "-flax-vector-conversions",
|
||||
// "-DWEBRTC_ARCH_ARM_V7A",
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
// The following clang-tidy checks are disabled in most webrtc modules,
|
||||
// until we upgrade to newer cleaner upstream webrtc.
|
||||
tidy_checks: [
|
||||
"-cert-*",
|
||||
"-clang-analyzer-*",
|
||||
"-hicpp-*",
|
||||
"-llvm-*",
|
||||
"-google-build-namespaces",
|
||||
"-google-default-arguments",
|
||||
"-google-explicit-constructor",
|
||||
"-google-runtime-int",
|
||||
"-google-runtime-operator",
|
||||
"-misc-incorrect-roundings",
|
||||
"-misc-macro-parentheses",
|
||||
"-misc-misplaced-widening-cast",
|
||||
"-misc-noexcept-move-constructor",
|
||||
"-misc-suspicious-string-compare",
|
||||
"-misc-unused-parameters",
|
||||
"-misc-unused-using-decls",
|
||||
"-performance-type-promotion-in-math-fn",
|
||||
"-performance-unnecessary-copy-initialization",
|
||||
"-performance-unnecessary-value-param",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libwebrtc_audio_preprocessing",
|
||||
vendor: true,
|
||||
|
||||
export_include_dirs: [
|
||||
".",
|
||||
"webrtc/modules/include",
|
||||
"webrtc/modules/audio_processing/include",
|
||||
],
|
||||
|
||||
whole_static_libs: [
|
||||
"libwebrtc_aec",
|
||||
"libwebrtc_aecm",
|
||||
"libwebrtc_agc",
|
||||
"libwebrtc_apm",
|
||||
"libwebrtc_apm_utility",
|
||||
"libwebrtc_apvad",
|
||||
"libwebrtc_base",
|
||||
"libwebrtc_beamformer",
|
||||
"libwebrtc_common",
|
||||
"libwebrtc_intell",
|
||||
"libwebrtc_isac",
|
||||
"libwebrtc_resampler",
|
||||
"libwebrtc_ns",
|
||||
"libwebrtc_spl",
|
||||
"libwebrtc_system_wrappers",
|
||||
"libwebrtc_transient",
|
||||
"libwebrtc_vad",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"liblog",
|
||||
"libcutils",
|
||||
"libdl",
|
||||
"libprotobuf-cpp-lite",
|
||||
],
|
||||
|
||||
arch: {
|
||||
arm: {
|
||||
instruction_set: "arm",
|
||||
},
|
||||
},
|
||||
|
||||
// Disable native_coverage since linking fails with -O0 (needed for
|
||||
// coverage). The fix is to mark InStream::Rewind and OutStream::Rewind as
|
||||
// pure virtual in webrtc/common_types.h
|
||||
native_coverage: false,
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libwebrtc_audio_coding",
|
||||
vendor: true,
|
||||
|
||||
whole_static_libs: [
|
||||
"libwebrtc_base",
|
||||
"libwebrtc_common",
|
||||
"libwebrtc_intell",
|
||||
"libwebrtc_isac",
|
||||
"libwebrtc_isacfix",
|
||||
"libwebrtc_resampler",
|
||||
"libwebrtc_spl",
|
||||
"libwebrtc_system_wrappers",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libprotobuf-cpp-lite",
|
||||
"liblog",
|
||||
"libcutils",
|
||||
"libdl",
|
||||
],
|
||||
|
||||
arch: {
|
||||
arm: {
|
||||
instruction_set: "arm",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "libwebrtc_headers",
|
||||
vendor: true,
|
||||
export_include_dirs: ["."],
|
||||
}
|
||||
|
||||
subdirs = ["webrtc/*"]
|
@ -1,5 +0,0 @@
|
||||
# Intentially empty, to prevent recursion
|
||||
#
|
||||
# There is an NDK test under modules/audio_procesing/test. The NDK build system
|
||||
# uses Android.mk files too, but they're not compatible with the Platform
|
||||
# Android.mk files.
|
715
BUILD.gn
715
BUILD.gn
@ -6,9 +6,714 @@
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
# This file is copied and modified from Chromium (src/BUILD.gn).
|
||||
group("root") {
|
||||
deps = [
|
||||
"//webrtc",
|
||||
]
|
||||
# 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.
|
||||
|
||||
import("//build/config/linux/pkg_config.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")
|
||||
}
|
||||
|
||||
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",
|
||||
":slow_tests",
|
||||
":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",
|
||||
"pc:peerconnection_unittests",
|
||||
"pc:rtc_pc_unittests",
|
||||
"rtc_tools:rtp_generator",
|
||||
"rtc_tools:video_replay",
|
||||
"stats:rtc_stats_unittests",
|
||||
"system_wrappers:system_wrappers_unittests",
|
||||
"test",
|
||||
"video:screenshare_loopback",
|
||||
"video:sv_loopback",
|
||||
"video:video_loopback",
|
||||
]
|
||||
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_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 += [
|
||||
"audio:low_bandwidth_audio_test",
|
||||
"logging:rtc_event_log_rtp_dump",
|
||||
"tools_webrtc/perf:webrtc_dashboard_upload",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 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 = []
|
||||
cflags = []
|
||||
ldflags = []
|
||||
|
||||
if (rtc_enable_symbol_export || is_component_build) {
|
||||
defines = [ "WEBRTC_ENABLE_SYMBOL_EXPORT" ]
|
||||
}
|
||||
|
||||
if (build_with_mozilla) {
|
||||
defines += [ "WEBRTC_MOZILLA_BUILD" ]
|
||||
}
|
||||
|
||||
if (!rtc_builtin_ssl_root_certificates) {
|
||||
defines += [ "WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS" ]
|
||||
}
|
||||
|
||||
if (rtc_disable_check_msg) {
|
||||
defines += [ "RTC_DISABLE_CHECK_MSG" ]
|
||||
}
|
||||
|
||||
# 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" ]
|
||||
include_dirs = [
|
||||
# The overrides must be included first as that is the mechanism for
|
||||
# selecting the override headers in Chromium.
|
||||
"../webrtc_overrides",
|
||||
|
||||
# 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 || is_fuchsia) {
|
||||
defines += [ "WEBRTC_POSIX" ]
|
||||
}
|
||||
if (is_ios) {
|
||||
defines += [
|
||||
"WEBRTC_MAC",
|
||||
"WEBRTC_IOS",
|
||||
]
|
||||
}
|
||||
if (is_linux) {
|
||||
defines += [ "WEBRTC_LINUX" ]
|
||||
}
|
||||
if (is_mac) {
|
||||
defines += [ "WEBRTC_MAC" ]
|
||||
}
|
||||
if (is_fuchsia) {
|
||||
defines += [ "WEBRTC_FUCHSIA" ]
|
||||
}
|
||||
if (is_win) {
|
||||
defines += [ "WEBRTC_WIN" ]
|
||||
}
|
||||
if (is_android) {
|
||||
defines += [
|
||||
"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" ]
|
||||
}
|
||||
}
|
||||
|
||||
# TODO(bugs.webrtc.org/9693): Remove the possibility to suppress this warning
|
||||
# as soon as WebRTC compiles without it.
|
||||
config("no_exit_time_destructors") {
|
||||
if (is_clang) {
|
||||
cflags = [ "-Wno-exit-time-destructors" ]
|
||||
}
|
||||
}
|
||||
|
||||
# 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",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
config("common_config") {
|
||||
cflags = []
|
||||
cflags_c = []
|
||||
cflags_cc = []
|
||||
cflags_objc = []
|
||||
defines = []
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
defines += [ "WEBRTC_ENABLE_PROTOBUF=1" ]
|
||||
} else {
|
||||
defines += [ "WEBRTC_ENABLE_PROTOBUF=0" ]
|
||||
}
|
||||
|
||||
if (rtc_include_internal_audio_device) {
|
||||
defines += [ "WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE" ]
|
||||
}
|
||||
|
||||
if (rtc_libvpx_build_vp9) {
|
||||
defines += [ "RTC_ENABLE_VP9" ]
|
||||
}
|
||||
|
||||
if (rtc_enable_sctp) {
|
||||
defines += [ "HAVE_SCTP" ]
|
||||
}
|
||||
|
||||
if (rtc_enable_external_auth) {
|
||||
defines += [ "ENABLE_EXTERNAL_AUTH" ]
|
||||
}
|
||||
|
||||
if (rtc_use_h264) {
|
||||
defines += [ "WEBRTC_USE_H264" ]
|
||||
}
|
||||
|
||||
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_transient_suppressor) {
|
||||
defines += [ "WEBRTC_EXCLUDE_TRANSIENT_SUPPRESSOR" ]
|
||||
}
|
||||
|
||||
if (rtc_exclude_audio_processing_module) {
|
||||
defines += [ "WEBRTC_EXCLUDE_AUDIO_PROCESSING_MODULE" ]
|
||||
}
|
||||
|
||||
cflags = []
|
||||
|
||||
if (build_with_chromium) {
|
||||
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",
|
||||
|
||||
# This is enabled for clang; enable for gcc as well.
|
||||
"-Woverloaded-virtual",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_clang) {
|
||||
cflags += [
|
||||
"-Wc++11-narrowing",
|
||||
"-Wimplicit-fallthrough",
|
||||
"-Wthread-safety",
|
||||
"-Winconsistent-missing-override",
|
||||
"-Wundef",
|
||||
]
|
||||
|
||||
# use_xcode_clang only refers to the iOS toolchain, host binaries use
|
||||
# chromium's clang always.
|
||||
if (!is_nacl &&
|
||||
(!use_xcode_clang || current_toolchain == host_toolchain)) {
|
||||
# Flags NaCl (Clang 3.7) and Xcode 7.3 (Clang clang-703.0.31) do not
|
||||
# recognize.
|
||||
cflags += [ "-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
|
||||
}
|
||||
}
|
||||
|
||||
if (current_cpu == "arm64") {
|
||||
defines += [ "WEBRTC_ARCH_ARM64" ]
|
||||
defines += [ "WEBRTC_HAS_NEON" ]
|
||||
}
|
||||
|
||||
if (current_cpu == "arm") {
|
||||
defines += [ "WEBRTC_ARCH_ARM" ]
|
||||
if (arm_version >= 7) {
|
||||
defines += [ "WEBRTC_ARCH_ARM_V7" ]
|
||||
if (arm_use_neon) {
|
||||
defines += [ "WEBRTC_HAS_NEON" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current_cpu == "mipsel") {
|
||||
defines += [ "MIPS32_LE" ]
|
||||
if (mips_float_abi == "hard") {
|
||||
defines += [ "MIPS_FPU_LE" ]
|
||||
}
|
||||
if (mips_arch_variant == "r2") {
|
||||
defines += [ "MIPS32_R2_LE" ]
|
||||
}
|
||||
if (mips_dsp_rev == 1) {
|
||||
defines += [ "MIPS_DSP_R1_LE" ]
|
||||
} else if (mips_dsp_rev == 2) {
|
||||
defines += [
|
||||
"MIPS_DSP_R1_LE",
|
||||
"MIPS_DSP_R2_LE",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_android && !is_clang) {
|
||||
# The Android NDK doesn"t provide optimized versions of these
|
||||
# functions. Ensure they are disabled for all compilers.
|
||||
cflags += [
|
||||
"-fno-builtin-cos",
|
||||
"-fno-builtin-sin",
|
||||
"-fno-builtin-cosf",
|
||||
"-fno-builtin-sinf",
|
||||
]
|
||||
}
|
||||
|
||||
if (use_fuzzing_engine && optimize_for_fuzzing) {
|
||||
# Used in Chromium's overrides to disable logging
|
||||
defines += [ "WEBRTC_UNSAFE_FUZZER_MODE" ]
|
||||
}
|
||||
|
||||
if (!build_with_chromium && rtc_win_undef_unicode) {
|
||||
cflags += [
|
||||
"/UUNICODE",
|
||||
"/U_UNICODE",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
config("common_objc") {
|
||||
libs = [ "Foundation.framework" ]
|
||||
|
||||
if (rtc_use_metal_rendering) {
|
||||
defines = [ "RTC_SUPPORTS_METAL" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (!build_with_chromium) {
|
||||
# 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 = [
|
||||
":webrtc_common",
|
||||
"api:create_peerconnection_factory",
|
||||
"api:libjingle_peerconnection_api",
|
||||
"api:rtc_error",
|
||||
"api:transport_api",
|
||||
"api/crypto",
|
||||
"api/rtc_event_log:rtc_event_log_factory",
|
||||
"api/task_queue",
|
||||
"api/task_queue:default_task_queue_factory",
|
||||
"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:peerconnection",
|
||||
"pc:rtc_pc",
|
||||
"pc:rtc_pc_base",
|
||||
"rtc_base",
|
||||
"sdk",
|
||||
"video",
|
||||
]
|
||||
|
||||
if (rtc_include_builtin_audio_codecs) {
|
||||
deps += [
|
||||
"api/audio_codecs:builtin_audio_decoder_factory",
|
||||
"api/audio_codecs:builtin_audio_encoder_factory",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_include_builtin_video_codecs) {
|
||||
deps += [
|
||||
"api/video_codecs:builtin_video_decoder_factory",
|
||||
"api/video_codecs:builtin_video_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
|
||||
|
||||
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",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rtc_source_set("webrtc_common") {
|
||||
# Client code SHOULD NOT USE THIS TARGET, but for now it needs to be public
|
||||
# because there exists client code that uses it.
|
||||
# TODO(bugs.webrtc.org/9808): Move to private visibility as soon as that
|
||||
# client code gets updated.
|
||||
visibility = [ "*" ]
|
||||
sources = [ "common_types.h" ]
|
||||
}
|
||||
|
||||
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) {
|
||||
rtc_test("rtc_unittests") {
|
||||
testonly = true
|
||||
|
||||
deps = [
|
||||
":webrtc_common",
|
||||
"api:compile_all_headers",
|
||||
"api:rtc_api_unittests",
|
||||
"api/audio/test:audio_api_unittests",
|
||||
"api/audio_codecs/test:audio_codecs_api_unittests",
|
||||
"api/transport:stun_unittest",
|
||||
"api/video/test:rtc_api_video_unittests",
|
||||
"api/video_codecs/test:video_codecs_api_unittests",
|
||||
"call:fake_network_pipe_unittests",
|
||||
"p2p:libstunprober_unittests",
|
||||
"p2p:rtc_p2p_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:weak_ptr_unittests",
|
||||
"rtc_base/experiments:experiments_unittests",
|
||||
"rtc_base/synchronization:sequence_checker_unittests",
|
||||
"rtc_base/task_utils:pending_task_safety_flag_unittests",
|
||||
"rtc_base/task_utils:to_queued_task_unittests",
|
||||
"sdk:sdk_tests",
|
||||
"test:rtp_test_utils",
|
||||
"test:test_main",
|
||||
"test/network:network_emulation_unittests",
|
||||
]
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
deps += [ "logging:rtc_event_log_tests" ]
|
||||
}
|
||||
|
||||
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 (is_ios || is_mac) {
|
||||
deps += [ "sdk:rtc_unittests_objc" ]
|
||||
}
|
||||
}
|
||||
|
||||
# This runs tests that must run in real time and therefore can take some
|
||||
# time to execute. They are in a separate executable to avoid making the
|
||||
# regular unittest suite too slow to run frequently.
|
||||
rtc_test("slow_tests") {
|
||||
testonly = true
|
||||
deps = [
|
||||
"rtc_base/task_utils:repeating_task_unittests",
|
||||
"test:test_main",
|
||||
]
|
||||
}
|
||||
|
||||
# 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",
|
||||
]
|
||||
|
||||
if (is_ios) {
|
||||
bundle_data("video_engine_tests_bundle_data") {
|
||||
testonly = true
|
||||
sources = video_engine_tests_resources
|
||||
outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_test("video_engine_tests") {
|
||||
testonly = true
|
||||
deps = [
|
||||
"audio:audio_tests",
|
||||
|
||||
# TODO(eladalon): call_tests aren't actually video-specific, so we
|
||||
# should move them to a more appropriate test suite.
|
||||
"call:call_tests",
|
||||
"call/adaptation:resource_adaptation_tests",
|
||||
"test:test_common",
|
||||
"test:test_main",
|
||||
"test:video_test_common",
|
||||
"video:video_tests",
|
||||
"video/adaptation:video_adaptation_tests",
|
||||
]
|
||||
data = video_engine_tests_resources
|
||||
if (is_android) {
|
||||
deps += [ "//testing/android/native_test:native_test_native_code" ]
|
||||
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 (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 = [
|
||||
"audio:audio_perf_tests",
|
||||
"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) {
|
||||
deps += [ "//testing/android/native_test:native_test_native_code" ]
|
||||
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: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",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# ---- 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_task_queue") {
|
||||
}
|
||||
|
||||
group("poison_rtc_json") {
|
||||
}
|
||||
|
||||
group("poison_software_video_codecs") {
|
||||
}
|
||||
|
68
CODE_OF_CONDUCT.md
Normal file
68
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,68 @@
|
||||
# Contributors Code of Conduct
|
||||
|
||||
Google and the WebRTC team are committed to preserving and fostering a diverse, welcoming and open
|
||||
community. The WebRTC project is open to contributors from all walks of life and should be a
|
||||
harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender
|
||||
identity and expression, level of experience, nationality, personal appearance, race, religion, or
|
||||
sexual identity and orientation.
|
||||
|
||||
## Scope
|
||||
This Code of Conduct applies to our repos and organizations, mailing lists, blog content, and any
|
||||
other WebRTC-supported communication group, as well as any private communication initiated in the
|
||||
context of these spaces.
|
||||
|
||||
## Standards
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit
|
||||
permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Responsibilities
|
||||
|
||||
You are empowered to politely engage when you feel that you or others are disrespected. The person
|
||||
making you feel uncomfortable may not be aware of what they are doing - politely bringing their
|
||||
behavior to their attention is encouraged.
|
||||
|
||||
If you are uncomfortable speaking up, or feel that your concerns are not being duly considered, you
|
||||
can email community@webrtc.org to request involvement from a community manager. All concerns shared
|
||||
with community managers will be kept confidential. While all reports will be taken seriously, the
|
||||
WebRTC community managers may not act on complaints that they feel are not violations of this code
|
||||
of conduct.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Consequences for failing to comply with this policy may include, at the sole discretion of the
|
||||
WebRTC community managers:
|
||||
|
||||
* a request for an apology;
|
||||
* a private or public warning or reprimand;
|
||||
* a temporary ban from the mailing list, blog, WebRTC repository or organization, or other
|
||||
WebRTC-supported communication group, including loss of committer status;
|
||||
* a permanent ban from any of the above, or from all current and future WebRTC-supported or
|
||||
Google-supported communities, including loss of committer status.
|
||||
|
||||
Participants warned to stop any harassing behavior are expected to comply immediately; failure to do
|
||||
so will result in an escalation of consequences.
|
||||
|
||||
The decisions of the WebRTC community managers may be appealed via community-appeals@webrtc.org.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
This Code of Conduct is based on Contributor Covenant, version 1.4,
|
||||
available [here](http://contributor-covenant.org/version/1/4) and [Chromium](https://chromium.googlesource.com/chromium/src/+/master/CODE_OF_CONDUCT.md)
|
||||
|
||||
## License
|
||||
|
||||
This Code of Conduct is available for reuse under the Creative Commons Zero (CC0) license.
|
11
ENG_REVIEW_OWNERS
Normal file
11
ENG_REVIEW_OWNERS
Normal file
@ -0,0 +1,11 @@
|
||||
# Current list of eng reviewers mostly for the purpose of reviewing
|
||||
# dependencies on third-party directories (because //ENG_REVIEW_OWNERS is
|
||||
# included by //third_party/OWNERS).
|
||||
|
||||
# People listed in this file will only have to coordinate with chromium's eng
|
||||
# review owners to ensure that the added dependency was OK.
|
||||
|
||||
danilchap@webrtc.org
|
||||
kwiberg@webrtc.org
|
||||
mbonadei@webrtc.org
|
||||
phoglund@webrtc.org
|
30
LICENSE
30
LICENSE
@ -1 +1,29 @@
|
||||
Refer to webrtc/LICENSE.
|
||||
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 +0,0 @@
|
||||
Refer to webrtc/LICENSE_THIRD_PARTY and talk/LICENSE_THIRD_PARTY.
|
8
METADATA
8
METADATA
@ -9,11 +9,11 @@ third_party {
|
||||
type: GIT
|
||||
value: "https://webrtc.googlesource.com/src/"
|
||||
}
|
||||
version: "04cb763955aadf29324ec124b55aa399a7645d51"
|
||||
version: "cc57b935cdd19bc78352ab7e3091b2b3ad653074"
|
||||
license_type: NOTICE
|
||||
last_upgrade_date {
|
||||
year: 2016
|
||||
month: 1
|
||||
day: 14
|
||||
year: 2020
|
||||
month: 6
|
||||
day: 26
|
||||
}
|
||||
}
|
||||
|
202
NOTICE
202
NOTICE
@ -1,202 +0,0 @@
|
||||
===============================================================================
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
===============================================================================
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the 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.
|
||||
*
|
||||
* Changes by the WebRTC authors:
|
||||
* - Trivial type modifications.
|
||||
* - Minimal code subset to do rdft of length 128.
|
||||
* - Optimizations because of known length.
|
||||
*
|
||||
* All changes are covered by the WebRTC license and IP grant:
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
===============================================================================
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Changes:
|
||||
* Trivial type modifications by the WebRTC authors.
|
||||
*/
|
||||
|
||||
===============================================================================
|
||||
|
||||
/*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.*/
|
||||
|
||||
===============================================================================
|
||||
|
||||
// Copyright Steven J. Ross 2001 - 2009.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/ for updates, documentation, and revision history.
|
||||
|
||||
/*
|
||||
Some improvements suggested by:
|
||||
Phil Endecott and Frank Gennari
|
||||
Cygwin fix provided by:
|
||||
Scott McMurray
|
||||
*/
|
||||
|
||||
===============================================================================
|
||||
|
||||
// Copyright (c) 2011 The Chromium 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 Inc. 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
|
||||
// OWNER 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.
|
||||
|
||||
===============================================================================
|
||||
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
|
||||
//
|
||||
|
||||
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
|
||||
// of the object pointed to, either on destruction of the scoped_ptr or via
|
||||
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
|
||||
// use shared_ptr or std::auto_ptr if your needs are more complex.
|
||||
|
||||
// scoped_ptr_malloc added in by Google. When one of
|
||||
// these goes out of scope, instead of doing a delete or delete[], it
|
||||
// calls free(). scoped_ptr_malloc<char> is likely to see much more
|
||||
// use than any other specializations.
|
||||
|
||||
// release() added in by Google. Use this to conditionally
|
||||
// transfer ownership of a heap-allocated object to the caller, usually on
|
||||
// method success.
|
||||
|
||||
|
||||
===============================================================================
|
||||
/*
|
||||
* Written by Wilco Dijkstra, 1996.
|
||||
* Refer to NOTICE file at the root of git project.
|
||||
*
|
||||
* Minor modifications in code style for WebRTC, 2012.
|
||||
*/
|
||||
|
||||
// The following email record is related to source files spl_sqrt_floor.c
|
||||
// and spl_sqrt_floor.s in trunk/src/common_audio/signal_processing/.
|
||||
//
|
||||
//
|
||||
// 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
|
3
OWNERS
3
OWNERS
@ -1,3 +0,0 @@
|
||||
# Since owners in upstream OWNERS files are not registered in AOSP Gerrit yet,
|
||||
# this AOSP project do not have owners.
|
||||
# TODO: Find some owners to watch changes in this AOSP project.
|
22
OWNERS.webrtc
Normal file
22
OWNERS.webrtc
Normal file
@ -0,0 +1,22 @@
|
||||
henrika@webrtc.org
|
||||
juberti@webrtc.org
|
||||
kwiberg@webrtc.org
|
||||
mflodman@webrtc.org
|
||||
stefan@webrtc.org
|
||||
tommi@webrtc.org
|
||||
per-file .gitignore=*
|
||||
per-file .gn=mbonadei@webrtc.org
|
||||
per-file *.gn=mbonadei@webrtc.org
|
||||
per-file *.gni=mbonadei@webrtc.org
|
||||
per-file AUTHORS=*
|
||||
per-file DEPS=*
|
||||
per-file pylintrc=phoglund@webrtc.org
|
||||
per-file WATCHLISTS=*
|
||||
per-file abseil-in-webrtc.md=danilchap@webrtc.org
|
||||
per-file abseil-in-webrtc.md=kwiberg@webrtc.org
|
||||
per-file abseil-in-webrtc.md=mbonadei@webrtc.org
|
||||
per-file style-guide.md=danilchap@webrtc.org
|
||||
per-file style-guide.md=kwiberg@webrtc.org
|
||||
per-file native-api.md=kwiberg@webrtc.org
|
||||
|
||||
# COMPONENT: Internals>WebRTC
|
25
PATENTS
25
PATENTS
@ -1 +1,24 @@
|
||||
Refer to src/PATENTS.
|
||||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the WebRTC code package.
|
||||
|
||||
Google hereby grants to you a perpetual, worldwide, non-exclusive,
|
||||
no-charge, irrevocable (except as stated in this section) patent
|
||||
license to make, have made, use, offer to sell, sell, import,
|
||||
transfer, and otherwise run, modify and propagate the contents of this
|
||||
implementation of the WebRTC code package, where such license applies
|
||||
only to those patent claims, both currently owned by Google and
|
||||
acquired in the future, licensable by Google that are necessarily
|
||||
infringed by this implementation of the WebRTC code package. This
|
||||
grant does not include claims that would be infringed only as a
|
||||
consequence of further modification of this implementation. If you or
|
||||
your agent or exclusive licensee institute or order or agree to the
|
||||
institution of patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that this
|
||||
implementation of the WebRTC code package or any code incorporated
|
||||
within this implementation of the WebRTC code package constitutes
|
||||
direct or contributory patent infringement, or inducement of patent
|
||||
infringement, then any patent rights granted to you under this License
|
||||
for this implementation of the WebRTC code package shall terminate as
|
||||
of the date such litigation is filed.
|
||||
|
1194
PRESUBMIT.py
1194
PRESUBMIT.py
File diff suppressed because it is too large
Load Diff
15
README.md
15
README.md
@ -7,17 +7,24 @@ developed for the browser, mobile platforms, and IoT devices, and allow them
|
||||
all to communicate via a common set of protocols.
|
||||
|
||||
The WebRTC initiative is a project supported by Google, Mozilla and Opera,
|
||||
amongst others. This page is maintained by the Google Chrome team.
|
||||
amongst others.
|
||||
|
||||
### Development
|
||||
|
||||
See http://www.webrtc.org/native-code/development for instructions on how to get
|
||||
started developing with the native code.
|
||||
See [here][native-dev] for instructions on how to get started
|
||||
developing with the native code.
|
||||
|
||||
[Authoritative list](native-api.md) of directories that contain the
|
||||
native API header files.
|
||||
|
||||
### More info
|
||||
|
||||
* Official web site: http://www.webrtc.org
|
||||
* Master source code repo: https://chromium.googlesource.com/external/webrtc
|
||||
* Master source code repo: https://webrtc.googlesource.com/src
|
||||
* Samples and reference apps: https://github.com/webrtc
|
||||
* Mailing list: http://groups.google.com/group/discuss-webrtc
|
||||
* Continuous build: http://build.chromium.org/p/client.webrtc
|
||||
* [Coding style guide](style-guide.md)
|
||||
* [Code of conduct](CODE_OF_CONDUCT.md)
|
||||
|
||||
[native-dev]: https://webrtc.googlesource.com/src/+/refs/heads/master/docs/native-code/index.md
|
||||
|
3
TODO
3
TODO
@ -1,3 +0,0 @@
|
||||
Alexander Gutkin <agutkin@google.com>: Switch the iSAC codec to be
|
||||
fixed rather than floating point. The current code uses floating
|
||||
point implementation for purely experimental reasons.
|
141
WATCHLISTS
141
WATCHLISTS
@ -16,148 +16,146 @@
|
||||
},
|
||||
'all_webrtc': {
|
||||
# NOTE: if you like this you might like webrtc-reviews@webrtc.org!
|
||||
'filepath': '^webrtc/.*',
|
||||
'filepath': '^.*',
|
||||
},
|
||||
'root_files': {
|
||||
# webrtc/build/ and non-recursive contents of ./ and webrtc/
|
||||
'filepath': '^[^/]*$|^webrtc/[^/]*$|^webrtc/build/.*',
|
||||
},
|
||||
'documented_interfaces': {
|
||||
'filepath': '^webrtc/[^/]*\.h$|'\
|
||||
'webrtc/voice_engine/include/.*',
|
||||
# Non-recursive contents of ./
|
||||
'filepath': '^[^/]*$',
|
||||
},
|
||||
'build_files': {
|
||||
'filepath': '\.gyp$|\.gypi$|Android\.mk$',
|
||||
'filepath': '\.gni$|\.gn$',
|
||||
},
|
||||
'java_files': {
|
||||
'filepath': '\.java$|\.xml$',
|
||||
},
|
||||
'api': {
|
||||
'filepath': 'api/.*',
|
||||
},
|
||||
'audio': {
|
||||
'filepath': 'webrtc/audio/.*',
|
||||
'filepath': 'audio/.*',
|
||||
},
|
||||
'base': {
|
||||
'filepath': 'rtc_base/.*',
|
||||
},
|
||||
'call': {
|
||||
'filepath': 'webrtc/call/.*',
|
||||
'filepath': 'call/.*',
|
||||
},
|
||||
'media_engine': {
|
||||
'filepath': 'media/engine/.*',
|
||||
},
|
||||
'video': {
|
||||
'filepath': 'webrtc/video/.*',
|
||||
},
|
||||
'voice_engine': {
|
||||
'filepath': 'webrtc/voice_engine/.*',
|
||||
'filepath': 'video/.*',
|
||||
},
|
||||
'common_audio': {
|
||||
'filepath': 'webrtc/common_audio/.*',
|
||||
'filepath': 'common_audio/.*',
|
||||
},
|
||||
'common_video': {
|
||||
'filepath': 'webrtc/common_video/.*',
|
||||
'filepath': 'common_video/.*',
|
||||
},
|
||||
'video_capture': {
|
||||
'filepath': 'webrtc/modules/video_capture/.*',
|
||||
},
|
||||
'video_render': {
|
||||
'filepath': 'webrtc/modules/video_render/.*',
|
||||
'filepath': 'modules/video_capture/.*',
|
||||
},
|
||||
'audio_device': {
|
||||
'filepath': 'webrtc/modules/audio_device/.*',
|
||||
'filepath': 'modules/audio_device/.*',
|
||||
},
|
||||
'audio_coding': {
|
||||
'filepath': 'webrtc/modules/audio_coding/.*',
|
||||
'filepath': 'modules/audio_coding/.*',
|
||||
},
|
||||
'neteq': {
|
||||
'filepath': 'webrtc/modules/audio_coding/neteq/.*',
|
||||
'filepath': 'modules/audio_coding/neteq/.*',
|
||||
},
|
||||
'audio_mixer': {
|
||||
'filepath': 'modules/audio_mixer/.*',
|
||||
},
|
||||
'audio_processing': {
|
||||
'filepath': 'webrtc/modules/audio_processing/.*',
|
||||
'filepath': 'modules/audio_processing/.*',
|
||||
},
|
||||
'video_coding': {
|
||||
'filepath': 'webrtc/modules/video_coding/.*',
|
||||
'filepath': 'modules/video_coding/.*',
|
||||
},
|
||||
'video_processing': {
|
||||
'filepath': 'webrtc/modules/video_processing/.*',
|
||||
'filepath': 'modules/video_processing/.*',
|
||||
},
|
||||
'bitrate_controller': {
|
||||
'filepath': 'webrtc/modules/bitrate_controller/.*'
|
||||
'filepath': 'modules/bitrate_controller/.*'
|
||||
},
|
||||
'congestion_controller': {
|
||||
'filepath': 'modules/congestion_controller/.*'
|
||||
},
|
||||
'remote_bitrate_estimator': {
|
||||
'filepath': 'webrtc/modules/remote_bitrate_estimator/.*'
|
||||
'filepath': 'modules/remote_bitrate_estimator/.*'
|
||||
},
|
||||
'pacing': {
|
||||
'filepath': 'webrtc/modules/pacing/.*'
|
||||
'filepath': 'modules/pacing/.*'
|
||||
},
|
||||
'rtp_rtcp': {
|
||||
'filepath': 'webrtc/modules/rtp_rtcp/.*'
|
||||
'filepath': 'modules/rtp_rtcp/.*'
|
||||
},
|
||||
'system_wrappers': {
|
||||
'filepath': 'webrtc/system_wrappers/.*',
|
||||
'filepath': 'system_wrappers/.*',
|
||||
},
|
||||
'pc': {
|
||||
'filepath': '^pc/.*',
|
||||
},
|
||||
},
|
||||
|
||||
'WATCHLISTS': {
|
||||
'this_file': [''],
|
||||
'all_webrtc': ['tterriberry@mozilla.com'],
|
||||
'root_files': ['niklas.enbom@webrtc.org',
|
||||
'peah@webrtc.org',
|
||||
'this_file': [],
|
||||
'all_webrtc': [],
|
||||
'root_files': ['peah@webrtc.org',
|
||||
'qiang.lu@intel.com',
|
||||
'yujie.mao@webrtc.org'],
|
||||
'documented_interfaces': ['interface-changes@webrtc.org',
|
||||
'rwolff@gocast.it'],
|
||||
'common_audio': ['aluebs@webrtc.org',
|
||||
'andrew@webrtc.org',
|
||||
'build_files': ['mbonadei@webrtc.org'],
|
||||
'common_audio': ['alessiob@webrtc.org',
|
||||
'aluebs@webrtc.org',
|
||||
'audio-team@agora.io',
|
||||
'bjornv@webrtc.org',
|
||||
'minyue@webrtc.org',
|
||||
'peah@webrtc.org'],
|
||||
'audio': ['solenberg@webrtc.org',
|
||||
'tina.legrand@webrtc.org'],
|
||||
'peah@webrtc.org',
|
||||
'saza@webrtc.org'],
|
||||
'audio': ['peah@webrtc.org'],
|
||||
'api': ['kwiberg@webrtc.org','peah@webrtc.org'],
|
||||
'base': ['kwiberg@webrtc.org'],
|
||||
'call': ['mflodman@webrtc.org',
|
||||
'pbos@webrtc.org',
|
||||
'solenberg@webrtc.org',
|
||||
'stefan@webrtc.org'],
|
||||
'video': ['andresp@webrtc.org',
|
||||
'mflodman@webrtc.org',
|
||||
'pbos@webrtc.org',
|
||||
'perkj@webrtc.org',
|
||||
'solenberg@webrtc.org',
|
||||
'video': ['mflodman@webrtc.org',
|
||||
'stefan@webrtc.org',
|
||||
'video-team@agora.io',
|
||||
'yujie.mao@webrtc.org',
|
||||
'zhengzhonghou@agora.io'],
|
||||
'voice_engine': ['andrew@webrtc.org',
|
||||
'audio-team@agora.io',
|
||||
'henrika@webrtc.org',
|
||||
'henrik.lundin@webrtc.org',
|
||||
'minyue@webrtc.org',
|
||||
'peah@webrtc.org',
|
||||
'solenberg@webrtc.org'],
|
||||
'video_capture': ['mflodman@webrtc.org',
|
||||
'perkj@webrtc.org',
|
||||
'sdk-team@agora.io',
|
||||
'zhengzhonghou@agora.io'],
|
||||
'video_render': ['mflodman@webrtc.org',
|
||||
'perkj@webrtc.org',
|
||||
'sdk-team@agora.io',
|
||||
'zhengzhonghou@agora.io'],
|
||||
'audio_device': ['audio-team@agora.io',
|
||||
'henrika@webrtc.org',
|
||||
'peah@webrtc.org',
|
||||
'saza@webrtc.org',
|
||||
'sdk-team@agora.io'],
|
||||
'audio_coding': ['audio-team@agora.io',
|
||||
'audio_coding': ['alessiob@webrtc.org',
|
||||
'audio-team@agora.io',
|
||||
'henrik.lundin@webrtc.org',
|
||||
'kwiberg@webrtc.org',
|
||||
'minyue@webrtc.org',
|
||||
'peah@webrtc.org',
|
||||
'tina.legrand@webrtc.org'],
|
||||
'neteq': ['audio-team@agora.io',
|
||||
'saza@webrtc.org'],
|
||||
'neteq': ['alessiob@webrtc.org',
|
||||
'audio-team@agora.io',
|
||||
'henrik.lundin@webrtc.org',
|
||||
'minyue@webrtc.org'],
|
||||
'audio_processing': ['aluebs@webrtc.org',
|
||||
'andrew@webrtc.org',
|
||||
'minyue@webrtc.org',
|
||||
'saza@webrtc.org'],
|
||||
'audio_mixer': ['aleloi@webrtc.org',
|
||||
'henrik.lundin@webrtc.org',
|
||||
'peah@webrtc.org',
|
||||
'saza@webrtc.org'],
|
||||
'audio_processing': ['alessiob@webrtc.org',
|
||||
'aluebs@webrtc.org',
|
||||
'audio-team@agora.io',
|
||||
'bjornv@webrtc.org',
|
||||
'fhernqvist@webrtc.org',
|
||||
'henrik.lundin@webrtc.org',
|
||||
'kwiberg@webrtc.org',
|
||||
'minyue@webrtc.org',
|
||||
'peah@webrtc.org',
|
||||
'solenberg@webrtc.org'],
|
||||
'saza@webrtc.org'],
|
||||
'video_coding': ['mflodman@webrtc.org',
|
||||
'stefan@webrtc.org',
|
||||
'video-team@agora.io',
|
||||
@ -167,20 +165,25 @@
|
||||
'zhengzhonghou@agora.io'],
|
||||
'bitrate_controller': ['mflodman@webrtc.org',
|
||||
'stefan@webrtc.org',
|
||||
'srte@webrtc.org',
|
||||
'zhuangzesen@agora.io'],
|
||||
'congestion_controller': ['srte@webrtc.org'],
|
||||
'remote_bitrate_estimator': ['mflodman@webrtc.org',
|
||||
'stefan@webrtc.org',
|
||||
'zhuangzesen@agora.io'],
|
||||
'pacing': ['mflodman@webrtc.org',
|
||||
'srte@webrtc.org',
|
||||
'stefan@webrtc.org',
|
||||
'zhuangzesen@agora.io'],
|
||||
'rtp_rtcp': ['mflodman@webrtc.org',
|
||||
'stefan@webrtc.org',
|
||||
'danilchap@webrtc.org',
|
||||
'zhuangzesen@agora.io'],
|
||||
'system_wrappers': ['fengyue@agora.io',
|
||||
'henrika@webrtc.org',
|
||||
'mflodman@webrtc.org',
|
||||
'peah@webrtc.org',
|
||||
'zhengzhonghou@agora.io'],
|
||||
'pc': ['steveanton+watch@webrtc.org'],
|
||||
},
|
||||
}
|
||||
|
63
abseil-in-webrtc.md
Normal file
63
abseil-in-webrtc.md
Normal file
@ -0,0 +1,63 @@
|
||||
# Using Abseil in WebRTC
|
||||
|
||||
You may use a subset of the utilities provided by the [Abseil][abseil]
|
||||
library when writing WebRTC C++ code. Below, we list the explicitly
|
||||
*allowed* and the explicitly *disallowed* subsets of Abseil; if you
|
||||
find yourself in need of something that isn’t in either subset,
|
||||
please add it to the *allowed* subset in this doc in the same CL that
|
||||
adds the first use.
|
||||
|
||||
[abseil]: https://abseil.io/about/
|
||||
|
||||
## **Allowed**
|
||||
|
||||
* `absl::InlinedVector`
|
||||
* `absl::WrapUnique`
|
||||
* `absl::optional` and related stuff from `absl/types/optional.h`.
|
||||
* `absl::string_view`
|
||||
* The functions in `absl/strings/ascii.h`, `absl/strings/match.h`,
|
||||
and `absl/strings/str_replace.h`.
|
||||
* `absl::is_trivially_copy_constructible`,
|
||||
`absl::is_trivially_copy_assignable`, and
|
||||
`absl::is_trivially_destructible` from `absl/meta/type_traits.h`.
|
||||
* `absl::variant` and related stuff from `absl/types/variant.h`.
|
||||
* The functions in `absl/algorithm/algorithm.h` and
|
||||
`absl/algorithm/container.h`.
|
||||
* The macros in `absl/base/attributes.h`, `absl/base/config.h` and
|
||||
`absl/base/macros.h`.
|
||||
|
||||
## **Disallowed**
|
||||
|
||||
### `absl::make_unique`
|
||||
|
||||
*Use `std::make_unique` instead.*
|
||||
|
||||
### `absl::Mutex`
|
||||
|
||||
*Use `rtc::CriticalSection` instead.*
|
||||
|
||||
Chromium has a ban on new static initializers, and `absl::Mutex` uses
|
||||
one. To make `absl::Mutex` available, we would need to nicely ask the
|
||||
Abseil team to remove that initializer (like they already did for a
|
||||
spinlock initializer). Additionally, `absl::Mutex` handles time in a
|
||||
way that may not be compatible with the rest of WebRTC.
|
||||
|
||||
### `absl::Span`
|
||||
|
||||
*Use `rtc::ArrayView` instead.*
|
||||
|
||||
`absl::Span` differs from `rtc::ArrayView` on several points, and both
|
||||
of them differ from the `std::span` that was voted into
|
||||
C++20—and `std::span` is likely to undergo further changes
|
||||
before C++20 is finalized. We should just keep using `rtc::ArrayView`
|
||||
and avoid `absl::Span` until C++20 is finalized and the Abseil team
|
||||
has decided if they will change `absl::Span` to match.
|
||||
[Bug](https://bugs.webrtc.org/9214).
|
||||
|
||||
### `absl::StrCat`, `absl::StrAppend`, `absl::StrJoin`, `absl::StrSplit`
|
||||
|
||||
*Use `rtc::SimpleStringBuilder` to build strings.*
|
||||
|
||||
These are optimized for speed, not binary size. Even `StrCat` calls
|
||||
with a modest number of arguments can easily add several hundred bytes
|
||||
to the binary.
|
38
all.gyp
38
all.gyp
@ -1,38 +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.
|
||||
|
||||
{
|
||||
'variables': {
|
||||
'include_examples%': 1,
|
||||
'include_tests%': 1,
|
||||
'webrtc_root_additional_dependencies': [],
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'All',
|
||||
'type': 'none',
|
||||
'dependencies': [
|
||||
'webrtc/webrtc.gyp:*',
|
||||
'talk/libjingle.gyp:*',
|
||||
'<@(webrtc_root_additional_dependencies)',
|
||||
],
|
||||
'conditions': [
|
||||
['include_examples==1', {
|
||||
'dependencies': [
|
||||
'webrtc/webrtc_examples.gyp:*',
|
||||
],
|
||||
}],
|
||||
['include_tests==1', {
|
||||
'dependencies': [
|
||||
'talk/libjingle_tests.gyp:*',
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
1052
api/BUILD.gn
Normal file
1052
api/BUILD.gn
Normal file
File diff suppressed because it is too large
Load Diff
309
api/DEPS
Normal file
309
api/DEPS
Normal file
@ -0,0 +1,309 @@
|
||||
# This is supposed to be a complete list of top-level directories,
|
||||
# excepting only api/ itself.
|
||||
include_rules = [
|
||||
"-audio",
|
||||
"-base",
|
||||
"-build",
|
||||
"-buildtools",
|
||||
"-build_overrides",
|
||||
"-call",
|
||||
"-common_audio",
|
||||
"-common_video",
|
||||
"-data",
|
||||
"-examples",
|
||||
"-ios",
|
||||
"-infra",
|
||||
"-logging",
|
||||
"-media",
|
||||
"-modules",
|
||||
"-out",
|
||||
"-p2p",
|
||||
"-pc",
|
||||
"-resources",
|
||||
"-rtc_base",
|
||||
"-rtc_tools",
|
||||
"-sdk",
|
||||
"-stats",
|
||||
"-style-guide",
|
||||
"-system_wrappers",
|
||||
"-test",
|
||||
"-testing",
|
||||
"-third_party",
|
||||
"-tools",
|
||||
"-tools_webrtc",
|
||||
"-video",
|
||||
"-external/webrtc/webrtc", # Android platform build.
|
||||
"-libyuv",
|
||||
"-common_types.h",
|
||||
"-WebRTC",
|
||||
]
|
||||
|
||||
specific_include_rules = {
|
||||
# Some internal headers are allowed even in API headers:
|
||||
".*\.h": [
|
||||
"+rtc_base/checks.h",
|
||||
"+rtc_base/system/rtc_export.h",
|
||||
"+rtc_base/system/rtc_export_template.h",
|
||||
"+rtc_base/units/unit_base.h",
|
||||
"+rtc_base/deprecation.h",
|
||||
],
|
||||
|
||||
"array_view\.h": [
|
||||
"+rtc_base/type_traits.h",
|
||||
],
|
||||
|
||||
# Needed because AudioEncoderOpus is in the wrong place for
|
||||
# backwards compatibilty reasons. See
|
||||
# https://bugs.chromium.org/p/webrtc/issues/detail?id=7847
|
||||
"audio_encoder_opus\.h": [
|
||||
"+modules/audio_coding/codecs/opus/audio_encoder_opus.h",
|
||||
],
|
||||
|
||||
"async_resolver_factory\.h": [
|
||||
"+rtc_base/async_resolver_interface.h",
|
||||
],
|
||||
|
||||
"candidate\.h": [
|
||||
"+rtc_base/network_constants.h",
|
||||
"+rtc_base/socket_address.h",
|
||||
],
|
||||
|
||||
"data_channel_interface\.h": [
|
||||
"+rtc_base/copy_on_write_buffer.h",
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"data_channel_transport_interface\.h": [
|
||||
"+rtc_base/copy_on_write_buffer.h",
|
||||
],
|
||||
|
||||
"dtls_transport_interface\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
"+rtc_base/ssl_certificate.h",
|
||||
],
|
||||
|
||||
"dtmf_sender_interface\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"fec_controller\.h": [
|
||||
"+modules/include/module_fec_types.h",
|
||||
],
|
||||
|
||||
"frame_transformer_interface\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"ice_transport_interface\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"jsep\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"jsep_ice_candidate\.h": [
|
||||
"+rtc_base/constructor_magic.h",
|
||||
],
|
||||
|
||||
"jsep_session_description\.h": [
|
||||
"+rtc_base/constructor_magic.h",
|
||||
],
|
||||
|
||||
"media_stream_interface\.h": [
|
||||
"+modules/audio_processing/include/audio_processing_statistics.h",
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"media_transport_interface\.h": [
|
||||
"+rtc_base/copy_on_write_buffer.h", # As used by datachannelinterface.h
|
||||
"+rtc_base/network_route.h",
|
||||
],
|
||||
|
||||
"packet_socket_factory\.h": [
|
||||
"+rtc_base/proxy_info.h",
|
||||
"+rtc_base/async_packet_socket.h",
|
||||
],
|
||||
|
||||
"peer_connection_factory_proxy\.h": [
|
||||
"+rtc_base/bind.h",
|
||||
],
|
||||
|
||||
"peer_connection_interface\.h": [
|
||||
"+media/base/media_config.h",
|
||||
"+media/base/media_engine.h",
|
||||
"+p2p/base/port_allocator.h",
|
||||
"+rtc_base/network.h",
|
||||
"+rtc_base/rtc_certificate.h",
|
||||
"+rtc_base/rtc_certificate_generator.h",
|
||||
"+rtc_base/socket_address.h",
|
||||
"+rtc_base/ssl_certificate.h",
|
||||
"+rtc_base/ssl_stream_adapter.h",
|
||||
],
|
||||
|
||||
"proxy\.h": [
|
||||
"+rtc_base/event.h",
|
||||
"+rtc_base/message_handler.h", # Inherits from it.
|
||||
"+rtc_base/ref_counted_object.h",
|
||||
"+rtc_base/thread.h",
|
||||
],
|
||||
|
||||
"ref_counted_base\.h": [
|
||||
"+rtc_base/constructor_magic.h",
|
||||
"+rtc_base/ref_count.h",
|
||||
"+rtc_base/ref_counter.h",
|
||||
],
|
||||
|
||||
"rtc_error\.h": [
|
||||
"+rtc_base/logging.h",
|
||||
],
|
||||
"rtc_event_log_output_file.h": [
|
||||
# For private member and constructor.
|
||||
"+rtc_base/system/file_wrapper.h",
|
||||
],
|
||||
"rtp_receiver_interface\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"rtp_sender_interface\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"rtp_transceiver_interface\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"sctp_transport_interface\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"set_remote_description_observer_interface\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"stats_types\.h": [
|
||||
"+rtc_base/constructor_magic.h",
|
||||
"+rtc_base/ref_count.h",
|
||||
"+rtc_base/string_encode.h",
|
||||
"+rtc_base/thread_checker.h",
|
||||
],
|
||||
|
||||
"uma_metrics\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"audio_frame\.h": [
|
||||
"+rtc_base/constructor_magic.h",
|
||||
],
|
||||
|
||||
"audio_mixer\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"audio_decoder\.h": [
|
||||
"+rtc_base/buffer.h",
|
||||
"+rtc_base/constructor_magic.h",
|
||||
],
|
||||
|
||||
"audio_decoder_factory\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"audio_decoder_factory_template\.h": [
|
||||
"+rtc_base/ref_counted_object.h",
|
||||
],
|
||||
|
||||
"audio_encoder\.h": [
|
||||
"+rtc_base/buffer.h",
|
||||
],
|
||||
|
||||
"audio_encoder_factory\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"audio_encoder_factory_template\.h": [
|
||||
"+rtc_base/ref_counted_object.h",
|
||||
],
|
||||
|
||||
"frame_decryptor_interface\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"frame_encryptor_interface\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"rtc_stats_collector_callback\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
"rtc_stats_report\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
"+rtc_base/ref_counted_object.h",
|
||||
],
|
||||
|
||||
"audioproc_float\.h": [
|
||||
"+modules/audio_processing/include/audio_processing.h",
|
||||
],
|
||||
|
||||
"fake_frame_decryptor\.h": [
|
||||
"+rtc_base/ref_counted_object.h",
|
||||
],
|
||||
|
||||
"fake_frame_encryptor\.h": [
|
||||
"+rtc_base/ref_counted_object.h",
|
||||
],
|
||||
|
||||
"mock.*\.h": [
|
||||
"+test/gmock.h",
|
||||
],
|
||||
|
||||
"simulated_network\.h": [
|
||||
"+rtc_base/critical_section.h",
|
||||
"+rtc_base/random.h",
|
||||
"+rtc_base/thread_annotations.h",
|
||||
],
|
||||
|
||||
"test_dependency_factory\.h": [
|
||||
"+rtc_base/thread_checker.h",
|
||||
],
|
||||
|
||||
"time_controller\.h": [
|
||||
"+rtc_base/thread.h",
|
||||
],
|
||||
|
||||
"videocodec_test_fixture\.h": [
|
||||
"+modules/video_coding/include/video_codec_interface.h"
|
||||
],
|
||||
|
||||
"video_encoder_config\.h": [
|
||||
"+rtc_base/ref_count.h",
|
||||
],
|
||||
|
||||
# .cc files in api/ should not be restricted in what they can #include,
|
||||
# so we re-add all the top-level directories here. (That's because .h
|
||||
# files leak their #includes to whoever's #including them, but .cc files
|
||||
# do not since no one #includes them.)
|
||||
".*\.cc": [
|
||||
"+audio",
|
||||
"+call",
|
||||
"+common_audio",
|
||||
"+common_video",
|
||||
"+examples",
|
||||
"+logging",
|
||||
"+media",
|
||||
"+modules",
|
||||
"+p2p",
|
||||
"+pc",
|
||||
"+rtc_base",
|
||||
"+rtc_tools",
|
||||
"+sdk",
|
||||
"+stats",
|
||||
"+system_wrappers",
|
||||
"+test",
|
||||
"+tools",
|
||||
"+tools_webrtc",
|
||||
"+video",
|
||||
"+third_party",
|
||||
],
|
||||
}
|
71
api/DESIGN.md
Normal file
71
api/DESIGN.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Design considerations
|
||||
|
||||
The header files in this directory form the API to the WebRTC library
|
||||
that is intended for client applications' use.
|
||||
|
||||
This API is designed to be used on top of a multithreaded runtime.
|
||||
|
||||
The public API functions are designed to be called from a single thread*
|
||||
(the "client thread"), and can do internal dispatching to the thread
|
||||
where activity needs to happen. Those threads can be passed in by the
|
||||
client, typically as arguments to factory constructors, or they can be
|
||||
created by the library if factory constructors that don't take threads
|
||||
are used.
|
||||
|
||||
Many of the functions are designed to be used in an asynchronous manner,
|
||||
where a function is called to initiate an activity, and a callback will
|
||||
be called when the activity is completed, or a handler function will
|
||||
be called on an observer object when interesting events happen.
|
||||
|
||||
Note: Often, even functions that look like simple functions (such as
|
||||
information query functions) will need to jump between threads to perform
|
||||
their function - which means that things may happen on other threads
|
||||
between calls; writing "increment(x); increment(x)" is not a safe
|
||||
way to increment X by exactly two, since the increment function may have
|
||||
jumped to another thread that already had a queue of things to handle,
|
||||
causing large amounts of other activity to have intervened between
|
||||
the two calls.
|
||||
|
||||
(*) The term "thread" is used here to denote any construct that guarantees
|
||||
sequential execution - other names for such constructs are task runners
|
||||
and sequenced task queues.
|
||||
|
||||
# Client threads and callbacks
|
||||
|
||||
At the moment, the API does not give any guarantee on which thread* the
|
||||
callbacks and events are called on. So it's best to write all callback
|
||||
and event handlers like this (pseudocode):
|
||||
<pre>
|
||||
void ObserverClass::Handler(event) {
|
||||
if (!called_on_client_thread()) {
|
||||
dispatch_to_client_thread(bind(handler(event)));
|
||||
return;
|
||||
}
|
||||
// Process event, we're now on the right thread
|
||||
}
|
||||
</pre>
|
||||
In the future, the implementation may change to always call the callbacks
|
||||
and event handlers on the client thread.
|
||||
|
||||
# Implementation considerations
|
||||
|
||||
The C++ classes that are part of the public API are also used to derive
|
||||
classes that form part of the implementation.
|
||||
|
||||
This should not directly concern users of the API, but may matter if one
|
||||
wants to look at how the WebRTC library is implemented, or for legacy code
|
||||
that directly accesses internal APIs.
|
||||
|
||||
Many APIs are defined in terms of a "proxy object", which will do a blocking
|
||||
dispatch of the function to another thread, and an "implementation object"
|
||||
which will do the actual
|
||||
work, but can only be created, invoked and destroyed on its "home thread".
|
||||
|
||||
Usually, the classes are named "xxxInterface" (in api/), "xxxProxy" and
|
||||
"xxx" (not in api/). WebRTC users should only need to depend on the files
|
||||
in api/. In many cases, the "xxxProxy" and "xxx" classes are subclasses
|
||||
of "xxxInterface", but this property is an implementation feature only,
|
||||
and should not be relied upon.
|
||||
|
||||
The threading properties of these internal APIs are NOT documented in
|
||||
this note, and need to be understood by inspecting those classes.
|
14
api/OWNERS.webrtc
Normal file
14
api/OWNERS.webrtc
Normal file
@ -0,0 +1,14 @@
|
||||
crodbro@webrtc.org
|
||||
deadbeef@webrtc.org
|
||||
hta@webrtc.org
|
||||
juberti@webrtc.org
|
||||
kwiberg@webrtc.org
|
||||
magjed@webrtc.org
|
||||
perkj@webrtc.org
|
||||
tkchin@webrtc.org
|
||||
tommi@webrtc.org
|
||||
|
||||
per-file peer_connection*=hbos@webrtc.org
|
||||
|
||||
per-file DEPS=mbonadei@webrtc.org
|
||||
per-file DEPS=kwiberg@webrtc.org
|
24
api/README.md
Normal file
24
api/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# How to write code in the `api/` directory
|
||||
|
||||
Mostly, just follow the regular [style guide](../style-guide.md), but:
|
||||
|
||||
* Note that `api/` code is not exempt from the “`.h` and `.cc` files come in
|
||||
pairs” rule, so if you declare something in `api/path/to/foo.h`, it should be
|
||||
defined in `api/path/to/foo.cc`.
|
||||
* Headers in `api/` should, if possible, not `#include` headers outside `api/`.
|
||||
It’s not always possible to avoid this, but be aware that it adds to a small
|
||||
mountain of technical debt that we’re trying to shrink.
|
||||
* `.cc` files in `api/`, on the other hand, are free to `#include` headers
|
||||
outside `api/`.
|
||||
|
||||
That is, the preferred way for `api/` code to access non-`api/` code is to call
|
||||
it from a `.cc` file, so that users of our API headers won’t transitively
|
||||
`#include` non-public headers.
|
||||
|
||||
For headers in `api/` that need to refer to non-public types, forward
|
||||
declarations are often a lesser evil than including non-public header files. The
|
||||
usual [rules](../style-guide.md#forward-declarations) still apply, though.
|
||||
|
||||
`.cc` files in `api/` should preferably be kept reasonably small. If a
|
||||
substantial implementation is needed, consider putting it with our non-public
|
||||
code, and just call it from the `api/` `.cc` file.
|
315
api/array_view.h
Normal file
315
api/array_view.h
Normal file
@ -0,0 +1,315 @@
|
||||
/*
|
||||
* 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 <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 impl {
|
||||
|
||||
// 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, impl::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 impl
|
||||
|
||||
template <typename T, std::ptrdiff_t Size = impl::kArrayViewVarSize>
|
||||
class ArrayView final : public impl::ArrayViewBase<T, Size> {
|
||||
public:
|
||||
using value_type = T;
|
||||
using const_iterator = const T*;
|
||||
|
||||
// Construct an ArrayView from a pointer and a length.
|
||||
template <typename U>
|
||||
ArrayView(U* data, size_t size)
|
||||
: impl::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 == impl::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 == impl::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 != impl::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 != impl::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 == impl::kArrayViewVarSize &&
|
||||
HasDataAndSize<U, T>::value>::type* = nullptr>
|
||||
ArrayView(U& u) // NOLINT
|
||||
: ArrayView(u.data(), u.size()) {}
|
||||
template <
|
||||
typename U,
|
||||
typename std::enable_if<Size == impl::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(); }
|
||||
|
||||
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_
|
578
api/array_view_unittest.cc
Normal file
578
api/array_view_unittest.cc
Normal file
@ -0,0 +1,578 @@
|
||||
/*
|
||||
* Copyright 2015 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/array_view.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/gunit.h"
|
||||
#include "test/gmock.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::IsEmpty;
|
||||
|
||||
template <typename T>
|
||||
size_t Call(ArrayView<T> av) {
|
||||
return av.size();
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
void CallFixed(ArrayView<T, N> av) {}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(ArrayViewTest, TestConstructFromPtrAndArray) {
|
||||
char arr[] = "Arrr!";
|
||||
const char carr[] = "Carrr!";
|
||||
EXPECT_EQ(6u, Call<const char>(arr));
|
||||
EXPECT_EQ(7u, Call<const char>(carr));
|
||||
EXPECT_EQ(6u, Call<char>(arr));
|
||||
// Call<char>(carr); // Compile error, because can't drop const.
|
||||
// Call<int>(arr); // Compile error, because incompatible types.
|
||||
ArrayView<int*> x;
|
||||
EXPECT_EQ(0u, x.size());
|
||||
EXPECT_EQ(nullptr, x.data());
|
||||
ArrayView<char> y = arr;
|
||||
EXPECT_EQ(6u, y.size());
|
||||
EXPECT_EQ(arr, y.data());
|
||||
ArrayView<char, 6> yf = arr;
|
||||
static_assert(yf.size() == 6, "");
|
||||
EXPECT_EQ(arr, yf.data());
|
||||
ArrayView<const char> z(arr + 1, 3);
|
||||
EXPECT_EQ(3u, z.size());
|
||||
EXPECT_EQ(arr + 1, z.data());
|
||||
ArrayView<const char, 3> zf(arr + 1, 3);
|
||||
static_assert(zf.size() == 3, "");
|
||||
EXPECT_EQ(arr + 1, zf.data());
|
||||
ArrayView<const char> w(arr, 2);
|
||||
EXPECT_EQ(2u, w.size());
|
||||
EXPECT_EQ(arr, w.data());
|
||||
ArrayView<const char, 2> wf(arr, 2);
|
||||
static_assert(wf.size() == 2, "");
|
||||
EXPECT_EQ(arr, wf.data());
|
||||
ArrayView<char> q(arr, 0);
|
||||
EXPECT_EQ(0u, q.size());
|
||||
EXPECT_EQ(nullptr, q.data());
|
||||
ArrayView<char, 0> qf(arr, 0);
|
||||
static_assert(qf.size() == 0, "");
|
||||
EXPECT_EQ(nullptr, qf.data());
|
||||
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
||||
// DCHECK error (nullptr with nonzero size).
|
||||
EXPECT_DEATH(ArrayView<int>(static_cast<int*>(nullptr), 5), "");
|
||||
#endif
|
||||
// These are compile errors, because incompatible types.
|
||||
// ArrayView<int> m = arr;
|
||||
// ArrayView<float> n(arr + 2, 2);
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestCopyConstructorVariableLvalue) {
|
||||
char arr[] = "Arrr!";
|
||||
ArrayView<char> x = arr;
|
||||
EXPECT_EQ(6u, x.size());
|
||||
EXPECT_EQ(arr, x.data());
|
||||
ArrayView<char> y = x; // Copy non-const -> non-const.
|
||||
EXPECT_EQ(6u, y.size());
|
||||
EXPECT_EQ(arr, y.data());
|
||||
ArrayView<const char> z = x; // Copy non-const -> const.
|
||||
EXPECT_EQ(6u, z.size());
|
||||
EXPECT_EQ(arr, z.data());
|
||||
ArrayView<const char> w = z; // Copy const -> const.
|
||||
EXPECT_EQ(6u, w.size());
|
||||
EXPECT_EQ(arr, w.data());
|
||||
// ArrayView<char> v = z; // Compile error, because can't drop const.
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestCopyConstructorVariableRvalue) {
|
||||
char arr[] = "Arrr!";
|
||||
ArrayView<char> x = arr;
|
||||
EXPECT_EQ(6u, x.size());
|
||||
EXPECT_EQ(arr, x.data());
|
||||
ArrayView<char> y = std::move(x); // Copy non-const -> non-const.
|
||||
EXPECT_EQ(6u, y.size());
|
||||
EXPECT_EQ(arr, y.data());
|
||||
ArrayView<const char> z = std::move(x); // Copy non-const -> const.
|
||||
EXPECT_EQ(6u, z.size());
|
||||
EXPECT_EQ(arr, z.data());
|
||||
ArrayView<const char> w = std::move(z); // Copy const -> const.
|
||||
EXPECT_EQ(6u, w.size());
|
||||
EXPECT_EQ(arr, w.data());
|
||||
// ArrayView<char> v = std::move(z); // Error, because can't drop const.
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestCopyConstructorFixedLvalue) {
|
||||
char arr[] = "Arrr!";
|
||||
ArrayView<char, 6> x = arr;
|
||||
static_assert(x.size() == 6, "");
|
||||
EXPECT_EQ(arr, x.data());
|
||||
|
||||
// Copy fixed -> fixed.
|
||||
ArrayView<char, 6> y = x; // Copy non-const -> non-const.
|
||||
static_assert(y.size() == 6, "");
|
||||
EXPECT_EQ(arr, y.data());
|
||||
ArrayView<const char, 6> z = x; // Copy non-const -> const.
|
||||
static_assert(z.size() == 6, "");
|
||||
EXPECT_EQ(arr, z.data());
|
||||
ArrayView<const char, 6> w = z; // Copy const -> const.
|
||||
static_assert(w.size() == 6, "");
|
||||
EXPECT_EQ(arr, w.data());
|
||||
// ArrayView<char, 6> v = z; // Compile error, because can't drop const.
|
||||
|
||||
// Copy fixed -> variable.
|
||||
ArrayView<char> yv = x; // Copy non-const -> non-const.
|
||||
EXPECT_EQ(6u, yv.size());
|
||||
EXPECT_EQ(arr, yv.data());
|
||||
ArrayView<const char> zv = x; // Copy non-const -> const.
|
||||
EXPECT_EQ(6u, zv.size());
|
||||
EXPECT_EQ(arr, zv.data());
|
||||
ArrayView<const char> wv = z; // Copy const -> const.
|
||||
EXPECT_EQ(6u, wv.size());
|
||||
EXPECT_EQ(arr, wv.data());
|
||||
// ArrayView<char> vv = z; // Compile error, because can't drop const.
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestCopyConstructorFixedRvalue) {
|
||||
char arr[] = "Arrr!";
|
||||
ArrayView<char, 6> x = arr;
|
||||
static_assert(x.size() == 6, "");
|
||||
EXPECT_EQ(arr, x.data());
|
||||
|
||||
// Copy fixed -> fixed.
|
||||
ArrayView<char, 6> y = std::move(x); // Copy non-const -> non-const.
|
||||
static_assert(y.size() == 6, "");
|
||||
EXPECT_EQ(arr, y.data());
|
||||
ArrayView<const char, 6> z = std::move(x); // Copy non-const -> const.
|
||||
static_assert(z.size() == 6, "");
|
||||
EXPECT_EQ(arr, z.data());
|
||||
ArrayView<const char, 6> w = std::move(z); // Copy const -> const.
|
||||
static_assert(w.size() == 6, "");
|
||||
EXPECT_EQ(arr, w.data());
|
||||
// ArrayView<char, 6> v = std::move(z); // Error, because can't drop const.
|
||||
|
||||
// Copy fixed -> variable.
|
||||
ArrayView<char> yv = std::move(x); // Copy non-const -> non-const.
|
||||
EXPECT_EQ(6u, yv.size());
|
||||
EXPECT_EQ(arr, yv.data());
|
||||
ArrayView<const char> zv = std::move(x); // Copy non-const -> const.
|
||||
EXPECT_EQ(6u, zv.size());
|
||||
EXPECT_EQ(arr, zv.data());
|
||||
ArrayView<const char> wv = std::move(z); // Copy const -> const.
|
||||
EXPECT_EQ(6u, wv.size());
|
||||
EXPECT_EQ(arr, wv.data());
|
||||
// ArrayView<char> vv = std::move(z); // Error, because can't drop const.
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestCopyAssignmentVariableLvalue) {
|
||||
char arr[] = "Arrr!";
|
||||
ArrayView<char> x(arr);
|
||||
EXPECT_EQ(6u, x.size());
|
||||
EXPECT_EQ(arr, x.data());
|
||||
ArrayView<char> y;
|
||||
y = x; // Copy non-const -> non-const.
|
||||
EXPECT_EQ(6u, y.size());
|
||||
EXPECT_EQ(arr, y.data());
|
||||
ArrayView<const char> z;
|
||||
z = x; // Copy non-const -> const.
|
||||
EXPECT_EQ(6u, z.size());
|
||||
EXPECT_EQ(arr, z.data());
|
||||
ArrayView<const char> w;
|
||||
w = z; // Copy const -> const.
|
||||
EXPECT_EQ(6u, w.size());
|
||||
EXPECT_EQ(arr, w.data());
|
||||
// ArrayView<char> v;
|
||||
// v = z; // Compile error, because can't drop const.
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestCopyAssignmentVariableRvalue) {
|
||||
char arr[] = "Arrr!";
|
||||
ArrayView<char> x(arr);
|
||||
EXPECT_EQ(6u, x.size());
|
||||
EXPECT_EQ(arr, x.data());
|
||||
ArrayView<char> y;
|
||||
y = std::move(x); // Copy non-const -> non-const.
|
||||
EXPECT_EQ(6u, y.size());
|
||||
EXPECT_EQ(arr, y.data());
|
||||
ArrayView<const char> z;
|
||||
z = std::move(x); // Copy non-const -> const.
|
||||
EXPECT_EQ(6u, z.size());
|
||||
EXPECT_EQ(arr, z.data());
|
||||
ArrayView<const char> w;
|
||||
w = std::move(z); // Copy const -> const.
|
||||
EXPECT_EQ(6u, w.size());
|
||||
EXPECT_EQ(arr, w.data());
|
||||
// ArrayView<char> v;
|
||||
// v = std::move(z); // Compile error, because can't drop const.
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestCopyAssignmentFixedLvalue) {
|
||||
char arr[] = "Arrr!";
|
||||
char init[] = "Init!";
|
||||
ArrayView<char, 6> x(arr);
|
||||
EXPECT_EQ(arr, x.data());
|
||||
|
||||
// Copy fixed -> fixed.
|
||||
ArrayView<char, 6> y(init);
|
||||
y = x; // Copy non-const -> non-const.
|
||||
EXPECT_EQ(arr, y.data());
|
||||
ArrayView<const char, 6> z(init);
|
||||
z = x; // Copy non-const -> const.
|
||||
EXPECT_EQ(arr, z.data());
|
||||
ArrayView<const char, 6> w(init);
|
||||
w = z; // Copy const -> const.
|
||||
EXPECT_EQ(arr, w.data());
|
||||
// ArrayView<char, 6> v(init);
|
||||
// v = z; // Compile error, because can't drop const.
|
||||
|
||||
// Copy fixed -> variable.
|
||||
ArrayView<char> yv;
|
||||
yv = x; // Copy non-const -> non-const.
|
||||
EXPECT_EQ(6u, yv.size());
|
||||
EXPECT_EQ(arr, yv.data());
|
||||
ArrayView<const char> zv;
|
||||
zv = x; // Copy non-const -> const.
|
||||
EXPECT_EQ(6u, zv.size());
|
||||
EXPECT_EQ(arr, zv.data());
|
||||
ArrayView<const char> wv;
|
||||
wv = z; // Copy const -> const.
|
||||
EXPECT_EQ(6u, wv.size());
|
||||
EXPECT_EQ(arr, wv.data());
|
||||
// ArrayView<char> v;
|
||||
// v = z; // Compile error, because can't drop const.
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestCopyAssignmentFixedRvalue) {
|
||||
char arr[] = "Arrr!";
|
||||
char init[] = "Init!";
|
||||
ArrayView<char, 6> x(arr);
|
||||
EXPECT_EQ(arr, x.data());
|
||||
|
||||
// Copy fixed -> fixed.
|
||||
ArrayView<char, 6> y(init);
|
||||
y = std::move(x); // Copy non-const -> non-const.
|
||||
EXPECT_EQ(arr, y.data());
|
||||
ArrayView<const char, 6> z(init);
|
||||
z = std::move(x); // Copy non-const -> const.
|
||||
EXPECT_EQ(arr, z.data());
|
||||
ArrayView<const char, 6> w(init);
|
||||
w = std::move(z); // Copy const -> const.
|
||||
EXPECT_EQ(arr, w.data());
|
||||
// ArrayView<char, 6> v(init);
|
||||
// v = std::move(z); // Compile error, because can't drop const.
|
||||
|
||||
// Copy fixed -> variable.
|
||||
ArrayView<char> yv;
|
||||
yv = std::move(x); // Copy non-const -> non-const.
|
||||
EXPECT_EQ(6u, yv.size());
|
||||
EXPECT_EQ(arr, yv.data());
|
||||
ArrayView<const char> zv;
|
||||
zv = std::move(x); // Copy non-const -> const.
|
||||
EXPECT_EQ(6u, zv.size());
|
||||
EXPECT_EQ(arr, zv.data());
|
||||
ArrayView<const char> wv;
|
||||
wv = std::move(z); // Copy const -> const.
|
||||
EXPECT_EQ(6u, wv.size());
|
||||
EXPECT_EQ(arr, wv.data());
|
||||
// ArrayView<char> v;
|
||||
// v = std::move(z); // Compile error, because can't drop const.
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestStdArray) {
|
||||
EXPECT_EQ(4u, Call<const int>(std::array<int, 4>{1, 2, 3, 4}));
|
||||
CallFixed<const int, 3>(std::array<int, 3>{2, 3, 4});
|
||||
constexpr size_t size = 5;
|
||||
std::array<float, size> arr{};
|
||||
// Fixed size view.
|
||||
rtc::ArrayView<float, size> arr_view_fixed(arr);
|
||||
EXPECT_EQ(arr.data(), arr_view_fixed.data());
|
||||
static_assert(size == arr_view_fixed.size(), "");
|
||||
// Variable size view.
|
||||
rtc::ArrayView<float> arr_view(arr);
|
||||
EXPECT_EQ(arr.data(), arr_view.data());
|
||||
EXPECT_EQ(size, arr_view.size());
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestConstStdArray) {
|
||||
constexpr size_t size = 5;
|
||||
|
||||
constexpr std::array<float, size> constexpr_arr{};
|
||||
rtc::ArrayView<const float, size> constexpr_arr_view(constexpr_arr);
|
||||
EXPECT_EQ(constexpr_arr.data(), constexpr_arr_view.data());
|
||||
static_assert(constexpr_arr.size() == constexpr_arr_view.size(), "");
|
||||
|
||||
const std::array<float, size> const_arr{};
|
||||
rtc::ArrayView<const float, size> const_arr_view(const_arr);
|
||||
EXPECT_EQ(const_arr.data(), const_arr_view.data());
|
||||
static_assert(const_arr.size() == const_arr_view.size(), "");
|
||||
|
||||
std::array<float, size> non_const_arr{};
|
||||
rtc::ArrayView<const float, size> non_const_arr_view(non_const_arr);
|
||||
EXPECT_EQ(non_const_arr.data(), non_const_arr_view.data());
|
||||
static_assert(non_const_arr.size() == non_const_arr_view.size(), "");
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestStdVector) {
|
||||
EXPECT_EQ(3u, Call<const int>(std::vector<int>{4, 5, 6}));
|
||||
std::vector<int> v;
|
||||
v.push_back(3);
|
||||
v.push_back(11);
|
||||
EXPECT_EQ(2u, Call<const int>(v));
|
||||
EXPECT_EQ(2u, Call<int>(v));
|
||||
// Call<unsigned int>(v); // Compile error, because incompatible types.
|
||||
ArrayView<int> x = v;
|
||||
EXPECT_EQ(2u, x.size());
|
||||
EXPECT_EQ(v.data(), x.data());
|
||||
ArrayView<const int> y;
|
||||
y = v;
|
||||
EXPECT_EQ(2u, y.size());
|
||||
EXPECT_EQ(v.data(), y.data());
|
||||
// ArrayView<double> d = v; // Compile error, because incompatible types.
|
||||
const std::vector<int> cv;
|
||||
EXPECT_EQ(0u, Call<const int>(cv));
|
||||
// Call<int>(cv); // Compile error, because can't drop const.
|
||||
ArrayView<const int> z = cv;
|
||||
EXPECT_EQ(0u, z.size());
|
||||
EXPECT_EQ(nullptr, z.data());
|
||||
// ArrayView<int> w = cv; // Compile error, because can't drop const.
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestRtcBuffer) {
|
||||
rtc::Buffer b = "so buffer";
|
||||
EXPECT_EQ(10u, Call<const uint8_t>(b));
|
||||
EXPECT_EQ(10u, Call<uint8_t>(b));
|
||||
// Call<int8_t>(b); // Compile error, because incompatible types.
|
||||
ArrayView<uint8_t> x = b;
|
||||
EXPECT_EQ(10u, x.size());
|
||||
EXPECT_EQ(b.data(), x.data());
|
||||
ArrayView<const uint8_t> y;
|
||||
y = b;
|
||||
EXPECT_EQ(10u, y.size());
|
||||
EXPECT_EQ(b.data(), y.data());
|
||||
// ArrayView<char> d = b; // Compile error, because incompatible types.
|
||||
const rtc::Buffer cb = "very const";
|
||||
EXPECT_EQ(11u, Call<const uint8_t>(cb));
|
||||
// Call<uint8_t>(cb); // Compile error, because can't drop const.
|
||||
ArrayView<const uint8_t> z = cb;
|
||||
EXPECT_EQ(11u, z.size());
|
||||
EXPECT_EQ(cb.data(), z.data());
|
||||
// ArrayView<uint8_t> w = cb; // Compile error, because can't drop const.
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestSwapVariable) {
|
||||
const char arr[] = "Arrr!";
|
||||
const char aye[] = "Aye, Cap'n!";
|
||||
ArrayView<const char> x(arr);
|
||||
EXPECT_EQ(6u, x.size());
|
||||
EXPECT_EQ(arr, x.data());
|
||||
ArrayView<const char> y(aye);
|
||||
EXPECT_EQ(12u, y.size());
|
||||
EXPECT_EQ(aye, y.data());
|
||||
using std::swap;
|
||||
swap(x, y);
|
||||
EXPECT_EQ(12u, x.size());
|
||||
EXPECT_EQ(aye, x.data());
|
||||
EXPECT_EQ(6u, y.size());
|
||||
EXPECT_EQ(arr, y.data());
|
||||
// ArrayView<char> z;
|
||||
// swap(x, z); // Compile error, because can't drop const.
|
||||
}
|
||||
|
||||
TEST(FixArrayViewTest, TestSwapFixed) {
|
||||
const char arr[] = "Arr!";
|
||||
char aye[] = "Aye!";
|
||||
ArrayView<const char, 5> x(arr);
|
||||
EXPECT_EQ(arr, x.data());
|
||||
ArrayView<const char, 5> y(aye);
|
||||
EXPECT_EQ(aye, y.data());
|
||||
using std::swap;
|
||||
swap(x, y);
|
||||
EXPECT_EQ(aye, x.data());
|
||||
EXPECT_EQ(arr, y.data());
|
||||
// ArrayView<char, 5> z(aye);
|
||||
// swap(x, z); // Compile error, because can't drop const.
|
||||
// ArrayView<const char, 4> w(aye, 4);
|
||||
// swap(x, w); // Compile error, because different sizes.
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestIndexing) {
|
||||
char arr[] = "abcdefg";
|
||||
ArrayView<char> x(arr);
|
||||
const ArrayView<char> y(arr);
|
||||
ArrayView<const char, 8> z(arr);
|
||||
EXPECT_EQ(8u, x.size());
|
||||
EXPECT_EQ(8u, y.size());
|
||||
EXPECT_EQ(8u, z.size());
|
||||
EXPECT_EQ('b', x[1]);
|
||||
EXPECT_EQ('c', y[2]);
|
||||
EXPECT_EQ('d', z[3]);
|
||||
x[3] = 'X';
|
||||
y[2] = 'Y';
|
||||
// z[1] = 'Z'; // Compile error, because z's element type is const char.
|
||||
EXPECT_EQ('b', x[1]);
|
||||
EXPECT_EQ('Y', y[2]);
|
||||
EXPECT_EQ('X', z[3]);
|
||||
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
||||
EXPECT_DEATH(z[8], ""); // DCHECK error (index out of bounds).
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestIterationEmpty) {
|
||||
// Variable-size.
|
||||
ArrayView<std::vector<std::vector<std::vector<std::string>>>> av;
|
||||
EXPECT_EQ(av.begin(), av.end());
|
||||
EXPECT_EQ(av.cbegin(), av.cend());
|
||||
for (auto& e : av) {
|
||||
EXPECT_TRUE(false);
|
||||
EXPECT_EQ(42u, e.size()); // Dummy use of e to prevent unused var warning.
|
||||
}
|
||||
|
||||
// Fixed-size.
|
||||
ArrayView<std::vector<std::vector<std::vector<std::string>>>, 0> af;
|
||||
EXPECT_EQ(af.begin(), af.end());
|
||||
EXPECT_EQ(af.cbegin(), af.cend());
|
||||
for (auto& e : af) {
|
||||
EXPECT_TRUE(false);
|
||||
EXPECT_EQ(42u, e.size()); // Dummy use of e to prevent unused var warning.
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestIterationVariable) {
|
||||
char arr[] = "Arrr!";
|
||||
ArrayView<char> av(arr);
|
||||
EXPECT_EQ('A', *av.begin());
|
||||
EXPECT_EQ('A', *av.cbegin());
|
||||
EXPECT_EQ('\0', *(av.end() - 1));
|
||||
EXPECT_EQ('\0', *(av.cend() - 1));
|
||||
char i = 0;
|
||||
for (auto& e : av) {
|
||||
EXPECT_EQ(arr + i, &e);
|
||||
e = 's' + i;
|
||||
++i;
|
||||
}
|
||||
i = 0;
|
||||
for (auto& e : ArrayView<const char>(av)) {
|
||||
EXPECT_EQ(arr + i, &e);
|
||||
// e = 'q' + i; // Compile error, because e is a const char&.
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestIterationFixed) {
|
||||
char arr[] = "Arrr!";
|
||||
ArrayView<char, 6> av(arr);
|
||||
EXPECT_EQ('A', *av.begin());
|
||||
EXPECT_EQ('A', *av.cbegin());
|
||||
EXPECT_EQ('\0', *(av.end() - 1));
|
||||
EXPECT_EQ('\0', *(av.cend() - 1));
|
||||
char i = 0;
|
||||
for (auto& e : av) {
|
||||
EXPECT_EQ(arr + i, &e);
|
||||
e = 's' + i;
|
||||
++i;
|
||||
}
|
||||
i = 0;
|
||||
for (auto& e : ArrayView<const char, 6>(av)) {
|
||||
EXPECT_EQ(arr + i, &e);
|
||||
// e = 'q' + i; // Compile error, because e is a const char&.
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestEmpty) {
|
||||
EXPECT_TRUE(ArrayView<int>().empty());
|
||||
const int a[] = {1, 2, 3};
|
||||
EXPECT_FALSE(ArrayView<const int>(a).empty());
|
||||
|
||||
static_assert(ArrayView<int, 0>::empty(), "");
|
||||
static_assert(!ArrayView<int, 3>::empty(), "");
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestCompare) {
|
||||
int a[] = {1, 2, 3};
|
||||
int b[] = {1, 2, 3};
|
||||
|
||||
EXPECT_EQ(ArrayView<int>(a), ArrayView<int>(a));
|
||||
EXPECT_EQ((ArrayView<int, 3>(a)), (ArrayView<int, 3>(a)));
|
||||
EXPECT_EQ(ArrayView<int>(a), (ArrayView<int, 3>(a)));
|
||||
EXPECT_EQ(ArrayView<int>(), ArrayView<int>());
|
||||
EXPECT_EQ(ArrayView<int>(), ArrayView<int>(a, 0));
|
||||
EXPECT_EQ(ArrayView<int>(a, 0), ArrayView<int>(b, 0));
|
||||
EXPECT_EQ((ArrayView<int, 0>(a, 0)), ArrayView<int>());
|
||||
|
||||
EXPECT_NE(ArrayView<int>(a), ArrayView<int>(b));
|
||||
EXPECT_NE((ArrayView<int, 3>(a)), (ArrayView<int, 3>(b)));
|
||||
EXPECT_NE((ArrayView<int, 3>(a)), ArrayView<int>(b));
|
||||
EXPECT_NE(ArrayView<int>(a), ArrayView<int>());
|
||||
EXPECT_NE(ArrayView<int>(a), ArrayView<int>(a, 2));
|
||||
EXPECT_NE((ArrayView<int, 3>(a)), (ArrayView<int, 2>(a, 2)));
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestSubViewVariable) {
|
||||
int a[] = {1, 2, 3};
|
||||
ArrayView<int> av(a);
|
||||
|
||||
EXPECT_EQ(av.subview(0), av);
|
||||
|
||||
EXPECT_THAT(av.subview(1), ElementsAre(2, 3));
|
||||
EXPECT_THAT(av.subview(2), ElementsAre(3));
|
||||
EXPECT_THAT(av.subview(3), IsEmpty());
|
||||
EXPECT_THAT(av.subview(4), IsEmpty());
|
||||
|
||||
EXPECT_THAT(av.subview(1, 0), IsEmpty());
|
||||
EXPECT_THAT(av.subview(1, 1), ElementsAre(2));
|
||||
EXPECT_THAT(av.subview(1, 2), ElementsAre(2, 3));
|
||||
EXPECT_THAT(av.subview(1, 3), ElementsAre(2, 3));
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestSubViewFixed) {
|
||||
int a[] = {1, 2, 3};
|
||||
ArrayView<int, 3> av(a);
|
||||
|
||||
EXPECT_EQ(av.subview(0), av);
|
||||
|
||||
EXPECT_THAT(av.subview(1), ElementsAre(2, 3));
|
||||
EXPECT_THAT(av.subview(2), ElementsAre(3));
|
||||
EXPECT_THAT(av.subview(3), IsEmpty());
|
||||
EXPECT_THAT(av.subview(4), IsEmpty());
|
||||
|
||||
EXPECT_THAT(av.subview(1, 0), IsEmpty());
|
||||
EXPECT_THAT(av.subview(1, 1), ElementsAre(2));
|
||||
EXPECT_THAT(av.subview(1, 2), ElementsAre(2, 3));
|
||||
EXPECT_THAT(av.subview(1, 3), ElementsAre(2, 3));
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestReinterpretCastFixedSize) {
|
||||
uint8_t bytes[] = {1, 2, 3};
|
||||
ArrayView<uint8_t, 3> uint8_av(bytes);
|
||||
ArrayView<int8_t, 3> int8_av = reinterpret_array_view<int8_t>(uint8_av);
|
||||
EXPECT_EQ(int8_av.size(), uint8_av.size());
|
||||
EXPECT_EQ(int8_av[0], 1);
|
||||
EXPECT_EQ(int8_av[1], 2);
|
||||
EXPECT_EQ(int8_av[2], 3);
|
||||
}
|
||||
|
||||
TEST(ArrayViewTest, TestReinterpretCastVariableSize) {
|
||||
std::vector<int8_t> v = {1, 2, 3};
|
||||
ArrayView<int8_t> int8_av(v);
|
||||
ArrayView<uint8_t> uint8_av = reinterpret_array_view<uint8_t>(int8_av);
|
||||
EXPECT_EQ(int8_av.size(), uint8_av.size());
|
||||
EXPECT_EQ(uint8_av[0], 1);
|
||||
EXPECT_EQ(uint8_av[1], 2);
|
||||
EXPECT_EQ(uint8_av[2], 3);
|
||||
}
|
||||
} // namespace rtc
|
32
api/async_resolver_factory.h
Normal file
32
api/async_resolver_factory.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_ASYNC_RESOLVER_FACTORY_H_
|
||||
#define API_ASYNC_RESOLVER_FACTORY_H_
|
||||
|
||||
#include "rtc_base/async_resolver_interface.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// An abstract factory for creating AsyncResolverInterfaces. This allows
|
||||
// client applications to provide WebRTC with their own mechanism for
|
||||
// performing DNS resolution.
|
||||
class AsyncResolverFactory {
|
||||
public:
|
||||
AsyncResolverFactory() = default;
|
||||
virtual ~AsyncResolverFactory() = default;
|
||||
|
||||
// The caller should call Destroy on the returned object to delete it.
|
||||
virtual rtc::AsyncResolverInterface* Create() = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_ASYNC_RESOLVER_FACTORY_H_
|
89
api/audio/BUILD.gn
Normal file
89
api/audio/BUILD.gn
Normal file
@ -0,0 +1,89 @@
|
||||
# Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("../../webrtc.gni")
|
||||
|
||||
rtc_library("audio_frame_api") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"audio_frame.cc",
|
||||
"audio_frame.h",
|
||||
"channel_layout.cc",
|
||||
"channel_layout.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"..:rtp_packet_info",
|
||||
"../../rtc_base:checks",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("audio_mixer_api") {
|
||||
visibility = [ "*" ]
|
||||
sources = [ "audio_mixer.h" ]
|
||||
|
||||
deps = [
|
||||
":audio_frame_api",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("aec3_config") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"echo_canceller3_config.cc",
|
||||
"echo_canceller3_config.h",
|
||||
]
|
||||
deps = [
|
||||
"../../rtc_base:checks",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"../../rtc_base:safe_minmax",
|
||||
"../../rtc_base/system:rtc_export",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("aec3_config_json") {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "rtc_json" ]
|
||||
sources = [
|
||||
"echo_canceller3_config_json.cc",
|
||||
"echo_canceller3_config_json.h",
|
||||
]
|
||||
deps = [
|
||||
":aec3_config",
|
||||
"../../rtc_base:checks",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"../../rtc_base:rtc_json",
|
||||
"../../rtc_base/system:rtc_export",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("aec3_factory") {
|
||||
visibility = [ "*" ]
|
||||
configs += [ "../../modules/audio_processing:apm_debug_dump" ]
|
||||
sources = [
|
||||
"echo_canceller3_factory.cc",
|
||||
"echo_canceller3_factory.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":aec3_config",
|
||||
":echo_control",
|
||||
"../../modules/audio_processing/aec3",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"../../rtc_base/system:rtc_export",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("echo_control") {
|
||||
visibility = [ "*" ]
|
||||
sources = [ "echo_control.h" ]
|
||||
deps = [ "../../rtc_base:checks" ]
|
||||
}
|
2
api/audio/OWNERS.webrtc
Normal file
2
api/audio/OWNERS.webrtc
Normal file
@ -0,0 +1,2 @@
|
||||
gustaf@webrtc.org
|
||||
peah@webrtc.org
|
140
api/audio/audio_frame.cc
Normal file
140
api/audio/audio_frame.cc
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio/audio_frame.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/time_utils.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
AudioFrame::AudioFrame() {
|
||||
// Visual Studio doesn't like this in the class definition.
|
||||
static_assert(sizeof(data_) == kMaxDataSizeBytes, "kMaxDataSizeBytes");
|
||||
}
|
||||
|
||||
void AudioFrame::Reset() {
|
||||
ResetWithoutMuting();
|
||||
muted_ = true;
|
||||
}
|
||||
|
||||
void AudioFrame::ResetWithoutMuting() {
|
||||
// TODO(wu): Zero is a valid value for |timestamp_|. We should initialize
|
||||
// to an invalid value, or add a new member to indicate invalidity.
|
||||
timestamp_ = 0;
|
||||
elapsed_time_ms_ = -1;
|
||||
ntp_time_ms_ = -1;
|
||||
samples_per_channel_ = 0;
|
||||
sample_rate_hz_ = 0;
|
||||
num_channels_ = 0;
|
||||
channel_layout_ = CHANNEL_LAYOUT_NONE;
|
||||
speech_type_ = kUndefined;
|
||||
vad_activity_ = kVadUnknown;
|
||||
profile_timestamp_ms_ = 0;
|
||||
packet_infos_ = RtpPacketInfos();
|
||||
absolute_capture_timestamp_ms_ = absl::nullopt;
|
||||
}
|
||||
|
||||
void AudioFrame::UpdateFrame(uint32_t timestamp,
|
||||
const int16_t* data,
|
||||
size_t samples_per_channel,
|
||||
int sample_rate_hz,
|
||||
SpeechType speech_type,
|
||||
VADActivity vad_activity,
|
||||
size_t num_channels) {
|
||||
timestamp_ = timestamp;
|
||||
samples_per_channel_ = samples_per_channel;
|
||||
sample_rate_hz_ = sample_rate_hz;
|
||||
speech_type_ = speech_type;
|
||||
vad_activity_ = vad_activity;
|
||||
num_channels_ = num_channels;
|
||||
channel_layout_ = GuessChannelLayout(num_channels);
|
||||
if (channel_layout_ != CHANNEL_LAYOUT_UNSUPPORTED) {
|
||||
RTC_DCHECK_EQ(num_channels, ChannelLayoutToChannelCount(channel_layout_));
|
||||
}
|
||||
|
||||
const size_t length = samples_per_channel * num_channels;
|
||||
RTC_CHECK_LE(length, kMaxDataSizeSamples);
|
||||
if (data != nullptr) {
|
||||
memcpy(data_, data, sizeof(int16_t) * length);
|
||||
muted_ = false;
|
||||
} else {
|
||||
muted_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioFrame::CopyFrom(const AudioFrame& src) {
|
||||
if (this == &src)
|
||||
return;
|
||||
|
||||
timestamp_ = src.timestamp_;
|
||||
elapsed_time_ms_ = src.elapsed_time_ms_;
|
||||
ntp_time_ms_ = src.ntp_time_ms_;
|
||||
packet_infos_ = src.packet_infos_;
|
||||
muted_ = src.muted();
|
||||
samples_per_channel_ = src.samples_per_channel_;
|
||||
sample_rate_hz_ = src.sample_rate_hz_;
|
||||
speech_type_ = src.speech_type_;
|
||||
vad_activity_ = src.vad_activity_;
|
||||
num_channels_ = src.num_channels_;
|
||||
channel_layout_ = src.channel_layout_;
|
||||
absolute_capture_timestamp_ms_ = src.absolute_capture_timestamp_ms();
|
||||
|
||||
const size_t length = samples_per_channel_ * num_channels_;
|
||||
RTC_CHECK_LE(length, kMaxDataSizeSamples);
|
||||
if (!src.muted()) {
|
||||
memcpy(data_, src.data(), sizeof(int16_t) * length);
|
||||
muted_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioFrame::UpdateProfileTimeStamp() {
|
||||
profile_timestamp_ms_ = rtc::TimeMillis();
|
||||
}
|
||||
|
||||
int64_t AudioFrame::ElapsedProfileTimeMs() const {
|
||||
if (profile_timestamp_ms_ == 0) {
|
||||
// Profiling has not been activated.
|
||||
return -1;
|
||||
}
|
||||
return rtc::TimeSince(profile_timestamp_ms_);
|
||||
}
|
||||
|
||||
const int16_t* AudioFrame::data() const {
|
||||
return muted_ ? empty_data() : data_;
|
||||
}
|
||||
|
||||
// TODO(henrik.lundin) Can we skip zeroing the buffer?
|
||||
// See https://bugs.chromium.org/p/webrtc/issues/detail?id=5647.
|
||||
int16_t* AudioFrame::mutable_data() {
|
||||
if (muted_) {
|
||||
memset(data_, 0, kMaxDataSizeBytes);
|
||||
muted_ = false;
|
||||
}
|
||||
return data_;
|
||||
}
|
||||
|
||||
void AudioFrame::Mute() {
|
||||
muted_ = true;
|
||||
}
|
||||
|
||||
bool AudioFrame::muted() const {
|
||||
return muted_;
|
||||
}
|
||||
|
||||
// static
|
||||
const int16_t* AudioFrame::empty_data() {
|
||||
static int16_t* null_data = new int16_t[kMaxDataSizeSamples]();
|
||||
return &null_data[0];
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
173
api/audio/audio_frame.h
Normal file
173
api/audio/audio_frame.h
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_AUDIO_FRAME_H_
|
||||
#define API_AUDIO_AUDIO_FRAME_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "api/audio/channel_layout.h"
|
||||
#include "api/rtp_packet_infos.h"
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
/* This class holds up to 120 ms of super-wideband (32 kHz) stereo audio. It
|
||||
* allows for adding and subtracting frames while keeping track of the resulting
|
||||
* states.
|
||||
*
|
||||
* Notes
|
||||
* - This is a de-facto api, not designed for external use. The AudioFrame class
|
||||
* is in need of overhaul or even replacement, and anyone depending on it
|
||||
* should be prepared for that.
|
||||
* - The total number of samples is samples_per_channel_ * num_channels_.
|
||||
* - Stereo data is interleaved starting with the left channel.
|
||||
*/
|
||||
class AudioFrame {
|
||||
public:
|
||||
// Using constexpr here causes linker errors unless the variable also has an
|
||||
// out-of-class definition, which is impractical in this header-only class.
|
||||
// (This makes no sense because it compiles as an enum value, which we most
|
||||
// certainly cannot take the address of, just fine.) C++17 introduces inline
|
||||
// variables which should allow us to switch to constexpr and keep this a
|
||||
// header-only class.
|
||||
enum : size_t {
|
||||
// Stereo, 32 kHz, 120 ms (2 * 32 * 120)
|
||||
// Stereo, 192 kHz, 20 ms (2 * 192 * 20)
|
||||
kMaxDataSizeSamples = 7680,
|
||||
kMaxDataSizeBytes = kMaxDataSizeSamples * sizeof(int16_t),
|
||||
};
|
||||
|
||||
enum VADActivity { kVadActive = 0, kVadPassive = 1, kVadUnknown = 2 };
|
||||
enum SpeechType {
|
||||
kNormalSpeech = 0,
|
||||
kPLC = 1,
|
||||
kCNG = 2,
|
||||
kPLCCNG = 3,
|
||||
kCodecPLC = 5,
|
||||
kUndefined = 4
|
||||
};
|
||||
|
||||
AudioFrame();
|
||||
|
||||
// Resets all members to their default state.
|
||||
void Reset();
|
||||
// Same as Reset(), but leaves mute state unchanged. Muting a frame requires
|
||||
// the buffer to be zeroed on the next call to mutable_data(). Callers
|
||||
// intending to write to the buffer immediately after Reset() can instead use
|
||||
// ResetWithoutMuting() to skip this wasteful zeroing.
|
||||
void ResetWithoutMuting();
|
||||
|
||||
void UpdateFrame(uint32_t timestamp,
|
||||
const int16_t* data,
|
||||
size_t samples_per_channel,
|
||||
int sample_rate_hz,
|
||||
SpeechType speech_type,
|
||||
VADActivity vad_activity,
|
||||
size_t num_channels = 1);
|
||||
|
||||
void CopyFrom(const AudioFrame& src);
|
||||
|
||||
// Sets a wall-time clock timestamp in milliseconds to be used for profiling
|
||||
// of time between two points in the audio chain.
|
||||
// Example:
|
||||
// t0: UpdateProfileTimeStamp()
|
||||
// t1: ElapsedProfileTimeMs() => t1 - t0 [msec]
|
||||
void UpdateProfileTimeStamp();
|
||||
// Returns the time difference between now and when UpdateProfileTimeStamp()
|
||||
// was last called. Returns -1 if UpdateProfileTimeStamp() has not yet been
|
||||
// called.
|
||||
int64_t ElapsedProfileTimeMs() const;
|
||||
|
||||
// data() returns a zeroed static buffer if the frame is muted.
|
||||
// mutable_frame() always returns a non-static buffer; the first call to
|
||||
// mutable_frame() zeros the non-static buffer and marks the frame unmuted.
|
||||
const int16_t* data() const;
|
||||
int16_t* mutable_data();
|
||||
|
||||
// Prefer to mute frames using AudioFrameOperations::Mute.
|
||||
void Mute();
|
||||
// Frame is muted by default.
|
||||
bool muted() const;
|
||||
|
||||
size_t max_16bit_samples() const { return kMaxDataSizeSamples; }
|
||||
size_t samples_per_channel() const { return samples_per_channel_; }
|
||||
size_t num_channels() const { return num_channels_; }
|
||||
ChannelLayout channel_layout() const { return channel_layout_; }
|
||||
int sample_rate_hz() const { return sample_rate_hz_; }
|
||||
|
||||
void set_absolute_capture_timestamp_ms(
|
||||
int64_t absolute_capture_time_stamp_ms) {
|
||||
absolute_capture_timestamp_ms_ = absolute_capture_time_stamp_ms;
|
||||
}
|
||||
|
||||
absl::optional<int64_t> absolute_capture_timestamp_ms() const {
|
||||
return absolute_capture_timestamp_ms_;
|
||||
}
|
||||
|
||||
// RTP timestamp of the first sample in the AudioFrame.
|
||||
uint32_t timestamp_ = 0;
|
||||
// Time since the first frame in milliseconds.
|
||||
// -1 represents an uninitialized value.
|
||||
int64_t elapsed_time_ms_ = -1;
|
||||
// NTP time of the estimated capture time in local timebase in milliseconds.
|
||||
// -1 represents an uninitialized value.
|
||||
int64_t ntp_time_ms_ = -1;
|
||||
size_t samples_per_channel_ = 0;
|
||||
int sample_rate_hz_ = 0;
|
||||
size_t num_channels_ = 0;
|
||||
ChannelLayout channel_layout_ = CHANNEL_LAYOUT_NONE;
|
||||
SpeechType speech_type_ = kUndefined;
|
||||
VADActivity vad_activity_ = kVadUnknown;
|
||||
// Monotonically increasing timestamp intended for profiling of audio frames.
|
||||
// Typically used for measuring elapsed time between two different points in
|
||||
// the audio path. No lock is used to save resources and we are thread safe
|
||||
// by design.
|
||||
// TODO(nisse@webrtc.org): consider using absl::optional.
|
||||
int64_t profile_timestamp_ms_ = 0;
|
||||
|
||||
// Information about packets used to assemble this audio frame. This is needed
|
||||
// by |SourceTracker| when the frame is delivered to the RTCRtpReceiver's
|
||||
// MediaStreamTrack, in order to implement getContributingSources(). See:
|
||||
// https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-getcontributingsources
|
||||
//
|
||||
// TODO(bugs.webrtc.org/10757):
|
||||
// Note that this information might not be fully accurate since we currently
|
||||
// don't have a proper way to track it across the audio sync buffer. The
|
||||
// sync buffer is the small sample-holding buffer located after the audio
|
||||
// decoder and before where samples are assembled into output frames.
|
||||
//
|
||||
// |RtpPacketInfos| may also be empty if the audio samples did not come from
|
||||
// RTP packets. E.g. if the audio were locally generated by packet loss
|
||||
// concealment, comfort noise generation, etc.
|
||||
RtpPacketInfos packet_infos_;
|
||||
|
||||
private:
|
||||
// A permanently zeroed out buffer to represent muted frames. This is a
|
||||
// header-only class, so the only way to avoid creating a separate empty
|
||||
// buffer per translation unit is to wrap a static in an inline function.
|
||||
static const int16_t* empty_data();
|
||||
|
||||
int16_t data_[kMaxDataSizeSamples];
|
||||
bool muted_ = true;
|
||||
|
||||
// Absolute capture timestamp when this audio frame was originally captured.
|
||||
// This is only valid for audio frames captured on this machine. The absolute
|
||||
// capture timestamp of a received frame is found in |packet_infos_|.
|
||||
// This timestamp MUST be based on the same clock as rtc::TimeMillis().
|
||||
absl::optional<int64_t> absolute_capture_timestamp_ms_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(AudioFrame);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_AUDIO_FRAME_H_
|
80
api/audio/audio_mixer.h
Normal file
80
api/audio/audio_mixer.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_AUDIO_MIXER_H_
|
||||
#define API_AUDIO_AUDIO_MIXER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "api/audio/audio_frame.h"
|
||||
#include "rtc_base/ref_count.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// WORK IN PROGRESS
|
||||
// This class is under development and is not yet intended for for use outside
|
||||
// of WebRtc/Libjingle.
|
||||
class AudioMixer : public rtc::RefCountInterface {
|
||||
public:
|
||||
// A callback class that all mixer participants must inherit from/implement.
|
||||
class Source {
|
||||
public:
|
||||
enum class AudioFrameInfo {
|
||||
kNormal, // The samples in audio_frame are valid and should be used.
|
||||
kMuted, // The samples in audio_frame should not be used, but
|
||||
// should be implicitly interpreted as zero. Other
|
||||
// fields in audio_frame may be read and should
|
||||
// contain meaningful values.
|
||||
kError, // The audio_frame will not be used.
|
||||
};
|
||||
|
||||
// Overwrites |audio_frame|. The data_ field is overwritten with
|
||||
// 10 ms of new audio (either 1 or 2 interleaved channels) at
|
||||
// |sample_rate_hz|. All fields in |audio_frame| must be updated.
|
||||
virtual AudioFrameInfo GetAudioFrameWithInfo(int sample_rate_hz,
|
||||
AudioFrame* audio_frame) = 0;
|
||||
|
||||
// A way for a mixer implementation to distinguish participants.
|
||||
virtual int Ssrc() const = 0;
|
||||
|
||||
// A way for this source to say that GetAudioFrameWithInfo called
|
||||
// with this sample rate or higher will not cause quality loss.
|
||||
virtual int PreferredSampleRate() const = 0;
|
||||
|
||||
virtual ~Source() {}
|
||||
};
|
||||
|
||||
// Returns true if adding was successful. A source is never added
|
||||
// twice. Addition and removal can happen on different threads.
|
||||
virtual bool AddSource(Source* audio_source) = 0;
|
||||
|
||||
// Removal is never attempted if a source has not been successfully
|
||||
// added to the mixer.
|
||||
virtual void RemoveSource(Source* audio_source) = 0;
|
||||
|
||||
// Performs mixing by asking registered audio sources for audio. The
|
||||
// mixed result is placed in the provided AudioFrame. This method
|
||||
// will only be called from a single thread. The channels argument
|
||||
// specifies the number of channels of the mix result. The mixer
|
||||
// should mix at a rate that doesn't cause quality loss of the
|
||||
// sources' audio. The mixing rate is one of the rates listed in
|
||||
// AudioProcessing::NativeRate. All fields in
|
||||
// |audio_frame_for_mixing| must be updated.
|
||||
virtual void Mix(size_t number_of_channels,
|
||||
AudioFrame* audio_frame_for_mixing) = 0;
|
||||
|
||||
protected:
|
||||
// Since the mixer is reference counted, the destructor may be
|
||||
// called from any thread.
|
||||
~AudioMixer() override {}
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_AUDIO_MIXER_H_
|
282
api/audio/channel_layout.cc
Normal file
282
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_NOTREACHED() << "Invalid channel layout provided: " << layout;
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
165
api/audio/channel_layout.h
Normal file
165
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_
|
270
api/audio/echo_canceller3_config.cc
Normal file
270
api/audio/echo_canceller3_config.cc
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* 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->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->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.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
|
227
api/audio/echo_canceller3_config.h
Normal file
227
api/audio/echo_canceller3_config.h
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* 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_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};
|
||||
} 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;
|
||||
bool conservative_initial_phase = false;
|
||||
bool enable_coarse_filter_output_usage = true;
|
||||
bool use_linear_filter = true;
|
||||
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;
|
||||
bool echo_can_saturate = true;
|
||||
bool bounded_erl = false;
|
||||
} 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;
|
||||
} 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);
|
||||
|
||||
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;
|
||||
} 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 = 25.f;
|
||||
float anti_howling_gain = 0.01f;
|
||||
} high_bands_suppression;
|
||||
|
||||
float floor_first_increase = 0.00001f;
|
||||
} suppressor;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_ECHO_CANCELLER3_CONFIG_H_
|
682
api/audio/echo_canceller3_config_json.cc
Normal file
682
api/audio/echo_canceller3_config_json.cc
Normal file
@ -0,0 +1,682 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include "api/audio/echo_canceller3_config_json.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/strings/json.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
void ReadParam(const Json::Value& root, std::string param_name, bool* param) {
|
||||
RTC_DCHECK(param);
|
||||
bool v;
|
||||
if (rtc::GetBoolFromJsonObject(root, param_name, &v)) {
|
||||
*param = v;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadParam(const Json::Value& root, std::string param_name, size_t* param) {
|
||||
RTC_DCHECK(param);
|
||||
int v;
|
||||
if (rtc::GetIntFromJsonObject(root, param_name, &v) && v >= 0) {
|
||||
*param = v;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadParam(const Json::Value& root, std::string param_name, int* param) {
|
||||
RTC_DCHECK(param);
|
||||
int v;
|
||||
if (rtc::GetIntFromJsonObject(root, param_name, &v)) {
|
||||
*param = v;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadParam(const Json::Value& root, std::string param_name, float* param) {
|
||||
RTC_DCHECK(param);
|
||||
double v;
|
||||
if (rtc::GetDoubleFromJsonObject(root, param_name, &v)) {
|
||||
*param = static_cast<float>(v);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadParam(const Json::Value& root,
|
||||
std::string param_name,
|
||||
EchoCanceller3Config::Filter::RefinedConfiguration* param) {
|
||||
RTC_DCHECK(param);
|
||||
Json::Value json_array;
|
||||
if (rtc::GetValueFromJsonObject(root, param_name, &json_array)) {
|
||||
std::vector<double> v;
|
||||
rtc::JsonArrayToDoubleVector(json_array, &v);
|
||||
if (v.size() != 6) {
|
||||
RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name;
|
||||
return;
|
||||
}
|
||||
param->length_blocks = static_cast<size_t>(v[0]);
|
||||
param->leakage_converged = static_cast<float>(v[1]);
|
||||
param->leakage_diverged = static_cast<float>(v[2]);
|
||||
param->error_floor = static_cast<float>(v[3]);
|
||||
param->error_ceil = static_cast<float>(v[4]);
|
||||
param->noise_gate = static_cast<float>(v[5]);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadParam(const Json::Value& root,
|
||||
std::string param_name,
|
||||
EchoCanceller3Config::Filter::CoarseConfiguration* param) {
|
||||
RTC_DCHECK(param);
|
||||
Json::Value json_array;
|
||||
if (rtc::GetValueFromJsonObject(root, param_name, &json_array)) {
|
||||
std::vector<double> v;
|
||||
rtc::JsonArrayToDoubleVector(json_array, &v);
|
||||
if (v.size() != 3) {
|
||||
RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name;
|
||||
return;
|
||||
}
|
||||
param->length_blocks = static_cast<size_t>(v[0]);
|
||||
param->rate = static_cast<float>(v[1]);
|
||||
param->noise_gate = static_cast<float>(v[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadParam(const Json::Value& root,
|
||||
std::string param_name,
|
||||
EchoCanceller3Config::Delay::AlignmentMixing* param) {
|
||||
RTC_DCHECK(param);
|
||||
|
||||
Json::Value subsection;
|
||||
if (rtc::GetValueFromJsonObject(root, param_name, &subsection)) {
|
||||
ReadParam(subsection, "downmix", ¶m->downmix);
|
||||
ReadParam(subsection, "adaptive_selection", ¶m->adaptive_selection);
|
||||
ReadParam(subsection, "activity_power_threshold",
|
||||
¶m->activity_power_threshold);
|
||||
ReadParam(subsection, "prefer_first_two_channels",
|
||||
¶m->prefer_first_two_channels);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadParam(
|
||||
const Json::Value& root,
|
||||
std::string param_name,
|
||||
EchoCanceller3Config::Suppressor::SubbandNearendDetection::SubbandRegion*
|
||||
param) {
|
||||
RTC_DCHECK(param);
|
||||
Json::Value json_array;
|
||||
if (rtc::GetValueFromJsonObject(root, param_name, &json_array)) {
|
||||
std::vector<int> v;
|
||||
rtc::JsonArrayToIntVector(json_array, &v);
|
||||
if (v.size() != 2) {
|
||||
RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name;
|
||||
return;
|
||||
}
|
||||
param->low = static_cast<size_t>(v[0]);
|
||||
param->high = static_cast<size_t>(v[1]);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadParam(const Json::Value& root,
|
||||
std::string param_name,
|
||||
EchoCanceller3Config::Suppressor::MaskingThresholds* param) {
|
||||
RTC_DCHECK(param);
|
||||
Json::Value json_array;
|
||||
if (rtc::GetValueFromJsonObject(root, param_name, &json_array)) {
|
||||
std::vector<double> v;
|
||||
rtc::JsonArrayToDoubleVector(json_array, &v);
|
||||
if (v.size() != 3) {
|
||||
RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name;
|
||||
return;
|
||||
}
|
||||
param->enr_transparent = static_cast<float>(v[0]);
|
||||
param->enr_suppress = static_cast<float>(v[1]);
|
||||
param->emr_transparent = static_cast<float>(v[2]);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void Aec3ConfigFromJsonString(absl::string_view json_string,
|
||||
EchoCanceller3Config* config,
|
||||
bool* parsing_successful) {
|
||||
RTC_DCHECK(config);
|
||||
RTC_DCHECK(parsing_successful);
|
||||
EchoCanceller3Config& cfg = *config;
|
||||
cfg = EchoCanceller3Config();
|
||||
*parsing_successful = true;
|
||||
|
||||
Json::Value root;
|
||||
bool success = Json::Reader().parse(std::string(json_string), root);
|
||||
if (!success) {
|
||||
RTC_LOG(LS_ERROR) << "Incorrect JSON format: " << json_string;
|
||||
*parsing_successful = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Json::Value aec3_root;
|
||||
success = rtc::GetValueFromJsonObject(root, "aec3", &aec3_root);
|
||||
if (!success) {
|
||||
RTC_LOG(LS_ERROR) << "Missing AEC3 config field: " << json_string;
|
||||
*parsing_successful = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Json::Value section;
|
||||
if (rtc::GetValueFromJsonObject(aec3_root, "buffering", §ion)) {
|
||||
ReadParam(section, "excess_render_detection_interval_blocks",
|
||||
&cfg.buffering.excess_render_detection_interval_blocks);
|
||||
ReadParam(section, "max_allowed_excess_render_blocks",
|
||||
&cfg.buffering.max_allowed_excess_render_blocks);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(aec3_root, "delay", §ion)) {
|
||||
ReadParam(section, "default_delay", &cfg.delay.default_delay);
|
||||
ReadParam(section, "down_sampling_factor", &cfg.delay.down_sampling_factor);
|
||||
ReadParam(section, "num_filters", &cfg.delay.num_filters);
|
||||
ReadParam(section, "delay_headroom_samples",
|
||||
&cfg.delay.delay_headroom_samples);
|
||||
ReadParam(section, "hysteresis_limit_blocks",
|
||||
&cfg.delay.hysteresis_limit_blocks);
|
||||
ReadParam(section, "fixed_capture_delay_samples",
|
||||
&cfg.delay.fixed_capture_delay_samples);
|
||||
ReadParam(section, "delay_estimate_smoothing",
|
||||
&cfg.delay.delay_estimate_smoothing);
|
||||
ReadParam(section, "delay_candidate_detection_threshold",
|
||||
&cfg.delay.delay_candidate_detection_threshold);
|
||||
|
||||
Json::Value subsection;
|
||||
if (rtc::GetValueFromJsonObject(section, "delay_selection_thresholds",
|
||||
&subsection)) {
|
||||
ReadParam(subsection, "initial",
|
||||
&cfg.delay.delay_selection_thresholds.initial);
|
||||
ReadParam(subsection, "converged",
|
||||
&cfg.delay.delay_selection_thresholds.converged);
|
||||
}
|
||||
|
||||
ReadParam(section, "use_external_delay_estimator",
|
||||
&cfg.delay.use_external_delay_estimator);
|
||||
ReadParam(section, "log_warning_on_delay_changes",
|
||||
&cfg.delay.log_warning_on_delay_changes);
|
||||
|
||||
ReadParam(section, "render_alignment_mixing",
|
||||
&cfg.delay.render_alignment_mixing);
|
||||
ReadParam(section, "capture_alignment_mixing",
|
||||
&cfg.delay.capture_alignment_mixing);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(aec3_root, "filter", §ion)) {
|
||||
ReadParam(section, "refined", &cfg.filter.refined);
|
||||
ReadParam(section, "coarse", &cfg.filter.coarse);
|
||||
ReadParam(section, "refined_initial", &cfg.filter.refined_initial);
|
||||
ReadParam(section, "coarse_initial", &cfg.filter.coarse_initial);
|
||||
ReadParam(section, "config_change_duration_blocks",
|
||||
&cfg.filter.config_change_duration_blocks);
|
||||
ReadParam(section, "initial_state_seconds",
|
||||
&cfg.filter.initial_state_seconds);
|
||||
ReadParam(section, "conservative_initial_phase",
|
||||
&cfg.filter.conservative_initial_phase);
|
||||
ReadParam(section, "enable_coarse_filter_output_usage",
|
||||
&cfg.filter.enable_coarse_filter_output_usage);
|
||||
ReadParam(section, "use_linear_filter", &cfg.filter.use_linear_filter);
|
||||
ReadParam(section, "export_linear_aec_output",
|
||||
&cfg.filter.export_linear_aec_output);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(aec3_root, "erle", §ion)) {
|
||||
ReadParam(section, "min", &cfg.erle.min);
|
||||
ReadParam(section, "max_l", &cfg.erle.max_l);
|
||||
ReadParam(section, "max_h", &cfg.erle.max_h);
|
||||
ReadParam(section, "onset_detection", &cfg.erle.onset_detection);
|
||||
ReadParam(section, "num_sections", &cfg.erle.num_sections);
|
||||
ReadParam(section, "clamp_quality_estimate_to_zero",
|
||||
&cfg.erle.clamp_quality_estimate_to_zero);
|
||||
ReadParam(section, "clamp_quality_estimate_to_one",
|
||||
&cfg.erle.clamp_quality_estimate_to_one);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(aec3_root, "ep_strength", §ion)) {
|
||||
ReadParam(section, "default_gain", &cfg.ep_strength.default_gain);
|
||||
ReadParam(section, "default_len", &cfg.ep_strength.default_len);
|
||||
ReadParam(section, "echo_can_saturate", &cfg.ep_strength.echo_can_saturate);
|
||||
ReadParam(section, "bounded_erl", &cfg.ep_strength.bounded_erl);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(aec3_root, "echo_audibility", §ion)) {
|
||||
ReadParam(section, "low_render_limit",
|
||||
&cfg.echo_audibility.low_render_limit);
|
||||
ReadParam(section, "normal_render_limit",
|
||||
&cfg.echo_audibility.normal_render_limit);
|
||||
|
||||
ReadParam(section, "floor_power", &cfg.echo_audibility.floor_power);
|
||||
ReadParam(section, "audibility_threshold_lf",
|
||||
&cfg.echo_audibility.audibility_threshold_lf);
|
||||
ReadParam(section, "audibility_threshold_mf",
|
||||
&cfg.echo_audibility.audibility_threshold_mf);
|
||||
ReadParam(section, "audibility_threshold_hf",
|
||||
&cfg.echo_audibility.audibility_threshold_hf);
|
||||
ReadParam(section, "use_stationarity_properties",
|
||||
&cfg.echo_audibility.use_stationarity_properties);
|
||||
ReadParam(section, "use_stationarity_properties_at_init",
|
||||
&cfg.echo_audibility.use_stationarity_properties_at_init);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(aec3_root, "render_levels", §ion)) {
|
||||
ReadParam(section, "active_render_limit",
|
||||
&cfg.render_levels.active_render_limit);
|
||||
ReadParam(section, "poor_excitation_render_limit",
|
||||
&cfg.render_levels.poor_excitation_render_limit);
|
||||
ReadParam(section, "poor_excitation_render_limit_ds8",
|
||||
&cfg.render_levels.poor_excitation_render_limit_ds8);
|
||||
ReadParam(section, "render_power_gain_db",
|
||||
&cfg.render_levels.render_power_gain_db);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(aec3_root, "echo_removal_control",
|
||||
§ion)) {
|
||||
ReadParam(section, "has_clock_drift",
|
||||
&cfg.echo_removal_control.has_clock_drift);
|
||||
ReadParam(section, "linear_and_stable_echo_path",
|
||||
&cfg.echo_removal_control.linear_and_stable_echo_path);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(aec3_root, "echo_model", §ion)) {
|
||||
Json::Value subsection;
|
||||
ReadParam(section, "noise_floor_hold", &cfg.echo_model.noise_floor_hold);
|
||||
ReadParam(section, "min_noise_floor_power",
|
||||
&cfg.echo_model.min_noise_floor_power);
|
||||
ReadParam(section, "stationary_gate_slope",
|
||||
&cfg.echo_model.stationary_gate_slope);
|
||||
ReadParam(section, "noise_gate_power", &cfg.echo_model.noise_gate_power);
|
||||
ReadParam(section, "noise_gate_slope", &cfg.echo_model.noise_gate_slope);
|
||||
ReadParam(section, "render_pre_window_size",
|
||||
&cfg.echo_model.render_pre_window_size);
|
||||
ReadParam(section, "render_post_window_size",
|
||||
&cfg.echo_model.render_post_window_size);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(aec3_root, "comfort_noise", §ion)) {
|
||||
ReadParam(section, "noise_floor_dbfs", &cfg.comfort_noise.noise_floor_dbfs);
|
||||
}
|
||||
|
||||
Json::Value subsection;
|
||||
if (rtc::GetValueFromJsonObject(aec3_root, "suppressor", §ion)) {
|
||||
ReadParam(section, "nearend_average_blocks",
|
||||
&cfg.suppressor.nearend_average_blocks);
|
||||
|
||||
if (rtc::GetValueFromJsonObject(section, "normal_tuning", &subsection)) {
|
||||
ReadParam(subsection, "mask_lf", &cfg.suppressor.normal_tuning.mask_lf);
|
||||
ReadParam(subsection, "mask_hf", &cfg.suppressor.normal_tuning.mask_hf);
|
||||
ReadParam(subsection, "max_inc_factor",
|
||||
&cfg.suppressor.normal_tuning.max_inc_factor);
|
||||
ReadParam(subsection, "max_dec_factor_lf",
|
||||
&cfg.suppressor.normal_tuning.max_dec_factor_lf);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(section, "nearend_tuning", &subsection)) {
|
||||
ReadParam(subsection, "mask_lf", &cfg.suppressor.nearend_tuning.mask_lf);
|
||||
ReadParam(subsection, "mask_hf", &cfg.suppressor.nearend_tuning.mask_hf);
|
||||
ReadParam(subsection, "max_inc_factor",
|
||||
&cfg.suppressor.nearend_tuning.max_inc_factor);
|
||||
ReadParam(subsection, "max_dec_factor_lf",
|
||||
&cfg.suppressor.nearend_tuning.max_dec_factor_lf);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(section, "dominant_nearend_detection",
|
||||
&subsection)) {
|
||||
ReadParam(subsection, "enr_threshold",
|
||||
&cfg.suppressor.dominant_nearend_detection.enr_threshold);
|
||||
ReadParam(subsection, "enr_exit_threshold",
|
||||
&cfg.suppressor.dominant_nearend_detection.enr_exit_threshold);
|
||||
ReadParam(subsection, "snr_threshold",
|
||||
&cfg.suppressor.dominant_nearend_detection.snr_threshold);
|
||||
ReadParam(subsection, "hold_duration",
|
||||
&cfg.suppressor.dominant_nearend_detection.hold_duration);
|
||||
ReadParam(subsection, "trigger_threshold",
|
||||
&cfg.suppressor.dominant_nearend_detection.trigger_threshold);
|
||||
ReadParam(
|
||||
subsection, "use_during_initial_phase",
|
||||
&cfg.suppressor.dominant_nearend_detection.use_during_initial_phase);
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(section, "subband_nearend_detection",
|
||||
&subsection)) {
|
||||
ReadParam(
|
||||
subsection, "nearend_average_blocks",
|
||||
&cfg.suppressor.subband_nearend_detection.nearend_average_blocks);
|
||||
ReadParam(subsection, "subband1",
|
||||
&cfg.suppressor.subband_nearend_detection.subband1);
|
||||
ReadParam(subsection, "subband2",
|
||||
&cfg.suppressor.subband_nearend_detection.subband2);
|
||||
ReadParam(subsection, "nearend_threshold",
|
||||
&cfg.suppressor.subband_nearend_detection.nearend_threshold);
|
||||
ReadParam(subsection, "snr_threshold",
|
||||
&cfg.suppressor.subband_nearend_detection.snr_threshold);
|
||||
}
|
||||
|
||||
ReadParam(section, "use_subband_nearend_detection",
|
||||
&cfg.suppressor.use_subband_nearend_detection);
|
||||
|
||||
if (rtc::GetValueFromJsonObject(section, "high_bands_suppression",
|
||||
&subsection)) {
|
||||
ReadParam(subsection, "enr_threshold",
|
||||
&cfg.suppressor.high_bands_suppression.enr_threshold);
|
||||
ReadParam(subsection, "max_gain_during_echo",
|
||||
&cfg.suppressor.high_bands_suppression.max_gain_during_echo);
|
||||
ReadParam(subsection, "anti_howling_activation_threshold",
|
||||
&cfg.suppressor.high_bands_suppression
|
||||
.anti_howling_activation_threshold);
|
||||
ReadParam(subsection, "anti_howling_gain",
|
||||
&cfg.suppressor.high_bands_suppression.anti_howling_gain);
|
||||
}
|
||||
|
||||
ReadParam(section, "floor_first_increase",
|
||||
&cfg.suppressor.floor_first_increase);
|
||||
}
|
||||
}
|
||||
|
||||
EchoCanceller3Config Aec3ConfigFromJsonString(absl::string_view json_string) {
|
||||
EchoCanceller3Config cfg;
|
||||
bool not_used;
|
||||
Aec3ConfigFromJsonString(json_string, &cfg, ¬_used);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
std::string Aec3ConfigToJsonString(const EchoCanceller3Config& config) {
|
||||
rtc::StringBuilder ost;
|
||||
ost << "{";
|
||||
ost << "\"aec3\": {";
|
||||
ost << "\"buffering\": {";
|
||||
ost << "\"excess_render_detection_interval_blocks\": "
|
||||
<< config.buffering.excess_render_detection_interval_blocks << ",";
|
||||
ost << "\"max_allowed_excess_render_blocks\": "
|
||||
<< config.buffering.max_allowed_excess_render_blocks;
|
||||
ost << "},";
|
||||
|
||||
ost << "\"delay\": {";
|
||||
ost << "\"default_delay\": " << config.delay.default_delay << ",";
|
||||
ost << "\"down_sampling_factor\": " << config.delay.down_sampling_factor
|
||||
<< ",";
|
||||
ost << "\"num_filters\": " << config.delay.num_filters << ",";
|
||||
ost << "\"delay_headroom_samples\": " << config.delay.delay_headroom_samples
|
||||
<< ",";
|
||||
ost << "\"hysteresis_limit_blocks\": " << config.delay.hysteresis_limit_blocks
|
||||
<< ",";
|
||||
ost << "\"fixed_capture_delay_samples\": "
|
||||
<< config.delay.fixed_capture_delay_samples << ",";
|
||||
ost << "\"delay_estimate_smoothing\": "
|
||||
<< config.delay.delay_estimate_smoothing << ",";
|
||||
ost << "\"delay_candidate_detection_threshold\": "
|
||||
<< config.delay.delay_candidate_detection_threshold << ",";
|
||||
|
||||
ost << "\"delay_selection_thresholds\": {";
|
||||
ost << "\"initial\": " << config.delay.delay_selection_thresholds.initial
|
||||
<< ",";
|
||||
ost << "\"converged\": " << config.delay.delay_selection_thresholds.converged;
|
||||
ost << "},";
|
||||
|
||||
ost << "\"use_external_delay_estimator\": "
|
||||
<< (config.delay.use_external_delay_estimator ? "true" : "false") << ",";
|
||||
ost << "\"log_warning_on_delay_changes\": "
|
||||
<< (config.delay.log_warning_on_delay_changes ? "true" : "false") << ",";
|
||||
|
||||
ost << "\"render_alignment_mixing\": {";
|
||||
ost << "\"downmix\": "
|
||||
<< (config.delay.render_alignment_mixing.downmix ? "true" : "false")
|
||||
<< ",";
|
||||
ost << "\"adaptive_selection\": "
|
||||
<< (config.delay.render_alignment_mixing.adaptive_selection ? "true"
|
||||
: "false")
|
||||
<< ",";
|
||||
ost << "\"activity_power_threshold\": "
|
||||
<< config.delay.render_alignment_mixing.activity_power_threshold << ",";
|
||||
ost << "\"prefer_first_two_channels\": "
|
||||
<< (config.delay.render_alignment_mixing.prefer_first_two_channels
|
||||
? "true"
|
||||
: "false");
|
||||
ost << "},";
|
||||
|
||||
ost << "\"capture_alignment_mixing\": {";
|
||||
ost << "\"downmix\": "
|
||||
<< (config.delay.capture_alignment_mixing.downmix ? "true" : "false")
|
||||
<< ",";
|
||||
ost << "\"adaptive_selection\": "
|
||||
<< (config.delay.capture_alignment_mixing.adaptive_selection ? "true"
|
||||
: "false")
|
||||
<< ",";
|
||||
ost << "\"activity_power_threshold\": "
|
||||
<< config.delay.capture_alignment_mixing.activity_power_threshold << ",";
|
||||
ost << "\"prefer_first_two_channels\": "
|
||||
<< (config.delay.capture_alignment_mixing.prefer_first_two_channels
|
||||
? "true"
|
||||
: "false");
|
||||
ost << "}";
|
||||
ost << "},";
|
||||
|
||||
ost << "\"filter\": {";
|
||||
|
||||
ost << "\"refined\": [";
|
||||
ost << config.filter.refined.length_blocks << ",";
|
||||
ost << config.filter.refined.leakage_converged << ",";
|
||||
ost << config.filter.refined.leakage_diverged << ",";
|
||||
ost << config.filter.refined.error_floor << ",";
|
||||
ost << config.filter.refined.error_ceil << ",";
|
||||
ost << config.filter.refined.noise_gate;
|
||||
ost << "],";
|
||||
|
||||
ost << "\"coarse\": [";
|
||||
ost << config.filter.coarse.length_blocks << ",";
|
||||
ost << config.filter.coarse.rate << ",";
|
||||
ost << config.filter.coarse.noise_gate;
|
||||
ost << "],";
|
||||
|
||||
ost << "\"refined_initial\": [";
|
||||
ost << config.filter.refined_initial.length_blocks << ",";
|
||||
ost << config.filter.refined_initial.leakage_converged << ",";
|
||||
ost << config.filter.refined_initial.leakage_diverged << ",";
|
||||
ost << config.filter.refined_initial.error_floor << ",";
|
||||
ost << config.filter.refined_initial.error_ceil << ",";
|
||||
ost << config.filter.refined_initial.noise_gate;
|
||||
ost << "],";
|
||||
|
||||
ost << "\"coarse_initial\": [";
|
||||
ost << config.filter.coarse_initial.length_blocks << ",";
|
||||
ost << config.filter.coarse_initial.rate << ",";
|
||||
ost << config.filter.coarse_initial.noise_gate;
|
||||
ost << "],";
|
||||
|
||||
ost << "\"config_change_duration_blocks\": "
|
||||
<< config.filter.config_change_duration_blocks << ",";
|
||||
ost << "\"initial_state_seconds\": " << config.filter.initial_state_seconds
|
||||
<< ",";
|
||||
ost << "\"conservative_initial_phase\": "
|
||||
<< (config.filter.conservative_initial_phase ? "true" : "false") << ",";
|
||||
ost << "\"enable_coarse_filter_output_usage\": "
|
||||
<< (config.filter.enable_coarse_filter_output_usage ? "true" : "false")
|
||||
<< ",";
|
||||
ost << "\"use_linear_filter\": "
|
||||
<< (config.filter.use_linear_filter ? "true" : "false") << ",";
|
||||
ost << "\"export_linear_aec_output\": "
|
||||
<< (config.filter.export_linear_aec_output ? "true" : "false");
|
||||
|
||||
ost << "},";
|
||||
|
||||
ost << "\"erle\": {";
|
||||
ost << "\"min\": " << config.erle.min << ",";
|
||||
ost << "\"max_l\": " << config.erle.max_l << ",";
|
||||
ost << "\"max_h\": " << config.erle.max_h << ",";
|
||||
ost << "\"onset_detection\": "
|
||||
<< (config.erle.onset_detection ? "true" : "false") << ",";
|
||||
ost << "\"num_sections\": " << config.erle.num_sections << ",";
|
||||
ost << "\"clamp_quality_estimate_to_zero\": "
|
||||
<< (config.erle.clamp_quality_estimate_to_zero ? "true" : "false") << ",";
|
||||
ost << "\"clamp_quality_estimate_to_one\": "
|
||||
<< (config.erle.clamp_quality_estimate_to_one ? "true" : "false");
|
||||
ost << "},";
|
||||
|
||||
ost << "\"ep_strength\": {";
|
||||
ost << "\"default_gain\": " << config.ep_strength.default_gain << ",";
|
||||
ost << "\"default_len\": " << config.ep_strength.default_len << ",";
|
||||
ost << "\"echo_can_saturate\": "
|
||||
<< (config.ep_strength.echo_can_saturate ? "true" : "false") << ",";
|
||||
ost << "\"bounded_erl\": "
|
||||
<< (config.ep_strength.bounded_erl ? "true" : "false");
|
||||
|
||||
ost << "},";
|
||||
|
||||
ost << "\"echo_audibility\": {";
|
||||
ost << "\"low_render_limit\": " << config.echo_audibility.low_render_limit
|
||||
<< ",";
|
||||
ost << "\"normal_render_limit\": "
|
||||
<< config.echo_audibility.normal_render_limit << ",";
|
||||
ost << "\"floor_power\": " << config.echo_audibility.floor_power << ",";
|
||||
ost << "\"audibility_threshold_lf\": "
|
||||
<< config.echo_audibility.audibility_threshold_lf << ",";
|
||||
ost << "\"audibility_threshold_mf\": "
|
||||
<< config.echo_audibility.audibility_threshold_mf << ",";
|
||||
ost << "\"audibility_threshold_hf\": "
|
||||
<< config.echo_audibility.audibility_threshold_hf << ",";
|
||||
ost << "\"use_stationarity_properties\": "
|
||||
<< (config.echo_audibility.use_stationarity_properties ? "true" : "false")
|
||||
<< ",";
|
||||
ost << "\"use_stationarity_properties_at_init\": "
|
||||
<< (config.echo_audibility.use_stationarity_properties_at_init ? "true"
|
||||
: "false");
|
||||
ost << "},";
|
||||
|
||||
ost << "\"render_levels\": {";
|
||||
ost << "\"active_render_limit\": " << config.render_levels.active_render_limit
|
||||
<< ",";
|
||||
ost << "\"poor_excitation_render_limit\": "
|
||||
<< config.render_levels.poor_excitation_render_limit << ",";
|
||||
ost << "\"poor_excitation_render_limit_ds8\": "
|
||||
<< config.render_levels.poor_excitation_render_limit_ds8 << ",";
|
||||
ost << "\"render_power_gain_db\": "
|
||||
<< config.render_levels.render_power_gain_db;
|
||||
ost << "},";
|
||||
|
||||
ost << "\"echo_removal_control\": {";
|
||||
ost << "\"has_clock_drift\": "
|
||||
<< (config.echo_removal_control.has_clock_drift ? "true" : "false")
|
||||
<< ",";
|
||||
ost << "\"linear_and_stable_echo_path\": "
|
||||
<< (config.echo_removal_control.linear_and_stable_echo_path ? "true"
|
||||
: "false");
|
||||
|
||||
ost << "},";
|
||||
|
||||
ost << "\"echo_model\": {";
|
||||
ost << "\"noise_floor_hold\": " << config.echo_model.noise_floor_hold << ",";
|
||||
ost << "\"min_noise_floor_power\": "
|
||||
<< config.echo_model.min_noise_floor_power << ",";
|
||||
ost << "\"stationary_gate_slope\": "
|
||||
<< config.echo_model.stationary_gate_slope << ",";
|
||||
ost << "\"noise_gate_power\": " << config.echo_model.noise_gate_power << ",";
|
||||
ost << "\"noise_gate_slope\": " << config.echo_model.noise_gate_slope << ",";
|
||||
ost << "\"render_pre_window_size\": "
|
||||
<< config.echo_model.render_pre_window_size << ",";
|
||||
ost << "\"render_post_window_size\": "
|
||||
<< config.echo_model.render_post_window_size;
|
||||
ost << "},";
|
||||
|
||||
ost << "\"comfort_noise\": {";
|
||||
ost << "\"noise_floor_dbfs\": " << config.comfort_noise.noise_floor_dbfs;
|
||||
ost << "},";
|
||||
|
||||
ost << "\"suppressor\": {";
|
||||
ost << "\"nearend_average_blocks\": "
|
||||
<< config.suppressor.nearend_average_blocks << ",";
|
||||
ost << "\"normal_tuning\": {";
|
||||
ost << "\"mask_lf\": [";
|
||||
ost << config.suppressor.normal_tuning.mask_lf.enr_transparent << ",";
|
||||
ost << config.suppressor.normal_tuning.mask_lf.enr_suppress << ",";
|
||||
ost << config.suppressor.normal_tuning.mask_lf.emr_transparent;
|
||||
ost << "],";
|
||||
ost << "\"mask_hf\": [";
|
||||
ost << config.suppressor.normal_tuning.mask_hf.enr_transparent << ",";
|
||||
ost << config.suppressor.normal_tuning.mask_hf.enr_suppress << ",";
|
||||
ost << config.suppressor.normal_tuning.mask_hf.emr_transparent;
|
||||
ost << "],";
|
||||
ost << "\"max_inc_factor\": "
|
||||
<< config.suppressor.normal_tuning.max_inc_factor << ",";
|
||||
ost << "\"max_dec_factor_lf\": "
|
||||
<< config.suppressor.normal_tuning.max_dec_factor_lf;
|
||||
ost << "},";
|
||||
ost << "\"nearend_tuning\": {";
|
||||
ost << "\"mask_lf\": [";
|
||||
ost << config.suppressor.nearend_tuning.mask_lf.enr_transparent << ",";
|
||||
ost << config.suppressor.nearend_tuning.mask_lf.enr_suppress << ",";
|
||||
ost << config.suppressor.nearend_tuning.mask_lf.emr_transparent;
|
||||
ost << "],";
|
||||
ost << "\"mask_hf\": [";
|
||||
ost << config.suppressor.nearend_tuning.mask_hf.enr_transparent << ",";
|
||||
ost << config.suppressor.nearend_tuning.mask_hf.enr_suppress << ",";
|
||||
ost << config.suppressor.nearend_tuning.mask_hf.emr_transparent;
|
||||
ost << "],";
|
||||
ost << "\"max_inc_factor\": "
|
||||
<< config.suppressor.nearend_tuning.max_inc_factor << ",";
|
||||
ost << "\"max_dec_factor_lf\": "
|
||||
<< config.suppressor.nearend_tuning.max_dec_factor_lf;
|
||||
ost << "},";
|
||||
ost << "\"dominant_nearend_detection\": {";
|
||||
ost << "\"enr_threshold\": "
|
||||
<< config.suppressor.dominant_nearend_detection.enr_threshold << ",";
|
||||
ost << "\"enr_exit_threshold\": "
|
||||
<< config.suppressor.dominant_nearend_detection.enr_exit_threshold << ",";
|
||||
ost << "\"snr_threshold\": "
|
||||
<< config.suppressor.dominant_nearend_detection.snr_threshold << ",";
|
||||
ost << "\"hold_duration\": "
|
||||
<< config.suppressor.dominant_nearend_detection.hold_duration << ",";
|
||||
ost << "\"trigger_threshold\": "
|
||||
<< config.suppressor.dominant_nearend_detection.trigger_threshold << ",";
|
||||
ost << "\"use_during_initial_phase\": "
|
||||
<< config.suppressor.dominant_nearend_detection.use_during_initial_phase;
|
||||
ost << "},";
|
||||
ost << "\"subband_nearend_detection\": {";
|
||||
ost << "\"nearend_average_blocks\": "
|
||||
<< config.suppressor.subband_nearend_detection.nearend_average_blocks
|
||||
<< ",";
|
||||
ost << "\"subband1\": [";
|
||||
ost << config.suppressor.subband_nearend_detection.subband1.low << ",";
|
||||
ost << config.suppressor.subband_nearend_detection.subband1.high;
|
||||
ost << "],";
|
||||
ost << "\"subband2\": [";
|
||||
ost << config.suppressor.subband_nearend_detection.subband2.low << ",";
|
||||
ost << config.suppressor.subband_nearend_detection.subband2.high;
|
||||
ost << "],";
|
||||
ost << "\"nearend_threshold\": "
|
||||
<< config.suppressor.subband_nearend_detection.nearend_threshold << ",";
|
||||
ost << "\"snr_threshold\": "
|
||||
<< config.suppressor.subband_nearend_detection.snr_threshold;
|
||||
ost << "},";
|
||||
ost << "\"use_subband_nearend_detection\": "
|
||||
<< config.suppressor.use_subband_nearend_detection << ",";
|
||||
ost << "\"high_bands_suppression\": {";
|
||||
ost << "\"enr_threshold\": "
|
||||
<< config.suppressor.high_bands_suppression.enr_threshold << ",";
|
||||
ost << "\"max_gain_during_echo\": "
|
||||
<< config.suppressor.high_bands_suppression.max_gain_during_echo << ",";
|
||||
ost << "\"anti_howling_activation_threshold\": "
|
||||
<< config.suppressor.high_bands_suppression
|
||||
.anti_howling_activation_threshold
|
||||
<< ",";
|
||||
ost << "\"anti_howling_gain\": "
|
||||
<< config.suppressor.high_bands_suppression.anti_howling_gain;
|
||||
ost << "},";
|
||||
ost << "\"floor_first_increase\": " << config.suppressor.floor_first_increase;
|
||||
ost << "}";
|
||||
ost << "}";
|
||||
ost << "}";
|
||||
|
||||
return ost.Release();
|
||||
}
|
||||
} // namespace webrtc
|
45
api/audio/echo_canceller3_config_json.h
Normal file
45
api/audio/echo_canceller3_config_json.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_ECHO_CANCELLER3_CONFIG_JSON_H_
|
||||
#define API_AUDIO_ECHO_CANCELLER3_CONFIG_JSON_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "api/audio/echo_canceller3_config.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
// Parses a JSON-encoded string into an Aec3 config. Fields corresponds to
|
||||
// substruct names, with the addition that there must be a top-level node
|
||||
// "aec3". Produces default config values for anything that cannot be parsed
|
||||
// from the string. If any error was found in the parsing, parsing_successful is
|
||||
// set to false.
|
||||
RTC_EXPORT void Aec3ConfigFromJsonString(absl::string_view json_string,
|
||||
EchoCanceller3Config* config,
|
||||
bool* parsing_successful);
|
||||
|
||||
// To be deprecated.
|
||||
// Parses a JSON-encoded string into an Aec3 config. Fields corresponds to
|
||||
// substruct names, with the addition that there must be a top-level node
|
||||
// "aec3". Returns default config values for anything that cannot be parsed from
|
||||
// the string.
|
||||
RTC_EXPORT EchoCanceller3Config
|
||||
Aec3ConfigFromJsonString(absl::string_view json_string);
|
||||
|
||||
// Encodes an Aec3 config in JSON format. Fields corresponds to substruct names,
|
||||
// with the addition that the top-level node is named "aec3".
|
||||
RTC_EXPORT std::string Aec3ConfigToJsonString(
|
||||
const EchoCanceller3Config& config);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_ECHO_CANCELLER3_CONFIG_JSON_H_
|
31
api/audio/echo_canceller3_factory.cc
Normal file
31
api/audio/echo_canceller3_factory.cc
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include "api/audio/echo_canceller3_factory.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "modules/audio_processing/aec3/echo_canceller3.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
EchoCanceller3Factory::EchoCanceller3Factory() {}
|
||||
|
||||
EchoCanceller3Factory::EchoCanceller3Factory(const EchoCanceller3Config& config)
|
||||
: config_(config) {}
|
||||
|
||||
std::unique_ptr<EchoControl> EchoCanceller3Factory::Create(
|
||||
int sample_rate_hz,
|
||||
int num_render_channels,
|
||||
int num_capture_channels) {
|
||||
return std::make_unique<EchoCanceller3>(
|
||||
config_, sample_rate_hz, num_render_channels, num_capture_channels);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
41
api/audio/echo_canceller3_factory.h
Normal file
41
api/audio/echo_canceller3_factory.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_ECHO_CANCELLER3_FACTORY_H_
|
||||
#define API_AUDIO_ECHO_CANCELLER3_FACTORY_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "api/audio/echo_canceller3_config.h"
|
||||
#include "api/audio/echo_control.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RTC_EXPORT EchoCanceller3Factory : public EchoControlFactory {
|
||||
public:
|
||||
// Factory producing EchoCanceller3 instances with the default configuration.
|
||||
EchoCanceller3Factory();
|
||||
|
||||
// Factory producing EchoCanceller3 instances with the specified
|
||||
// configuration.
|
||||
explicit EchoCanceller3Factory(const EchoCanceller3Config& config);
|
||||
|
||||
// Creates an EchoCanceller3 with a specified channel count and sampling rate.
|
||||
std::unique_ptr<EchoControl> Create(int sample_rate_hz,
|
||||
int num_render_channels,
|
||||
int num_capture_channels) override;
|
||||
|
||||
private:
|
||||
const EchoCanceller3Config config_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_ECHO_CANCELLER3_FACTORY_H_
|
68
api/audio/echo_control.h
Normal file
68
api/audio/echo_control.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
// 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_
|
31
api/audio/test/BUILD.gn
Normal file
31
api/audio/test/BUILD.gn
Normal file
@ -0,0 +1,31 @@
|
||||
# Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("../../../webrtc.gni")
|
||||
if (is_android) {
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/android/rules.gni")
|
||||
}
|
||||
|
||||
if (rtc_include_tests) {
|
||||
rtc_library("audio_api_unittests") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"audio_frame_unittest.cc",
|
||||
"echo_canceller3_config_json_unittest.cc",
|
||||
"echo_canceller3_config_unittest.cc",
|
||||
]
|
||||
deps = [
|
||||
"..:aec3_config",
|
||||
"..:aec3_config_json",
|
||||
"..:audio_frame_api",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../test:test_support",
|
||||
]
|
||||
}
|
||||
}
|
136
api/audio/test/audio_frame_unittest.cc
Normal file
136
api/audio/test/audio_frame_unittest.cc
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio/audio_frame.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h> // memcmp
|
||||
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
bool AllSamplesAre(int16_t sample, const AudioFrame& frame) {
|
||||
const int16_t* frame_data = frame.data();
|
||||
for (size_t i = 0; i < frame.max_16bit_samples(); i++) {
|
||||
if (frame_data[i] != sample) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr uint32_t kTimestamp = 27;
|
||||
constexpr int kSampleRateHz = 16000;
|
||||
constexpr size_t kNumChannelsMono = 1;
|
||||
constexpr size_t kNumChannelsStereo = 2;
|
||||
constexpr size_t kNumChannels5_1 = 6;
|
||||
constexpr size_t kSamplesPerChannel = kSampleRateHz / 100;
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(AudioFrameTest, FrameStartsMuted) {
|
||||
AudioFrame frame;
|
||||
EXPECT_TRUE(frame.muted());
|
||||
EXPECT_TRUE(AllSamplesAre(0, frame));
|
||||
}
|
||||
|
||||
TEST(AudioFrameTest, UnmutedFrameIsInitiallyZeroed) {
|
||||
AudioFrame frame;
|
||||
frame.mutable_data();
|
||||
EXPECT_FALSE(frame.muted());
|
||||
EXPECT_TRUE(AllSamplesAre(0, frame));
|
||||
}
|
||||
|
||||
TEST(AudioFrameTest, MutedFrameBufferIsZeroed) {
|
||||
AudioFrame frame;
|
||||
int16_t* frame_data = frame.mutable_data();
|
||||
for (size_t i = 0; i < frame.max_16bit_samples(); i++) {
|
||||
frame_data[i] = 17;
|
||||
}
|
||||
ASSERT_TRUE(AllSamplesAre(17, frame));
|
||||
frame.Mute();
|
||||
EXPECT_TRUE(frame.muted());
|
||||
EXPECT_TRUE(AllSamplesAre(0, frame));
|
||||
}
|
||||
|
||||
TEST(AudioFrameTest, UpdateFrameMono) {
|
||||
AudioFrame frame;
|
||||
int16_t samples[kNumChannelsMono * kSamplesPerChannel] = {17};
|
||||
frame.UpdateFrame(kTimestamp, samples, kSamplesPerChannel, kSampleRateHz,
|
||||
AudioFrame::kPLC, AudioFrame::kVadActive, kNumChannelsMono);
|
||||
|
||||
EXPECT_EQ(kTimestamp, frame.timestamp_);
|
||||
EXPECT_EQ(kSamplesPerChannel, frame.samples_per_channel());
|
||||
EXPECT_EQ(kSampleRateHz, frame.sample_rate_hz());
|
||||
EXPECT_EQ(AudioFrame::kPLC, frame.speech_type_);
|
||||
EXPECT_EQ(AudioFrame::kVadActive, frame.vad_activity_);
|
||||
EXPECT_EQ(kNumChannelsMono, frame.num_channels());
|
||||
EXPECT_EQ(CHANNEL_LAYOUT_MONO, frame.channel_layout());
|
||||
|
||||
EXPECT_FALSE(frame.muted());
|
||||
EXPECT_EQ(0, memcmp(samples, frame.data(), sizeof(samples)));
|
||||
|
||||
frame.UpdateFrame(kTimestamp, nullptr /* data*/, kSamplesPerChannel,
|
||||
kSampleRateHz, AudioFrame::kPLC, AudioFrame::kVadActive,
|
||||
kNumChannelsMono);
|
||||
EXPECT_TRUE(frame.muted());
|
||||
EXPECT_TRUE(AllSamplesAre(0, frame));
|
||||
}
|
||||
|
||||
TEST(AudioFrameTest, UpdateFrameMultiChannel) {
|
||||
AudioFrame frame;
|
||||
frame.UpdateFrame(kTimestamp, nullptr /* data */, kSamplesPerChannel,
|
||||
kSampleRateHz, AudioFrame::kPLC, AudioFrame::kVadActive,
|
||||
kNumChannelsStereo);
|
||||
EXPECT_EQ(kSamplesPerChannel, frame.samples_per_channel());
|
||||
EXPECT_EQ(kNumChannelsStereo, frame.num_channels());
|
||||
EXPECT_EQ(CHANNEL_LAYOUT_STEREO, frame.channel_layout());
|
||||
|
||||
frame.UpdateFrame(kTimestamp, nullptr /* data */, kSamplesPerChannel,
|
||||
kSampleRateHz, AudioFrame::kPLC, AudioFrame::kVadActive,
|
||||
kNumChannels5_1);
|
||||
EXPECT_EQ(kSamplesPerChannel, frame.samples_per_channel());
|
||||
EXPECT_EQ(kNumChannels5_1, frame.num_channels());
|
||||
EXPECT_EQ(CHANNEL_LAYOUT_5_1, frame.channel_layout());
|
||||
}
|
||||
|
||||
TEST(AudioFrameTest, CopyFrom) {
|
||||
AudioFrame frame1;
|
||||
AudioFrame frame2;
|
||||
|
||||
int16_t samples[kNumChannelsMono * kSamplesPerChannel] = {17};
|
||||
frame2.UpdateFrame(kTimestamp, samples, kSamplesPerChannel, kSampleRateHz,
|
||||
AudioFrame::kPLC, AudioFrame::kVadActive,
|
||||
kNumChannelsMono);
|
||||
frame1.CopyFrom(frame2);
|
||||
|
||||
EXPECT_EQ(frame2.timestamp_, frame1.timestamp_);
|
||||
EXPECT_EQ(frame2.samples_per_channel_, frame1.samples_per_channel_);
|
||||
EXPECT_EQ(frame2.sample_rate_hz_, frame1.sample_rate_hz_);
|
||||
EXPECT_EQ(frame2.speech_type_, frame1.speech_type_);
|
||||
EXPECT_EQ(frame2.vad_activity_, frame1.vad_activity_);
|
||||
EXPECT_EQ(frame2.num_channels_, frame1.num_channels_);
|
||||
|
||||
EXPECT_EQ(frame2.muted(), frame1.muted());
|
||||
EXPECT_EQ(0, memcmp(frame2.data(), frame1.data(), sizeof(samples)));
|
||||
|
||||
frame2.UpdateFrame(kTimestamp, nullptr /* data */, kSamplesPerChannel,
|
||||
kSampleRateHz, AudioFrame::kPLC, AudioFrame::kVadActive,
|
||||
kNumChannelsMono);
|
||||
frame1.CopyFrom(frame2);
|
||||
|
||||
EXPECT_EQ(frame2.muted(), frame1.muted());
|
||||
EXPECT_EQ(0, memcmp(frame2.data(), frame1.data(), sizeof(samples)));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
70
api/audio/test/echo_canceller3_config_json_unittest.cc
Normal file
70
api/audio/test/echo_canceller3_config_json_unittest.cc
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio/echo_canceller3_config_json.h"
|
||||
|
||||
#include "api/audio/echo_canceller3_config.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TEST(EchoCanceller3JsonHelpers, ToStringAndParseJson) {
|
||||
EchoCanceller3Config cfg;
|
||||
cfg.delay.down_sampling_factor = 1u;
|
||||
cfg.delay.log_warning_on_delay_changes = true;
|
||||
cfg.filter.refined.error_floor = 2.f;
|
||||
cfg.filter.coarse_initial.length_blocks = 3u;
|
||||
cfg.comfort_noise.noise_floor_dbfs = 100.f;
|
||||
cfg.suppressor.normal_tuning.mask_hf.enr_suppress = .5f;
|
||||
cfg.suppressor.subband_nearend_detection.nearend_average_blocks = 3;
|
||||
cfg.suppressor.subband_nearend_detection.subband1 = {1, 3};
|
||||
cfg.suppressor.subband_nearend_detection.subband1 = {4, 5};
|
||||
cfg.suppressor.subband_nearend_detection.nearend_threshold = 2.f;
|
||||
cfg.suppressor.subband_nearend_detection.snr_threshold = 100.f;
|
||||
std::string json_string = Aec3ConfigToJsonString(cfg);
|
||||
EchoCanceller3Config cfg_transformed = Aec3ConfigFromJsonString(json_string);
|
||||
|
||||
// Expect unchanged values to remain default.
|
||||
EXPECT_EQ(cfg.ep_strength.default_len,
|
||||
cfg_transformed.ep_strength.default_len);
|
||||
EXPECT_EQ(cfg.suppressor.normal_tuning.mask_lf.enr_suppress,
|
||||
cfg_transformed.suppressor.normal_tuning.mask_lf.enr_suppress);
|
||||
|
||||
// Expect changed values to carry through the transformation.
|
||||
EXPECT_EQ(cfg.delay.down_sampling_factor,
|
||||
cfg_transformed.delay.down_sampling_factor);
|
||||
EXPECT_EQ(cfg.delay.log_warning_on_delay_changes,
|
||||
cfg_transformed.delay.log_warning_on_delay_changes);
|
||||
EXPECT_EQ(cfg.filter.coarse_initial.length_blocks,
|
||||
cfg_transformed.filter.coarse_initial.length_blocks);
|
||||
EXPECT_EQ(cfg.filter.refined.error_floor,
|
||||
cfg_transformed.filter.refined.error_floor);
|
||||
EXPECT_EQ(cfg.comfort_noise.noise_floor_dbfs,
|
||||
cfg_transformed.comfort_noise.noise_floor_dbfs);
|
||||
EXPECT_EQ(cfg.suppressor.normal_tuning.mask_hf.enr_suppress,
|
||||
cfg_transformed.suppressor.normal_tuning.mask_hf.enr_suppress);
|
||||
EXPECT_EQ(cfg.suppressor.subband_nearend_detection.nearend_average_blocks,
|
||||
cfg_transformed.suppressor.subband_nearend_detection
|
||||
.nearend_average_blocks);
|
||||
EXPECT_EQ(cfg.suppressor.subband_nearend_detection.subband1.low,
|
||||
cfg_transformed.suppressor.subband_nearend_detection.subband1.low);
|
||||
EXPECT_EQ(cfg.suppressor.subband_nearend_detection.subband1.high,
|
||||
cfg_transformed.suppressor.subband_nearend_detection.subband1.high);
|
||||
EXPECT_EQ(cfg.suppressor.subband_nearend_detection.subband2.low,
|
||||
cfg_transformed.suppressor.subband_nearend_detection.subband2.low);
|
||||
EXPECT_EQ(cfg.suppressor.subband_nearend_detection.subband2.high,
|
||||
cfg_transformed.suppressor.subband_nearend_detection.subband2.high);
|
||||
EXPECT_EQ(
|
||||
cfg.suppressor.subband_nearend_detection.nearend_threshold,
|
||||
cfg_transformed.suppressor.subband_nearend_detection.nearend_threshold);
|
||||
EXPECT_EQ(cfg.suppressor.subband_nearend_detection.snr_threshold,
|
||||
cfg_transformed.suppressor.subband_nearend_detection.snr_threshold);
|
||||
}
|
||||
} // namespace webrtc
|
46
api/audio/test/echo_canceller3_config_unittest.cc
Normal file
46
api/audio/test/echo_canceller3_config_unittest.cc
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio/echo_canceller3_config.h"
|
||||
|
||||
#include "api/audio/echo_canceller3_config_json.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TEST(EchoCanceller3Config, ValidConfigIsNotModified) {
|
||||
EchoCanceller3Config config;
|
||||
EXPECT_TRUE(EchoCanceller3Config::Validate(&config));
|
||||
EchoCanceller3Config default_config;
|
||||
EXPECT_EQ(Aec3ConfigToJsonString(config),
|
||||
Aec3ConfigToJsonString(default_config));
|
||||
}
|
||||
|
||||
TEST(EchoCanceller3Config, InvalidConfigIsCorrected) {
|
||||
// Change a parameter and validate.
|
||||
EchoCanceller3Config config;
|
||||
config.echo_model.min_noise_floor_power = -1600000.f;
|
||||
EXPECT_FALSE(EchoCanceller3Config::Validate(&config));
|
||||
EXPECT_GE(config.echo_model.min_noise_floor_power, 0.f);
|
||||
// Verify remaining parameters are unchanged.
|
||||
EchoCanceller3Config default_config;
|
||||
config.echo_model.min_noise_floor_power =
|
||||
default_config.echo_model.min_noise_floor_power;
|
||||
EXPECT_EQ(Aec3ConfigToJsonString(config),
|
||||
Aec3ConfigToJsonString(default_config));
|
||||
}
|
||||
|
||||
TEST(EchoCanceller3Config, ValidatedConfigsAreValid) {
|
||||
EchoCanceller3Config config;
|
||||
config.delay.down_sampling_factor = 983;
|
||||
EXPECT_FALSE(EchoCanceller3Config::Validate(&config));
|
||||
EXPECT_TRUE(EchoCanceller3Config::Validate(&config));
|
||||
}
|
||||
} // namespace webrtc
|
144
api/audio_codecs/BUILD.gn
Normal file
144
api/audio_codecs/BUILD.gn
Normal file
@ -0,0 +1,144 @@
|
||||
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("../../webrtc.gni")
|
||||
if (is_android) {
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/android/rules.gni")
|
||||
}
|
||||
|
||||
rtc_library("audio_codecs_api") {
|
||||
visibility = [ "*" ]
|
||||
sources = [
|
||||
"audio_codec_pair_id.cc",
|
||||
"audio_codec_pair_id.h",
|
||||
"audio_decoder.cc",
|
||||
"audio_decoder.h",
|
||||
"audio_decoder_factory.h",
|
||||
"audio_decoder_factory_template.h",
|
||||
"audio_encoder.cc",
|
||||
"audio_encoder.h",
|
||||
"audio_encoder_factory.h",
|
||||
"audio_encoder_factory_template.h",
|
||||
"audio_format.cc",
|
||||
"audio_format.h",
|
||||
]
|
||||
deps = [
|
||||
"..:array_view",
|
||||
"..:bitrate_allocation",
|
||||
"..:scoped_refptr",
|
||||
"../../rtc_base:checks",
|
||||
"../../rtc_base:deprecation",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"../../rtc_base:sanitizer",
|
||||
"../../rtc_base/system:rtc_export",
|
||||
"../units:time_delta",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("builtin_audio_decoder_factory") {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"builtin_audio_decoder_factory.cc",
|
||||
"builtin_audio_decoder_factory.h",
|
||||
]
|
||||
deps = [
|
||||
":audio_codecs_api",
|
||||
"..:scoped_refptr",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"L16:audio_decoder_L16",
|
||||
"g711:audio_decoder_g711",
|
||||
"g722:audio_decoder_g722",
|
||||
"isac:audio_decoder_isac",
|
||||
]
|
||||
defines = []
|
||||
if (rtc_include_ilbc) {
|
||||
deps += [ "ilbc:audio_decoder_ilbc" ]
|
||||
defines += [ "WEBRTC_USE_BUILTIN_ILBC=1" ]
|
||||
} else {
|
||||
defines += [ "WEBRTC_USE_BUILTIN_ILBC=0" ]
|
||||
}
|
||||
if (rtc_include_opus) {
|
||||
deps += [
|
||||
"opus:audio_decoder_multiopus",
|
||||
"opus:audio_decoder_opus",
|
||||
]
|
||||
defines += [ "WEBRTC_USE_BUILTIN_OPUS=1" ]
|
||||
} else {
|
||||
defines += [ "WEBRTC_USE_BUILTIN_OPUS=0" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_library("builtin_audio_encoder_factory") {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"builtin_audio_encoder_factory.cc",
|
||||
"builtin_audio_encoder_factory.h",
|
||||
]
|
||||
deps = [
|
||||
":audio_codecs_api",
|
||||
"..:scoped_refptr",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"L16:audio_encoder_L16",
|
||||
"g711:audio_encoder_g711",
|
||||
"g722:audio_encoder_g722",
|
||||
"isac:audio_encoder_isac",
|
||||
]
|
||||
defines = []
|
||||
if (rtc_include_ilbc) {
|
||||
deps += [ "ilbc:audio_encoder_ilbc" ]
|
||||
defines += [ "WEBRTC_USE_BUILTIN_ILBC=1" ]
|
||||
} else {
|
||||
defines += [ "WEBRTC_USE_BUILTIN_ILBC=0" ]
|
||||
}
|
||||
if (rtc_include_opus) {
|
||||
deps += [
|
||||
"opus:audio_encoder_multiopus",
|
||||
"opus:audio_encoder_opus",
|
||||
]
|
||||
defines += [ "WEBRTC_USE_BUILTIN_OPUS=1" ]
|
||||
} else {
|
||||
defines += [ "WEBRTC_USE_BUILTIN_OPUS=0" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_library("opus_audio_decoder_factory") {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"opus_audio_decoder_factory.cc",
|
||||
"opus_audio_decoder_factory.h",
|
||||
]
|
||||
deps = [
|
||||
":audio_codecs_api",
|
||||
"..:scoped_refptr",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"opus:audio_decoder_multiopus",
|
||||
"opus:audio_decoder_opus",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("opus_audio_encoder_factory") {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"opus_audio_encoder_factory.cc",
|
||||
"opus_audio_encoder_factory.h",
|
||||
]
|
||||
deps = [
|
||||
":audio_codecs_api",
|
||||
"..:scoped_refptr",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"opus:audio_encoder_multiopus",
|
||||
"opus:audio_encoder_opus",
|
||||
]
|
||||
}
|
48
api/audio_codecs/L16/BUILD.gn
Normal file
48
api/audio_codecs/L16/BUILD.gn
Normal file
@ -0,0 +1,48 @@
|
||||
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("../../../webrtc.gni")
|
||||
if (is_android) {
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/android/rules.gni")
|
||||
}
|
||||
|
||||
rtc_library("audio_encoder_L16") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_encoder_L16.cc",
|
||||
"audio_encoder_L16.h",
|
||||
]
|
||||
deps = [
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:pcm16b",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base:safe_minmax",
|
||||
"../../../rtc_base/system:rtc_export",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("audio_decoder_L16") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_decoder_L16.cc",
|
||||
"audio_decoder_L16.h",
|
||||
]
|
||||
deps = [
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:pcm16b",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base/system:rtc_export",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
45
api/audio_codecs/L16/audio_decoder_L16.cc
Normal file
45
api/audio_codecs/L16/audio_decoder_L16.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/audio_codecs/L16/audio_decoder_L16.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h"
|
||||
#include "modules/audio_coding/codecs/pcm16b/pcm16b_common.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
absl::optional<AudioDecoderL16::Config> AudioDecoderL16::SdpToConfig(
|
||||
const SdpAudioFormat& format) {
|
||||
Config config;
|
||||
config.sample_rate_hz = format.clockrate_hz;
|
||||
config.num_channels = rtc::checked_cast<int>(format.num_channels);
|
||||
return absl::EqualsIgnoreCase(format.name, "L16") && config.IsOk()
|
||||
? absl::optional<Config>(config)
|
||||
: absl::nullopt;
|
||||
}
|
||||
|
||||
void AudioDecoderL16::AppendSupportedDecoders(
|
||||
std::vector<AudioCodecSpec>* specs) {
|
||||
Pcm16BAppendSupportedCodecSpecs(specs);
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioDecoder> AudioDecoderL16::MakeAudioDecoder(
|
||||
const Config& config,
|
||||
absl::optional<AudioCodecPairId> /*codec_pair_id*/) {
|
||||
return config.IsOk() ? std::make_unique<AudioDecoderPcm16B>(
|
||||
config.sample_rate_hz, config.num_channels)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
46
api/audio_codecs/L16/audio_decoder_L16.h
Normal file
46
api/audio_codecs/L16/audio_decoder_L16.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_L16_AUDIO_DECODER_L16_H_
|
||||
#define API_AUDIO_CODECS_L16_AUDIO_DECODER_L16_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// L16 decoder API for use as a template parameter to
|
||||
// CreateAudioDecoderFactory<...>().
|
||||
struct RTC_EXPORT AudioDecoderL16 {
|
||||
struct Config {
|
||||
bool IsOk() const {
|
||||
return (sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
|
||||
sample_rate_hz == 32000 || sample_rate_hz == 48000) &&
|
||||
num_channels >= 1;
|
||||
}
|
||||
int sample_rate_hz = 8000;
|
||||
int num_channels = 1;
|
||||
};
|
||||
static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format);
|
||||
static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);
|
||||
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
const Config& config,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_L16_AUDIO_DECODER_L16_H_
|
70
api/audio_codecs/L16/audio_encoder_L16.cc
Normal file
70
api/audio_codecs/L16/audio_encoder_L16.cc
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/L16/audio_encoder_L16.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
|
||||
#include "modules/audio_coding/codecs/pcm16b/pcm16b_common.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "rtc_base/numerics/safe_minmax.h"
|
||||
#include "rtc_base/string_to_number.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
absl::optional<AudioEncoderL16::Config> AudioEncoderL16::SdpToConfig(
|
||||
const SdpAudioFormat& format) {
|
||||
if (!rtc::IsValueInRangeForNumericType<int>(format.num_channels)) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
Config config;
|
||||
config.sample_rate_hz = format.clockrate_hz;
|
||||
config.num_channels = rtc::dchecked_cast<int>(format.num_channels);
|
||||
auto ptime_iter = format.parameters.find("ptime");
|
||||
if (ptime_iter != format.parameters.end()) {
|
||||
const auto ptime = rtc::StringToNumber<int>(ptime_iter->second);
|
||||
if (ptime && *ptime > 0) {
|
||||
config.frame_size_ms = rtc::SafeClamp(10 * (*ptime / 10), 10, 60);
|
||||
}
|
||||
}
|
||||
return absl::EqualsIgnoreCase(format.name, "L16") && config.IsOk()
|
||||
? absl::optional<Config>(config)
|
||||
: absl::nullopt;
|
||||
}
|
||||
|
||||
void AudioEncoderL16::AppendSupportedEncoders(
|
||||
std::vector<AudioCodecSpec>* specs) {
|
||||
Pcm16BAppendSupportedCodecSpecs(specs);
|
||||
}
|
||||
|
||||
AudioCodecInfo AudioEncoderL16::QueryAudioEncoder(
|
||||
const AudioEncoderL16::Config& config) {
|
||||
RTC_DCHECK(config.IsOk());
|
||||
return {config.sample_rate_hz,
|
||||
rtc::dchecked_cast<size_t>(config.num_channels),
|
||||
config.sample_rate_hz * config.num_channels * 16};
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioEncoder> AudioEncoderL16::MakeAudioEncoder(
|
||||
const AudioEncoderL16::Config& config,
|
||||
int payload_type,
|
||||
absl::optional<AudioCodecPairId> /*codec_pair_id*/) {
|
||||
RTC_DCHECK(config.IsOk());
|
||||
AudioEncoderPcm16B::Config c;
|
||||
c.sample_rate_hz = config.sample_rate_hz;
|
||||
c.num_channels = config.num_channels;
|
||||
c.frame_size_ms = config.frame_size_ms;
|
||||
c.payload_type = payload_type;
|
||||
return std::make_unique<AudioEncoderPcm16B>(c);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
50
api/audio_codecs/L16/audio_encoder_L16.h
Normal file
50
api/audio_codecs/L16/audio_encoder_L16.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_L16_AUDIO_ENCODER_L16_H_
|
||||
#define API_AUDIO_CODECS_L16_AUDIO_ENCODER_L16_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// L16 encoder API for use as a template parameter to
|
||||
// CreateAudioEncoderFactory<...>().
|
||||
struct RTC_EXPORT AudioEncoderL16 {
|
||||
struct Config {
|
||||
bool IsOk() const {
|
||||
return (sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
|
||||
sample_rate_hz == 32000 || sample_rate_hz == 48000) &&
|
||||
num_channels >= 1 && frame_size_ms > 0 && frame_size_ms <= 120 &&
|
||||
frame_size_ms % 10 == 0;
|
||||
}
|
||||
int sample_rate_hz = 8000;
|
||||
int num_channels = 1;
|
||||
int frame_size_ms = 10;
|
||||
};
|
||||
static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format);
|
||||
static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs);
|
||||
static AudioCodecInfo QueryAudioEncoder(const Config& config);
|
||||
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
|
||||
const Config& config,
|
||||
int payload_type,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_L16_AUDIO_ENCODER_L16_H_
|
1
api/audio_codecs/OWNERS.webrtc
Normal file
1
api/audio_codecs/OWNERS.webrtc
Normal file
@ -0,0 +1 @@
|
||||
kwiberg@webrtc.org
|
91
api/audio_codecs/audio_codec_pair_id.cc
Normal file
91
api/audio_codecs/audio_codec_pair_id.cc
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
// Returns a new value that it has never returned before. You may call it at
|
||||
// most 2^63 times in the lifetime of the program. Note: The returned values
|
||||
// may be easily predictable.
|
||||
uint64_t GetNextId() {
|
||||
static std::atomic<uint64_t> next_id(0);
|
||||
|
||||
// Atomically increment `next_id`, and return the previous value. Relaxed
|
||||
// memory order is sufficient, since all we care about is that different
|
||||
// callers return different values.
|
||||
const uint64_t new_id = next_id.fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
// This check isn't atomic with the increment, so if we start 2^63 + 1
|
||||
// invocations of GetNextId() in parallel, the last one to do the atomic
|
||||
// increment could return the ID 0 before any of the others had time to
|
||||
// trigger this DCHECK. We blithely assume that this won't happen.
|
||||
RTC_DCHECK_LT(new_id, uint64_t{1} << 63) << "Used up all ID values";
|
||||
|
||||
return new_id;
|
||||
}
|
||||
|
||||
// Make an integer ID more unpredictable. This is a 1:1 mapping, so you can
|
||||
// feed it any value, but the idea is that you can feed it a sequence such as
|
||||
// 0, 1, 2, ... and get a new sequence that isn't as trivially predictable, so
|
||||
// that users won't rely on it being consecutive or increasing or anything like
|
||||
// that.
|
||||
constexpr uint64_t ObfuscateId(uint64_t id) {
|
||||
// Any nonzero coefficient that's relatively prime to 2^64 (that is, any odd
|
||||
// number) and any constant will give a 1:1 mapping. These high-entropy
|
||||
// values will prevent the sequence from being trivially predictable.
|
||||
//
|
||||
// Both the multiplication and the addition going to overflow almost always,
|
||||
// but that's fine---we *want* arithmetic mod 2^64.
|
||||
return uint64_t{0x85fdb20e1294309a} + uint64_t{0xc516ef5c37462469} * id;
|
||||
}
|
||||
|
||||
// The first ten values. Verified against the Python function
|
||||
//
|
||||
// def f(n):
|
||||
// return (0x85fdb20e1294309a + 0xc516ef5c37462469 * n) % 2**64
|
||||
//
|
||||
// Callers should obviously not depend on these exact values...
|
||||
//
|
||||
// (On Visual C++, we have to disable warning C4307 (integral constant
|
||||
// overflow), even though unsigned integers have perfectly well-defined
|
||||
// overflow behavior.)
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4307)
|
||||
#endif
|
||||
static_assert(ObfuscateId(0) == uint64_t{0x85fdb20e1294309a}, "");
|
||||
static_assert(ObfuscateId(1) == uint64_t{0x4b14a16a49da5503}, "");
|
||||
static_assert(ObfuscateId(2) == uint64_t{0x102b90c68120796c}, "");
|
||||
static_assert(ObfuscateId(3) == uint64_t{0xd5428022b8669dd5}, "");
|
||||
static_assert(ObfuscateId(4) == uint64_t{0x9a596f7eefacc23e}, "");
|
||||
static_assert(ObfuscateId(5) == uint64_t{0x5f705edb26f2e6a7}, "");
|
||||
static_assert(ObfuscateId(6) == uint64_t{0x24874e375e390b10}, "");
|
||||
static_assert(ObfuscateId(7) == uint64_t{0xe99e3d93957f2f79}, "");
|
||||
static_assert(ObfuscateId(8) == uint64_t{0xaeb52cefccc553e2}, "");
|
||||
static_assert(ObfuscateId(9) == uint64_t{0x73cc1c4c040b784b}, "");
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
AudioCodecPairId AudioCodecPairId::Create() {
|
||||
return AudioCodecPairId(ObfuscateId(GetNextId()));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
74
api/audio_codecs/audio_codec_pair_id.h
Normal file
74
api/audio_codecs/audio_codec_pair_id.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_AUDIO_CODEC_PAIR_ID_H_
|
||||
#define API_AUDIO_CODECS_AUDIO_CODEC_PAIR_ID_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioCodecPairId final {
|
||||
public:
|
||||
// Copyable, but not default constructible.
|
||||
AudioCodecPairId() = delete;
|
||||
AudioCodecPairId(const AudioCodecPairId&) = default;
|
||||
AudioCodecPairId(AudioCodecPairId&&) = default;
|
||||
AudioCodecPairId& operator=(const AudioCodecPairId&) = default;
|
||||
AudioCodecPairId& operator=(AudioCodecPairId&&) = default;
|
||||
|
||||
friend void swap(AudioCodecPairId& a, AudioCodecPairId& b) {
|
||||
using std::swap;
|
||||
swap(a.id_, b.id_);
|
||||
}
|
||||
|
||||
// Creates a new ID, unequal to any previously created ID.
|
||||
static AudioCodecPairId Create();
|
||||
|
||||
// IDs can be tested for equality.
|
||||
friend bool operator==(AudioCodecPairId a, AudioCodecPairId b) {
|
||||
return a.id_ == b.id_;
|
||||
}
|
||||
friend bool operator!=(AudioCodecPairId a, AudioCodecPairId b) {
|
||||
return a.id_ != b.id_;
|
||||
}
|
||||
|
||||
// Comparisons. The ordering of ID values is completely arbitrary, but
|
||||
// stable, so it's useful e.g. if you want to use IDs as keys in an ordered
|
||||
// map.
|
||||
friend bool operator<(AudioCodecPairId a, AudioCodecPairId b) {
|
||||
return a.id_ < b.id_;
|
||||
}
|
||||
friend bool operator<=(AudioCodecPairId a, AudioCodecPairId b) {
|
||||
return a.id_ <= b.id_;
|
||||
}
|
||||
friend bool operator>=(AudioCodecPairId a, AudioCodecPairId b) {
|
||||
return a.id_ >= b.id_;
|
||||
}
|
||||
friend bool operator>(AudioCodecPairId a, AudioCodecPairId b) {
|
||||
return a.id_ > b.id_;
|
||||
}
|
||||
|
||||
// Returns a numeric representation of the ID. The numeric values are
|
||||
// completely arbitrary, but stable, collision-free, and reasonably evenly
|
||||
// distributed, so they are e.g. useful as hash values in unordered maps.
|
||||
uint64_t NumericRepresentation() const { return id_; }
|
||||
|
||||
private:
|
||||
explicit AudioCodecPairId(uint64_t id) : id_(id) {}
|
||||
|
||||
uint64_t id_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_AUDIO_CODEC_PAIR_ID_H_
|
170
api/audio_codecs/audio_decoder.cc
Normal file
170
api/audio_codecs/audio_decoder.cc
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/sanitizer.h"
|
||||
#include "rtc_base/trace_event.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
class OldStyleEncodedFrame final : public AudioDecoder::EncodedAudioFrame {
|
||||
public:
|
||||
OldStyleEncodedFrame(AudioDecoder* decoder, rtc::Buffer&& payload)
|
||||
: decoder_(decoder), payload_(std::move(payload)) {}
|
||||
|
||||
size_t Duration() const override {
|
||||
const int ret = decoder_->PacketDuration(payload_.data(), payload_.size());
|
||||
return ret < 0 ? 0 : static_cast<size_t>(ret);
|
||||
}
|
||||
|
||||
absl::optional<DecodeResult> Decode(
|
||||
rtc::ArrayView<int16_t> decoded) const override {
|
||||
auto speech_type = AudioDecoder::kSpeech;
|
||||
const int ret = decoder_->Decode(
|
||||
payload_.data(), payload_.size(), decoder_->SampleRateHz(),
|
||||
decoded.size() * sizeof(int16_t), decoded.data(), &speech_type);
|
||||
return ret < 0 ? absl::nullopt
|
||||
: absl::optional<DecodeResult>(
|
||||
{static_cast<size_t>(ret), speech_type});
|
||||
}
|
||||
|
||||
private:
|
||||
AudioDecoder* const decoder_;
|
||||
const rtc::Buffer payload_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool AudioDecoder::EncodedAudioFrame::IsDtxPacket() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioDecoder::ParseResult::ParseResult() = default;
|
||||
AudioDecoder::ParseResult::ParseResult(ParseResult&& b) = default;
|
||||
AudioDecoder::ParseResult::ParseResult(uint32_t timestamp,
|
||||
int priority,
|
||||
std::unique_ptr<EncodedAudioFrame> frame)
|
||||
: timestamp(timestamp), priority(priority), frame(std::move(frame)) {
|
||||
RTC_DCHECK_GE(priority, 0);
|
||||
}
|
||||
|
||||
AudioDecoder::ParseResult::~ParseResult() = default;
|
||||
|
||||
AudioDecoder::ParseResult& AudioDecoder::ParseResult::operator=(
|
||||
ParseResult&& b) = default;
|
||||
|
||||
std::vector<AudioDecoder::ParseResult> AudioDecoder::ParsePayload(
|
||||
rtc::Buffer&& payload,
|
||||
uint32_t timestamp) {
|
||||
std::vector<ParseResult> results;
|
||||
std::unique_ptr<EncodedAudioFrame> frame(
|
||||
new OldStyleEncodedFrame(this, std::move(payload)));
|
||||
results.emplace_back(timestamp, 0, std::move(frame));
|
||||
return results;
|
||||
}
|
||||
|
||||
int AudioDecoder::Decode(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
size_t max_decoded_bytes,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) {
|
||||
TRACE_EVENT0("webrtc", "AudioDecoder::Decode");
|
||||
rtc::MsanCheckInitialized(rtc::MakeArrayView(encoded, encoded_len));
|
||||
int duration = PacketDuration(encoded, encoded_len);
|
||||
if (duration >= 0 &&
|
||||
duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {
|
||||
return -1;
|
||||
}
|
||||
return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,
|
||||
speech_type);
|
||||
}
|
||||
|
||||
int AudioDecoder::DecodeRedundant(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
size_t max_decoded_bytes,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) {
|
||||
TRACE_EVENT0("webrtc", "AudioDecoder::DecodeRedundant");
|
||||
rtc::MsanCheckInitialized(rtc::MakeArrayView(encoded, encoded_len));
|
||||
int duration = PacketDurationRedundant(encoded, encoded_len);
|
||||
if (duration >= 0 &&
|
||||
duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {
|
||||
return -1;
|
||||
}
|
||||
return DecodeRedundantInternal(encoded, encoded_len, sample_rate_hz, decoded,
|
||||
speech_type);
|
||||
}
|
||||
|
||||
int AudioDecoder::DecodeRedundantInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) {
|
||||
return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,
|
||||
speech_type);
|
||||
}
|
||||
|
||||
bool AudioDecoder::HasDecodePlc() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t AudioDecoder::DecodePlc(size_t num_frames, int16_t* decoded) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO(bugs.webrtc.org/9676): Remove default implementation.
|
||||
void AudioDecoder::GeneratePlc(size_t /*requested_samples_per_channel*/,
|
||||
rtc::BufferT<int16_t>* /*concealment_audio*/) {}
|
||||
|
||||
int AudioDecoder::ErrorCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioDecoder::PacketDuration(const uint8_t* encoded,
|
||||
size_t encoded_len) const {
|
||||
return kNotImplemented;
|
||||
}
|
||||
|
||||
int AudioDecoder::PacketDurationRedundant(const uint8_t* encoded,
|
||||
size_t encoded_len) const {
|
||||
return kNotImplemented;
|
||||
}
|
||||
|
||||
bool AudioDecoder::PacketHasFec(const uint8_t* encoded,
|
||||
size_t encoded_len) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioDecoder::SpeechType AudioDecoder::ConvertSpeechType(int16_t type) {
|
||||
switch (type) {
|
||||
case 0: // TODO(hlundin): Both iSAC and Opus return 0 for speech.
|
||||
case 1:
|
||||
return kSpeech;
|
||||
case 2:
|
||||
return kComfortNoise;
|
||||
default:
|
||||
assert(false);
|
||||
return kSpeech;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
193
api/audio_codecs/audio_decoder.h
Normal file
193
api/audio_codecs/audio_decoder.h
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_AUDIO_DECODER_H_
|
||||
#define API_AUDIO_CODECS_AUDIO_DECODER_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/array_view.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class AudioDecoder {
|
||||
public:
|
||||
enum SpeechType {
|
||||
kSpeech = 1,
|
||||
kComfortNoise = 2,
|
||||
};
|
||||
|
||||
// Used by PacketDuration below. Save the value -1 for errors.
|
||||
enum { kNotImplemented = -2 };
|
||||
|
||||
AudioDecoder() = default;
|
||||
virtual ~AudioDecoder() = default;
|
||||
|
||||
class EncodedAudioFrame {
|
||||
public:
|
||||
struct DecodeResult {
|
||||
size_t num_decoded_samples;
|
||||
SpeechType speech_type;
|
||||
};
|
||||
|
||||
virtual ~EncodedAudioFrame() = default;
|
||||
|
||||
// Returns the duration in samples-per-channel of this audio frame.
|
||||
// If no duration can be ascertained, returns zero.
|
||||
virtual size_t Duration() const = 0;
|
||||
|
||||
// Returns true if this packet contains DTX.
|
||||
virtual bool IsDtxPacket() const;
|
||||
|
||||
// Decodes this frame of audio and writes the result in |decoded|.
|
||||
// |decoded| must be large enough to store as many samples as indicated by a
|
||||
// call to Duration() . On success, returns an absl::optional containing the
|
||||
// total number of samples across all channels, as well as whether the
|
||||
// decoder produced comfort noise or speech. On failure, returns an empty
|
||||
// absl::optional. Decode may be called at most once per frame object.
|
||||
virtual absl::optional<DecodeResult> Decode(
|
||||
rtc::ArrayView<int16_t> decoded) const = 0;
|
||||
};
|
||||
|
||||
struct ParseResult {
|
||||
ParseResult();
|
||||
ParseResult(uint32_t timestamp,
|
||||
int priority,
|
||||
std::unique_ptr<EncodedAudioFrame> frame);
|
||||
ParseResult(ParseResult&& b);
|
||||
~ParseResult();
|
||||
|
||||
ParseResult& operator=(ParseResult&& b);
|
||||
|
||||
// The timestamp of the frame is in samples per channel.
|
||||
uint32_t timestamp;
|
||||
// The relative priority of the frame compared to other frames of the same
|
||||
// payload and the same timeframe. A higher value means a lower priority.
|
||||
// The highest priority is zero - negative values are not allowed.
|
||||
int priority;
|
||||
std::unique_ptr<EncodedAudioFrame> frame;
|
||||
};
|
||||
|
||||
// Let the decoder parse this payload and prepare zero or more decodable
|
||||
// frames. Each frame must be between 10 ms and 120 ms long. The caller must
|
||||
// ensure that the AudioDecoder object outlives any frame objects returned by
|
||||
// this call. The decoder is free to swap or move the data from the |payload|
|
||||
// buffer. |timestamp| is the input timestamp, in samples, corresponding to
|
||||
// the start of the payload.
|
||||
virtual std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
|
||||
uint32_t timestamp);
|
||||
|
||||
// TODO(bugs.webrtc.org/10098): The Decode and DecodeRedundant methods are
|
||||
// obsolete; callers should call ParsePayload instead. For now, subclasses
|
||||
// must still implement DecodeInternal.
|
||||
|
||||
// Decodes |encode_len| bytes from |encoded| and writes the result in
|
||||
// |decoded|. The maximum bytes allowed to be written into |decoded| is
|
||||
// |max_decoded_bytes|. Returns the total number of samples across all
|
||||
// channels. If the decoder produced comfort noise, |speech_type|
|
||||
// is set to kComfortNoise, otherwise it is kSpeech. The desired output
|
||||
// sample rate is provided in |sample_rate_hz|, which must be valid for the
|
||||
// codec at hand.
|
||||
int Decode(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
size_t max_decoded_bytes,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type);
|
||||
|
||||
// Same as Decode(), but interfaces to the decoders redundant decode function.
|
||||
// The default implementation simply calls the regular Decode() method.
|
||||
int DecodeRedundant(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
size_t max_decoded_bytes,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type);
|
||||
|
||||
// Indicates if the decoder implements the DecodePlc method.
|
||||
virtual bool HasDecodePlc() const;
|
||||
|
||||
// Calls the packet-loss concealment of the decoder to update the state after
|
||||
// one or several lost packets. The caller has to make sure that the
|
||||
// memory allocated in |decoded| should accommodate |num_frames| frames.
|
||||
virtual size_t DecodePlc(size_t num_frames, int16_t* decoded);
|
||||
|
||||
// Asks the decoder to generate packet-loss concealment and append it to the
|
||||
// end of |concealment_audio|. The concealment audio should be in
|
||||
// channel-interleaved format, with as many channels as the last decoded
|
||||
// packet produced. The implementation must produce at least
|
||||
// requested_samples_per_channel, or nothing at all. This is a signal to the
|
||||
// caller to conceal the loss with other means. If the implementation provides
|
||||
// concealment samples, it is also responsible for "stitching" it together
|
||||
// with the decoded audio on either side of the concealment.
|
||||
// Note: The default implementation of GeneratePlc will be deleted soon. All
|
||||
// implementations must provide their own, which can be a simple as a no-op.
|
||||
// TODO(bugs.webrtc.org/9676): Remove default impementation.
|
||||
virtual void GeneratePlc(size_t requested_samples_per_channel,
|
||||
rtc::BufferT<int16_t>* concealment_audio);
|
||||
|
||||
// Resets the decoder state (empty buffers etc.).
|
||||
virtual void Reset() = 0;
|
||||
|
||||
// Returns the last error code from the decoder.
|
||||
virtual int ErrorCode();
|
||||
|
||||
// Returns the duration in samples-per-channel of the payload in |encoded|
|
||||
// which is |encoded_len| bytes long. Returns kNotImplemented if no duration
|
||||
// estimate is available, or -1 in case of an error.
|
||||
virtual int PacketDuration(const uint8_t* encoded, size_t encoded_len) const;
|
||||
|
||||
// Returns the duration in samples-per-channel of the redandant payload in
|
||||
// |encoded| which is |encoded_len| bytes long. Returns kNotImplemented if no
|
||||
// duration estimate is available, or -1 in case of an error.
|
||||
virtual int PacketDurationRedundant(const uint8_t* encoded,
|
||||
size_t encoded_len) const;
|
||||
|
||||
// Detects whether a packet has forward error correction. The packet is
|
||||
// comprised of the samples in |encoded| which is |encoded_len| bytes long.
|
||||
// Returns true if the packet has FEC and false otherwise.
|
||||
virtual bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const;
|
||||
|
||||
// Returns the actual sample rate of the decoder's output. This value may not
|
||||
// change during the lifetime of the decoder.
|
||||
virtual int SampleRateHz() const = 0;
|
||||
|
||||
// The number of channels in the decoder's output. This value may not change
|
||||
// during the lifetime of the decoder.
|
||||
virtual size_t Channels() const = 0;
|
||||
|
||||
protected:
|
||||
static SpeechType ConvertSpeechType(int16_t type);
|
||||
|
||||
virtual int DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) = 0;
|
||||
|
||||
virtual int DecodeRedundantInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type);
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoder);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // API_AUDIO_CODECS_AUDIO_DECODER_H_
|
51
api/audio_codecs/audio_decoder_factory.h
Normal file
51
api/audio_codecs/audio_decoder_factory.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_H_
|
||||
#define API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "rtc_base/ref_count.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// A factory that creates AudioDecoders.
|
||||
class AudioDecoderFactory : public rtc::RefCountInterface {
|
||||
public:
|
||||
virtual std::vector<AudioCodecSpec> GetSupportedDecoders() = 0;
|
||||
|
||||
virtual bool IsSupportedDecoder(const SdpAudioFormat& format) = 0;
|
||||
|
||||
// Create a new decoder instance. The `codec_pair_id` argument is used to link
|
||||
// encoders and decoders that talk to the same remote entity: if a
|
||||
// AudioEncoderFactory::MakeAudioEncoder() and a
|
||||
// AudioDecoderFactory::MakeAudioDecoder() call receive non-null IDs that
|
||||
// compare equal, the factory implementations may assume that the encoder and
|
||||
// decoder form a pair. (The intended use case for this is to set up
|
||||
// communication between the AudioEncoder and AudioDecoder instances, which is
|
||||
// needed for some codecs with built-in bandwidth adaptation.)
|
||||
//
|
||||
// Note: Implementations need to be robust against combinations other than
|
||||
// one encoder, one decoder getting the same ID; such decoders must still
|
||||
// work.
|
||||
virtual std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
const SdpAudioFormat& format,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id) = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_H_
|
133
api/audio_codecs/audio_decoder_factory_template.h
Normal file
133
api/audio_codecs/audio_decoder_factory_template.h
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_TEMPLATE_H_
|
||||
#define API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_TEMPLATE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "api/audio_codecs/audio_decoder_factory.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "rtc_base/ref_counted_object.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace audio_decoder_factory_template_impl {
|
||||
|
||||
template <typename... Ts>
|
||||
struct Helper;
|
||||
|
||||
// Base case: 0 template parameters.
|
||||
template <>
|
||||
struct Helper<> {
|
||||
static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) {}
|
||||
static bool IsSupportedDecoder(const SdpAudioFormat& format) { return false; }
|
||||
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
const SdpAudioFormat& format,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id) {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Inductive case: Called with n + 1 template parameters; calls subroutines
|
||||
// with n template parameters.
|
||||
template <typename T, typename... Ts>
|
||||
struct Helper<T, Ts...> {
|
||||
static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) {
|
||||
T::AppendSupportedDecoders(specs);
|
||||
Helper<Ts...>::AppendSupportedDecoders(specs);
|
||||
}
|
||||
static bool IsSupportedDecoder(const SdpAudioFormat& format) {
|
||||
auto opt_config = T::SdpToConfig(format);
|
||||
static_assert(std::is_same<decltype(opt_config),
|
||||
absl::optional<typename T::Config>>::value,
|
||||
"T::SdpToConfig() must return a value of type "
|
||||
"absl::optional<T::Config>");
|
||||
return opt_config ? true : Helper<Ts...>::IsSupportedDecoder(format);
|
||||
}
|
||||
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
const SdpAudioFormat& format,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id) {
|
||||
auto opt_config = T::SdpToConfig(format);
|
||||
return opt_config ? T::MakeAudioDecoder(*opt_config, codec_pair_id)
|
||||
: Helper<Ts...>::MakeAudioDecoder(format, codec_pair_id);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
class AudioDecoderFactoryT : public AudioDecoderFactory {
|
||||
public:
|
||||
std::vector<AudioCodecSpec> GetSupportedDecoders() override {
|
||||
std::vector<AudioCodecSpec> specs;
|
||||
Helper<Ts...>::AppendSupportedDecoders(&specs);
|
||||
return specs;
|
||||
}
|
||||
|
||||
bool IsSupportedDecoder(const SdpAudioFormat& format) override {
|
||||
return Helper<Ts...>::IsSupportedDecoder(format);
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
const SdpAudioFormat& format,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id) override {
|
||||
return Helper<Ts...>::MakeAudioDecoder(format, codec_pair_id);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace audio_decoder_factory_template_impl
|
||||
|
||||
// Make an AudioDecoderFactory that can create instances of the given decoders.
|
||||
//
|
||||
// Each decoder type is given as a template argument to the function; it should
|
||||
// be a struct with the following static member functions:
|
||||
//
|
||||
// // Converts |audio_format| to a ConfigType instance. Returns an empty
|
||||
// // optional if |audio_format| doesn't correctly specify a decoder of our
|
||||
// // type.
|
||||
// absl::optional<ConfigType> SdpToConfig(const SdpAudioFormat& audio_format);
|
||||
//
|
||||
// // Appends zero or more AudioCodecSpecs to the list that will be returned
|
||||
// // by AudioDecoderFactory::GetSupportedDecoders().
|
||||
// void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);
|
||||
//
|
||||
// // Creates an AudioDecoder for the specified format. Used to implement
|
||||
// // AudioDecoderFactory::MakeAudioDecoder().
|
||||
// std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
// const ConfigType& config,
|
||||
// absl::optional<AudioCodecPairId> codec_pair_id);
|
||||
//
|
||||
// ConfigType should be a type that encapsulates all the settings needed to
|
||||
// create an AudioDecoder. T::Config (where T is the decoder struct) should
|
||||
// either be the config type, or an alias for it.
|
||||
//
|
||||
// Whenever it tries to do something, the new factory will try each of the
|
||||
// decoder types in the order they were specified in the template argument
|
||||
// list, stopping at the first one that claims to be able to do the job.
|
||||
//
|
||||
// TODO(kwiberg): Point at CreateBuiltinAudioDecoderFactory() for an example of
|
||||
// how it is used.
|
||||
template <typename... Ts>
|
||||
rtc::scoped_refptr<AudioDecoderFactory> CreateAudioDecoderFactory() {
|
||||
// There's no technical reason we couldn't allow zero template parameters,
|
||||
// but such a factory couldn't create any decoders, and callers can do this
|
||||
// by mistake by simply forgetting the <> altogether. So we forbid it in
|
||||
// order to prevent caller foot-shooting.
|
||||
static_assert(sizeof...(Ts) >= 1,
|
||||
"Caller must give at least one template parameter");
|
||||
|
||||
return rtc::scoped_refptr<AudioDecoderFactory>(
|
||||
new rtc::RefCountedObject<
|
||||
audio_decoder_factory_template_impl::AudioDecoderFactoryT<Ts...>>());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_TEMPLATE_H_
|
113
api/audio_codecs/audio_encoder.cc
Normal file
113
api/audio_codecs/audio_encoder.cc
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/trace_event.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
ANAStats::ANAStats() = default;
|
||||
ANAStats::~ANAStats() = default;
|
||||
ANAStats::ANAStats(const ANAStats&) = default;
|
||||
|
||||
AudioEncoder::EncodedInfo::EncodedInfo() = default;
|
||||
AudioEncoder::EncodedInfo::EncodedInfo(const EncodedInfo&) = default;
|
||||
AudioEncoder::EncodedInfo::EncodedInfo(EncodedInfo&&) = default;
|
||||
AudioEncoder::EncodedInfo::~EncodedInfo() = default;
|
||||
AudioEncoder::EncodedInfo& AudioEncoder::EncodedInfo::operator=(
|
||||
const EncodedInfo&) = default;
|
||||
AudioEncoder::EncodedInfo& AudioEncoder::EncodedInfo::operator=(EncodedInfo&&) =
|
||||
default;
|
||||
|
||||
int AudioEncoder::RtpTimestampRateHz() const {
|
||||
return SampleRateHz();
|
||||
}
|
||||
|
||||
AudioEncoder::EncodedInfo AudioEncoder::Encode(
|
||||
uint32_t rtp_timestamp,
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
rtc::Buffer* encoded) {
|
||||
TRACE_EVENT0("webrtc", "AudioEncoder::Encode");
|
||||
RTC_CHECK_EQ(audio.size(),
|
||||
static_cast<size_t>(NumChannels() * SampleRateHz() / 100));
|
||||
|
||||
const size_t old_size = encoded->size();
|
||||
EncodedInfo info = EncodeImpl(rtp_timestamp, audio, encoded);
|
||||
RTC_CHECK_EQ(encoded->size() - old_size, info.encoded_bytes);
|
||||
return info;
|
||||
}
|
||||
|
||||
bool AudioEncoder::SetFec(bool enable) {
|
||||
return !enable;
|
||||
}
|
||||
|
||||
bool AudioEncoder::SetDtx(bool enable) {
|
||||
return !enable;
|
||||
}
|
||||
|
||||
bool AudioEncoder::GetDtx() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AudioEncoder::SetApplication(Application application) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void AudioEncoder::SetMaxPlaybackRate(int frequency_hz) {}
|
||||
|
||||
void AudioEncoder::SetTargetBitrate(int target_bps) {}
|
||||
|
||||
rtc::ArrayView<std::unique_ptr<AudioEncoder>>
|
||||
AudioEncoder::ReclaimContainedEncoders() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool AudioEncoder::EnableAudioNetworkAdaptor(const std::string& config_string,
|
||||
RtcEventLog* event_log) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void AudioEncoder::DisableAudioNetworkAdaptor() {}
|
||||
|
||||
void AudioEncoder::OnReceivedUplinkPacketLossFraction(
|
||||
float uplink_packet_loss_fraction) {}
|
||||
|
||||
void AudioEncoder::OnReceivedUplinkRecoverablePacketLossFraction(
|
||||
float uplink_recoverable_packet_loss_fraction) {
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
|
||||
void AudioEncoder::OnReceivedTargetAudioBitrate(int target_audio_bitrate_bps) {
|
||||
OnReceivedUplinkBandwidth(target_audio_bitrate_bps, absl::nullopt);
|
||||
}
|
||||
|
||||
void AudioEncoder::OnReceivedUplinkBandwidth(
|
||||
int target_audio_bitrate_bps,
|
||||
absl::optional<int64_t> bwe_period_ms) {}
|
||||
|
||||
void AudioEncoder::OnReceivedUplinkAllocation(BitrateAllocationUpdate update) {
|
||||
OnReceivedUplinkBandwidth(update.target_bitrate.bps(),
|
||||
update.bwe_period.ms());
|
||||
}
|
||||
|
||||
void AudioEncoder::OnReceivedRtt(int rtt_ms) {}
|
||||
|
||||
void AudioEncoder::OnReceivedOverhead(size_t overhead_bytes_per_packet) {}
|
||||
|
||||
void AudioEncoder::SetReceiverFrameLengthRange(int min_frame_length_ms,
|
||||
int max_frame_length_ms) {}
|
||||
|
||||
ANAStats AudioEncoder::GetANAStats() const {
|
||||
return ANAStats();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
257
api/audio_codecs/audio_encoder.h
Normal file
257
api/audio_codecs/audio_encoder.h
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_AUDIO_ENCODER_H_
|
||||
#define API_AUDIO_CODECS_AUDIO_ENCODER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/array_view.h"
|
||||
#include "api/call/bitrate_allocation.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "rtc_base/buffer.h"
|
||||
#include "rtc_base/deprecation.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class RtcEventLog;
|
||||
|
||||
// Statistics related to Audio Network Adaptation.
|
||||
struct ANAStats {
|
||||
ANAStats();
|
||||
ANAStats(const ANAStats&);
|
||||
~ANAStats();
|
||||
// Number of actions taken by the ANA bitrate controller since the start of
|
||||
// the call. If this value is not set, it indicates that the bitrate
|
||||
// controller is disabled.
|
||||
absl::optional<uint32_t> bitrate_action_counter;
|
||||
// Number of actions taken by the ANA channel controller since the start of
|
||||
// the call. If this value is not set, it indicates that the channel
|
||||
// controller is disabled.
|
||||
absl::optional<uint32_t> channel_action_counter;
|
||||
// Number of actions taken by the ANA DTX controller since the start of the
|
||||
// call. If this value is not set, it indicates that the DTX controller is
|
||||
// disabled.
|
||||
absl::optional<uint32_t> dtx_action_counter;
|
||||
// Number of actions taken by the ANA FEC controller since the start of the
|
||||
// call. If this value is not set, it indicates that the FEC controller is
|
||||
// disabled.
|
||||
absl::optional<uint32_t> fec_action_counter;
|
||||
// Number of times the ANA frame length controller decided to increase the
|
||||
// frame length since the start of the call. If this value is not set, it
|
||||
// indicates that the frame length controller is disabled.
|
||||
absl::optional<uint32_t> frame_length_increase_counter;
|
||||
// Number of times the ANA frame length controller decided to decrease the
|
||||
// frame length since the start of the call. If this value is not set, it
|
||||
// indicates that the frame length controller is disabled.
|
||||
absl::optional<uint32_t> frame_length_decrease_counter;
|
||||
// The uplink packet loss fractions as set by the ANA FEC controller. If this
|
||||
// value is not set, it indicates that the ANA FEC controller is not active.
|
||||
absl::optional<float> uplink_packet_loss_fraction;
|
||||
};
|
||||
|
||||
// This is the interface class for encoders in AudioCoding module. Each codec
|
||||
// type must have an implementation of this class.
|
||||
class AudioEncoder {
|
||||
public:
|
||||
// Used for UMA logging of codec usage. The same codecs, with the
|
||||
// same values, must be listed in
|
||||
// src/tools/metrics/histograms/histograms.xml in chromium to log
|
||||
// correct values.
|
||||
enum class CodecType {
|
||||
kOther = 0, // Codec not specified, and/or not listed in this enum
|
||||
kOpus = 1,
|
||||
kIsac = 2,
|
||||
kPcmA = 3,
|
||||
kPcmU = 4,
|
||||
kG722 = 5,
|
||||
kIlbc = 6,
|
||||
|
||||
// Number of histogram bins in the UMA logging of codec types. The
|
||||
// total number of different codecs that are logged cannot exceed this
|
||||
// number.
|
||||
kMaxLoggedAudioCodecTypes
|
||||
};
|
||||
|
||||
struct EncodedInfoLeaf {
|
||||
size_t encoded_bytes = 0;
|
||||
uint32_t encoded_timestamp = 0;
|
||||
int payload_type = 0;
|
||||
bool send_even_if_empty = false;
|
||||
bool speech = true;
|
||||
CodecType encoder_type = CodecType::kOther;
|
||||
};
|
||||
|
||||
// This is the main struct for auxiliary encoding information. Each encoded
|
||||
// packet should be accompanied by one EncodedInfo struct, containing the
|
||||
// total number of |encoded_bytes|, the |encoded_timestamp| and the
|
||||
// |payload_type|. If the packet contains redundant encodings, the |redundant|
|
||||
// vector will be populated with EncodedInfoLeaf structs. Each struct in the
|
||||
// vector represents one encoding; the order of structs in the vector is the
|
||||
// same as the order in which the actual payloads are written to the byte
|
||||
// stream. When EncoderInfoLeaf structs are present in the vector, the main
|
||||
// struct's |encoded_bytes| will be the sum of all the |encoded_bytes| in the
|
||||
// vector.
|
||||
struct EncodedInfo : public EncodedInfoLeaf {
|
||||
EncodedInfo();
|
||||
EncodedInfo(const EncodedInfo&);
|
||||
EncodedInfo(EncodedInfo&&);
|
||||
~EncodedInfo();
|
||||
EncodedInfo& operator=(const EncodedInfo&);
|
||||
EncodedInfo& operator=(EncodedInfo&&);
|
||||
|
||||
std::vector<EncodedInfoLeaf> redundant;
|
||||
};
|
||||
|
||||
virtual ~AudioEncoder() = default;
|
||||
|
||||
// Returns the input sample rate in Hz and the number of input channels.
|
||||
// These are constants set at instantiation time.
|
||||
virtual int SampleRateHz() const = 0;
|
||||
virtual size_t NumChannels() const = 0;
|
||||
|
||||
// Returns the rate at which the RTP timestamps are updated. The default
|
||||
// implementation returns SampleRateHz().
|
||||
virtual int RtpTimestampRateHz() const;
|
||||
|
||||
// Returns the number of 10 ms frames the encoder will put in the next
|
||||
// packet. This value may only change when Encode() outputs a packet; i.e.,
|
||||
// the encoder may vary the number of 10 ms frames from packet to packet, but
|
||||
// it must decide the length of the next packet no later than when outputting
|
||||
// the preceding packet.
|
||||
virtual size_t Num10MsFramesInNextPacket() const = 0;
|
||||
|
||||
// Returns the maximum value that can be returned by
|
||||
// Num10MsFramesInNextPacket().
|
||||
virtual size_t Max10MsFramesInAPacket() const = 0;
|
||||
|
||||
// Returns the current target bitrate in bits/s. The value -1 means that the
|
||||
// codec adapts the target automatically, and a current target cannot be
|
||||
// provided.
|
||||
virtual int GetTargetBitrate() const = 0;
|
||||
|
||||
// Accepts one 10 ms block of input audio (i.e., SampleRateHz() / 100 *
|
||||
// NumChannels() samples). Multi-channel audio must be sample-interleaved.
|
||||
// The encoder appends zero or more bytes of output to |encoded| and returns
|
||||
// additional encoding information. Encode() checks some preconditions, calls
|
||||
// EncodeImpl() which does the actual work, and then checks some
|
||||
// postconditions.
|
||||
EncodedInfo Encode(uint32_t rtp_timestamp,
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
rtc::Buffer* encoded);
|
||||
|
||||
// Resets the encoder to its starting state, discarding any input that has
|
||||
// been fed to the encoder but not yet emitted in a packet.
|
||||
virtual void Reset() = 0;
|
||||
|
||||
// Enables or disables codec-internal FEC (forward error correction). Returns
|
||||
// true if the codec was able to comply. The default implementation returns
|
||||
// true when asked to disable FEC and false when asked to enable it (meaning
|
||||
// that FEC isn't supported).
|
||||
virtual bool SetFec(bool enable);
|
||||
|
||||
// Enables or disables codec-internal VAD/DTX. Returns true if the codec was
|
||||
// able to comply. The default implementation returns true when asked to
|
||||
// disable DTX and false when asked to enable it (meaning that DTX isn't
|
||||
// supported).
|
||||
virtual bool SetDtx(bool enable);
|
||||
|
||||
// Returns the status of codec-internal DTX. The default implementation always
|
||||
// returns false.
|
||||
virtual bool GetDtx() const;
|
||||
|
||||
// Sets the application mode. Returns true if the codec was able to comply.
|
||||
// The default implementation just returns false.
|
||||
enum class Application { kSpeech, kAudio };
|
||||
virtual bool SetApplication(Application application);
|
||||
|
||||
// Tells the encoder about the highest sample rate the decoder is expected to
|
||||
// use when decoding the bitstream. The encoder would typically use this
|
||||
// information to adjust the quality of the encoding. The default
|
||||
// implementation does nothing.
|
||||
virtual void SetMaxPlaybackRate(int frequency_hz);
|
||||
|
||||
// This is to be deprecated. Please use |OnReceivedTargetAudioBitrate|
|
||||
// instead.
|
||||
// Tells the encoder what average bitrate we'd like it to produce. The
|
||||
// encoder is free to adjust or disregard the given bitrate (the default
|
||||
// implementation does the latter).
|
||||
RTC_DEPRECATED virtual void SetTargetBitrate(int target_bps);
|
||||
|
||||
// Causes this encoder to let go of any other encoders it contains, and
|
||||
// returns a pointer to an array where they are stored (which is required to
|
||||
// live as long as this encoder). Unless the returned array is empty, you may
|
||||
// not call any methods on this encoder afterwards, except for the
|
||||
// destructor. The default implementation just returns an empty array.
|
||||
// NOTE: This method is subject to change. Do not call or override it.
|
||||
virtual rtc::ArrayView<std::unique_ptr<AudioEncoder>>
|
||||
ReclaimContainedEncoders();
|
||||
|
||||
// Enables audio network adaptor. Returns true if successful.
|
||||
virtual bool EnableAudioNetworkAdaptor(const std::string& config_string,
|
||||
RtcEventLog* event_log);
|
||||
|
||||
// Disables audio network adaptor.
|
||||
virtual void DisableAudioNetworkAdaptor();
|
||||
|
||||
// Provides uplink packet loss fraction to this encoder to allow it to adapt.
|
||||
// |uplink_packet_loss_fraction| is in the range [0.0, 1.0].
|
||||
virtual void OnReceivedUplinkPacketLossFraction(
|
||||
float uplink_packet_loss_fraction);
|
||||
|
||||
RTC_DEPRECATED virtual void OnReceivedUplinkRecoverablePacketLossFraction(
|
||||
float uplink_recoverable_packet_loss_fraction);
|
||||
|
||||
// Provides target audio bitrate to this encoder to allow it to adapt.
|
||||
virtual void OnReceivedTargetAudioBitrate(int target_bps);
|
||||
|
||||
// Provides target audio bitrate and corresponding probing interval of
|
||||
// the bandwidth estimator to this encoder to allow it to adapt.
|
||||
virtual void OnReceivedUplinkBandwidth(int target_audio_bitrate_bps,
|
||||
absl::optional<int64_t> bwe_period_ms);
|
||||
|
||||
// Provides target audio bitrate and corresponding probing interval of
|
||||
// the bandwidth estimator to this encoder to allow it to adapt.
|
||||
virtual void OnReceivedUplinkAllocation(BitrateAllocationUpdate update);
|
||||
|
||||
// Provides RTT to this encoder to allow it to adapt.
|
||||
virtual void OnReceivedRtt(int rtt_ms);
|
||||
|
||||
// Provides overhead to this encoder to adapt. The overhead is the number of
|
||||
// bytes that will be added to each packet the encoder generates.
|
||||
virtual void OnReceivedOverhead(size_t overhead_bytes_per_packet);
|
||||
|
||||
// To allow encoder to adapt its frame length, it must be provided the frame
|
||||
// length range that receivers can accept.
|
||||
virtual void SetReceiverFrameLengthRange(int min_frame_length_ms,
|
||||
int max_frame_length_ms);
|
||||
|
||||
// Get statistics related to audio network adaptation.
|
||||
virtual ANAStats GetANAStats() const;
|
||||
|
||||
// The range of frame lengths that are supported or nullopt if there's no sch
|
||||
// information. This is used to calculated the full bitrate range, including
|
||||
// overhead.
|
||||
virtual absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
|
||||
const = 0;
|
||||
|
||||
protected:
|
||||
// Subclasses implement this to perform the actual encoding. Called by
|
||||
// Encode().
|
||||
virtual EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
rtc::Buffer* encoded) = 0;
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // API_AUDIO_CODECS_AUDIO_ENCODER_H_
|
60
api/audio_codecs/audio_encoder_factory.h
Normal file
60
api/audio_codecs/audio_encoder_factory.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_H_
|
||||
#define API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "rtc_base/ref_count.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// A factory that creates AudioEncoders.
|
||||
class AudioEncoderFactory : public rtc::RefCountInterface {
|
||||
public:
|
||||
// Returns a prioritized list of audio codecs, to use for signaling etc.
|
||||
virtual std::vector<AudioCodecSpec> GetSupportedEncoders() = 0;
|
||||
|
||||
// Returns information about how this format would be encoded, provided it's
|
||||
// supported. More format and format variations may be supported than those
|
||||
// returned by GetSupportedEncoders().
|
||||
virtual absl::optional<AudioCodecInfo> QueryAudioEncoder(
|
||||
const SdpAudioFormat& format) = 0;
|
||||
|
||||
// Creates an AudioEncoder for the specified format. The encoder will tags its
|
||||
// payloads with the specified payload type. The `codec_pair_id` argument is
|
||||
// used to link encoders and decoders that talk to the same remote entity: if
|
||||
// a AudioEncoderFactory::MakeAudioEncoder() and a
|
||||
// AudioDecoderFactory::MakeAudioDecoder() call receive non-null IDs that
|
||||
// compare equal, the factory implementations may assume that the encoder and
|
||||
// decoder form a pair. (The intended use case for this is to set up
|
||||
// communication between the AudioEncoder and AudioDecoder instances, which is
|
||||
// needed for some codecs with built-in bandwidth adaptation.)
|
||||
//
|
||||
// Note: Implementations need to be robust against combinations other than
|
||||
// one encoder, one decoder getting the same ID; such encoders must still
|
||||
// work.
|
||||
//
|
||||
// TODO(ossu): Try to avoid audio encoders having to know their payload type.
|
||||
virtual std::unique_ptr<AudioEncoder> MakeAudioEncoder(
|
||||
int payload_type,
|
||||
const SdpAudioFormat& format,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id) = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_H_
|
152
api/audio_codecs/audio_encoder_factory_template.h
Normal file
152
api/audio_codecs/audio_encoder_factory_template.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_TEMPLATE_H_
|
||||
#define API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_TEMPLATE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "api/audio_codecs/audio_encoder_factory.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "rtc_base/ref_counted_object.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace audio_encoder_factory_template_impl {
|
||||
|
||||
template <typename... Ts>
|
||||
struct Helper;
|
||||
|
||||
// Base case: 0 template parameters.
|
||||
template <>
|
||||
struct Helper<> {
|
||||
static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {}
|
||||
static absl::optional<AudioCodecInfo> QueryAudioEncoder(
|
||||
const SdpAudioFormat& format) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
|
||||
int payload_type,
|
||||
const SdpAudioFormat& format,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id) {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// Inductive case: Called with n + 1 template parameters; calls subroutines
|
||||
// with n template parameters.
|
||||
template <typename T, typename... Ts>
|
||||
struct Helper<T, Ts...> {
|
||||
static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {
|
||||
T::AppendSupportedEncoders(specs);
|
||||
Helper<Ts...>::AppendSupportedEncoders(specs);
|
||||
}
|
||||
static absl::optional<AudioCodecInfo> QueryAudioEncoder(
|
||||
const SdpAudioFormat& format) {
|
||||
auto opt_config = T::SdpToConfig(format);
|
||||
static_assert(std::is_same<decltype(opt_config),
|
||||
absl::optional<typename T::Config>>::value,
|
||||
"T::SdpToConfig() must return a value of type "
|
||||
"absl::optional<T::Config>");
|
||||
return opt_config ? absl::optional<AudioCodecInfo>(
|
||||
T::QueryAudioEncoder(*opt_config))
|
||||
: Helper<Ts...>::QueryAudioEncoder(format);
|
||||
}
|
||||
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
|
||||
int payload_type,
|
||||
const SdpAudioFormat& format,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id) {
|
||||
auto opt_config = T::SdpToConfig(format);
|
||||
if (opt_config) {
|
||||
return T::MakeAudioEncoder(*opt_config, payload_type, codec_pair_id);
|
||||
} else {
|
||||
return Helper<Ts...>::MakeAudioEncoder(payload_type, format,
|
||||
codec_pair_id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
class AudioEncoderFactoryT : public AudioEncoderFactory {
|
||||
public:
|
||||
std::vector<AudioCodecSpec> GetSupportedEncoders() override {
|
||||
std::vector<AudioCodecSpec> specs;
|
||||
Helper<Ts...>::AppendSupportedEncoders(&specs);
|
||||
return specs;
|
||||
}
|
||||
|
||||
absl::optional<AudioCodecInfo> QueryAudioEncoder(
|
||||
const SdpAudioFormat& format) override {
|
||||
return Helper<Ts...>::QueryAudioEncoder(format);
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioEncoder> MakeAudioEncoder(
|
||||
int payload_type,
|
||||
const SdpAudioFormat& format,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id) override {
|
||||
return Helper<Ts...>::MakeAudioEncoder(payload_type, format, codec_pair_id);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace audio_encoder_factory_template_impl
|
||||
|
||||
// Make an AudioEncoderFactory that can create instances of the given encoders.
|
||||
//
|
||||
// Each encoder type is given as a template argument to the function; it should
|
||||
// be a struct with the following static member functions:
|
||||
//
|
||||
// // Converts |audio_format| to a ConfigType instance. Returns an empty
|
||||
// // optional if |audio_format| doesn't correctly specify an encoder of our
|
||||
// // type.
|
||||
// absl::optional<ConfigType> SdpToConfig(const SdpAudioFormat& audio_format);
|
||||
//
|
||||
// // Appends zero or more AudioCodecSpecs to the list that will be returned
|
||||
// // by AudioEncoderFactory::GetSupportedEncoders().
|
||||
// void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs);
|
||||
//
|
||||
// // Returns information about how this format would be encoded. Used to
|
||||
// // implement AudioEncoderFactory::QueryAudioEncoder().
|
||||
// AudioCodecInfo QueryAudioEncoder(const ConfigType& config);
|
||||
//
|
||||
// // Creates an AudioEncoder for the specified format. Used to implement
|
||||
// // AudioEncoderFactory::MakeAudioEncoder().
|
||||
// std::unique_ptr<AudioDecoder> MakeAudioEncoder(
|
||||
// const ConfigType& config,
|
||||
// int payload_type,
|
||||
// absl::optional<AudioCodecPairId> codec_pair_id);
|
||||
//
|
||||
// ConfigType should be a type that encapsulates all the settings needed to
|
||||
// create an AudioEncoder. T::Config (where T is the encoder struct) should
|
||||
// either be the config type, or an alias for it.
|
||||
//
|
||||
// Whenever it tries to do something, the new factory will try each of the
|
||||
// encoders in the order they were specified in the template argument list,
|
||||
// stopping at the first one that claims to be able to do the job.
|
||||
//
|
||||
// TODO(kwiberg): Point at CreateBuiltinAudioEncoderFactory() for an example of
|
||||
// how it is used.
|
||||
template <typename... Ts>
|
||||
rtc::scoped_refptr<AudioEncoderFactory> CreateAudioEncoderFactory() {
|
||||
// There's no technical reason we couldn't allow zero template parameters,
|
||||
// but such a factory couldn't create any encoders, and callers can do this
|
||||
// by mistake by simply forgetting the <> altogether. So we forbid it in
|
||||
// order to prevent caller foot-shooting.
|
||||
static_assert(sizeof...(Ts) >= 1,
|
||||
"Caller must give at least one template parameter");
|
||||
|
||||
return rtc::scoped_refptr<AudioEncoderFactory>(
|
||||
new rtc::RefCountedObject<
|
||||
audio_encoder_factory_template_impl::AudioEncoderFactoryT<Ts...>>());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_AUDIO_ENCODER_FACTORY_TEMPLATE_H_
|
86
api/audio_codecs/audio_format.cc
Normal file
86
api/audio_codecs/audio_format.cc
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
SdpAudioFormat::SdpAudioFormat(const SdpAudioFormat&) = default;
|
||||
SdpAudioFormat::SdpAudioFormat(SdpAudioFormat&&) = default;
|
||||
|
||||
SdpAudioFormat::SdpAudioFormat(absl::string_view name,
|
||||
int clockrate_hz,
|
||||
size_t num_channels)
|
||||
: name(name), clockrate_hz(clockrate_hz), num_channels(num_channels) {}
|
||||
|
||||
SdpAudioFormat::SdpAudioFormat(absl::string_view name,
|
||||
int clockrate_hz,
|
||||
size_t num_channels,
|
||||
const Parameters& param)
|
||||
: name(name),
|
||||
clockrate_hz(clockrate_hz),
|
||||
num_channels(num_channels),
|
||||
parameters(param) {}
|
||||
|
||||
SdpAudioFormat::SdpAudioFormat(absl::string_view name,
|
||||
int clockrate_hz,
|
||||
size_t num_channels,
|
||||
Parameters&& param)
|
||||
: name(name),
|
||||
clockrate_hz(clockrate_hz),
|
||||
num_channels(num_channels),
|
||||
parameters(std::move(param)) {}
|
||||
|
||||
bool SdpAudioFormat::Matches(const SdpAudioFormat& o) const {
|
||||
return absl::EqualsIgnoreCase(name, o.name) &&
|
||||
clockrate_hz == o.clockrate_hz && num_channels == o.num_channels;
|
||||
}
|
||||
|
||||
SdpAudioFormat::~SdpAudioFormat() = default;
|
||||
SdpAudioFormat& SdpAudioFormat::operator=(const SdpAudioFormat&) = default;
|
||||
SdpAudioFormat& SdpAudioFormat::operator=(SdpAudioFormat&&) = default;
|
||||
|
||||
bool operator==(const SdpAudioFormat& a, const SdpAudioFormat& b) {
|
||||
return absl::EqualsIgnoreCase(a.name, b.name) &&
|
||||
a.clockrate_hz == b.clockrate_hz && a.num_channels == b.num_channels &&
|
||||
a.parameters == b.parameters;
|
||||
}
|
||||
|
||||
AudioCodecInfo::AudioCodecInfo(int sample_rate_hz,
|
||||
size_t num_channels,
|
||||
int bitrate_bps)
|
||||
: AudioCodecInfo(sample_rate_hz,
|
||||
num_channels,
|
||||
bitrate_bps,
|
||||
bitrate_bps,
|
||||
bitrate_bps) {}
|
||||
|
||||
AudioCodecInfo::AudioCodecInfo(int sample_rate_hz,
|
||||
size_t num_channels,
|
||||
int default_bitrate_bps,
|
||||
int min_bitrate_bps,
|
||||
int max_bitrate_bps)
|
||||
: sample_rate_hz(sample_rate_hz),
|
||||
num_channels(num_channels),
|
||||
default_bitrate_bps(default_bitrate_bps),
|
||||
min_bitrate_bps(min_bitrate_bps),
|
||||
max_bitrate_bps(max_bitrate_bps) {
|
||||
RTC_DCHECK_GT(sample_rate_hz, 0);
|
||||
RTC_DCHECK_GT(num_channels, 0);
|
||||
RTC_DCHECK_GE(min_bitrate_bps, 0);
|
||||
RTC_DCHECK_LE(min_bitrate_bps, default_bitrate_bps);
|
||||
RTC_DCHECK_GE(max_bitrate_bps, default_bitrate_bps);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
133
api/audio_codecs/audio_format.h
Normal file
133
api/audio_codecs/audio_format.h
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_AUDIO_FORMAT_H_
|
||||
#define API_AUDIO_CODECS_AUDIO_FORMAT_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// SDP specification for a single audio codec.
|
||||
struct RTC_EXPORT SdpAudioFormat {
|
||||
using Parameters = std::map<std::string, std::string>;
|
||||
|
||||
SdpAudioFormat(const SdpAudioFormat&);
|
||||
SdpAudioFormat(SdpAudioFormat&&);
|
||||
SdpAudioFormat(absl::string_view name, int clockrate_hz, size_t num_channels);
|
||||
SdpAudioFormat(absl::string_view name,
|
||||
int clockrate_hz,
|
||||
size_t num_channels,
|
||||
const Parameters& param);
|
||||
SdpAudioFormat(absl::string_view name,
|
||||
int clockrate_hz,
|
||||
size_t num_channels,
|
||||
Parameters&& param);
|
||||
~SdpAudioFormat();
|
||||
|
||||
// Returns true if this format is compatible with |o|. In SDP terminology:
|
||||
// would it represent the same codec between an offer and an answer? As
|
||||
// opposed to operator==, this method disregards codec parameters.
|
||||
bool Matches(const SdpAudioFormat& o) const;
|
||||
|
||||
SdpAudioFormat& operator=(const SdpAudioFormat&);
|
||||
SdpAudioFormat& operator=(SdpAudioFormat&&);
|
||||
|
||||
friend bool operator==(const SdpAudioFormat& a, const SdpAudioFormat& b);
|
||||
friend bool operator!=(const SdpAudioFormat& a, const SdpAudioFormat& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
int clockrate_hz;
|
||||
size_t num_channels;
|
||||
Parameters parameters;
|
||||
};
|
||||
|
||||
// Information about how an audio format is treated by the codec implementation.
|
||||
// Contains basic information, such as sample rate and number of channels, which
|
||||
// isn't uniformly presented by SDP. Also contains flags indicating support for
|
||||
// integrating with other parts of WebRTC, like external VAD and comfort noise
|
||||
// level calculation.
|
||||
//
|
||||
// To avoid API breakage, and make the code clearer, AudioCodecInfo should not
|
||||
// be directly initializable with any flags indicating optional support. If it
|
||||
// were, these initializers would break any time a new flag was added. It's also
|
||||
// more difficult to understand:
|
||||
// AudioCodecInfo info{16000, 1, 32000, true, false, false, true, true};
|
||||
// than
|
||||
// AudioCodecInfo info(16000, 1, 32000);
|
||||
// info.allow_comfort_noise = true;
|
||||
// info.future_flag_b = true;
|
||||
// info.future_flag_c = true;
|
||||
struct AudioCodecInfo {
|
||||
AudioCodecInfo(int sample_rate_hz, size_t num_channels, int bitrate_bps);
|
||||
AudioCodecInfo(int sample_rate_hz,
|
||||
size_t num_channels,
|
||||
int default_bitrate_bps,
|
||||
int min_bitrate_bps,
|
||||
int max_bitrate_bps);
|
||||
AudioCodecInfo(const AudioCodecInfo& b) = default;
|
||||
~AudioCodecInfo() = default;
|
||||
|
||||
bool operator==(const AudioCodecInfo& b) const {
|
||||
return sample_rate_hz == b.sample_rate_hz &&
|
||||
num_channels == b.num_channels &&
|
||||
default_bitrate_bps == b.default_bitrate_bps &&
|
||||
min_bitrate_bps == b.min_bitrate_bps &&
|
||||
max_bitrate_bps == b.max_bitrate_bps &&
|
||||
allow_comfort_noise == b.allow_comfort_noise &&
|
||||
supports_network_adaption == b.supports_network_adaption;
|
||||
}
|
||||
|
||||
bool operator!=(const AudioCodecInfo& b) const { return !(*this == b); }
|
||||
|
||||
bool HasFixedBitrate() const {
|
||||
RTC_DCHECK_GE(min_bitrate_bps, 0);
|
||||
RTC_DCHECK_LE(min_bitrate_bps, default_bitrate_bps);
|
||||
RTC_DCHECK_GE(max_bitrate_bps, default_bitrate_bps);
|
||||
return min_bitrate_bps == max_bitrate_bps;
|
||||
}
|
||||
|
||||
int sample_rate_hz;
|
||||
size_t num_channels;
|
||||
int default_bitrate_bps;
|
||||
int min_bitrate_bps;
|
||||
int max_bitrate_bps;
|
||||
|
||||
bool allow_comfort_noise = true; // This codec can be used with an external
|
||||
// comfort noise generator.
|
||||
bool supports_network_adaption = false; // This codec can adapt to varying
|
||||
// network conditions.
|
||||
};
|
||||
|
||||
// AudioCodecSpec ties an audio format to specific information about the codec
|
||||
// and its implementation.
|
||||
struct AudioCodecSpec {
|
||||
bool operator==(const AudioCodecSpec& b) const {
|
||||
return format == b.format && info == b.info;
|
||||
}
|
||||
|
||||
bool operator!=(const AudioCodecSpec& b) const { return !(*this == b); }
|
||||
|
||||
SdpAudioFormat format;
|
||||
AudioCodecInfo info;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_AUDIO_FORMAT_H_
|
69
api/audio_codecs/builtin_audio_decoder_factory.cc
Normal file
69
api/audio_codecs/builtin_audio_decoder_factory.cc
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "api/audio_codecs/L16/audio_decoder_L16.h"
|
||||
#include "api/audio_codecs/audio_decoder_factory_template.h"
|
||||
#include "api/audio_codecs/g711/audio_decoder_g711.h"
|
||||
#include "api/audio_codecs/g722/audio_decoder_g722.h"
|
||||
#if WEBRTC_USE_BUILTIN_ILBC
|
||||
#include "api/audio_codecs/ilbc/audio_decoder_ilbc.h" // nogncheck
|
||||
#endif
|
||||
#include "api/audio_codecs/isac/audio_decoder_isac.h"
|
||||
#if WEBRTC_USE_BUILTIN_OPUS
|
||||
#include "api/audio_codecs/opus/audio_decoder_multi_channel_opus.h"
|
||||
#include "api/audio_codecs/opus/audio_decoder_opus.h" // nogncheck
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
// Modify an audio decoder to not advertise support for anything.
|
||||
template <typename T>
|
||||
struct NotAdvertised {
|
||||
using Config = typename T::Config;
|
||||
static absl::optional<Config> SdpToConfig(
|
||||
const SdpAudioFormat& audio_format) {
|
||||
return T::SdpToConfig(audio_format);
|
||||
}
|
||||
static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) {
|
||||
// Don't advertise support for anything.
|
||||
}
|
||||
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
const Config& config,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt) {
|
||||
return T::MakeAudioDecoder(config, codec_pair_id);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
rtc::scoped_refptr<AudioDecoderFactory> CreateBuiltinAudioDecoderFactory() {
|
||||
return CreateAudioDecoderFactory<
|
||||
|
||||
#if WEBRTC_USE_BUILTIN_OPUS
|
||||
AudioDecoderOpus, NotAdvertised<AudioDecoderMultiChannelOpus>,
|
||||
#endif
|
||||
|
||||
AudioDecoderIsac, AudioDecoderG722,
|
||||
|
||||
#if WEBRTC_USE_BUILTIN_ILBC
|
||||
AudioDecoderIlbc,
|
||||
#endif
|
||||
|
||||
AudioDecoderG711, NotAdvertised<AudioDecoderL16>>();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
28
api/audio_codecs/builtin_audio_decoder_factory.h
Normal file
28
api/audio_codecs/builtin_audio_decoder_factory.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_
|
||||
#define API_AUDIO_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_
|
||||
|
||||
#include "api/audio_codecs/audio_decoder_factory.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Creates a new factory that can create the built-in types of audio decoders.
|
||||
// Note: This will link with all the code implementing those codecs, so if you
|
||||
// only need a subset of the codecs, consider using
|
||||
// CreateAudioDecoderFactory<...codecs listed here...>() or
|
||||
// CreateOpusAudioDecoderFactory() instead.
|
||||
rtc::scoped_refptr<AudioDecoderFactory> CreateBuiltinAudioDecoderFactory();
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_
|
73
api/audio_codecs/builtin_audio_encoder_factory.cc
Normal file
73
api/audio_codecs/builtin_audio_encoder_factory.cc
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "api/audio_codecs/L16/audio_encoder_L16.h"
|
||||
#include "api/audio_codecs/audio_encoder_factory_template.h"
|
||||
#include "api/audio_codecs/g711/audio_encoder_g711.h"
|
||||
#include "api/audio_codecs/g722/audio_encoder_g722.h"
|
||||
#if WEBRTC_USE_BUILTIN_ILBC
|
||||
#include "api/audio_codecs/ilbc/audio_encoder_ilbc.h" // nogncheck
|
||||
#endif
|
||||
#include "api/audio_codecs/isac/audio_encoder_isac.h"
|
||||
#if WEBRTC_USE_BUILTIN_OPUS
|
||||
#include "api/audio_codecs/opus/audio_encoder_multi_channel_opus.h"
|
||||
#include "api/audio_codecs/opus/audio_encoder_opus.h" // nogncheck
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
// Modify an audio encoder to not advertise support for anything.
|
||||
template <typename T>
|
||||
struct NotAdvertised {
|
||||
using Config = typename T::Config;
|
||||
static absl::optional<Config> SdpToConfig(
|
||||
const SdpAudioFormat& audio_format) {
|
||||
return T::SdpToConfig(audio_format);
|
||||
}
|
||||
static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {
|
||||
// Don't advertise support for anything.
|
||||
}
|
||||
static AudioCodecInfo QueryAudioEncoder(const Config& config) {
|
||||
return T::QueryAudioEncoder(config);
|
||||
}
|
||||
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
|
||||
const Config& config,
|
||||
int payload_type,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt) {
|
||||
return T::MakeAudioEncoder(config, payload_type, codec_pair_id);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
rtc::scoped_refptr<AudioEncoderFactory> CreateBuiltinAudioEncoderFactory() {
|
||||
return CreateAudioEncoderFactory<
|
||||
|
||||
#if WEBRTC_USE_BUILTIN_OPUS
|
||||
AudioEncoderOpus, NotAdvertised<AudioEncoderMultiChannelOpus>,
|
||||
#endif
|
||||
|
||||
AudioEncoderIsac, AudioEncoderG722,
|
||||
|
||||
#if WEBRTC_USE_BUILTIN_ILBC
|
||||
AudioEncoderIlbc,
|
||||
#endif
|
||||
|
||||
AudioEncoderG711, NotAdvertised<AudioEncoderL16>>();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
28
api/audio_codecs/builtin_audio_encoder_factory.h
Normal file
28
api/audio_codecs/builtin_audio_encoder_factory.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_BUILTIN_AUDIO_ENCODER_FACTORY_H_
|
||||
#define API_AUDIO_CODECS_BUILTIN_AUDIO_ENCODER_FACTORY_H_
|
||||
|
||||
#include "api/audio_codecs/audio_encoder_factory.h"
|
||||
#include "api/scoped_refptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Creates a new factory that can create the built-in types of audio encoders.
|
||||
// Note: This will link with all the code implementing those codecs, so if you
|
||||
// only need a subset of the codecs, consider using
|
||||
// CreateAudioEncoderFactory<...codecs listed here...>() or
|
||||
// CreateOpusAudioEncoderFactory() instead.
|
||||
rtc::scoped_refptr<AudioEncoderFactory> CreateBuiltinAudioEncoderFactory();
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_BUILTIN_AUDIO_ENCODER_FACTORY_H_
|
48
api/audio_codecs/g711/BUILD.gn
Normal file
48
api/audio_codecs/g711/BUILD.gn
Normal file
@ -0,0 +1,48 @@
|
||||
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("../../../webrtc.gni")
|
||||
if (is_android) {
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/android/rules.gni")
|
||||
}
|
||||
|
||||
rtc_library("audio_encoder_g711") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_encoder_g711.cc",
|
||||
"audio_encoder_g711.h",
|
||||
]
|
||||
deps = [
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:g711",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base:safe_minmax",
|
||||
"../../../rtc_base/system:rtc_export",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("audio_decoder_g711") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_decoder_g711.cc",
|
||||
"audio_decoder_g711.h",
|
||||
]
|
||||
deps = [
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:g711",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base/system:rtc_export",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
59
api/audio_codecs/g711/audio_decoder_g711.cc
Normal file
59
api/audio_codecs/g711/audio_decoder_g711.cc
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/g711/audio_decoder_g711.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "modules/audio_coding/codecs/g711/audio_decoder_pcm.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
absl::optional<AudioDecoderG711::Config> AudioDecoderG711::SdpToConfig(
|
||||
const SdpAudioFormat& format) {
|
||||
const bool is_pcmu = absl::EqualsIgnoreCase(format.name, "PCMU");
|
||||
const bool is_pcma = absl::EqualsIgnoreCase(format.name, "PCMA");
|
||||
if (format.clockrate_hz == 8000 && format.num_channels >= 1 &&
|
||||
(is_pcmu || is_pcma)) {
|
||||
Config config;
|
||||
config.type = is_pcmu ? Config::Type::kPcmU : Config::Type::kPcmA;
|
||||
config.num_channels = rtc::dchecked_cast<int>(format.num_channels);
|
||||
RTC_DCHECK(config.IsOk());
|
||||
return config;
|
||||
} else {
|
||||
return absl::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioDecoderG711::AppendSupportedDecoders(
|
||||
std::vector<AudioCodecSpec>* specs) {
|
||||
for (const char* type : {"PCMU", "PCMA"}) {
|
||||
specs->push_back({{type, 8000, 1}, {8000, 1, 64000}});
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioDecoder> AudioDecoderG711::MakeAudioDecoder(
|
||||
const Config& config,
|
||||
absl::optional<AudioCodecPairId> /*codec_pair_id*/) {
|
||||
RTC_DCHECK(config.IsOk());
|
||||
switch (config.type) {
|
||||
case Config::Type::kPcmU:
|
||||
return std::make_unique<AudioDecoderPcmU>(config.num_channels);
|
||||
case Config::Type::kPcmA:
|
||||
return std::make_unique<AudioDecoderPcmA>(config.num_channels);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
45
api/audio_codecs/g711/audio_decoder_g711.h
Normal file
45
api/audio_codecs/g711/audio_decoder_g711.h
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.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_G711_AUDIO_DECODER_G711_H_
|
||||
#define API_AUDIO_CODECS_G711_AUDIO_DECODER_G711_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// G711 decoder API for use as a template parameter to
|
||||
// CreateAudioDecoderFactory<...>().
|
||||
struct RTC_EXPORT AudioDecoderG711 {
|
||||
struct Config {
|
||||
enum class Type { kPcmU, kPcmA };
|
||||
bool IsOk() const {
|
||||
return (type == Type::kPcmU || type == Type::kPcmA) && num_channels >= 1;
|
||||
}
|
||||
Type type;
|
||||
int num_channels;
|
||||
};
|
||||
static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format);
|
||||
static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);
|
||||
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
const Config& config,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_G711_AUDIO_DECODER_G711_H_
|
87
api/audio_codecs/g711/audio_encoder_g711.cc
Normal file
87
api/audio_codecs/g711/audio_encoder_g711.cc
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/g711/audio_encoder_g711.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "rtc_base/numerics/safe_minmax.h"
|
||||
#include "rtc_base/string_to_number.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
absl::optional<AudioEncoderG711::Config> AudioEncoderG711::SdpToConfig(
|
||||
const SdpAudioFormat& format) {
|
||||
const bool is_pcmu = absl::EqualsIgnoreCase(format.name, "PCMU");
|
||||
const bool is_pcma = absl::EqualsIgnoreCase(format.name, "PCMA");
|
||||
if (format.clockrate_hz == 8000 && format.num_channels >= 1 &&
|
||||
(is_pcmu || is_pcma)) {
|
||||
Config config;
|
||||
config.type = is_pcmu ? Config::Type::kPcmU : Config::Type::kPcmA;
|
||||
config.num_channels = rtc::dchecked_cast<int>(format.num_channels);
|
||||
config.frame_size_ms = 20;
|
||||
auto ptime_iter = format.parameters.find("ptime");
|
||||
if (ptime_iter != format.parameters.end()) {
|
||||
const auto ptime = rtc::StringToNumber<int>(ptime_iter->second);
|
||||
if (ptime && *ptime > 0) {
|
||||
config.frame_size_ms = rtc::SafeClamp(10 * (*ptime / 10), 10, 60);
|
||||
}
|
||||
}
|
||||
RTC_DCHECK(config.IsOk());
|
||||
return config;
|
||||
} else {
|
||||
return absl::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioEncoderG711::AppendSupportedEncoders(
|
||||
std::vector<AudioCodecSpec>* specs) {
|
||||
for (const char* type : {"PCMU", "PCMA"}) {
|
||||
specs->push_back({{type, 8000, 1}, {8000, 1, 64000}});
|
||||
}
|
||||
}
|
||||
|
||||
AudioCodecInfo AudioEncoderG711::QueryAudioEncoder(const Config& config) {
|
||||
RTC_DCHECK(config.IsOk());
|
||||
return {8000, rtc::dchecked_cast<size_t>(config.num_channels),
|
||||
64000 * config.num_channels};
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioEncoder> AudioEncoderG711::MakeAudioEncoder(
|
||||
const Config& config,
|
||||
int payload_type,
|
||||
absl::optional<AudioCodecPairId> /*codec_pair_id*/) {
|
||||
RTC_DCHECK(config.IsOk());
|
||||
switch (config.type) {
|
||||
case Config::Type::kPcmU: {
|
||||
AudioEncoderPcmU::Config impl_config;
|
||||
impl_config.num_channels = config.num_channels;
|
||||
impl_config.frame_size_ms = config.frame_size_ms;
|
||||
impl_config.payload_type = payload_type;
|
||||
return std::make_unique<AudioEncoderPcmU>(impl_config);
|
||||
}
|
||||
case Config::Type::kPcmA: {
|
||||
AudioEncoderPcmA::Config impl_config;
|
||||
impl_config.num_channels = config.num_channels;
|
||||
impl_config.frame_size_ms = config.frame_size_ms;
|
||||
impl_config.payload_type = payload_type;
|
||||
return std::make_unique<AudioEncoderPcmA>(impl_config);
|
||||
}
|
||||
default: {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
50
api/audio_codecs/g711/audio_encoder_g711.h
Normal file
50
api/audio_codecs/g711/audio_encoder_g711.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_G711_AUDIO_ENCODER_G711_H_
|
||||
#define API_AUDIO_CODECS_G711_AUDIO_ENCODER_G711_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// G711 encoder API for use as a template parameter to
|
||||
// CreateAudioEncoderFactory<...>().
|
||||
struct RTC_EXPORT AudioEncoderG711 {
|
||||
struct Config {
|
||||
enum class Type { kPcmU, kPcmA };
|
||||
bool IsOk() const {
|
||||
return (type == Type::kPcmU || type == Type::kPcmA) &&
|
||||
frame_size_ms > 0 && frame_size_ms % 10 == 0 && num_channels >= 1;
|
||||
}
|
||||
Type type = Type::kPcmU;
|
||||
int num_channels = 1;
|
||||
int frame_size_ms = 20;
|
||||
};
|
||||
static absl::optional<AudioEncoderG711::Config> SdpToConfig(
|
||||
const SdpAudioFormat& audio_format);
|
||||
static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs);
|
||||
static AudioCodecInfo QueryAudioEncoder(const Config& config);
|
||||
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
|
||||
const Config& config,
|
||||
int payload_type,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_G711_AUDIO_ENCODER_G711_H_
|
54
api/audio_codecs/g722/BUILD.gn
Normal file
54
api/audio_codecs/g722/BUILD.gn
Normal file
@ -0,0 +1,54 @@
|
||||
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("../../../webrtc.gni")
|
||||
if (is_android) {
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/android/rules.gni")
|
||||
}
|
||||
|
||||
rtc_source_set("audio_encoder_g722_config") {
|
||||
visibility = [ "*" ]
|
||||
sources = [ "audio_encoder_g722_config.h" ]
|
||||
}
|
||||
|
||||
rtc_library("audio_encoder_g722") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_encoder_g722.cc",
|
||||
"audio_encoder_g722.h",
|
||||
]
|
||||
deps = [
|
||||
":audio_encoder_g722_config",
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:g722",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base:safe_minmax",
|
||||
"../../../rtc_base/system:rtc_export",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("audio_decoder_g722") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_decoder_g722.cc",
|
||||
"audio_decoder_g722.h",
|
||||
]
|
||||
deps = [
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:g722",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base/system:rtc_export",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
50
api/audio_codecs/g722/audio_decoder_g722.cc
Normal file
50
api/audio_codecs/g722/audio_decoder_g722.cc
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/g722/audio_decoder_g722.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "modules/audio_coding/codecs/g722/audio_decoder_g722.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
absl::optional<AudioDecoderG722::Config> AudioDecoderG722::SdpToConfig(
|
||||
const SdpAudioFormat& format) {
|
||||
return absl::EqualsIgnoreCase(format.name, "G722") &&
|
||||
format.clockrate_hz == 8000 &&
|
||||
(format.num_channels == 1 || format.num_channels == 2)
|
||||
? absl::optional<Config>(
|
||||
Config{rtc::dchecked_cast<int>(format.num_channels)})
|
||||
: absl::nullopt;
|
||||
}
|
||||
|
||||
void AudioDecoderG722::AppendSupportedDecoders(
|
||||
std::vector<AudioCodecSpec>* specs) {
|
||||
specs->push_back({{"G722", 8000, 1}, {16000, 1, 64000}});
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioDecoder> AudioDecoderG722::MakeAudioDecoder(
|
||||
Config config,
|
||||
absl::optional<AudioCodecPairId> /*codec_pair_id*/) {
|
||||
switch (config.num_channels) {
|
||||
case 1:
|
||||
return std::make_unique<AudioDecoderG722Impl>();
|
||||
case 2:
|
||||
return std::make_unique<AudioDecoderG722StereoImpl>();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
41
api/audio_codecs/g722/audio_decoder_g722.h
Normal file
41
api/audio_codecs/g722/audio_decoder_g722.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_G722_AUDIO_DECODER_G722_H_
|
||||
#define API_AUDIO_CODECS_G722_AUDIO_DECODER_G722_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// G722 decoder API for use as a template parameter to
|
||||
// CreateAudioDecoderFactory<...>().
|
||||
struct RTC_EXPORT AudioDecoderG722 {
|
||||
struct Config {
|
||||
bool IsOk() const { return num_channels == 1 || num_channels == 2; }
|
||||
int num_channels;
|
||||
};
|
||||
static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format);
|
||||
static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);
|
||||
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
Config config,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_G722_AUDIO_DECODER_G722_H_
|
67
api/audio_codecs/g722/audio_encoder_g722.cc
Normal file
67
api/audio_codecs/g722/audio_encoder_g722.cc
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/g722/audio_encoder_g722.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "modules/audio_coding/codecs/g722/audio_encoder_g722.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "rtc_base/numerics/safe_minmax.h"
|
||||
#include "rtc_base/string_to_number.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
absl::optional<AudioEncoderG722Config> AudioEncoderG722::SdpToConfig(
|
||||
const SdpAudioFormat& format) {
|
||||
if (!absl::EqualsIgnoreCase(format.name, "g722") ||
|
||||
format.clockrate_hz != 8000) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
AudioEncoderG722Config config;
|
||||
config.num_channels = rtc::checked_cast<int>(format.num_channels);
|
||||
auto ptime_iter = format.parameters.find("ptime");
|
||||
if (ptime_iter != format.parameters.end()) {
|
||||
auto ptime = rtc::StringToNumber<int>(ptime_iter->second);
|
||||
if (ptime && *ptime > 0) {
|
||||
const int whole_packets = *ptime / 10;
|
||||
config.frame_size_ms = rtc::SafeClamp<int>(whole_packets * 10, 10, 60);
|
||||
}
|
||||
}
|
||||
return config.IsOk() ? absl::optional<AudioEncoderG722Config>(config)
|
||||
: absl::nullopt;
|
||||
}
|
||||
|
||||
void AudioEncoderG722::AppendSupportedEncoders(
|
||||
std::vector<AudioCodecSpec>* specs) {
|
||||
const SdpAudioFormat fmt = {"G722", 8000, 1};
|
||||
const AudioCodecInfo info = QueryAudioEncoder(*SdpToConfig(fmt));
|
||||
specs->push_back({fmt, info});
|
||||
}
|
||||
|
||||
AudioCodecInfo AudioEncoderG722::QueryAudioEncoder(
|
||||
const AudioEncoderG722Config& config) {
|
||||
RTC_DCHECK(config.IsOk());
|
||||
return {16000, rtc::dchecked_cast<size_t>(config.num_channels),
|
||||
64000 * config.num_channels};
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioEncoder> AudioEncoderG722::MakeAudioEncoder(
|
||||
const AudioEncoderG722Config& config,
|
||||
int payload_type,
|
||||
absl::optional<AudioCodecPairId> /*codec_pair_id*/) {
|
||||
RTC_DCHECK(config.IsOk());
|
||||
return std::make_unique<AudioEncoderG722Impl>(config, payload_type);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
42
api/audio_codecs/g722/audio_encoder_g722.h
Normal file
42
api/audio_codecs/g722/audio_encoder_g722.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_H_
|
||||
#define API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "api/audio_codecs/g722/audio_encoder_g722_config.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// G722 encoder API for use as a template parameter to
|
||||
// CreateAudioEncoderFactory<...>().
|
||||
struct RTC_EXPORT AudioEncoderG722 {
|
||||
using Config = AudioEncoderG722Config;
|
||||
static absl::optional<AudioEncoderG722Config> SdpToConfig(
|
||||
const SdpAudioFormat& audio_format);
|
||||
static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs);
|
||||
static AudioCodecInfo QueryAudioEncoder(const AudioEncoderG722Config& config);
|
||||
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
|
||||
const AudioEncoderG722Config& config,
|
||||
int payload_type,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_H_
|
26
api/audio_codecs/g722/audio_encoder_g722_config.h
Normal file
26
api/audio_codecs/g722/audio_encoder_g722_config.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_CONFIG_H_
|
||||
#define API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_CONFIG_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
struct AudioEncoderG722Config {
|
||||
bool IsOk() const {
|
||||
return frame_size_ms > 0 && frame_size_ms % 10 == 0 && num_channels >= 1;
|
||||
}
|
||||
int frame_size_ms = 20;
|
||||
int num_channels = 1;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_G722_AUDIO_ENCODER_G722_CONFIG_H_
|
52
api/audio_codecs/ilbc/BUILD.gn
Normal file
52
api/audio_codecs/ilbc/BUILD.gn
Normal file
@ -0,0 +1,52 @@
|
||||
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("../../../webrtc.gni")
|
||||
if (is_android) {
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/android/rules.gni")
|
||||
}
|
||||
|
||||
rtc_source_set("audio_encoder_ilbc_config") {
|
||||
visibility = [ "*" ]
|
||||
sources = [ "audio_encoder_ilbc_config.h" ]
|
||||
}
|
||||
|
||||
rtc_library("audio_encoder_ilbc") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_encoder_ilbc.cc",
|
||||
"audio_encoder_ilbc.h",
|
||||
]
|
||||
deps = [
|
||||
":audio_encoder_ilbc_config",
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:ilbc",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base:safe_minmax",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("audio_decoder_ilbc") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_decoder_ilbc.cc",
|
||||
"audio_decoder_ilbc.h",
|
||||
]
|
||||
deps = [
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:ilbc",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
40
api/audio_codecs/ilbc/audio_decoder_ilbc.cc
Normal file
40
api/audio_codecs/ilbc/audio_decoder_ilbc.cc
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/ilbc/audio_decoder_ilbc.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
absl::optional<AudioDecoderIlbc::Config> AudioDecoderIlbc::SdpToConfig(
|
||||
const SdpAudioFormat& format) {
|
||||
return absl::EqualsIgnoreCase(format.name, "ILBC") &&
|
||||
format.clockrate_hz == 8000 && format.num_channels == 1
|
||||
? absl::optional<Config>(Config())
|
||||
: absl::nullopt;
|
||||
}
|
||||
|
||||
void AudioDecoderIlbc::AppendSupportedDecoders(
|
||||
std::vector<AudioCodecSpec>* specs) {
|
||||
specs->push_back({{"ILBC", 8000, 1}, {8000, 1, 13300}});
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioDecoder> AudioDecoderIlbc::MakeAudioDecoder(
|
||||
Config config,
|
||||
absl::optional<AudioCodecPairId> /*codec_pair_id*/) {
|
||||
return std::make_unique<AudioDecoderIlbcImpl>();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
37
api/audio_codecs/ilbc/audio_decoder_ilbc.h
Normal file
37
api/audio_codecs/ilbc/audio_decoder_ilbc.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
|
||||
#define API_AUDIO_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// ILBC decoder API for use as a template parameter to
|
||||
// CreateAudioDecoderFactory<...>().
|
||||
struct AudioDecoderIlbc {
|
||||
struct Config {}; // Empty---no config values needed!
|
||||
static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format);
|
||||
static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);
|
||||
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
Config config,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
|
81
api/audio_codecs/ilbc/audio_encoder_ilbc.cc
Normal file
81
api/audio_codecs/ilbc/audio_encoder_ilbc.cc
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/ilbc/audio_encoder_ilbc.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "rtc_base/numerics/safe_minmax.h"
|
||||
#include "rtc_base/string_to_number.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
int GetIlbcBitrate(int ptime) {
|
||||
switch (ptime) {
|
||||
case 20:
|
||||
case 40:
|
||||
// 38 bytes per frame of 20 ms => 15200 bits/s.
|
||||
return 15200;
|
||||
case 30:
|
||||
case 60:
|
||||
// 50 bytes per frame of 30 ms => (approx) 13333 bits/s.
|
||||
return 13333;
|
||||
default:
|
||||
FATAL();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
absl::optional<AudioEncoderIlbcConfig> AudioEncoderIlbc::SdpToConfig(
|
||||
const SdpAudioFormat& format) {
|
||||
if (!absl::EqualsIgnoreCase(format.name.c_str(), "ILBC") ||
|
||||
format.clockrate_hz != 8000 || format.num_channels != 1) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
AudioEncoderIlbcConfig config;
|
||||
auto ptime_iter = format.parameters.find("ptime");
|
||||
if (ptime_iter != format.parameters.end()) {
|
||||
auto ptime = rtc::StringToNumber<int>(ptime_iter->second);
|
||||
if (ptime && *ptime > 0) {
|
||||
const int whole_packets = *ptime / 10;
|
||||
config.frame_size_ms = rtc::SafeClamp<int>(whole_packets * 10, 20, 60);
|
||||
}
|
||||
}
|
||||
return config.IsOk() ? absl::optional<AudioEncoderIlbcConfig>(config)
|
||||
: absl::nullopt;
|
||||
}
|
||||
|
||||
void AudioEncoderIlbc::AppendSupportedEncoders(
|
||||
std::vector<AudioCodecSpec>* specs) {
|
||||
const SdpAudioFormat fmt = {"ILBC", 8000, 1};
|
||||
const AudioCodecInfo info = QueryAudioEncoder(*SdpToConfig(fmt));
|
||||
specs->push_back({fmt, info});
|
||||
}
|
||||
|
||||
AudioCodecInfo AudioEncoderIlbc::QueryAudioEncoder(
|
||||
const AudioEncoderIlbcConfig& config) {
|
||||
RTC_DCHECK(config.IsOk());
|
||||
return {8000, 1, GetIlbcBitrate(config.frame_size_ms)};
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioEncoder> AudioEncoderIlbc::MakeAudioEncoder(
|
||||
const AudioEncoderIlbcConfig& config,
|
||||
int payload_type,
|
||||
absl::optional<AudioCodecPairId> /*codec_pair_id*/) {
|
||||
RTC_DCHECK(config.IsOk());
|
||||
return std::make_unique<AudioEncoderIlbcImpl>(config, payload_type);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
41
api/audio_codecs/ilbc/audio_encoder_ilbc.h
Normal file
41
api/audio_codecs/ilbc/audio_encoder_ilbc.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
|
||||
#define API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_encoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "api/audio_codecs/ilbc/audio_encoder_ilbc_config.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// ILBC encoder API for use as a template parameter to
|
||||
// CreateAudioEncoderFactory<...>().
|
||||
struct AudioEncoderIlbc {
|
||||
using Config = AudioEncoderIlbcConfig;
|
||||
static absl::optional<AudioEncoderIlbcConfig> SdpToConfig(
|
||||
const SdpAudioFormat& audio_format);
|
||||
static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs);
|
||||
static AudioCodecInfo QueryAudioEncoder(const AudioEncoderIlbcConfig& config);
|
||||
static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
|
||||
const AudioEncoderIlbcConfig& config,
|
||||
int payload_type,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
|
28
api/audio_codecs/ilbc/audio_encoder_ilbc_config.h
Normal file
28
api/audio_codecs/ilbc/audio_encoder_ilbc_config.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_CONFIG_H_
|
||||
#define API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_CONFIG_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
struct AudioEncoderIlbcConfig {
|
||||
bool IsOk() const {
|
||||
return (frame_size_ms == 20 || frame_size_ms == 30 || frame_size_ms == 40 ||
|
||||
frame_size_ms == 60);
|
||||
}
|
||||
int frame_size_ms = 30; // Valid values are 20, 30, 40, and 60 ms.
|
||||
// Note that frame size 40 ms produces encodings with two 20 ms frames in
|
||||
// them, and frame size 60 ms consists of two 30 ms frames.
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_CONFIG_H_
|
125
api/audio_codecs/isac/BUILD.gn
Normal file
125
api/audio_codecs/isac/BUILD.gn
Normal file
@ -0,0 +1,125 @@
|
||||
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("../../../webrtc.gni")
|
||||
if (is_android) {
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/android/rules.gni")
|
||||
}
|
||||
|
||||
# The targets with _fix and _float suffixes unconditionally use the
|
||||
# fixed-point and floating-point iSAC implementations, respectively.
|
||||
# The targets without suffixes pick one of the implementations based
|
||||
# on cleverly chosen criteria.
|
||||
|
||||
rtc_source_set("audio_encoder_isac") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
public = [ "audio_encoder_isac.h" ]
|
||||
public_configs = [ ":isac_config" ]
|
||||
if (current_cpu == "arm") {
|
||||
deps = [ ":audio_encoder_isac_fix" ]
|
||||
} else {
|
||||
deps = [ ":audio_encoder_isac_float" ]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_source_set("audio_decoder_isac") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
public = [ "audio_decoder_isac.h" ]
|
||||
public_configs = [ ":isac_config" ]
|
||||
if (current_cpu == "arm") {
|
||||
deps = [ ":audio_decoder_isac_fix" ]
|
||||
} else {
|
||||
deps = [ ":audio_decoder_isac_float" ]
|
||||
}
|
||||
}
|
||||
|
||||
config("isac_config") {
|
||||
visibility = [ ":*" ]
|
||||
if (current_cpu == "arm") {
|
||||
defines = [
|
||||
"WEBRTC_USE_BUILTIN_ISAC_FIX=1",
|
||||
"WEBRTC_USE_BUILTIN_ISAC_FLOAT=0",
|
||||
]
|
||||
} else {
|
||||
defines = [
|
||||
"WEBRTC_USE_BUILTIN_ISAC_FIX=0",
|
||||
"WEBRTC_USE_BUILTIN_ISAC_FLOAT=1",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
rtc_library("audio_encoder_isac_fix") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_encoder_isac_fix.cc",
|
||||
"audio_encoder_isac_fix.h",
|
||||
]
|
||||
deps = [
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:isac_fix",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base/system:rtc_export",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("audio_decoder_isac_fix") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_decoder_isac_fix.cc",
|
||||
"audio_decoder_isac_fix.h",
|
||||
]
|
||||
deps = [
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:isac_fix",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base/system:rtc_export",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("audio_encoder_isac_float") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_encoder_isac_float.cc",
|
||||
"audio_encoder_isac_float.h",
|
||||
]
|
||||
deps = [
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:isac",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base/system:rtc_export",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("audio_decoder_isac_float") {
|
||||
visibility = [ "*" ]
|
||||
poisonous = [ "audio_codecs" ]
|
||||
sources = [
|
||||
"audio_decoder_isac_float.cc",
|
||||
"audio_decoder_isac_float.h",
|
||||
]
|
||||
deps = [
|
||||
"..:audio_codecs_api",
|
||||
"../../../modules/audio_coding:isac",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base/system:rtc_export",
|
||||
"//third_party/abseil-cpp/absl/strings",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
32
api/audio_codecs/isac/audio_decoder_isac.h
Normal file
32
api/audio_codecs/isac/audio_decoder_isac.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_ISAC_AUDIO_DECODER_ISAC_H_
|
||||
#define API_AUDIO_CODECS_ISAC_AUDIO_DECODER_ISAC_H_
|
||||
|
||||
#if WEBRTC_USE_BUILTIN_ISAC_FIX && !WEBRTC_USE_BUILTIN_ISAC_FLOAT
|
||||
#include "api/audio_codecs/isac/audio_decoder_isac_fix.h" // nogncheck
|
||||
#elif WEBRTC_USE_BUILTIN_ISAC_FLOAT && !WEBRTC_USE_BUILTIN_ISAC_FIX
|
||||
#include "api/audio_codecs/isac/audio_decoder_isac_float.h" // nogncheck
|
||||
#else
|
||||
#error "Must choose either fix or float"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#if WEBRTC_USE_BUILTIN_ISAC_FIX
|
||||
using AudioDecoderIsac = AudioDecoderIsacFix;
|
||||
#elif WEBRTC_USE_BUILTIN_ISAC_FLOAT
|
||||
using AudioDecoderIsac = AudioDecoderIsacFloat;
|
||||
#endif
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_ISAC_AUDIO_DECODER_ISAC_H_
|
41
api/audio_codecs/isac/audio_decoder_isac_fix.cc
Normal file
41
api/audio_codecs/isac/audio_decoder_isac_fix.cc
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/isac/audio_decoder_isac_fix.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
absl::optional<AudioDecoderIsacFix::Config> AudioDecoderIsacFix::SdpToConfig(
|
||||
const SdpAudioFormat& format) {
|
||||
return absl::EqualsIgnoreCase(format.name, "ISAC") &&
|
||||
format.clockrate_hz == 16000 && format.num_channels == 1
|
||||
? absl::optional<Config>(Config())
|
||||
: absl::nullopt;
|
||||
}
|
||||
|
||||
void AudioDecoderIsacFix::AppendSupportedDecoders(
|
||||
std::vector<AudioCodecSpec>* specs) {
|
||||
specs->push_back({{"ISAC", 16000, 1}, {16000, 1, 32000, 10000, 32000}});
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioDecoder> AudioDecoderIsacFix::MakeAudioDecoder(
|
||||
Config config,
|
||||
absl::optional<AudioCodecPairId> /*codec_pair_id*/) {
|
||||
AudioDecoderIsacFixImpl::Config c;
|
||||
c.sample_rate_hz = 16000;
|
||||
return std::make_unique<AudioDecoderIsacFixImpl>(c);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
38
api/audio_codecs/isac/audio_decoder_isac_fix.h
Normal file
38
api/audio_codecs/isac/audio_decoder_isac_fix.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_ISAC_AUDIO_DECODER_ISAC_FIX_H_
|
||||
#define API_AUDIO_CODECS_ISAC_AUDIO_DECODER_ISAC_FIX_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// iSAC decoder API (fixed-point implementation) for use as a template
|
||||
// parameter to CreateAudioDecoderFactory<...>().
|
||||
struct RTC_EXPORT AudioDecoderIsacFix {
|
||||
struct Config {}; // Empty---no config values needed!
|
||||
static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format);
|
||||
static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);
|
||||
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
Config config,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_ISAC_AUDIO_DECODER_ISAC_FIX_H_
|
48
api/audio_codecs/isac/audio_decoder_isac_float.cc
Normal file
48
api/audio_codecs/isac/audio_decoder_isac_float.cc
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "api/audio_codecs/isac/audio_decoder_isac_float.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
absl::optional<AudioDecoderIsacFloat::Config>
|
||||
AudioDecoderIsacFloat::SdpToConfig(const SdpAudioFormat& format) {
|
||||
if (absl::EqualsIgnoreCase(format.name, "ISAC") &&
|
||||
(format.clockrate_hz == 16000 || format.clockrate_hz == 32000) &&
|
||||
format.num_channels == 1) {
|
||||
Config config;
|
||||
config.sample_rate_hz = format.clockrate_hz;
|
||||
return config;
|
||||
} else {
|
||||
return absl::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioDecoderIsacFloat::AppendSupportedDecoders(
|
||||
std::vector<AudioCodecSpec>* specs) {
|
||||
specs->push_back({{"ISAC", 16000, 1}, {16000, 1, 32000, 10000, 32000}});
|
||||
specs->push_back({{"ISAC", 32000, 1}, {32000, 1, 56000, 10000, 56000}});
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioDecoder> AudioDecoderIsacFloat::MakeAudioDecoder(
|
||||
Config config,
|
||||
absl::optional<AudioCodecPairId> /*codec_pair_id*/) {
|
||||
RTC_DCHECK(config.IsOk());
|
||||
AudioDecoderIsacFloatImpl::Config c;
|
||||
c.sample_rate_hz = config.sample_rate_hz;
|
||||
return std::make_unique<AudioDecoderIsacFloatImpl>(c);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
43
api/audio_codecs/isac/audio_decoder_isac_float.h
Normal file
43
api/audio_codecs/isac/audio_decoder_isac_float.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_ISAC_AUDIO_DECODER_ISAC_FLOAT_H_
|
||||
#define API_AUDIO_CODECS_ISAC_AUDIO_DECODER_ISAC_FLOAT_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio_codecs/audio_codec_pair_id.h"
|
||||
#include "api/audio_codecs/audio_decoder.h"
|
||||
#include "api/audio_codecs/audio_format.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// iSAC decoder API (floating-point implementation) for use as a template
|
||||
// parameter to CreateAudioDecoderFactory<...>().
|
||||
struct RTC_EXPORT AudioDecoderIsacFloat {
|
||||
struct Config {
|
||||
bool IsOk() const {
|
||||
return sample_rate_hz == 16000 || sample_rate_hz == 32000;
|
||||
}
|
||||
int sample_rate_hz = 16000;
|
||||
};
|
||||
static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format);
|
||||
static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);
|
||||
static std::unique_ptr<AudioDecoder> MakeAudioDecoder(
|
||||
Config config,
|
||||
absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_ISAC_AUDIO_DECODER_ISAC_FLOAT_H_
|
32
api/audio_codecs/isac/audio_encoder_isac.h
Normal file
32
api/audio_codecs/isac/audio_encoder_isac.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef API_AUDIO_CODECS_ISAC_AUDIO_ENCODER_ISAC_H_
|
||||
#define API_AUDIO_CODECS_ISAC_AUDIO_ENCODER_ISAC_H_
|
||||
|
||||
#if WEBRTC_USE_BUILTIN_ISAC_FIX && !WEBRTC_USE_BUILTIN_ISAC_FLOAT
|
||||
#include "api/audio_codecs/isac/audio_encoder_isac_fix.h" // nogncheck
|
||||
#elif WEBRTC_USE_BUILTIN_ISAC_FLOAT && !WEBRTC_USE_BUILTIN_ISAC_FIX
|
||||
#include "api/audio_codecs/isac/audio_encoder_isac_float.h" // nogncheck
|
||||
#else
|
||||
#error "Must choose either fix or float"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
#if WEBRTC_USE_BUILTIN_ISAC_FIX
|
||||
using AudioEncoderIsac = AudioEncoderIsacFix;
|
||||
#elif WEBRTC_USE_BUILTIN_ISAC_FLOAT
|
||||
using AudioEncoderIsac = AudioEncoderIsacFloat;
|
||||
#endif
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_AUDIO_CODECS_ISAC_AUDIO_ENCODER_ISAC_H_
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user