Merge branch 'upstream-master'

Bug: 153469641
Test: none
Change-Id: Ic33e363deb0d1ac4bb4d57c3c239eb2e45370802
Merged-In: Ic33e363deb0d1ac4bb4d57c3c239eb2e45370802
This commit is contained in:
Jorge E. Moreira
2020-07-20 17:23:46 -07:00
9929 changed files with 1031155 additions and 779502 deletions

View File

@ -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
View 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
View File

@ -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
View File

@ -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
View 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
View File

@ -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>

View File

@ -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/*"]

View File

@ -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
View File

@ -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
View 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.

View File

@ -1 +0,0 @@
Refer to talk/COPYING.

2782
DEPS

File diff suppressed because it is too large Load Diff

11
ENG_REVIEW_OWNERS Normal file
View 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
View File

@ -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.

View File

@ -1 +0,0 @@
Refer to webrtc/LICENSE_THIRD_PARTY and talk/LICENSE_THIRD_PARTY.

View File

@ -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
View File

@ -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
View File

@ -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
View 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
View File

@ -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.

File diff suppressed because it is too large Load Diff

View File

@ -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
View File

@ -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.

View File

@ -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
View 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&rsquo;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&mdash;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
View File

@ -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

File diff suppressed because it is too large Load Diff

309
api/DEPS Normal file
View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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
View File

@ -0,0 +1,2 @@
gustaf@webrtc.org
peah@webrtc.org

140
api/audio/audio_frame.cc Normal file
View 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
View 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
View 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
View 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
View 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_

View 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

View 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_

View 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", &param->downmix);
ReadParam(subsection, "adaptive_selection", &param->adaptive_selection);
ReadParam(subsection, "activity_power_threshold",
&param->activity_power_threshold);
ReadParam(subsection, "prefer_first_two_channels",
&param->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", &section)) {
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", &section)) {
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", &section)) {
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", &section)) {
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", &section)) {
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", &section)) {
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", &section)) {
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",
&section)) {
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", &section)) {
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", &section)) {
ReadParam(section, "noise_floor_dbfs", &cfg.comfort_noise.noise_floor_dbfs);
}
Json::Value subsection;
if (rtc::GetValueFromJsonObject(aec3_root, "suppressor", &section)) {
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, &not_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

View 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_

View 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

View 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
View 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
View 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",
]
}
}

View 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

View 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

View 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
View 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",
]
}

View 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",
]
}

View 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

View 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_

View 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

View 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_

View File

@ -0,0 +1 @@
kwiberg@webrtc.org

View 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

View 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_

View 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

View 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_

View 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_

View 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_

View 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

View 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_

View 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_

View 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_

View 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

View 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_

View 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

View 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_

View 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

View 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_

View 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",
]
}

View 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

View 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_

View 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

View 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_

View 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",
]
}

View 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

View 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_

View 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

View 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_

View 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_

View 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",
]
}

View 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

View 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_

View 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

View 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_

View 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_

View 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",
]
}

View 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_

View 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

View 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_

View 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

View 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_

View 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