123 Commits
v0.3 ... master

Author SHA1 Message Date
846fe90a28 doc: Add release notes for v2.1 2025-01-22 17:32:18 -05:00
8f445c36cc meson: Bump version to 2.1 2025-01-22 17:30:47 -05:00
a24b45cc19 patches: Track some MinGW fixups 2025-01-10 15:07:56 -05:00
a9f97c9fdd Some fixes for MinGW
* Rename Windows.h uses to windows.h
  * Comment out structured exception handling usage

Makes MinGW happier. Mostly the same as previous work by
Nicolas Dufresne <nicolas.dufresne@collabora.com>, with the exception
that we now don't try to invoke RaiseException which would fail in MinGW
as it raises a Windows structured exception.
2025-01-10 15:07:34 -05:00
f8a6ea0a9a meson: Add absl_numeric as a dep
Another implicit cascading dependency.
2025-01-10 12:49:22 -05:00
222790ad57 meson: Update abseil-cpp wrap for missing headers 2025-01-10 12:01:31 -05:00
1818e5eb50 patches: Track patch for Windows builds 2025-01-09 16:36:34 -05:00
c555fb6eaf meson: Fixes for MSVC build
winsock2.h must be included before windows.h or alternative
definitions of `struct sockaddr` are defined.

```
FAILED: webrtc/rtc_base/liblibbase.a.p/logging.cc.obj
"cl" "-Iwebrtc\rtc_base\liblibbase.a.p" "-Iwebrtc\rtc_base" "-I..\webrtc\rtc_base" "-Iwebrtc" "-I..\webrtc" "-Isubprojects\abseil-cpp-20230125.1" "-I..\subprojects\abseil-cpp-20230125.1" "/MD" "/nologo" "/showIncludes" "/utf-8" "/Zc:__cplusplus" "/W2" "/EHsc" "/std:c++17" "/permissive-" "/O2" "/Zi" "-DWEBRTC_LIBRARY_
IMPL" "-DWEBRTC_ENABLE_SYMBOL_EXPORT" "-DNDEBUG" "-DWEBRTC_WIN" "-D_WIN32" "-U__STRICT_ANSI__" "-D__STDC_FORMAT_MACROS=1" "-DNOMINMAX" "-DWEBRTC_ENABLE_AVX2" "/Fdwebrtc\rtc_base\liblibbase.a.p\logging.cc.pdb" /Fowebrtc/rtc_base/liblibbase.a.p/logging.cc.obj "/c" ../webrtc/rtc_base/logging.cc
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(103): warning C4005: 'AF_IPX': macro redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(457): note: see previous definition of 'AF_IPX'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(147): warning C4005: 'AF_MAX': macro redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(476): note: see previous definition of 'AF_MAX'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(187): warning C4005: 'SO_DONTLINGER': macro redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(399): note: see previous definition of 'SO_DONTLINGER'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(240): error C2011: 'sockaddr': 'struct' type redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(482): note: see declaration of 'sockaddr'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(442): error C2143: syntax error: missing '}' before 'constant'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(442): error C2059: syntax error: 'constant'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C2143: syntax error: missing ';' before '}'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
...
```
2025-01-09 16:35:01 -05:00
845e79a2a7 meson: Install some new headers
The main header has moved to api/audio/... and there are a bunch of new
dependent headers.
2025-01-09 15:53:16 -05:00
0743cb5ce5 doc: Document changes for 2.0 2025-01-08 11:58:17 -05:00
971f026d55 doc: Backfill 1.x releases 2025-01-08 11:51:04 -05:00
774ac54e71 meson: Only disable SIMD for non-SSE machines on x86
This ended up disabling SIMD everywhere except where SSE/AVX was
enabled.
2024-12-30 16:21:20 -05:00
54a632f018 meson: Convert the 'neon' option into a feature
Easier to express things, now that runtime is a no-op.
2024-12-30 16:21:08 -05:00
d63a2c9714 meson: pffft: Warn about not having runtime neon checks
The pffft.c file does not have runtime checks for NEON, and silently
falls back to disabling it when the neon option is 'runtime'. Print a
warning in this case.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 14:19:07 -05:00
73aed233b2 meson: Use neon_opt to control building neon files
Using the have_neon boolean to enable NEON code means we have to either
fully enable it or fully disable it. When using -Dneon=runtime, ideally
only the parts that support runtime checks would be built for NEON, and
those that don't would be built without NEON. Though, there are no
longer any runtime checks for NEON anywhere, so it's equivalent to 'no'
with a warning.

In general, we should use have_* variables to indicate compiler support,
and *_opt options to choose if and how we want to utilize that. Use
neon_opt to control NEON compilation and avoid modifying have_neon which
now would fully refer to compiler support.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 14:18:44 -05:00
2493b6e659 meson: Raise error for setting 'neon' when unsupported
We can set -Dneon=yes on x86, which will fail during build because the
x86 compiler doesn't understand the resulting `-mfpu=neon` flag. Make the
'neon' build option cause an error in the setup stage if we didn't
detect hardware support for NEON.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 14:18:00 -05:00
fc5a4946af meson: Set 'auto' as the default neon option value
The default for the neon build option is 'no', which disabled NEON code
for 32-bit ARM but enabled it for ARM64. Now that 'no' can disable NEON
code for ARM64, the default should be 'auto' which would enable it where
possible. Handle the 'auto' value, and set it as the default.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 14:17:32 -05:00
b7a194f824 meson: Check arm neon support before parsing neon option
The main if statment for the NEON option has been quite convoluted. The
previous commits reduced what it does to a simple case: check NEON
support and set have_neon on 32-bit ARM CPUs. Do that near the
architecture definitions.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 14:16:43 -05:00
6c914be933 meson: Make -Dneon=no disable neon-specific code
When the neon build option is set to 'no', we should disable optimized
implementations that use NEON. Change have_neon to false in that case,
so that we skip the flags and skip building NEON-specific files.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 14:16:43 -05:00
8b0255991e meson: Set WEBRTC_HAS_NEON macro after handling neon build option
The WEBRTC_HAS_NEON macro that enables using NEON implementations is
unconditionally set for arm64 and the 'neon' build option is ignored,
assuming we always want to use the NEON-specific implementations instead
of generic ones. This is an OK assumption to make because arm64 CPUs
always support NEON.

But the code handling the build option ended up quite convoluted. As
part of cleaning up, set the relevant cflags after we handle the build
option. This also means that we can make 'runtime' fall back to 'no',
and disable NEON-specific code with -Dneon=no.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 14:16:43 -05:00
b22ce018c8 meson: Drop obsolete WEBRTC_DETECT_NEON macro
Upstream has dropped runtime checks for NEON instructions around 2016,
and the WEBRTC_DETECT_NEON macro is removed along with it. Disable NEON
when building with -Dneon=runtime and omit a warning instead.

Link: https://webrtc.googlesource.com/src/+/e305d956c0717a28ca88cd8547e5b310dfa74594
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 14:16:43 -05:00
a1ccd6c700 Track patches to WebRTC code in patches/
This should make it easier to not lose track during the next bump.
2024-12-30 14:05:31 -05:00
297fd4f2ef AECM: MIPS: Use uintptr_t for pointer arithmetic
Trying to compile the MIPS-specific AECM audio processing file for
mips64el on Debian results in the following errors:

  ../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc: In function ‘int webrtc::WebRtcAecm_ProcessBlock(AecmCore*, const int16_t*, const int16_t*, const int16_t*, int16_t*)’:
  ../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:955:30: error: cast from ‘int16_t*’ {aka ‘short int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
    955 |   int16_t* fft = (int16_t*)(((uint32_t)fft_buf + 31) & ~31);
        |                              ^~~~~~~~~~~~~~~~~
  ../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:955:18: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
    955 |   int16_t* fft = (int16_t*)(((uint32_t)fft_buf + 31) & ~31);
        |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:956:36: error: cast from ‘int32_t*’ {aka ‘int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
    956 |   int32_t* echoEst32 = (int32_t*)(((uint32_t)echoEst32_buf + 31) & ~31);
        |                                    ^~~~~~~~~~~~~~~~~~~~~~~
  ../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:956:24: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
    956 |   int32_t* echoEst32 = (int32_t*)(((uint32_t)echoEst32_buf + 31) & ~31);
        |                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:957:40: error: cast from ‘int32_t*’ {aka ‘int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
    957 |   ComplexInt16* dfw = (ComplexInt16*)(((uint32_t)dfw_buf + 31) & ~31);
        |                                        ^~~~~~~~~~~~~~~~~
  ../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:957:23: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
    957 |   ComplexInt16* dfw = (ComplexInt16*)(((uint32_t)dfw_buf + 31) & ~31);
        |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:958:40: error: cast from ‘int32_t*’ {aka ‘int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
    958 |   ComplexInt16* efw = (ComplexInt16*)(((uint32_t)efw_buf + 31) & ~31);
        |                                        ^~~~~~~~~~~~~~~~~
  ../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:958:23: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
    958 |   ComplexInt16* efw = (ComplexInt16*)(((uint32_t)efw_buf + 31) & ~31);
        |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Presumably, this file was written for 32-bit MIPS so the author used
uint32_t to do pointer arithmetic over these arrays. Fix the errors by
using uintptr_t to work with pointers.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 18:11:05 +00:00
ecb8817972 Remove some unused files 2024-12-30 12:48:46 -05:00
6119c05d7d meson: Drop WEBRTC_THREAD_RR
The define was dropped upstream a while back and is unused.
2024-12-30 12:20:27 -05:00
2a318149f8 Add support for BSD systems
webrtc/rtc_base/checks.cc:158:28: error: use of undeclared identifier 'LAST_SYSTEM_ERROR'
  158 |                file, line, LAST_SYSTEM_ERROR, message);
      |                            ^
webrtc/rtc_base/checks.cc:220:16: error: use of undeclared identifier 'LAST_SYSTEM_ERROR'
  220 |                LAST_SYSTEM_ERROR);
      |                ^
In file included from webrtc/rtc_base/platform_thread_types.cc:11:
webrtc/rtc_base/platform_thread_types.h:47:1: error: unknown type name 'PlatformThreadId'
   47 | PlatformThreadId CurrentThreadId();
      | ^
webrtc/rtc_base/platform_thread_types.h:52:1: error: unknown type name 'PlatformThreadRef'
   52 | PlatformThreadRef CurrentThreadRef();
      | ^
webrtc/rtc_base/platform_thread_types.h:55:29: error: unknown type name 'PlatformThreadRef'
   55 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b);
      |                             ^
webrtc/rtc_base/platform_thread_types.h:55:57: error: unknown type name 'PlatformThreadRef'
   55 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b);
      |                                                         ^
webrtc/rtc_base/platform_thread_types.cc:37:1: error: unknown type name 'PlatformThreadId'
   37 | PlatformThreadId CurrentThreadId() {
      | ^
webrtc/rtc_base/platform_thread_types.cc:58:1: error: unknown type name 'PlatformThreadRef'
   58 | PlatformThreadRef CurrentThreadRef() {
      | ^
webrtc/rtc_base/platform_thread_types.cc:68:29: error: unknown type name 'PlatformThreadRef'
   68 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) {
      |                             ^
webrtc/rtc_base/platform_thread_types.cc:68:57: error: unknown type name 'PlatformThreadRef'
   68 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) {
      |                                                         ^
In file included from webrtc/rtc_base/event_tracer.cc:30:
In file included from webrtc/api/sequence_checker.h:15:
In file included from webrtc/rtc_base/synchronization/sequence_checker_internal.h:18:
webrtc/rtc_base/synchronization/mutex.h:28:2: error: Unsupported platform.
   28 | #error Unsupported platform.
      |  ^
webrtc/rtc_base/synchronization/mutex.h:52:3: error: unknown type name 'MutexImpl'
   52 |   MutexImpl impl_;
      |   ^
2024-12-30 17:18:54 +00:00
4a17c682e9 common_audio: Add MIPS_DSP_R1_LE guard for vector scaling ops
The MIPS-specific source for vector scaling operations fails to build on
Debian's mips64el:

  [97/303] Compiling C object webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o
  FAILED: webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o
  cc [...] webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o.d -o webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o -c ../webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c
  /tmp/cc7UGPkY.s: Assembler messages:
  /tmp/cc7UGPkY.s:57: Error: opcode not supported on this processor: mips64r2 (mips64r2) `extrv_r.w $3,$ac0,$8'
  ninja: build stopped: subcommand failed.

The EXTRV_R.W instruction it uses is part of DSP extensions for this
architecture. In signal_processing_library.h, this function's prototype
is guarded with #if defined(MIPS_DSP_R1_LE). Guard the implementation
like that as well to fix the error.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 12:06:56 -05:00
5252919799 meson: Avoid default AECM implementation on MIPS
Trying to link both aecm/aecm_core_mips.cc and aecm/aecm_core_c.cc into
the same library results in an error because they both try to implement
webrtc::WebRtcAecm_ProcessBlock():

  [306/306] Linking target webrtc/modules/audio_processing/libwebrtc-audio-processing-1.so.3
  FAILED: webrtc/modules/audio_processing/libwebrtc-audio-processing-1.so.3
  c++ @webrtc/modules/audio_processing/libwebrtc-audio-processing-1.so.3.rsp
  /usr/bin/ld: webrtc/modules/audio_processing/libwebrtc-audio-processing-1.so.3.p/aecm_aecm_core_mips.cc.o: in function `webrtc::WebRtcAecm_ProcessBlock(webrtc::AecmCore*, short const*, short const*, short const*, short*)':
  [...]/webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:934: multiple definition of `webrtc::WebRtcAecm_ProcessBlock(webrtc::AecmCore*, short const*, short const*, short const*, short*)'; webrtc/modules/audio_processing/libwebrtc-audio-processing-1.so.3.p/aecm_aecm_core_c.cc.o:[...]/webrtc/modules/audio_processing/aecm/aecm_core_c.cc:377: first defined here
  collect2: error: ld returned 1 exit status
  ninja: build stopped: subcommand failed.

The MIPS-specific file is a replacement for the other, unlike the NEON
case. Don't add the default implementation unconditionally, add it only
for non-MIPS builds.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 12:06:55 -05:00
85556fd38b meson: Drop malformed WEBRTC_ARCH_MIPS_FAMILY cflags argument
The top-level meson.build file adds WEBRTC_ARCH_MIPS_FAMILY to
arch_cflags for mips architectures, which causes the following error:

  [1/306] Compiling C++ object webrtc/rtc_base/liblibbase.a.p/synchronization_yield.cc.o
  FAILED: webrtc/rtc_base/liblibbase.a.p/synchronization_yield.cc.o
  c++ [...] -DWEBRTC_THREAD_RR WEBRTC_ARCH_MIPS_FAMILY -MD [...] ../webrtc/rtc_base/synchronization/yield.cc
  c++: warning: WEBRTC_ARCH_MIPS_FAMILY: linker input file unused because linking not done
  c++: error: WEBRTC_ARCH_MIPS_FAMILY: linker input file not found: No such file or directory

It is supposed to be "-DWEBRTC_ARCH_MIPS_FAMILY". But, that macro is
already defined in arch.h when building for mips:

  [30/306] Compiling C++ object webrtc/system_wrappers/libsystem_wrappers.a.p/source_cpu_features.cc.o
  In file included from ../webrtc/system_wrappers/source/cpu_features.cc:13:
  ../webrtc/rtc_base/system/arch.h:47:9: warning: "WEBRTC_ARCH_MIPS_FAMILY" redefined
     47 | #define WEBRTC_ARCH_MIPS_FAMILY
        |         ^~~~~~~~~~~~~~~~~~~~~~~
  <command-line>: note: this is the location of the previous definition

Drop the broken, unnecessary argument from cflags.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-30 12:06:49 -05:00
da757ff09f Fix MIPS-specific source path
Link: https://sources.debian.org/patches/webrtc-audio-processing/1.0-0.2/fix-mips-source-path.patch
2024-12-30 12:06:46 -05:00
fed81a77c9 Allow disabling inline SSE
Should make building on i686 without SSE feasible.

Fixes: https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing/-/issues/5
2024-12-26 17:35:08 -05:00
c144c53039 Drop WAV-related files
These are only used when WEBRTC_APM_DEBUG_DUMP=1, which we do not set.
Hopefully this makes building on big-endian machines possible.

Fixes: https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing/-/issues/31
2024-12-26 13:07:40 -05:00
0d4c5f27b5 build: Bump version to 2.0 2024-12-26 12:55:16 -05:00
9b194c2d99 ci: Switch CI over to Fedora
Ubuntu/Debian absl are currently lagging. We should switch back to
Debian once recent abseil lands in unstable/testing.
2024-12-26 12:55:16 -05:00
d090f7a927 ci: Bump iOS version to 11.0
This is needed for std::optional to be usable (specifically for .value()
to be available).
2024-12-26 12:55:16 -05:00
ad563b095c Fix up XMM intrinsics usage on MSVC
Repplying 0a0050746b after M131 bump.
2024-12-26 12:55:16 -05:00
b5c48b97f6 Bump to WebRTC M131 release
Ongoing fixes and improvements, transient suppressor is gone. Also,
dropping isac because it doesn't seem to be useful, and is just build
system deadweight now.

Upstream references:

  Version: 131.0.6778.200
  WebRTC: 79aff54b0fa9238ce3518dd9eaf9610cd6f22e82
  Chromium: 2a19506ad24af755f2a215a4c61f775393e0db42
2024-12-26 12:55:16 -05:00
8bdb53d91c meson: Update abseil wrap to 20240722
We need something recent enough with the stringify API for the M131 bump.
2024-12-26 12:55:12 -05:00
ced0ff6765 ci: Fix up workflow rules for MR vs. branch pipelines 2024-12-26 09:27:14 -05:00
1ff1a0b860 Decode base64-encoded third-party files
Some files were committed into the repository as base64 encoded files.
Presumably, this is because the "text" download links on Google's
Gitiles web interface sends them as such. These can be found by running
`git grep "^[[:alnum:]]\{128,\}=*$"`. Decode them with `base64 -d`.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
2024-12-24 19:42:56 -05:00
867e2d875b Add a trivial example to run AEC offline
Just allows for some sanity testing for now, will improve for
configurability and add some sample data in the future.
2024-12-24 18:57:37 -05:00
a729ccfe0f ci: Bump to Ubuntu 24.04 2024-12-24 18:57:37 -05:00
4c81b31652 ci: Bump Windows to cpp_std=c++20
Required for designated initializers.
2024-12-24 12:02:19 -05:00
0a0050746b Fix up XMM intrinsics usage on MSVC 2024-12-24 12:02:19 -05:00
06157f1659 build: Use Visual Studio-specific flags for AVX
Needed for now, but unstable-simd is likely a better fix for all our
SIMD building.
2024-12-24 12:02:19 -05:00
c6abf6cd3f Bump to WebRTC M120 release
Some API deprecation -- ExperimentalAgc and ExperimentalNs are gone.
We're continuing to carry iSAC even though it's gone upstream, but maybe
we'll want to drop that soon.
2024-12-24 11:05:39 -05:00
9a202fb8c2 file_wrapper.h: Fix build with GCC13
It is a missed instance of cdec109331 (!31).

Fixes #32
2024-04-04 18:32:39 -03:00
a949f1de2d build: Appease MSYS2 UCRT64 GCC 13
Undefining this macro makes GCC in standards C++ mode very unhappy:

In file included from D:/msys64/ucrt64/include/c++/13.2.0/bits/requires_hosted.h:31,
                 from D:/msys64/ucrt64/include/c++/13.2.0/string:38,
                 from ..\subprojects\webrtc-audio-processing\webrtc/rtc_base/system/file_wrapper.h:17,
                 from ../subprojects/webrtc-audio-processing/webrtc/rtc_base/system/file_wrapper.cc:11:
D:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++config.h:666:2: warning: #warning "__STRICT_ANSI__ seems to have been undefined; this is not supported" [-Wcpp]
  666 | #warning "__STRICT_ANSI__ seems to have been undefined; this is not supported"
      |  ^~~~~~~

See: https://github.com/fmtlib/fmt/issues/2059#issue-761209068

See: #32
2024-03-23 16:34:50 -03:00
f89958d824 Bring arch.h in line with upstream webrtc
Largely to bring in preprocessor support for additional architectures as
based on 6215ba804eb500f3e28b39088c73af3c4f4cd10a by
Timothy Gu <timothygu99@gmail.com>:

Add preprocessor support for additional architectures

- _M_ARM is used by Microsoft [1]
- __riscv and __riscv_xlen are defined by [2]
- __sparc and __sparc__ are documented at [3]
- __MIPSEB__, __PPC__, __PPC64__ are documented at [3] and used in
  Chromium's build/build_config.h [4]
  Note: Chromium assumes that all PowerPC architectures are 64-bit. This
  is in fact not true.

[1]: https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-160
[2]: feca479356 (cc-preprocessor-definitions)
[3]: https://sourceforge.net/p/predef/wiki/Architectures/
[4]: https://source.chromium.org/chromium/chromium/src/+/master:build/build_config.h;drc=e12bf2e5ff1eacb9aca3e9a26bdeebdbdad5965a
2023-11-29 16:59:12 +00:00
8e258a1933 build: Bump version to 1.3 2023-09-05 11:19:47 -04:00
0691ae20d8 meson: Fix generation of pkgconfig files
Too much information was specified manually. All this is deduced
automatically if you specify the library as the first positional
argument.

Only absl_base needs to be in Requires: because absl_optional's header
file is needed at build time.

Also add a check in the CI for the pc files being usable.
2023-09-05 01:50:51 +05:30
c9b0a675e4 build: Bump version to 1.2 2023-09-01 11:05:31 -04:00
315b2222a8 meson: Update minimum version based on what abseil wrap needs 2023-08-13 17:42:29 -04:00
bc401b3cbf build: Expose absl as a dependency of webrtc-audio-processing
This is needed because the audio processing header references
abseil's optional.h. Clean up the declared dependencies while we're at
it.

Fixes: https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing/-/merge_requests/34
2023-08-13 17:42:29 -04:00
92a4765a7e meson: Update to latest wrap, install required absl headers 2023-06-01 17:46:28 +05:30
c76b8bf340 doc: Update tarball generation process
Use meson dist, include subproject tarballs, and sha256sum files are
also autogenerated.
2023-05-25 18:25:51 -04:00
cdec109331 file_utils.h: Fix build with gcc-13
* add missing include as reported by gcc-13:
webrtc/modules/audio_processing/transient/file_utils.cc:11:
../webrtc-audio-processing-1.0/webrtc/modules/audio_processing/transient/file_utils.h:36:35: error: 'uint8_t' does not name a type
   36 | int ConvertByteArrayToFloat(const uint8_t bytes[4], float* out);
      |                                   ^~~~~~~
webrtc/modules/audio_processing/transient/file_utils.h:17:1: note: 'uint8_t' is defined in header '<cstdint>'; did you forget to '#include <cstdint>'?
   16 | #include "rtc_base/system/file_wrapper.h"
  +++ |+#include <cstdint>
   17 |

Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
2023-05-25 18:13:04 -04:00
096b0eaed2 meson: Fixes for MSVC build
winsock2.h must be included before windows.h or alternative
definitions of `struct sockaddr` are defined.

```
FAILED: webrtc/rtc_base/liblibbase.a.p/logging.cc.obj
"cl" "-Iwebrtc\rtc_base\liblibbase.a.p" "-Iwebrtc\rtc_base" "-I..\webrtc\rtc_base" "-Iwebrtc" "-I..\webrtc" "-Isubprojects\abseil-cpp-20230125.1" "-I..\subprojects\abseil-cpp-20230125.1" "/MD" "/nologo" "/showIncludes" "/utf-8" "/Zc:__cplusplus" "/W2" "/EHsc" "/std:c++17" "/permissive-" "/O2" "/Zi" "-DWEBRTC_LIBRARY_
IMPL" "-DWEBRTC_ENABLE_SYMBOL_EXPORT" "-DNDEBUG" "-DWEBRTC_WIN" "-D_WIN32" "-U__STRICT_ANSI__" "-D__STDC_FORMAT_MACROS=1" "-DNOMINMAX" "-DWEBRTC_ENABLE_AVX2" "/Fdwebrtc\rtc_base\liblibbase.a.p\logging.cc.pdb" /Fowebrtc/rtc_base/liblibbase.a.p/logging.cc.obj "/c" ../webrtc/rtc_base/logging.cc
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(103): warning C4005: 'AF_IPX': macro redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(457): note: see previous definition of 'AF_IPX'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(147): warning C4005: 'AF_MAX': macro redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(476): note: see previous definition of 'AF_MAX'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(187): warning C4005: 'SO_DONTLINGER': macro redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(399): note: see previous definition of 'SO_DONTLINGER'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(240): error C2011: 'sockaddr': 'struct' type redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(482): note: see declaration of 'sockaddr'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(442): error C2143: syntax error: missing '}' before 'constant'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(442): error C2059: syntax error: 'constant'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C2143: syntax error: missing ';' before '}'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
...
```
2023-05-26 03:17:31 +05:30
b24229cbbc meson: Ensure that abseil is built with c++17 too
subprojects do not inherit $lang_std default values from the project.
2023-05-26 03:17:31 +05:30
55239c4ca2 ci: Add jobs for MSVC, macOS, iOS, Android 2023-05-26 03:17:31 +05:30
a47df351ca ci: Bump ubuntu version to 22.10
Contains absl with pkgconfig files.
2023-05-26 03:17:31 +05:30
4125ace620 meson: Fix compatibility with Fedora's abseil-cpp package
1. Fedora abseil-cpp package is built with C++17:
   https://src.fedoraproject.org/rpms/abseil-cpp/blob/rawhide/f/abseil-cpp.spec
2. There is no `absl_types` pkgconfig file, and it's only needed on iOS
2023-05-26 03:16:38 +05:30
aa32d179d0 meson: Update abseil-cpp to latest wrap 2023-05-26 00:45:29 +05:30
9a362bd149 meson: Don't require cross files to set host_system = ios
It's not specified as a host_system by meson, so people will often not
set it.
2023-05-26 00:45:29 +05:30
8366ff0ce0 meson: Get rid of cmake and manual library searching
Simplify fallback, and prefer it. `[provide]` section requires meson
0.55, so require that.

pkg-config lookup is only provided for distros, since they dislike
static linking / vendoring.
2023-05-26 00:45:00 +05:30
ca1186946d build: don't detect neon again when building on aarch64
it will try to add -mfpu=neon to cflags not available on aarch64 since
neon is mandatory there
2022-05-21 14:10:48 +02:00
26f4493405 build: fix -Dneon=runtime 2022-05-21 14:08:15 +02:00
e31340c243 Add builds for distro and vendored versions of abseil 2021-10-20 11:16:19 -04:00
5a5aa66ada Add an abseil subproject and correctly specify fallback deps 2021-10-20 11:16:18 -04:00
0cc2ebeda2 Add missing absl library for bad_optional_access 2021-10-20 11:15:57 -04:00
6064932abf Add missing header for C++17 compatibility
Hopefully we can drop this change with the next update.
2021-10-19 18:06:37 -04:00
8bf9efad15 Use pkg-config for abseil-cpp detection if available
This should make things a bit easier.
2021-10-19 18:06:37 -04:00
ff85c98683 Some fixes for MinGW
* Rename Windows.h uses to windows.h
  * Comment out structured exception handling usage

Makes MinGW happier. Mostly the same as previous work by
Nicolas Dufresne <nicolas.dufresne@collabora.com>, with the exception
that we now don't try to invoke RaiseException which would fail in MinGW
as it raises a Windows structured exception.
2021-10-19 16:09:07 -04:00
57ec282d4f Remove rnn_vad_tool.cc that contains main(). 2021-09-08 12:21:50 +00:00
6e37f37c4e build: Split out iSAC VAD sources into a separate dependency
Avoid having to link webrtc-audio-processing with webrtc-audio-coding,
and makes the required symbols directly available.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing/-/merge_requests/22>
2021-06-19 13:06:12 -04:00
b8ad0dfc22 build: Add framework deps on macOS and iOS
Part-of: <https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing/-/merge_requests/21>
2021-06-18 23:44:18 -04:00
e47b68df57 arch.h: Add RISC-V support 2021-06-17 01:48:37 +00:00
e74894baeb build: Add library-based absl detection as a fallback
This should help for cases where users can make abseil-cpp available but
wiring up the CMake-build isn't that easy (for example, while
cross-compiling).
2021-06-05 18:37:23 -04:00
589a744585 Fix build on Android
There's a bit of system integration that we haven't pulled in (as it has
transitive dependencies), so we manually stub it out.
2021-06-05 18:16:18 -04:00
8ac052ad6f doc: Add some build instructions to README 2021-02-12 15:44:49 -05:00
b34c1d5746 build: Fix ARM ISA detection
armv7 isn't a real cpu_family in meson, so drop that. The detection for
__ARM_ARCH_ISA_ARM was also inverted.

Fixes: https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing/-/issues/6
2020-12-11 08:16:04 -05:00
3f9907f93d build: Use cmake to look up abseil dependency
This should be much more robust than looking up the library directly.

Fixes: https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing/-/issues/4
2020-12-10 19:20:09 -05:00
ce1a78887a build: Revert top-level project name to not have a prefix
Should make meson dist easier to work with.
2020-12-10 18:24:05 -05:00
8ce8bebb7d build: Bump project version to 1.1 2020-12-10 18:24:05 -05:00
00ae7eb234 doc: Fix up release process
Missed a trailing '/' while generating the archive with disastrous
results.
2020-11-27 16:47:09 -05:00
d353e92425 doc: Fix up links in markdown 2020-11-27 14:50:02 -05:00
6a4d14d5c0 doc: Some minor README cleanups 2020-11-27 14:46:36 -05:00
6a67b5ba7e doc: Add some documentation about the release process 2020-11-27 14:30:53 -05:00
e5402cd638 build: Fix up some ARM-related mistakes 2020-11-27 14:03:06 -05:00
e23c10c5e0 ci: Add an aarch64 build 2020-11-27 13:20:12 -05:00
d938d2cf52 meson: override dependency
Will allow us to build the libs as part of gst-build as subprojects.
2020-10-28 16:03:08 +01:00
593986ec5e ci: Add a gitlab-ci.yml 2020-10-26 14:58:04 -04:00
2fabea79e0 gitignore: Drop autotools-related paths 2020-10-23 13:30:23 -04:00
21d78a4267 build: Make packages versioned
Since we cannot rely on the API to be stable upstream, let's start
making the pkg-config, library, and include dir have a version suffix.
This will allow different downstream projects depending on us to
independently switch versions without packagers having to jump through
hoops.
2020-10-23 13:30:23 -04:00
bcec8b0b21 Update to current webrtc library
This is from the upstream library commit id
3326535126e435f1ba647885ce43a8f0f3d317eb, corresponding to Chromium
88.0.4290.1.
2020-10-23 13:30:23 -04:00
b1b02581d3 gitignore: Add install/ for local prefixed installs 2020-10-20 17:22:19 -04:00
a54ffa1220 Add build directory to gitignore
This is what is expected to commonly be used with the meson build
system.
2020-10-12 11:25:23 -04:00
34efc689c2 add webrtc-audio-coding public library
This new lib contains the bare minimum to implement an iSAC encoder and
decoder.

The webrtc files have been copied from the revision as the existing
imported files (c8b569e0a7ad0b369e15f0197b3a558699ec8efa).
2020-03-27 14:52:22 +01:00
f13529b5b8 UPDATING: update with meson instructions 2020-03-24 15:00:53 +01:00
f2003f80d1 meson: fix pkgconfig generation
The bug preventing us to pass the library object to
pkgconfig.generate() has been fixed in meson 0.52.

By doing so the generated pc file has the right -L linker flag, making
it easier to test the lib from non standard location.
We also no longer have to pass libraries_private, it will handle it
automatically.
2020-03-24 15:00:53 +01:00
301110c655 remove autotools
In Meson we trust.
2020-03-24 14:10:59 +01:00
9def8cf10d Add support for non-Linux GNU
GNU/Hurd and GNU/kFreeBSD have basically the same userland as GNU/Linux,
just not the same kernel.
2019-08-31 23:00:29 +02:00
27e93ee86b build/meson: fix compilation on arm64
The assembly files used don't use the right comments for arm64
2018-11-08 20:56:52 +11:00
682857751b build: Factor out common POSIX flag setting in meson build 2018-10-28 14:57:00 +00:00
b47c302cef build: Fix project() invocation in meson build 2018-10-28 14:56:54 +00:00
eb398328ab Initial meson build files 2018-10-28 23:25:18 +11:00
e882a5442a build: Update version to 0.3.1 2018-07-23 18:28:08 +05:30
ee8cfef49b build: Fix configure option '--with-ns-mode'
Make *really* take '--with-ns-mode'-option into account.
Before it was bogus (wrong if-check) and it always resulted
in the float version being used.

Signed-off-by: Mirko Vogt <mirko-dev@nanl.de>
2017-01-06 10:31:17 +05:30
0d937fbc71 doc: file invalid reference to pulseaudio mailing list
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
2016-08-10 20:37:31 +05:30
ff77a85c28 build: fix architecture detection
The current architecture detection, based on the "host_cpu" part of the
tuple does not work properly for a number of reason:

 - The code assumes that if host_cpu starts with "arm" then ARM
   instructions are available, which is incorrect. Indeed, Cortex-M
   platforms can run Linux, they are ARM platforms (so host_cpu = arm),
   but they don't support ARM instructions: they support only the
   Thumb-2 instruction set.

 - The armv7 case is also not very useful, as it is not standard at all
   to pass armv7 as host_cpu even if the host system is actually ARMv7
   based.

 - For the same reason, the armv8 case is not very useful: ARMv8 is
   AArch64, and there is already a separate case to handle this
   architecture.

So, this commit moves away from a host_cpu based logic, and instead
tests using AC_CHECK_DECLS() the built-in definitions of the compiler:

 - If we have __ARM_ARCH_ISA_ARM defined, then it's an ARM processor
   that supports the ARM instruction set (this allows to exclude Thumb-2
   only processors).

 - If we have __ARM_ARCH_7A__, then we have an ARMv7-A processor, and
   we can enable the corresponding optimizations

 - Same for __aarch64__, __i386__ and __x86_64__.

In addition, we remove the AC_MSG_ERROR() that makes the build fail for
all architectures but the ones that are explicitly supported. Indeed,
webrtc-audio-processing builds just fine for other architectures (tested
on MIPS), it's just that none of the architecture-specific optimizations
will be used.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
2016-08-10 20:37:27 +05:30
7d15b10fb0 build: Add ARM 64bit support 2016-07-14 12:57:43 +09:00
7a37a8bca3 build: Re-add pthread linking on linux 2016-07-14 12:57:43 +09:00
b8be6d1095 build: Use -no-undefined to support both clang and gcc 2016-07-14 12:57:43 +09:00
c9cffb9e3d build: Sync defines and libs with build.gn 2016-07-14 12:57:43 +09:00
1378babdf0 osx: Fix type OS_FLAGS instead of OS_CFLAGS 2016-07-14 12:57:43 +09:00
75ef0de241 build: Protect against unsupported CPU types 2016-07-14 12:57:43 +09:00
6ad2f51e9e Add missing windows conditions variable
Those are used by generic RW lock implementation.

https://bugs.freedesktop.org/show_bug.cgi?id=96754
2016-07-14 12:57:43 +09:00
db2f422578 build: Define MSVC _WIN32 so we can build on mingw
https://bugs.freedesktop.org/show_bug.cgi?id=96754
2016-07-14 12:57:43 +09:00
bf6b9de143 build: Properly select the right system wrappers
This is needed for windows build to be usable.

https://bugs.freedesktop.org/show_bug.cgi?id=96754
2016-07-14 12:57:43 +09:00
12ac8441f7 build: Add required define for Windows
This will also add it to the .pc file as WEBRTC_WIN leaks into the
public interface and undefined __STRICT_ANSI__ so M_PI is available.

https://bugs.freedesktop.org/show_bug.cgi?id=96754
2016-07-14 12:57:43 +09:00
44cf7726ca build: Don't blindly link to pthread
This otherwise breaks the build on Android and Windows. The flag is
required on some Linux builds, and is readded in a subsequent commit.

https://bugs.freedesktop.org/show_bug.cgi?id=96754
2016-07-14 12:57:28 +09:00
560f300a3d build: Add cerbero gnustl support for Android 2016-07-14 12:49:29 +09:00
bf25c45e54 Add missing windows specific headers
https://bugs.freedesktop.org/show_bug.cgi?id=96754
2016-07-14 12:38:42 +09:00
875 changed files with 85834 additions and 59418 deletions

25
.gitignore vendored
View File

@ -1,30 +1,11 @@
*.o
*.lo
*.la
*.pc
.*.swp
*~
.deps*
.dirstamp
.libs*
Makefile
Makefile.in
aclocal.m4
autom4te.cache
compile
config.guess
config.h
config.h.in
config.log
config.rpath
config.status
config.sub
configure
build/
depcomp
install-sh
libltdl
libtool
ltmain.sh
missing
mkinstalldirs
stamp-*
install/
subprojects/*/

299
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,299 @@
# The build has two stages. The 'container' stage is used to build a Docker
# container and push it to the project's container registry on fd.o GitLab.
# This step is only run when the tag for the container changes, else it is
# effectively a no-op. All of this infrastructure is inherited from the
# wayland/ci-templates repository which is the recommended way to set up CI
# infrastructure on fd.o GitLab.
#
# Once the container stage is done, we move on to the 'build' stage where we
# run an autotools and meson build in parallel. Currently, tests are also run
# as part of the build stage as there doesn't seem to be significant value to
# splitting the stages at the moment.
# Create merge request pipelines for open merge requests, branch pipelines
# otherwise. This allows MRs for new users to run CI, and prevents duplicate
# pipelines for branches with open MRs.
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
- if: $CI_COMMIT_BRANCH
stages:
- container
- build
variables:
# Update this tag when you want to trigger a rebuild the container in which
# CI runs, for example when adding new packages to FDO_DISTRIBUTION_PACKAGES.
# The tag is an arbitrary string that identifies the exact container
# contents.
BASE_TAG: '2024-12-26.0'
FDO_DISTRIBUTION_VERSION: '41'
FDO_UPSTREAM_REPO: 'pulseaudio/webrtc-audio-processing'
include:
# We pull templates from master to avoid the overhead of periodically
# scanning for changes upstream. This does means builds might occasionally
# break due to upstream changing things, so if you see unexpected build
# failures, this might be one cause.
- project: 'freedesktop/ci-templates'
ref: 'master'
file: '/templates/fedora.yml'
# Common container build template
.fedora-container-build:
variables:
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
# Remember to update FDO_DISTRIBUTION_TAG when modifying this package list!
# Otherwise the changes won't have effect since an old container image will
# be used.
FDO_DISTRIBUTION_PACKAGES: >-
ca-certificates
g++
gcc
git-core
cmake
abseil-cpp-devel
meson
ninja-build
pkg-config
python3-setuptools
# Used to extend both container and build jobs
.fedora-x86_64:
variables:
FDO_DISTRIBUTION_TAG: "x86_64-$BASE_TAG"
# Used to extend both container and build jobs
.fedora-aarch64:
tags:
- aarch64
variables:
FDO_DISTRIBUTION_TAG: "aarch64-$BASE_TAG"
build-container-x86_64:
extends:
- .fdo.container-build@fedora@x86_64
- .fedora-container-build
- .fedora-x86_64
stage: container
build-container-aarch64:
extends:
- .fdo.container-build@fedora@aarch64
- .fedora-container-build
- .fedora-aarch64
stage: container
# Common build template
.build-distro-absl:
stage: build
extends:
- .fdo.distribution-image@fedora
script:
- meson setup --wrap-mode=nofallback --prefix=/usr --libdir=lib builddir
- ninja -C builddir
- DESTDIR=$PWD/_install ninja install -C builddir
# Test that the pc files are usable
- PKG_CONFIG_PATH=$PWD/_install/usr/lib/pkgconfig pkg-config --cflags --libs webrtc-audio-processing-2
artifacts:
expire_in: '5 days'
when: 'always'
paths:
- "builddir/meson-logs/*txt"
.build-vendored-absl:
stage: build
extends:
- .fdo.distribution-image@fedora
script:
- meson setup --force-fallback-for=abseil-cpp --prefix=/usr --libdir=lib builddir
- ninja -C builddir
- DESTDIR=$PWD/_install ninja install -C builddir
# Test that the pc files are usable
- PKG_CONFIG_LIBDIR=$PWD/_install/usr/lib/pkgconfig pkg-config --cflags --libs webrtc-audio-processing-2
artifacts:
expire_in: '5 days'
when: 'always'
paths:
- "builddir/meson-logs/*txt"
build-distro-absl-x86_64:
extends:
- .build-distro-absl
- .fedora-x86_64
build-vendored-absl-x86_64:
extends:
- .build-vendored-absl
- .fedora-x86_64
build-distro-absl-aarch64:
extends:
- .build-distro-absl
- .fedora-aarch64
build-vendored-absl-aarch64:
extends:
- .build-vendored-absl
- .fedora-aarch64
# Update from:
# https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/main/.gitlab-ci.yml
# https://gitlab.freedesktop.org/gstreamer/orc/-/blob/main/.gitlab-ci.yml
vs2019 amd64:
# Update from https://gitlab.freedesktop.org/gstreamer/gstreamer/container_registry
image: 'registry.freedesktop.org/gstreamer/gstreamer/amd64/windows:2023-04-21.0-main'
stage: 'build'
tags:
- 'docker'
- 'windows'
- '2022'
artifacts:
expire_in: '5 days'
when: 'always'
paths:
- "builddir/meson-logs/*txt"
variables:
# Make sure any failure in PowerShell scripts is fatal
ErrorActionPreference: 'Stop'
WarningPreference: 'Stop'
ARCH: 'amd64'
PLAT: 'Desktop'
before_script:
# Make sure meson is up to date, so we don't need to rebuild the image with each release
- pip3 install -U meson ninja
script:
# Gitlab executes PowerShell in docker, but VsDevCmd.bat is a batch script.
# Environment variables substitutions is done by PowerShell before calling
# cmd.exe, that's why we use $env:FOO instead of %FOO%
- cmd.exe /C "C:\BuildTools\Common7\Tools\VsDevCmd.bat -host_arch=amd64 -arch=$env:ARCH -app_platform=$env:PLAT &&
meson setup builddir -Dcpp_std=c++20 &&
meson compile --verbose -C builddir"
# Update from:
# https://gitlab.freedesktop.org/gstreamer/cerbero/-/blob/main/.gitlab-ci.yml
# https://gitlab.freedesktop.org/gstreamer/orc/-/blob/main/.gitlab-ci.yml
macos x86_64:
stage: 'build'
tags:
- gst-macos-13
artifacts:
expire_in: '5 days'
when: 'always'
paths:
- "builddir/meson-logs/*txt"
before_script:
- pip3 install --upgrade pip
# Need to install certificates for python
- pip3 install --upgrade certifi
# Anther way to install certificates
- open /Applications/Python\ 3.8/Install\ Certificates.command
# Make sure meson and ninja are up to date
- pip3 install -U meson ninja
script:
- CERT_PATH=$(python3 -m certifi) && export SSL_CERT_FILE=${CERT_PATH} && export REQUESTS_CA_BUNDLE=${CERT_PATH}
- meson setup builddir
- meson compile --verbose -C builddir
# Update from:
# https://gitlab.freedesktop.org/gstreamer/cerbero/-/blob/main/.gitlab-ci.yml
# https://gitlab.freedesktop.org/gstreamer/orc/-/blob/main/.gitlab-ci.yml
ios arm64:
stage: 'build'
tags:
- gst-ios-16
artifacts:
name: "${CI_JOB_NAME}_${CI_COMMIT_SHA}"
expire_in: '5 days'
when: 'always'
paths:
- "builddir/meson-logs/*txt"
before_script:
- pip3 install --upgrade pip
# Need to install certificates for python
- pip3 install --upgrade certifi
# Anther way to install certificates
- open /Applications/Python\ 3.8/Install\ Certificates.command
# Make sure meson and ninja are up to date
- pip3 install -U meson ninja
script:
- CERT_PATH=$(python3 -m certifi) && export SSL_CERT_FILE=${CERT_PATH} && export REQUESTS_CA_BUNDLE=${CERT_PATH}
- |
cat > ios-cross-file.txt <<EOF
[host_machine]
system = 'darwin'
cpu_family = 'aarch64'
cpu = 'aarch64'
endian = 'little'
[properties]
c_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
objc_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
cpp_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
objcpp_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
c_link_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
objc_link_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
cpp_link_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
objcpp_link_args = ['-arch', 'arm64', '--sysroot=$(xcrun --sdk iphoneos --show-sdk-path)', '-miphoneos-version-min=11.0']
[binaries]
ar = '$(xcrun --find --sdk iphoneos ar)'
c = '$(xcrun --find --sdk iphoneos clang)'
objc = '$(xcrun --find --sdk iphoneos clang)'
cpp = '$(xcrun --find --sdk iphoneos clang++)'
objcpp = '$(xcrun --find --sdk iphoneos clang++)'
ranlib = '$(xcrun --find --sdk iphoneos ranlib)'
strip = '$(xcrun --find --sdk iphoneos strip)'
pkgconfig = 'false'
cmake = 'false'
EOF
- meson setup --cross-file ios-cross-file.txt builddir
- meson compile --verbose -C builddir
# Update from:
# https://gitlab.freedesktop.org/gstreamer/cerbero/-/blob/main/.gitlab-ci.yml
# https://gitlab.freedesktop.org/gstreamer/orc/-/blob/main/.gitlab-ci.yml
android fedora arm64:
# Update from https://gitlab.freedesktop.org/gstreamer/cerbero/container_registry
image: 'registry.freedesktop.org/gstreamer/cerbero/amd64/android-fedora:2021-10-22.0-1.18'
stage: 'build'
artifacts:
expire_in: '5 days'
when: 'always'
paths:
- "builddir/meson-logs/*.txt"
before_script:
- dnf install -y python3-pip gcc ninja-build
- pip3 install --user meson
script:
- export PATH="$HOME/.local/bin:$PATH"
- |
cat > android-cross-file.txt <<EOF
[constants]
ndk_path = '/android/ndk'
toolchain = ndk_path + '/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android'
api = '28'
[host_machine]
system = 'android'
cpu_family = 'aarch64'
cpu = 'aarch64'
endian = 'little'
[properties]
sys_root = ndk_path + '/sysroot'
c_link_args = ['-fuse-ld=gold']
cpp_link_args = ['-fuse-ld=gold']
[binaries]
c = toolchain + api + '-clang'
cpp = toolchain + api + '-clang++'
ar = toolchain + '-ar'
strip = toolchain + '-strip'
EOF
- meson setup --cross-file android-cross-file.txt builddir
- meson compile --verbose -C builddir

View File

@ -1,23 +0,0 @@
SUBDIRS = webrtc
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = webrtc-audio-processing.pc
webrtcincludedir = $(includedir)/webrtc_audio_processing
nobase_webrtcinclude_HEADERS = webrtc/base/arraysize.h \
webrtc/base/checks.h \
webrtc/base/constructormagic.h \
webrtc/base/basictypes.h \
webrtc/base/maybe.h \
webrtc/base/platform_file.h \
webrtc/common.h \
webrtc/common_types.h \
webrtc/typedefs.h \
webrtc/modules/audio_processing/beamformer/array_util.h \
webrtc/modules/audio_processing/include/audio_processing.h \
webrtc/modules/interface/module_common_types.h \
webrtc/system_wrappers/include/trace.h
EXTRA_DIST = NEWS \
README.md \
UPDATING.md

70
NEWS
View File

@ -1,3 +1,73 @@
Release 2.1
-----------
Build-system fixups to install more headers, add a missing absl dependency, and
forward port some missing patches to fix Windows builds.
Release 2.0
-----------
Bump to code from WebRTC M131 version.
Changes include:
* Minor (breaking) API changes upstream
* Various improvements to the AEC implementation
* Transient suppression is removed
* ExperimentalAgc and ExperimentalNs are removed
* iSAC and the webrtc-audio-coding library were removed
* abseil-cpp dependency bumped to 20240722
* NEON runtime detection dropped following upstream
* Fixes for building on i686 and MIPS
* Support for BSDs is added
* Other build-system cleanups
* Patches to upstream are now also tracked in patches/
Release 1.3
-----------
Fix for generate pkg-config file.
Release 1.2
-----------
Improvements for building with abseil-cpp as a subproject, and pkg-config
improvements for abseil dependency detection.
Release 1.1
-----------
Build fixes for various platforms.
Release 1.0
-----------
This is an API breaking release (as a reminder, the AudioProcessing module does
not provide a stable public API, so we expose whatever API exists in the
upstream project).
In order to make package management easier with these inevitable breakages, the
package is now suffixed with a version (currently it is
webrtc-audio-processing-1). When the next API break happens, we will bump the
major version, allowing incompatible versions to coexist. This also means that
the previous version can also coexist with this one. Non-breaking changes will
see a minor version update only.
Changes:
* The code base is now updated to correspond to the version shipping with the
Chromium 88.0.4290.1 tag
* There are a very large number changes to the underlying AEC implementation
since the last update was a while ago. Most visibly the use of the AEC3
canceller by default, the deletion of the beamformer code
* The autotools build system is replaced by meson
* The pkg-config name is changed as described above
Release 0.3
-----------

View File

@ -1,9 +1,9 @@
About
=====
# About
This is meant to be a more Linux packaging friendly copy of the AudioProcessing
module from the WebRTC[1][2] project. The ideal case is that we make no changes to
the code to make tracking upstream code easy.
module from the [ WebRTC ](https://webrtc.googlesource.com/src) project. The
ideal case is that we make no changes to the code to make tracking upstream
code easy.
This package currently only includes the AudioProcessing bits, but I am very
open to collaborating with other projects that wish to distribute other bits of
@ -11,26 +11,33 @@ the code and hopefully eventually have a single point of packaging all the
WebRTC code to help people reuse the code and avoid keeping private copies in
several different projects.
[1] http://code.google.com/p/webrtc/
[2] https://chromium.googlesource.com/external/webrtc/trunk/webrtc.git
# Building
Feedback
========
This project uses the [Meson build system](https://mesonbuild.com/). The
quickest way to build is:
Patches, suggestions welcome. You can send them to the PulseAudio mailing
list[2] or to me at the address below.
```sh
# Initialise into the build/ directory, for a prefixed install into the
# install/ directory
meson . build -Dprefix=$PWD/install
-- Arun Raghavan <mail@arunraghavan.net>
# Run the actual build
ninja -C build
[3] http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
# Install locally
ninja -C build install
Notes
====
# The libraries, headers, and pkg-config files are now in the install/
# directory
```
1. Some files need to be patch to avoid pulling in the gtest framework. This
should ideally be pushed upstream in some way so we're able to just pull
in what we need without changing anything.
# Feedback
2. It might be nice to try LTO on the library. We build a lot of code as part
Patches, suggestions welcome. You can file an issue on our Gitlab
[repository](https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing/).
# Notes
1. It might be nice to try LTO on the library. We build a lot of code as part
of the main AudioProcessing module deps, and it's possible that this could
provide significant space savings.

64
RELEASING.md Normal file
View File

@ -0,0 +1,64 @@
# Release process
## Update the code
Follow the instructions in `UPDATING.md` to update the code.
## Update the package version
If there is no API breakage, update the minor version (X.y -> X.y+1). If there
is API breakage, update the major version (X.y -> X+1.0).
## Make sure builds are successful on all platforms
There is CI for `x86_64` and `aarch64` builds, but 32-bit ARM and MIPS builds
need manual verfification (or testing downstream).
## Tag the release
Tag the release with:
```sh
git tag -s -m 'WebRTC AudioProcessing v<X.y>' v<X.y>
```
## Make a tarball
```sh
# The output will be in build/meson-dist/
meson dist -C build --formats=gztar,xztar --include-subprojects
```
## Do a test build
```sh
tar xvf webrtc-audio-processing-X.y.tar.xz
cd webrtc-audio-processing-X.y
meson . build -Dprefix=$PWD/install
ninja -C build
ninja -C build install
cd ..
```
## Publish the files
```sh
scp webrtc-audio-processing-*.tar.* \
annarchy.freedesktop.org:/srv/www.freedesktop.org/www/software/pulseaudio/webrtc-audio-processing/
```
## Push the tag
```sh
git push origin master
git push origin vX.y
```
## Update the website
This is currently an embarrassing manual process.
## Send out a release announcement
This goes to the `pulseaudio-discuss` and `gstreamer-devel` mailing lists, and
possibly `discuss-webrtc` if it seems relevant.

View File

@ -8,7 +8,7 @@ project source code.
webrtc git repository Chromium uses.
2. Instructions on checking out the Chromium tree are on the
[Chromium site][get-chromium]. As a shortcut, you can look at the DEPS file
[WebRTC repo][get-webrtc]. As a shortcut, you can look at the DEPS file
in the Chromium tree for the current webrtc version being used, and then
just use that commit hash with the webrtc tree.
@ -29,7 +29,7 @@ project source code.
system upstreama.
* Arch-specific files usually have special handling in the corresponding
Makefile.am.
meson.build.
4. Once everything has been copied and updated, everything needs to be built.
Missing dependencies (files that were not copied, or new modules that are
@ -43,25 +43,24 @@ project source code.
* The current policy is that we mirror upstream API as-is.
* Update configure.ac with the appropriate version info based on how the
* Update soversion in meson.build with the appropriate version info based on how the
code has changed. Details on how to do this are included in the
[libtool documentation][libtool-version-info].
5. Build PulseAudio (and/or any other dependent projects) against the new code.
The easy way to do this is via a prefixed install.
* Run ```configure``` webrtc-audio-processing with
```--prefix=/some/local/path```, then do a ```make``` and
```make install```.
* Configure webrtc-audio-processing with
```meson build -D prefix=$(pwd)/install```, then do a ```ninja -C build/ install```
* Run ```configure``` on PulseAudio with
```PKG_CONFIG_PATH=/some/local/path/lib/pkgconfig```, which will cause the
build to pick up the prefixed install. Then do a ```make```, run the built
* Configure PulseAudio with
```meson build -D pkg_config_path=/path/to/webrtc-audio-processing/install/lib64/pkgconfig/```, which will cause the
build to pick up the prefixed install. Then do a ```ninja -C build```, run the built
PulseAudio, and load ```module-echo-cancel``` to make sure it loads fine.
* Run some test streams through the canceller to make sure it is working
fine.
[get-chromium]: http://dev.chromium.org/developers/how-tos/get-the-code
[get-webrtc]: https://webrtc.googlesource.com/src/
[meld]: http://meldmerge.org/
[libtool-version-info]: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html

View File

@ -1,6 +0,0 @@
#!/bin/sh
libtoolize
aclocal
automake --add-missing --copy
autoconf
./configure ${@}

View File

@ -1,123 +0,0 @@
AC_INIT([webrtc-audio-processing], [0.3])
AM_INIT_AUTOMAKE([dist-xz subdir-objects tar-ustar])
AC_SUBST(LIBWEBRTC_AUDIO_PROCESSING_VERSION_INFO, [1:0:0])
AM_SILENT_RULES([yes])
# Set up the host_* variables
AC_CANONICAL_HOST
AC_PROG_CC
AC_PROG_CXX
AC_PROG_LIBTOOL
AC_PROG_INSTALL
AM_PROG_AS
AC_LANG_C
AC_LANG_CPLUSPLUS
AC_ARG_WITH([ns-mode],
AS_HELP_STRING([--with-ns-mode=float|fixed], [Noise suppresion mode to use. Default is float]))
AS_CASE(["x${with_ns_mode}"],
["fixed"], [NS_FIXED=1],
["float"], [NS_FIXED=0],
[NS_FIXED=0])
AM_CONDITIONAL(NS_FIXED, [test "x${NS_FIXED}" = "x1"])
# Borrowed from gst-plugins-bad
AC_CHECK_HEADER(MobileCoreServices/MobileCoreServices.h, HAVE_IOS="yes", HAVE_IOS="no", [-])
# Based on gst-plugins-bad configure.ac and defines in
# <chromium source>/build/config/BUILDCONFIG.gn and
# webrtc/BUILD.gn
AS_CASE(["${host}"],
[*android*],
[
OS_CFLAGS="-DWEBRTC_ANDROID -DWEBRTC_LINUX"
PLATFORM_CFLAGS="-DWEBRTC_POSIX"
],
[*-*linux*],
[
OS_CFLAGS="-DWEBRTC_LINUX"
PLATFORM_CFLAGS="-DWEBRTC_POSIX"
],
[*-*darwin*],
[
AS_IF([test "$HAVE_IOS" = "yes"],
[OS_FLAGS="-DWEBRTC_MAC -DWEBRTC_IOS"],
[OS_FLAGS="-DWEBRTC_MAC"])
PLATFORM_CFLAGS="-DWEBRTC_POSIX"
]
# FIXME: Add Windows support
)
AC_SUBST(PLATFORM_CFLAGS)
AS_CASE(["${host_cpu}"],
[i?86|x86_64],
[
HAVE_X86=1
],
[armv7*|armv8*],
[
HAVE_ARM=1
HAVE_ARMV7=1
ARCH_CFLAGS="-DWEBRTC_ARCH_ARM -DWEBRTC_ARCH_ARM_V7"
],
[arm*],
[
HAVE_ARM=1
ARCH_CFLAGS="-DWEBRTC_ARCH_ARM"
]
# FIXME: Add MIPS support, see webrtc/BUILD.gn for defines
)
AM_CONDITIONAL(HAVE_X86, [test "x${HAVE_X86}" = "x1"])
AM_CONDITIONAL(HAVE_ARM, [test "x${HAVE_ARM}" = "x1"])
AM_CONDITIONAL(HAVE_ARMV7, [test "x${HAVE_ARMV7}" = "x1"])
# Borrowed from pulseaudio's configure.ac
AC_ARG_ENABLE([neon],
AS_HELP_STRING([--enable-neon], [Enable NEON optimisations on ARM CPUs that support it (yes|no|auto|runtime)]))
AS_IF([test "x$enable_neon" != "xno"],
AS_IF([test "x$enable_neon" != "xruntime"],
[
save_CXXFLAGS="$CXXFLAGS"; CXXFLAGS="-mfpu=neon $CXXFLAGS"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[
#include <arm_neon.h>
], [])],
[
HAVE_NEON=1
ARCH_CFLAGS="$ARCH_CFLAGS -DWEBRTC_HAS_NEON -mfpu=neon"
])
CXXFLAGS="$save_CXXFLAGS"
],
[
HAVE_NEON=1
ARCH_CFLAGS="$ARCH_CFLAGS -DWEBRTC_DETECT_NEON -mfpu=neon"
])
)
AM_CONDITIONAL([HAVE_NEON], [test "x$HAVE_NEON" = "x1"])
COMMON_CFLAGS="-DWEBRTC_AUDIO_PROCESSING_ONLY_BUILD ${PLATFORM_CFLAGS} ${OS_CFLAGS} ${ARCH_CFLAGS} -DNDEBUG -I\$(top_srcdir)"
COMMON_CXXFLAGS="-std=c++11 -DWEBRTC_AUDIO_PROCESSING_ONLY_BUILD ${PLATFORM_CFLAGS} ${OS_CFLAGS} ${ARCH_CFLAGS} -DNDEBUG -I\$(top_srcdir)"
AC_SUBST([COMMON_CFLAGS])
AC_SUBST([COMMON_CXXFLAGS])
AC_CONFIG_FILES([
webrtc-audio-processing.pc
Makefile
webrtc/Makefile
webrtc/base/Makefile
webrtc/common_audio/Makefile
webrtc/system_wrappers/Makefile
webrtc/modules/Makefile
webrtc/modules/audio_coding/Makefile
webrtc/modules/audio_processing/Makefile
])
AC_OUTPUT

8
examples/meson.build Normal file
View File

@ -0,0 +1,8 @@
top_incdir = include_directories('..')
executable('run-offline',
'run-offline.cpp',
install: false,
include_directories: top_incdir,
dependencies: [audio_processing_dep, absl_dep]
)

67
examples/run-offline.cpp Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2024 Asymptotic Inc. All Rights Reserved.
* Author: Arun Raghavan <arun@asymptotic.io>
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/scoped_refptr.h"
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <webrtc/modules/audio_processing/include/audio_processing.h>
#define DEFAULT_BLOCK_MS 10
#define DEFAULT_RATE 32000
#define DEFAULT_CHANNELS 1
int main(int argc, char **argv) {
if (argc != 4) {
std::cerr << "Usage: " << argv[0] << " <play_file> <rec_file> <out_file>" << std::endl;
return EXIT_FAILURE;
}
std::ifstream play_file(argv[1], std::ios::binary);
std::ifstream rec_file(argv[2], std::ios::binary);
std::ofstream aec_file(argv[3], std::ios::binary);
rtc::scoped_refptr<webrtc::AudioProcessing> apm = webrtc::AudioProcessingBuilder().Create();
webrtc::AudioProcessing::Config config;
config.echo_canceller.enabled = true;
config.echo_canceller.mobile_mode = false;
config.gain_controller1.enabled = true;
config.gain_controller1.mode = webrtc::AudioProcessing::Config::GainController1::kAdaptiveAnalog;
config.gain_controller2.enabled = true;
config.high_pass_filter.enabled = true;
apm->ApplyConfig(config);
webrtc::StreamConfig stream_config(DEFAULT_RATE, DEFAULT_CHANNELS);
while (!play_file.eof() && !rec_file.eof()) {
int16_t play_frame[DEFAULT_RATE * DEFAULT_BLOCK_MS / 1000 * DEFAULT_CHANNELS];
int16_t rec_frame[DEFAULT_RATE * DEFAULT_BLOCK_MS / 1000 * DEFAULT_CHANNELS];
play_file.read(reinterpret_cast<char *>(play_frame), sizeof(play_frame));
rec_file.read(reinterpret_cast<char *>(rec_frame), sizeof(rec_frame));
apm->ProcessReverseStream(play_frame, stream_config, stream_config, play_frame);
apm->ProcessStream(rec_frame, stream_config, stream_config, rec_frame);
aec_file.write(reinterpret_cast<char *>(rec_frame), sizeof(rec_frame));
}
play_file.close();
rec_file.close();
aec_file.close();
return EXIT_SUCCESS;
}

217
meson.build Normal file
View File

@ -0,0 +1,217 @@
project('webrtc-audio-processing', 'c', 'cpp',
version : '2.1',
meson_version : '>= 0.63',
default_options : [ 'warning_level=1',
'buildtype=debugoptimized',
'c_std=c11',
'cpp_std=c++17',
]
)
version_split = meson.project_version().split('.')
# This will be incremented each time a breaking API change occurs
major_version = version_split[0]
# This will be incremented when there are backwards-compatible changes
minor_version = version_split[1]
# We maintain per-package versions to not have to break API for one if only the
# other has breaking changes
apm_major_version = major_version
apm_minor_version = minor_version
apm_project_name = 'webrtc-audio-processing-' + apm_major_version
include_subdir = apm_project_name
cc = meson.get_compiler('c')
cpp = meson.get_compiler('cpp')
host_system = host_machine.system()
# Don't rely on the cross file setting the system properly when targeting ios
if host_system == 'darwin' and meson.is_cross_build()
ios_test_code = '''#include <TargetConditionals.h>
#if ! TARGET_OS_IPHONE
#error "Not iOS/tvOS/watchOS/iPhoneSimulator"
#endif'''
if cc.compiles(ios_test_code, name : 'building for iOS')
host_system = 'ios'
endif
endif
platform_cflags = []
os_cflags = []
os_deps = []
have_posix = false
have_win = false
# Let's use pkg-config if available. This will also fallback to the subproject
# if pkg-config is not found, which is really the most reliable way of building
# abseil due to strict C++ standard match requirements.
absl_dep = [
dependency('absl_base', default_options: ['cpp_std=c++17'], version: '>=20240722'),
dependency('absl_flags'),
dependency('absl_strings'),
dependency('absl_numeric'),
dependency('absl_synchronization'),
dependency('absl_bad_optional_access'),
]
if absl_dep[0].type_name() == 'internal'
absl_subproj = subproject('abseil-cpp')
headers = [
absl_subproj.get_variable('absl_base_headers'),
absl_subproj.get_variable('absl_flags_headers'),
absl_subproj.get_variable('absl_strings_headers'),
absl_subproj.get_variable('absl_numeric_headers'),
absl_subproj.get_variable('absl_synchronization_headers'),
absl_subproj.get_variable('absl_types_headers'),
]
install_headers(headers, preserve_path: true)
pc_requires = []
else
pc_requires = [absl_dep[0]]
endif
if ['darwin', 'ios'].contains(host_system)
os_cflags = ['-DWEBRTC_MAC']
if host_system == 'ios'
os_cflags += ['-DWEBRTC_IOS']
endif
have_posix = true
elif host_system == 'android'
os_cflags += ['-DWEBRTC_ANDROID', '-DWEBRTC_LINUX']
os_deps += [cc.find_library('log')]
os_deps += [dependency('gnustl', required : get_option('gnustl'))]
have_posix = true
elif host_system == 'linux'
os_cflags += ['-DWEBRTC_LINUX']
os_deps += [cc.find_library('rt', required : false)]
os_deps += [dependency('threads')]
have_posix = true
elif (host_system == 'dragonfly' or host_system == 'freebsd' or
host_system == 'netbsd' or host_system == 'openbsd')
os_cflags += ['-DWEBRTC_BSD']
os_deps += [dependency('threads')]
have_posix = true
elif host_system == 'windows'
platform_cflags += ['-DWEBRTC_WIN', '-D_WIN32']
# this one is for MinGW to get format specifiers from inttypes.h in C++
platform_cflags += ['-D__STDC_FORMAT_MACROS=1']
# Avoid min/max from windows.h which breaks std::min/max
platform_cflags += ['-DNOMINMAX']
# Ensure M_PI etc are defined
platform_cflags += ['-D_USE_MATH_DEFINES']
os_deps += [cc.find_library('winmm')]
have_win = true
endif
if have_posix
platform_cflags += ['-DWEBRTC_POSIX']
endif
arch_cflags = []
have_arm = false
have_armv7 = false
have_arm64 = false
have_neon = false
have_mips = false
have_mips64 = false
have_x86 = false
have_inline_sse = false
have_avx2 = false
if host_machine.cpu_family() == 'arm'
if cc.compiles('''#ifndef __ARM_ARCH_ISA_ARM
#error no arm arch
#endif''')
have_arm = true
arch_cflags += ['-DWEBRTC_ARCH_ARM']
endif
if cc.compiles('''#ifndef __ARM_ARCH_7A__
#error no armv7 arch
#endif''')
have_armv7 = true
arch_cflags += ['-DWEBRTC_ARCH_ARM_V7']
endif
if cc.compiles('#include <arm_neon.h>', args : '-mfpu=neon')
have_neon = true
endif
endif
if host_machine.cpu_family() == 'aarch64'
have_arm64 = true
have_neon = true
arch_cflags += ['-DWEBRTC_ARCH_ARM64']
endif
if ['mips', 'mips64'].contains(host_machine.cpu_family())
have_mips = true
endif
if host_machine.cpu_family() == 'mips64'
have_mips64 = true
endif
if ['x86', 'x86_64'].contains(host_machine.cpu_family())
have_x86 = true
# AVX2 support is unconditionally available, since all the code (compiled
# with -mavx2) is in separate files from runtime detection (which should not
# be compiled with SIMD flags for cases where the CPU does not support it).
# Unfortunately, a bunch of SSE code is inline with the runtime detection,
# and we can't support that on systems that don't support SSE.
have_avx2 = true
arch_cflags += ['-DWEBRTC_ENABLE_AVX2']
if get_option('inline-sse')
have_inline_sse = true
else
have_inline_sse = false
arch_cflags += ['-DWAP_DISABLE_INLINE_SSE']
endif
endif
neon_opt = get_option('neon').require(have_neon)
if neon_opt.enabled()
arch_cflags += ['-DWEBRTC_HAS_NEON']
if not have_arm64
arch_cflags += ['-mfpu=neon']
endif
endif
common_cflags = [
'-DWEBRTC_LIBRARY_IMPL',
'-DWEBRTC_ENABLE_SYMBOL_EXPORT',
# avoid windows.h/winsock2.h conflicts
'-D_WINSOCKAPI_',
'-DNDEBUG'
] + platform_cflags + os_cflags + arch_cflags
common_cxxflags = common_cflags
common_deps = os_deps + [absl_dep]
webrtc_inc = include_directories('.')
# FIXME: use the unstable-simd module instead
if cc.get_define('_MSC_VER') != ''
avx_flags = ['/arch:AVX2']
else
avx_flags = ['-mavx2', '-mfma']
endif
subdir('webrtc')
pkgconfig = import('pkgconfig')
pkgconfig.generate(
libwebrtc_audio_processing,
description: 'WebRTC Audio Processing library',
subdirs: include_subdir,
requires: pc_requires,
extra_cflags: [
'-DWEBRTC_LIBRARY_IMPL',
] + platform_cflags,
)
audio_processing_dep = declare_dependency(
link_with: libwebrtc_audio_processing,
dependencies: [absl_dep],
include_directories: [webrtc_inc]
)
meson.override_dependency(apm_project_name, audio_processing_dep)
subdir('examples')

9
meson_options.txt Normal file
View File

@ -0,0 +1,9 @@
option('gnustl', type: 'feature',
value: 'auto',
description: 'Use gnustl for a c++ library implementation (only used on Android)')
option('neon', type: 'feature',
value: 'auto',
description: 'Enable NEON optimisations')
option('inline-sse', type: 'boolean',
value: true,
description: 'Enable inline SSE/SSE2 optimisations (i.e. assume CPU supports SSE/SSE2)')

View File

@ -0,0 +1,68 @@
From 297fd4f2efc53b6d49433eaad91a8e09a0f9cbec Mon Sep 17 00:00:00 2001
From: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Date: Fri, 25 Oct 2024 00:40:59 +0300
Subject: [PATCH] AECM: MIPS: Use uintptr_t for pointer arithmetic
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Trying to compile the MIPS-specific AECM audio processing file for
mips64el on Debian results in the following errors:
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc: In function int webrtc::WebRtcAecm_ProcessBlock(AecmCore*, const int16_t*, const int16_t*, const int16_t*, int16_t*):
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:955:30: error: cast from int16_t* {aka short int*} to uint32_t {aka unsigned int} loses precision [-fpermissive]
955 | int16_t* fft = (int16_t*)(((uint32_t)fft_buf + 31) & ~31);
| ^~~~~~~~~~~~~~~~~
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:955:18: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
955 | int16_t* fft = (int16_t*)(((uint32_t)fft_buf + 31) & ~31);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:956:36: error: cast from int32_t* {aka int*} to uint32_t {aka unsigned int} loses precision [-fpermissive]
956 | int32_t* echoEst32 = (int32_t*)(((uint32_t)echoEst32_buf + 31) & ~31);
| ^~~~~~~~~~~~~~~~~~~~~~~
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:956:24: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
956 | int32_t* echoEst32 = (int32_t*)(((uint32_t)echoEst32_buf + 31) & ~31);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:957:40: error: cast from int32_t* {aka int*} to uint32_t {aka unsigned int} loses precision [-fpermissive]
957 | ComplexInt16* dfw = (ComplexInt16*)(((uint32_t)dfw_buf + 31) & ~31);
| ^~~~~~~~~~~~~~~~~
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:957:23: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
957 | ComplexInt16* dfw = (ComplexInt16*)(((uint32_t)dfw_buf + 31) & ~31);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:958:40: error: cast from int32_t* {aka int*} to uint32_t {aka unsigned int} loses precision [-fpermissive]
958 | ComplexInt16* efw = (ComplexInt16*)(((uint32_t)efw_buf + 31) & ~31);
| ^~~~~~~~~~~~~~~~~
../webrtc/modules/audio_processing/aecm/aecm_core_mips.cc:958:23: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
958 | ComplexInt16* efw = (ComplexInt16*)(((uint32_t)efw_buf + 31) & ~31);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Presumably, this file was written for 32-bit MIPS so the author used
uint32_t to do pointer arithmetic over these arrays. Fix the errors by
using uintptr_t to work with pointers.
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
---
webrtc/modules/audio_processing/aecm/aecm_core_mips.cc | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/webrtc/modules/audio_processing/aecm/aecm_core_mips.cc b/webrtc/modules/audio_processing/aecm/aecm_core_mips.cc
index 16b03cf..07c785e 100644
--- a/webrtc/modules/audio_processing/aecm/aecm_core_mips.cc
+++ b/webrtc/modules/audio_processing/aecm/aecm_core_mips.cc
@@ -952,10 +952,10 @@ int WebRtcAecm_ProcessBlock(AecmCore* aecm,
int32_t dfw_buf[PART_LEN2 + 8];
int32_t efw_buf[PART_LEN2 + 8];
- int16_t* fft = (int16_t*)(((uint32_t)fft_buf + 31) & ~31);
- int32_t* echoEst32 = (int32_t*)(((uint32_t)echoEst32_buf + 31) & ~31);
- ComplexInt16* dfw = (ComplexInt16*)(((uint32_t)dfw_buf + 31) & ~31);
- ComplexInt16* efw = (ComplexInt16*)(((uint32_t)efw_buf + 31) & ~31);
+ int16_t* fft = (int16_t*)(((uintptr_t)fft_buf + 31) & ~31);
+ int32_t* echoEst32 = (int32_t*)(((uintptr_t)echoEst32_buf + 31) & ~31);
+ ComplexInt16* dfw = (ComplexInt16*)(((uintptr_t)dfw_buf + 31) & ~31);
+ ComplexInt16* efw = (ComplexInt16*)(((uintptr_t)efw_buf + 31) & ~31);
int16_t hnl[PART_LEN1];
int16_t numPosCoef = 0;
--
2.47.1

View File

@ -0,0 +1,110 @@
From 2a318149f8d5094c82306b8091a7a8b5194bf9c1 Mon Sep 17 00:00:00 2001
From: Jan Beich <jbeich@FreeBSD.org>
Date: Tue, 7 Jan 2020 18:08:24 +0000
Subject: [PATCH] Add support for BSD systems
webrtc/rtc_base/checks.cc:158:28: error: use of undeclared identifier 'LAST_SYSTEM_ERROR'
158 | file, line, LAST_SYSTEM_ERROR, message);
| ^
webrtc/rtc_base/checks.cc:220:16: error: use of undeclared identifier 'LAST_SYSTEM_ERROR'
220 | LAST_SYSTEM_ERROR);
| ^
In file included from webrtc/rtc_base/platform_thread_types.cc:11:
webrtc/rtc_base/platform_thread_types.h:47:1: error: unknown type name 'PlatformThreadId'
47 | PlatformThreadId CurrentThreadId();
| ^
webrtc/rtc_base/platform_thread_types.h:52:1: error: unknown type name 'PlatformThreadRef'
52 | PlatformThreadRef CurrentThreadRef();
| ^
webrtc/rtc_base/platform_thread_types.h:55:29: error: unknown type name 'PlatformThreadRef'
55 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b);
| ^
webrtc/rtc_base/platform_thread_types.h:55:57: error: unknown type name 'PlatformThreadRef'
55 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b);
| ^
webrtc/rtc_base/platform_thread_types.cc:37:1: error: unknown type name 'PlatformThreadId'
37 | PlatformThreadId CurrentThreadId() {
| ^
webrtc/rtc_base/platform_thread_types.cc:58:1: error: unknown type name 'PlatformThreadRef'
58 | PlatformThreadRef CurrentThreadRef() {
| ^
webrtc/rtc_base/platform_thread_types.cc:68:29: error: unknown type name 'PlatformThreadRef'
68 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) {
| ^
webrtc/rtc_base/platform_thread_types.cc:68:57: error: unknown type name 'PlatformThreadRef'
68 | bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) {
| ^
In file included from webrtc/rtc_base/event_tracer.cc:30:
In file included from webrtc/api/sequence_checker.h:15:
In file included from webrtc/rtc_base/synchronization/sequence_checker_internal.h:18:
webrtc/rtc_base/synchronization/mutex.h:28:2: error: Unsupported platform.
28 | #error Unsupported platform.
| ^
webrtc/rtc_base/synchronization/mutex.h:52:3: error: unknown type name 'MutexImpl'
52 | MutexImpl impl_;
| ^
---
meson.build | 5 +++++
webrtc/rtc_base/platform_thread_types.cc | 16 ++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/meson.build b/meson.build
index 8d85d56..05a434a 100644
--- a/meson.build
+++ b/meson.build
@@ -87,6 +87,11 @@ elif host_system == 'linux'
os_deps += [cc.find_library('rt', required : false)]
os_deps += [dependency('threads')]
have_posix = true
+elif (host_system == 'dragonfly' or host_system == 'freebsd' or
+ host_system == 'netbsd' or host_system == 'openbsd')
+ os_cflags += ['-DWEBRTC_BSD', '-DWEBRTC_THREAD_RR']
+ os_deps += [dependency('threads')]
+ have_posix = true
elif host_system == 'windows'
platform_cflags += ['-DWEBRTC_WIN', '-D_WIN32']
# this one is for MinGW to get format specifiers from inttypes.h in C++
diff --git a/webrtc/rtc_base/platform_thread_types.cc b/webrtc/rtc_base/platform_thread_types.cc
index d64ea68..e98e8ec 100644
--- a/webrtc/rtc_base/platform_thread_types.cc
+++ b/webrtc/rtc_base/platform_thread_types.cc
@@ -15,6 +15,12 @@
#include <sys/syscall.h>
#endif
+#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) // WEBRTC_BSD
+#include <pthread_np.h>
+#elif defined(__NetBSD__) // WEBRTC_BSD
+#include <lwp.h>
+#endif
+
#if defined(WEBRTC_WIN)
#include "rtc_base/arraysize.h"
@@ -46,6 +52,12 @@ PlatformThreadId CurrentThreadId() {
return zx_thread_self();
#elif defined(WEBRTC_LINUX)
return syscall(__NR_gettid);
+#elif defined(__DragonFly__) || defined(__FreeBSD__) // WEBRTC_BSD
+ return pthread_getthreadid_np();
+#elif defined(__NetBSD__) // WEBRTC_BSD
+ return _lwp_self();
+#elif defined(__OpenBSD__) // WEBRTC_BSD
+ return getthrid();
#elif defined(__EMSCRIPTEN__)
return static_cast<PlatformThreadId>(pthread_self());
#else
@@ -116,6 +128,10 @@ void SetCurrentThreadName(const char* name) {
prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name)); // NOLINT
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
pthread_setname_np(name);
+#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) // WEBRTC_BSD
+ pthread_set_name_np(pthread_self(), name);
+#elif defined(__NetBSD__) // WEBRTC_BSD
+ pthread_setname_np(pthread_self(), "%s", (void*)name);
#elif defined(WEBRTC_FUCHSIA)
zx_status_t status = zx_object_set_property(zx_thread_self(), ZX_PROP_NAME,
name, strlen(name));
--
2.47.1

View File

@ -0,0 +1,336 @@
From fed81a77c9a9bc366556f732324cdc5f9e7b09e9 Mon Sep 17 00:00:00 2001
From: Arun Raghavan <arun@asymptotic.io>
Date: Thu, 26 Dec 2024 14:24:40 -0500
Subject: [PATCH] Allow disabling inline SSE
Should make building on i686 without SSE feasible.
Fixes: https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing/-/issues/5
---
meson.build | 14 ++++++++++++--
meson_options.txt | 5 ++++-
.../audio_processing/aec3/adaptive_fir_filter.cc | 14 ++++++++++----
.../aec3/adaptive_fir_filter_erl.cc | 6 ++++--
webrtc/modules/audio_processing/aec3/fft_data.h | 4 +++-
.../audio_processing/aec3/matched_filter.cc | 6 ++++--
webrtc/modules/audio_processing/aec3/vector_math.h | 8 +++++---
.../audio_processing/agc2/rnn_vad/vector_math.h | 4 +++-
webrtc/third_party/pffft/meson.build | 2 +-
9 files changed, 46 insertions(+), 17 deletions(-)
diff --git a/meson.build b/meson.build
index 811d795..ebf053a 100644
--- a/meson.build
+++ b/meson.build
@@ -110,6 +110,7 @@ have_neon = false
have_mips = false
have_mips64 = false
have_x86 = false
+have_inline_sse = false
have_avx2 = false
if host_machine.cpu_family() == 'arm'
if cc.compiles('''#ifndef __ARM_ARCH_ISA_ARM
@@ -140,10 +141,19 @@ if host_machine.cpu_family() == 'mips64'
endif
if ['x86', 'x86_64'].contains(host_machine.cpu_family())
have_x86 = true
- # This is unconditionally enabled for now, actual usage is determined by
- # runtime CPU detection, so we're just assuming the compiler supports avx2
+ # AVX2 support is unconditionally available, since all the code (compiled
+ # with -mavx2) is in separate files from runtime detection (which should not
+ # be compiled with SIMD flags for cases where the CPU does not support it).
+ # Unfortunately, a bunch of SSE code is inline with the runtime detection,
+ # and we can't support that on systems that don't support SSE.
have_avx2 = true
arch_cflags += ['-DWEBRTC_ENABLE_AVX2']
+ if get_option('inline-sse')
+ have_inline_sse = true
+ else
+ have_inline_sse = false
+ arch_cflags += ['-DWAP_DISABLE_INLINE_SSE']
+ endif
endif
neon_opt = get_option('neon')
diff --git a/meson_options.txt b/meson_options.txt
index c939fb9..d08f356 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -3,4 +3,7 @@ option('gnustl', type: 'feature',
description: 'Use gnustl for a c++ library implementation (only used on Android)')
option('neon', type: 'combo',
choices: ['no', 'yes', 'auto', 'runtime'],
- description: '')
+ description: 'Enable NEON optimisations')
+option('inline-sse', type: 'boolean',
+ value: true,
+ description: 'Enable inline SSE/SSE2 optimisations (i.e. assume CPU supports SSE/SSE2)')
diff --git a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc
index 917aa95..ded0511 100644
--- a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc
+++ b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.cc
@@ -16,7 +16,7 @@
#if defined(WEBRTC_HAS_NEON)
#include <arm_neon.h>
#endif
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
#include <emmintrin.h>
#endif
#include <math.h>
@@ -88,7 +88,7 @@ void ComputeFrequencyResponse_Neon(
}
#endif
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
// Computes and stores the frequency response of the filter.
void ComputeFrequencyResponse_Sse2(
size_t num_partitions,
@@ -212,7 +212,7 @@ void AdaptPartitions_Neon(const RenderBuffer& render_buffer,
}
#endif
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
// Adapts the filter partitions. (SSE2 variant)
void AdaptPartitions_Sse2(const RenderBuffer& render_buffer,
const FftData& G,
@@ -377,7 +377,7 @@ void ApplyFilter_Neon(const RenderBuffer& render_buffer,
}
#endif
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
// Produces the filter output (SSE2 variant).
void ApplyFilter_Sse2(const RenderBuffer& render_buffer,
size_t num_partitions,
@@ -557,9 +557,11 @@ void AdaptiveFirFilter::Filter(const RenderBuffer& render_buffer,
RTC_DCHECK(S);
switch (optimization_) {
#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if !defined(WAP_DISABLE_INLINE_SSE)
case Aec3Optimization::kSse2:
aec3::ApplyFilter_Sse2(render_buffer, current_size_partitions_, H_, S);
break;
+#endif
case Aec3Optimization::kAvx2:
aec3::ApplyFilter_Avx2(render_buffer, current_size_partitions_, H_, S);
break;
@@ -601,9 +603,11 @@ void AdaptiveFirFilter::ComputeFrequencyResponse(
switch (optimization_) {
#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if !defined(WAP_DISABLE_INLINE_SSE)
case Aec3Optimization::kSse2:
aec3::ComputeFrequencyResponse_Sse2(current_size_partitions_, H_, H2);
break;
+#endif
case Aec3Optimization::kAvx2:
aec3::ComputeFrequencyResponse_Avx2(current_size_partitions_, H_, H2);
break;
@@ -626,10 +630,12 @@ void AdaptiveFirFilter::AdaptAndUpdateSize(const RenderBuffer& render_buffer,
// Adapt the filter.
switch (optimization_) {
#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if !defined(WAP_DISABLE_INLINE_SSE)
case Aec3Optimization::kSse2:
aec3::AdaptPartitions_Sse2(render_buffer, G, current_size_partitions_,
&H_);
break;
+#endif
case Aec3Optimization::kAvx2:
aec3::AdaptPartitions_Avx2(render_buffer, G, current_size_partitions_,
&H_);
diff --git a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc
index 45b8813..920d51c 100644
--- a/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc
+++ b/webrtc/modules/audio_processing/aec3/adaptive_fir_filter_erl.cc
@@ -16,7 +16,7 @@
#if defined(WEBRTC_HAS_NEON)
#include <arm_neon.h>
#endif
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
#include <emmintrin.h>
#endif
@@ -54,7 +54,7 @@ void ErlComputer_NEON(
}
#endif
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
// Computes and stores the echo return loss estimate of the filter, which is the
// sum of the partition frequency responses.
void ErlComputer_SSE2(
@@ -82,9 +82,11 @@ void ComputeErl(const Aec3Optimization& optimization,
// Update the frequency response and echo return loss for the filter.
switch (optimization) {
#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if !defined(WAP_DISABLE_INLINE_SSE)
case Aec3Optimization::kSse2:
aec3::ErlComputer_SSE2(H2, erl);
break;
+#endif
case Aec3Optimization::kAvx2:
aec3::ErlComputer_AVX2(H2, erl);
break;
diff --git a/webrtc/modules/audio_processing/aec3/fft_data.h b/webrtc/modules/audio_processing/aec3/fft_data.h
index 9c25e78..892407d 100644
--- a/webrtc/modules/audio_processing/aec3/fft_data.h
+++ b/webrtc/modules/audio_processing/aec3/fft_data.h
@@ -14,7 +14,7 @@
// Defines WEBRTC_ARCH_X86_FAMILY, used below.
#include "rtc_base/system/arch.h"
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
#include <emmintrin.h>
#endif
#include <algorithm>
@@ -49,6 +49,7 @@ struct FftData {
RTC_DCHECK_EQ(kFftLengthBy2Plus1, power_spectrum.size());
switch (optimization) {
#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if !defined(WAP_DISABLE_INLINE_SSE)
case Aec3Optimization::kSse2: {
constexpr int kNumFourBinBands = kFftLengthBy2 / 4;
constexpr int kLimit = kNumFourBinBands * 4;
@@ -63,6 +64,7 @@ struct FftData {
power_spectrum[kFftLengthBy2] = re[kFftLengthBy2] * re[kFftLengthBy2] +
im[kFftLengthBy2] * im[kFftLengthBy2];
} break;
+#endif
case Aec3Optimization::kAvx2:
SpectrumAVX2(power_spectrum);
break;
diff --git a/webrtc/modules/audio_processing/aec3/matched_filter.cc b/webrtc/modules/audio_processing/aec3/matched_filter.cc
index 59a3b46..86f365a 100644
--- a/webrtc/modules/audio_processing/aec3/matched_filter.cc
+++ b/webrtc/modules/audio_processing/aec3/matched_filter.cc
@@ -15,7 +15,7 @@
#if defined(WEBRTC_HAS_NEON)
#include <arm_neon.h>
#endif
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
#include <emmintrin.h>
#endif
#include <algorithm>
@@ -286,7 +286,7 @@ void MatchedFilterCore_NEON(size_t x_start_index,
#endif
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
void MatchedFilterCore_AccumulatedError_SSE2(
size_t x_start_index,
@@ -695,12 +695,14 @@ void MatchedFilter::Update(const DownsampledRenderBuffer& render_buffer,
switch (optimization_) {
#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if !defined(WAP_DISABLE_INLINE_SSE)
case Aec3Optimization::kSse2:
aec3::MatchedFilterCore_SSE2(
x_start_index, x2_sum_threshold, smoothing, render_buffer.buffer, y,
filters_[n], &filters_updated, &error_sum, compute_pre_echo,
instantaneous_accumulated_error_, scratch_memory_);
break;
+#endif
case Aec3Optimization::kAvx2:
aec3::MatchedFilterCore_AVX2(
x_start_index, x2_sum_threshold, smoothing, render_buffer.buffer, y,
diff --git a/webrtc/modules/audio_processing/aec3/vector_math.h b/webrtc/modules/audio_processing/aec3/vector_math.h
index e4d1381..1506a44 100644
--- a/webrtc/modules/audio_processing/aec3/vector_math.h
+++ b/webrtc/modules/audio_processing/aec3/vector_math.h
@@ -17,7 +17,7 @@
#if defined(WEBRTC_HAS_NEON)
#include <arm_neon.h>
#endif
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
#include <emmintrin.h>
#endif
#include <math.h>
@@ -43,7 +43,7 @@ class VectorMath {
void SqrtAVX2(rtc::ArrayView<float> x);
void Sqrt(rtc::ArrayView<float> x) {
switch (optimization_) {
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
case Aec3Optimization::kSse2: {
const int x_size = static_cast<int>(x.size());
const int vector_limit = x_size >> 2;
@@ -123,7 +123,7 @@ class VectorMath {
RTC_DCHECK_EQ(z.size(), x.size());
RTC_DCHECK_EQ(z.size(), y.size());
switch (optimization_) {
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
case Aec3Optimization::kSse2: {
const int x_size = static_cast<int>(x.size());
const int vector_limit = x_size >> 2;
@@ -174,6 +174,7 @@ class VectorMath {
RTC_DCHECK_EQ(z.size(), x.size());
switch (optimization_) {
#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if !defined(WAP_DISABLE_INLINE_SSE)
case Aec3Optimization::kSse2: {
const int x_size = static_cast<int>(x.size());
const int vector_limit = x_size >> 2;
@@ -190,6 +191,7 @@ class VectorMath {
z[j] += x[j];
}
} break;
+#endif
case Aec3Optimization::kAvx2:
AccumulateAVX2(x, z);
break;
diff --git a/webrtc/modules/audio_processing/agc2/rnn_vad/vector_math.h b/webrtc/modules/audio_processing/agc2/rnn_vad/vector_math.h
index 47f6811..f965086 100644
--- a/webrtc/modules/audio_processing/agc2/rnn_vad/vector_math.h
+++ b/webrtc/modules/audio_processing/agc2/rnn_vad/vector_math.h
@@ -17,7 +17,7 @@
#if defined(WEBRTC_HAS_NEON)
#include <arm_neon.h>
#endif
-#if defined(WEBRTC_ARCH_X86_FAMILY)
+#if defined(WEBRTC_ARCH_X86_FAMILY) && !defined(WAP_DISABLE_INLINE_SSE)
#include <emmintrin.h>
#endif
@@ -47,6 +47,7 @@ class VectorMath {
if (cpu_features_.avx2) {
return DotProductAvx2(x, y);
} else if (cpu_features_.sse2) {
+#if !defined(WAP_DISABLE_INLINE_SSE)
__m128 accumulator = _mm_setzero_ps();
constexpr int kBlockSizeLog2 = 2;
constexpr int kBlockSize = 1 << kBlockSizeLog2;
@@ -72,6 +73,7 @@ class VectorMath {
dot_product += x[i] * y[i];
}
return dot_product;
+#endif
}
#elif defined(WEBRTC_HAS_NEON) && defined(WEBRTC_ARCH_ARM64)
if (cpu_features_.neon) {
diff --git a/webrtc/third_party/pffft/meson.build b/webrtc/third_party/pffft/meson.build
index c1eb5c6..cf4c9c7 100644
--- a/webrtc/third_party/pffft/meson.build
+++ b/webrtc/third_party/pffft/meson.build
@@ -4,7 +4,7 @@ pffft_sources = [
pffft_cflags = [ '-D_GNU_SOURCE' ]
-if (have_arm and not have_neon) or (have_mips and host_machine.endian() == 'little') or have_mips64
+if not have_inline_sse or (have_arm and not have_neon) or (have_mips and host_machine.endian() == 'little') or have_mips64
pffft_cflags += [ '-DPFFFT_SIMD_DISABLE' ]
endif
--
2.47.1

View File

@ -0,0 +1,68 @@
From ad563b095cea13730ca95e77d50e352ea9e344a9 Mon Sep 17 00:00:00 2001
From: Arun Raghavan <arun@asymptotic.io>
Date: Fri, 15 Dec 2023 16:06:05 -0500
Subject: [PATCH] Fix up XMM intrinsics usage on MSVC
Repplying 0a0050746bc20ef970b9f260d485e4367c7ba854 after M131 bump.
---
.../aec3/matched_filter_avx2.cc | 30 ++++++++++++-------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/webrtc/modules/audio_processing/aec3/matched_filter_avx2.cc b/webrtc/modules/audio_processing/aec3/matched_filter_avx2.cc
index 8c2ffcb..65a1b76 100644
--- a/webrtc/modules/audio_processing/aec3/matched_filter_avx2.cc
+++ b/webrtc/modules/audio_processing/aec3/matched_filter_avx2.cc
@@ -13,6 +13,16 @@
#include "modules/audio_processing/aec3/matched_filter.h"
#include "rtc_base/checks.h"
+#ifdef _MSC_VER
+// Visual Studio
+#define LOOKUP_M128(v, i) v.m128_f32[i]
+#define LOOKUP_M256(v, i) v.m256_f32[i]
+#else
+// GCC/Clang
+#define LOOKUP_M128(v, i) v[i]
+#define LOOKUP_M256(v, i) v[i]
+#endif
+
namespace webrtc {
namespace aec3 {
@@ -81,14 +91,14 @@ void MatchedFilterCore_AccumulatedError_AVX2(
s_inst_256_8 = _mm256_mul_ps(h_k_8, x_k_8);
s_inst_hadd_256 = _mm256_hadd_ps(s_inst_256, s_inst_256_8);
s_inst_hadd_256 = _mm256_hadd_ps(s_inst_hadd_256, s_inst_hadd_256);
- s_acum += s_inst_hadd_256[0];
- e_128[0] = s_acum - y[i];
- s_acum += s_inst_hadd_256[4];
- e_128[1] = s_acum - y[i];
- s_acum += s_inst_hadd_256[1];
- e_128[2] = s_acum - y[i];
- s_acum += s_inst_hadd_256[5];
- e_128[3] = s_acum - y[i];
+ s_acum += LOOKUP_M256(s_inst_hadd_256, 0);
+ LOOKUP_M128(e_128, 0) = s_acum - y[i];
+ s_acum += LOOKUP_M256(s_inst_hadd_256,4);
+ LOOKUP_M128(e_128, 1) = s_acum - y[i];
+ s_acum += LOOKUP_M256(s_inst_hadd_256,1);
+ LOOKUP_M128(e_128, 2) = s_acum - y[i];
+ s_acum += LOOKUP_M256(s_inst_hadd_256,5);
+ LOOKUP_M128(e_128, 3) = s_acum - y[i];
__m128 accumulated_error = _mm_load_ps(a_p);
accumulated_error = _mm_fmadd_ps(e_128, e_128, accumulated_error);
@@ -209,8 +219,8 @@ void MatchedFilterCore_AVX2(size_t x_start_index,
x2_sum_256 = _mm256_add_ps(x2_sum_256, x2_sum_256_8);
s_256 = _mm256_add_ps(s_256, s_256_8);
__m128 sum = hsum_ab(x2_sum_256, s_256);
- x2_sum += sum[0];
- s += sum[1];
+ x2_sum += LOOKUP_M128(sum, 0);
+ s += LOOKUP_M128(sum, 1);
// Compute the matched filter error.
float e = y[i] - s;
--
2.47.1

View File

@ -0,0 +1,51 @@
From a9f97c9fdd490e35bd43d6463424eee5b44c4a7d Mon Sep 17 00:00:00 2001
From: Arun Raghavan <arun@asymptotic.io>
Date: Fri, 18 Jun 2021 18:40:32 -0400
Subject: [PATCH] Some fixes for MinGW
* Rename Windows.h uses to windows.h
* Comment out structured exception handling usage
Makes MinGW happier. Mostly the same as previous work by
Nicolas Dufresne <nicolas.dufresne@collabora.com>, with the exception
that we now don't try to invoke RaiseException which would fail in MinGW
as it raises a Windows structured exception.
---
webrtc/rtc_base/platform_thread_types.cc | 2 ++
webrtc/rtc_base/system/file_wrapper.cc | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/webrtc/rtc_base/platform_thread_types.cc b/webrtc/rtc_base/platform_thread_types.cc
index e98e8ec..1a24881 100644
--- a/webrtc/rtc_base/platform_thread_types.cc
+++ b/webrtc/rtc_base/platform_thread_types.cc
@@ -118,11 +118,13 @@ void SetCurrentThreadName(const char* name) {
#pragma warning(push)
#pragma warning(disable : 6320 6322)
+#ifndef __MINGW32__
__try {
::RaiseException(0x406D1388, 0, sizeof(threadname_info) / sizeof(ULONG_PTR),
reinterpret_cast<ULONG_PTR*>(&threadname_info));
} __except (EXCEPTION_EXECUTE_HANDLER) { // NOLINT
}
+#endif
#pragma warning(pop)
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name)); // NOLINT
diff --git a/webrtc/rtc_base/system/file_wrapper.cc b/webrtc/rtc_base/system/file_wrapper.cc
index 12c27a5..3203bc6 100644
--- a/webrtc/rtc_base/system/file_wrapper.cc
+++ b/webrtc/rtc_base/system/file_wrapper.cc
@@ -22,7 +22,7 @@
#include "rtc_base/numerics/safe_conversions.h"
#ifdef _WIN32
-#include <Windows.h>
+#include <windows.h>
#else
#endif
--
2.47.1

View File

@ -0,0 +1,45 @@
From 4a17c682e9a173c27feec9e67fb8c4c36090b1a6 Mon Sep 17 00:00:00 2001
From: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Date: Fri, 25 Oct 2024 01:53:16 +0300
Subject: [PATCH] common_audio: Add MIPS_DSP_R1_LE guard for vector scaling ops
The MIPS-specific source for vector scaling operations fails to build on
Debian's mips64el:
[97/303] Compiling C object webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o
FAILED: webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o
cc [...] webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o.d -o webrtc/common_audio/libcommon_audio.a.p/signal_processing_vector_scaling_operations_mips.c.o -c ../webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c
/tmp/cc7UGPkY.s: Assembler messages:
/tmp/cc7UGPkY.s:57: Error: opcode not supported on this processor: mips64r2 (mips64r2) `extrv_r.w $3,$ac0,$8'
ninja: build stopped: subcommand failed.
The EXTRV_R.W instruction it uses is part of DSP extensions for this
architecture. In signal_processing_library.h, this function's prototype
is guarded with #if defined(MIPS_DSP_R1_LE). Guard the implementation
like that as well to fix the error.
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
---
.../signal_processing/vector_scaling_operations_mips.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c b/webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c
index ba2d26d..08ca293 100644
--- a/webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c
+++ b/webrtc/common_audio/signal_processing/vector_scaling_operations_mips.c
@@ -16,6 +16,7 @@
#include "common_audio/signal_processing/include/signal_processing_library.h"
+#if defined(MIPS_DSP_R1_LE)
int WebRtcSpl_ScaleAndAddVectorsWithRound_mips(const int16_t* in_vector1,
int16_t in_vector1_scale,
const int16_t* in_vector2,
@@ -55,3 +56,4 @@ int WebRtcSpl_ScaleAndAddVectorsWithRound_mips(const int16_t* in_vector1,
}
return 0;
}
+#endif
--
2.47.1

View File

@ -0,0 +1,46 @@
From c555fb6eaf0568c2205bbd197ebbcc0e85714c77 Mon Sep 17 00:00:00 2001
From: Nirbheek Chauhan <nirbheek@centricular.com>
Date: Fri, 26 May 2023 02:20:56 +0530
Subject: [PATCH] meson: Fixes for MSVC build
winsock2.h must be included before windows.h or alternative
definitions of `struct sockaddr` are defined.
```
FAILED: webrtc/rtc_base/liblibbase.a.p/logging.cc.obj
"cl" "-Iwebrtc\rtc_base\liblibbase.a.p" "-Iwebrtc\rtc_base" "-I..\webrtc\rtc_base" "-Iwebrtc" "-I..\webrtc" "-Isubprojects\abseil-cpp-20230125.1" "-I..\subprojects\abseil-cpp-20230125.1" "/MD" "/nologo" "/showIncludes" "/utf-8" "/Zc:__cplusplus" "/W2" "/EHsc" "/std:c++17" "/permissive-" "/O2" "/Zi" "-DWEBRTC_LIBRARY_
IMPL" "-DWEBRTC_ENABLE_SYMBOL_EXPORT" "-DNDEBUG" "-DWEBRTC_WIN" "-D_WIN32" "-U__STRICT_ANSI__" "-D__STDC_FORMAT_MACROS=1" "-DNOMINMAX" "-DWEBRTC_ENABLE_AVX2" "/Fdwebrtc\rtc_base\liblibbase.a.p\logging.cc.pdb" /Fowebrtc/rtc_base/liblibbase.a.p/logging.cc.obj "/c" ../webrtc/rtc_base/logging.cc
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(103): warning C4005: 'AF_IPX': macro redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(457): note: see previous definition of 'AF_IPX'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(147): warning C4005: 'AF_MAX': macro redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(476): note: see previous definition of 'AF_MAX'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(187): warning C4005: 'SO_DONTLINGER': macro redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(399): note: see previous definition of 'SO_DONTLINGER'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(240): error C2011: 'sockaddr': 'struct' type redefinition
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um\winsock.h(482): note: see declaration of 'sockaddr'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(442): error C2143: syntax error: missing '}' before 'constant'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(442): error C2059: syntax error: 'constant'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C2143: syntax error: missing ';' before '}'
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared\ws2def.h(496): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
...
```
---
webrtc/rtc_base/logging.cc | 1 +
1 file changed, 1 insertion(+)
diff --git a/webrtc/rtc_base/logging.cc b/webrtc/rtc_base/logging.cc
index 61a3c66..825c686 100644
--- a/webrtc/rtc_base/logging.cc
+++ b/webrtc/rtc_base/logging.cc
@@ -15,6 +15,7 @@
#if RTC_LOG_ENABLED()
#if defined(WEBRTC_WIN)
+#include <winsock2.h>
#include <windows.h>
#if _MSC_VER < 1900
#define snprintf _snprintf
--
2.47.1

108
subprojects/abseil-cpp.wrap Normal file
View File

@ -0,0 +1,108 @@
[wrap-file]
directory = abseil-cpp-20240722.0
source_url = https://github.com/abseil/abseil-cpp/releases/download/20240722.0/abseil-cpp-20240722.0.tar.gz
source_filename = abseil-cpp-20240722.0.tar.gz
source_hash = f50e5ac311a81382da7fa75b97310e4b9006474f9560ac46f54a9967f07d4ae3
patch_filename = abseil-cpp_20240722.0-3_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20240722.0-3/get_patch
patch_hash = 12dd8df1488a314c53e3751abd2750cf233b830651d168b6a9f15e7d0cf71f7b
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/abseil-cpp_20240722.0-3/abseil-cpp-20240722.0.tar.gz
wrapdb_version = 20240722.0-3
[provide]
absl_base = absl_base_dep
absl_container = absl_container_dep
absl_debugging = absl_debugging_dep
absl_log = absl_log_dep
absl_flags = absl_flags_dep
absl_hash = absl_hash_dep
absl_crc = absl_crc_dep
absl_numeric = absl_numeric_dep
absl_profiling = absl_profiling_dep
absl_random = absl_random_dep
absl_status = absl_status_dep
absl_strings = absl_strings_dep
absl_synchronization = absl_synchronization_dep
absl_time = absl_time_dep
absl_types = absl_types_dep
absl_algorithm_container = absl_base_dep
absl_any_invocable = absl_base_dep
absl_bad_any_cast_impl = absl_types_dep
absl_bad_optional_access = absl_types_dep
absl_bad_variant_access = absl_types_dep
absl_bind_front = absl_base_dep
absl_city = absl_hash_dep
absl_civil_time = absl_time_dep
absl_cleanup = absl_base_dep
absl_cord = absl_strings_dep
absl_cord_internal = absl_strings_dep
absl_cordz_functions = absl_strings_dep
absl_cordz_handle = absl_strings_dep
absl_cordz_info = absl_strings_dep
absl_cordz_sample_token = absl_strings_dep
absl_core_headers = absl_base_dep
absl_crc32c = absl_crc_dep
absl_debugging_internal = absl_debugging_dep
absl_demangle_internal = absl_debugging_dep
absl_die_if_null = absl_log_dep
absl_examine_stack = absl_debugging_dep
absl_exponential_biased = absl_profiling_dep
absl_failure_signal_handler = absl_debugging_dep
absl_flags_commandlineflag = absl_flags_dep
absl_flags_commandlineflag_internal = absl_flags_dep
absl_flags_config = absl_flags_dep
absl_flags_internal = absl_flags_dep
absl_flags_marshalling = absl_flags_dep
absl_flags_parse = absl_flags_dep
absl_flags_private_handle_accessor = absl_flags_dep
absl_flags_program_name = absl_flags_dep
absl_flags_reflection = absl_flags_dep
absl_flags_usage = absl_flags_dep
absl_flags_usage_internal = absl_flags_dep
absl_flat_hash_map = absl_container_dep
absl_flat_hash_set = absl_container_dep
absl_function_ref = absl_base_dep
absl_graphcycles_internal = absl_synchronization_dep
absl_hashtablez_sampler = absl_container_dep
absl_inlined_vector = absl_container_dep
absl_int128 = absl_numeric_dep
absl_leak_check = absl_debugging_dep
absl_log_initialize = absl_log_dep
absl_log_internal_check_op = absl_log_dep
absl_log_internal_message = absl_log_dep
absl_log_severity = absl_base_dep
absl_low_level_hash = absl_hash_dep
absl_memory = absl_base_dep
absl_optional = absl_types_dep
absl_periodic_sampler = absl_profiling_dep
absl_random_bit_gen_ref = absl_random_dep
absl_random_distributions = absl_random_dep
absl_random_internal_distribution_test_util = absl_random_dep
absl_random_internal_platform = absl_random_dep
absl_random_internal_pool_urbg = absl_random_dep
absl_random_internal_randen = absl_random_dep
absl_random_internal_randen_hwaes = absl_random_dep
absl_random_internal_randen_hwaes_impl = absl_random_dep
absl_random_internal_randen_slow = absl_random_dep
absl_random_internal_seed_material = absl_random_dep
absl_random_random = absl_random_dep
absl_random_seed_gen_exception = absl_random_dep
absl_random_seed_sequences = absl_random_dep
absl_raw_hash_set = absl_container_dep
absl_raw_logging_internal = absl_base_dep
absl_scoped_set_env = absl_base_dep
absl_span = absl_types_dep
absl_spinlock_wait = absl_base_dep
absl_stacktrace = absl_debugging_dep
absl_statusor = absl_status_dep
absl_str_format = absl_strings_dep
absl_str_format_internal = absl_strings_dep
absl_strerror = absl_base_dep
absl_string_view = absl_strings_dep
absl_strings_internal = absl_strings_dep
absl_symbolize = absl_debugging_dep
absl_throw_delegate = absl_base_dep
absl_time_zone = absl_time_dep
absl_type_traits = absl_base_dep
absl_utility = absl_base_dep
absl_variant = absl_types_dep

View File

@ -1,10 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: webrtc-audio-processing
Description: WebRTC Audio Processing library
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lwebrtc_audio_processing
Cflags: -DWEBRTC_AUDIO_PROCESSING_ONLY_BUILD -I${includedir}/webrtc_audio_processing @PLATFORM_CFLAGS@

View File

@ -6,22 +6,188 @@
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
# TODO(kjellander): Rebase this to webrtc/build/common.gypi changes after r6330.
# This is the root build file for GN. GN will start processing by loading this
# file, and recursively load all dependencies until all dependencies are either
# resolved or known not to exist (which will cause the build to fail). So if
# you add a new build file, there must be some path of dependencies from this
# file to your new one or GN won't know about it.
# Use of visibility = clauses:
# The default visibility for all rtc_ targets is equivalent to "//*", or
# "all targets in webrtc can depend on this, nothing outside can".
#
# When overriding, the choices are:
# - visibility = [ "*" ] - public. Stuff outside webrtc can use this.
# - visibility = [ ":*" ] - directory private.
# As a general guideline, only targets in api/ should have public visibility.
import("//build/config/crypto.gni")
import("//build/config/linux/pkg_config.gni")
import("build/webrtc.gni")
import("//third_party/protobuf/proto_library.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("webrtc.gni")
if (rtc_enable_protobuf) {
import("//third_party/protobuf/proto_library.gni")
}
if (is_android) {
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
import("//third_party/jni_zero/jni_zero.gni")
}
if (!build_with_chromium) {
# This target should (transitively) cause everything to be built; if you run
# 'ninja default' and then 'ninja all', the second build should do no work.
group("default") {
testonly = true
deps = [ ":webrtc" ]
if (rtc_build_examples) {
deps += [ "examples" ]
}
if (rtc_build_tools) {
deps += [ "rtc_tools" ]
}
if (rtc_include_tests) {
deps += [
":rtc_unittests",
":video_engine_tests",
":voip_unittests",
":webrtc_nonparallel_tests",
":webrtc_perf_tests",
"common_audio:common_audio_unittests",
"common_video:common_video_unittests",
"examples:examples_unittests",
"media:rtc_media_unittests",
"modules:modules_tests",
"modules:modules_unittests",
"modules/audio_coding:audio_coding_tests",
"modules/audio_processing:audio_processing_tests",
"modules/remote_bitrate_estimator:rtp_to_text",
"modules/rtp_rtcp:test_packet_masks_metrics",
"modules/video_capture:video_capture_internal_impl",
"modules/video_coding:video_codec_perf_tests",
"net/dcsctp:dcsctp_unittests",
"pc:peerconnection_unittests",
"pc:rtc_pc_unittests",
"pc:slow_peer_connection_unittests",
"pc:svc_tests",
"rtc_tools:rtp_generator",
"rtc_tools:video_encoder",
"rtc_tools:video_replay",
"stats:rtc_stats_unittests",
"system_wrappers:system_wrappers_unittests",
"test",
"video:screenshare_loopback",
"video:sv_loopback",
"video:video_loopback",
]
if (use_libfuzzer) {
deps += [ "test/fuzzers" ]
}
if (!is_asan) {
# Do not build :webrtc_lib_link_test because lld complains on some OS
# (e.g. when target_os = "mac") when is_asan=true. For more details,
# see bugs.webrtc.org/11027#c5.
deps += [ ":webrtc_lib_link_test" ]
}
if (is_ios) {
deps += [
"examples:apprtcmobile_tests",
"sdk:sdk_framework_unittests",
"sdk:sdk_unittests",
]
}
if (is_android) {
deps += [
"examples:android_examples_junit_tests",
"sdk/android:android_instrumentation_test_apk",
"sdk/android:android_sdk_junit_tests",
]
} else {
deps += [ "modules/video_capture:video_capture_tests" ]
}
if (rtc_enable_protobuf) {
deps += [
"logging:rtc_event_log_rtp_dump",
"tools_webrtc/perf:webrtc_dashboard_upload",
]
}
if ((is_linux || is_chromeos) && rtc_use_pipewire) {
deps += [ "modules/desktop_capture:shared_screencast_stream_test" ]
}
}
if (target_os == "android") {
deps += [ "tools_webrtc:binary_version_check" ]
}
}
}
# Abseil Flags by default doesn't register command line flags on mobile
# platforms, WebRTC tests requires them (e.g. on simualtors) so this
# config will be applied to testonly targets globally (see webrtc.gni).
config("absl_flags_configs") {
defines = [ "ABSL_FLAGS_STRIP_NAMES=0" ]
}
config("library_impl_config") {
# Build targets that contain WebRTC implementation need this macro to
# be defined in order to correctly export symbols when is_component_build
# is true.
# For more info see: rtc_base/build/rtc_export.h.
defines = [ "WEBRTC_LIBRARY_IMPL" ]
}
# Contains the defines and includes in common.gypi that are duplicated both as
# target_defaults and direct_dependent_settings.
config("common_inherited_config") {
defines = []
if (build_with_mozilla) {
defines += [ "WEBRTC_MOZILLA_BUILD" ]
cflags = []
ldflags = []
if (rtc_objc_prefix != "") {
defines += [ "RTC_OBJC_TYPE_PREFIX=${rtc_objc_prefix}" ]
}
if (rtc_dlog_always_on) {
defines += [ "DLOG_ALWAYS_ON" ]
}
if (rtc_enable_symbol_export || is_component_build) {
defines += [ "WEBRTC_ENABLE_SYMBOL_EXPORT" ]
}
if (rtc_enable_objc_symbol_export) {
defines += [ "WEBRTC_ENABLE_OBJC_SYMBOL_EXPORT" ]
}
if (!rtc_builtin_ssl_root_certificates) {
defines += [ "WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS" ]
}
if (rtc_disable_check_msg) {
defines += [ "RTC_DISABLE_CHECK_MSG" ]
}
if (rtc_enable_avx2) {
defines += [ "WEBRTC_ENABLE_AVX2" ]
}
if (rtc_enable_win_wgc) {
defines += [ "RTC_ENABLE_WIN_WGC" ]
}
if (!rtc_use_perfetto) {
# Some tests need to declare their own trace event handlers. If this define is
# not set, the first time TRACE_EVENT_* is called it will store the return
# value for the current handler in an static variable, so that subsequent
# changes to the handler for that TRACE_EVENT_* will be ignored.
# So when tests are included, we set this define, making it possible to use
# different event handlers in different tests.
if (rtc_include_tests) {
defines += [ "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=1" ]
} else {
defines += [ "WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0" ]
}
}
if (build_with_chromium) {
defines = [ "WEBRTC_CHROMIUM_BUILD" ]
defines += [ "WEBRTC_CHROMIUM_BUILD" ]
include_dirs = [
# The overrides must be included first as that is the mechanism for
# selecting the override headers in Chromium.
@ -29,10 +195,18 @@ config("common_inherited_config") {
# Allow includes to be prefixed with webrtc/ in case it is not an
# immediate subdirectory of the top-level.
"..",
".",
# Just like the root WebRTC directory is added to include path, the
# corresponding directory tree with generated files needs to be added too.
# Note: this path does not change depending on the current target, e.g.
# it is always "//gen/third_party/webrtc" when building with Chromium.
# See also: http://cs.chromium.org/?q=%5C"default_include_dirs
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_gen_dir
target_gen_dir,
]
}
if (is_posix) {
if (is_posix || is_fuchsia) {
defines += [ "WEBRTC_POSIX" ]
}
if (is_ios) {
@ -41,15 +215,15 @@ config("common_inherited_config") {
"WEBRTC_IOS",
]
}
if (is_ios && rtc_use_objc_h264) {
defines += [ "WEBRTC_OBJC_H264" ]
}
if (is_linux) {
if (is_linux || is_chromeos) {
defines += [ "WEBRTC_LINUX" ]
}
if (is_mac) {
defines += [ "WEBRTC_MAC" ]
}
if (is_fuchsia) {
defines += [ "WEBRTC_FUCHSIA" ]
}
if (is_win) {
defines += [ "WEBRTC_WIN" ]
}
@ -58,63 +232,210 @@ config("common_inherited_config") {
"WEBRTC_LINUX",
"WEBRTC_ANDROID",
]
if (build_with_mozilla) {
defines += [ "WEBRTC_ANDROID_OPENSLES" ]
}
}
if (is_chromeos) {
defines += [ "CHROMEOS" ]
}
if (rtc_sanitize_coverage != "") {
assert(is_clang, "sanitizer coverage requires clang")
cflags += [ "-fsanitize-coverage=${rtc_sanitize_coverage}" ]
ldflags += [ "-fsanitize-coverage=${rtc_sanitize_coverage}" ]
}
if (is_ubsan) {
cflags += [ "-fsanitize=float-cast-overflow" ]
}
}
if (rtc_have_dbus_glib) {
pkg_config("dbus-glib") {
packages = [ "dbus-glib-1" ]
# TODO(bugs.webrtc.org/9693): Remove the possibility to suppress this warning
# as soon as WebRTC compiles without it.
config("no_global_constructors") {
if (is_clang) {
cflags = [ "-Wno-global-constructors" ]
}
}
config("rtc_prod_config") {
# Ideally, WebRTC production code (but not test code) should have these flags.
if (is_clang) {
cflags = [
"-Wexit-time-destructors",
"-Wglobal-constructors",
]
}
}
group("tracing") {
all_dependent_configs = [ "//third_party/perfetto/gn:public_config" ]
if (rtc_use_perfetto) {
if (build_with_chromium) {
public_deps = # no-presubmit-check TODO(webrtc:8603)
[ "//third_party/perfetto:libperfetto" ]
} else {
public_deps = [ # no-presubmit-check TODO(webrtc:8603)
":webrtc_libperfetto",
"//third_party/perfetto/include/perfetto/tracing",
]
}
} else {
public_deps = # no-presubmit-check TODO(webrtc:8603)
[ "//third_party/perfetto/include/perfetto/tracing" ]
}
}
if (rtc_use_perfetto) {
rtc_library("webrtc_libperfetto") {
deps = [
"//third_party/perfetto/src/tracing:client_api_without_backends",
"//third_party/perfetto/src/tracing:platform_impl",
]
}
}
config("common_config") {
cflags = []
cflags_c = []
cflags_cc = []
if (rtc_restrict_logging) {
defines = [ "WEBRTC_RESTRICT_LOGGING" ]
cflags_objc = []
defines = []
if (rtc_enable_protobuf) {
defines += [ "WEBRTC_ENABLE_PROTOBUF=1" ]
} else {
defines += [ "WEBRTC_ENABLE_PROTOBUF=0" ]
}
if (rtc_have_dbus_glib) {
defines += [ "HAVE_DBUS_GLIB" ]
if (rtc_strict_field_trials == "") {
defines += [ "WEBRTC_STRICT_FIELD_TRIALS=0" ]
} else if (rtc_strict_field_trials == "dcheck") {
defines += [ "WEBRTC_STRICT_FIELD_TRIALS=1" ]
} else if (rtc_strict_field_trials == "warn") {
defines += [ "WEBRTC_STRICT_FIELD_TRIALS=2" ]
} else {
assert(false,
"Unsupported value for rtc_strict_field_trials: " +
"$rtc_strict_field_trials")
}
# TODO(kjellander): Investigate this, it seems like include <dbus/dbus.h>
# is still not found even if the execution of
# build/config/linux/pkg-config.py dbus-glib-1 returns correct include
# dirs on Linux.
all_dependent_configs = [ "dbus-glib" ]
if (rtc_include_internal_audio_device) {
defines += [ "WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE" ]
}
if (rtc_libvpx_build_vp9) {
defines += [ "RTC_ENABLE_VP9" ]
}
if (rtc_use_h265) {
defines += [ "RTC_ENABLE_H265" ]
}
if (rtc_include_dav1d_in_internal_decoder_factory) {
defines += [ "RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY" ]
}
if (rtc_enable_sctp) {
defines += [ "WEBRTC_HAVE_SCTP" ]
}
if (rtc_enable_external_auth) {
defines += [ "ENABLE_EXTERNAL_AUTH" ]
}
if (rtc_use_h264) {
defines += [ "WEBRTC_USE_H264" ]
}
if (rtc_use_absl_mutex) {
defines += [ "WEBRTC_ABSL_MUTEX" ]
}
if (rtc_enable_libevent) {
defines += [ "WEBRTC_ENABLE_LIBEVENT" ]
}
if (rtc_disable_logging) {
defines += [ "RTC_DISABLE_LOGGING" ]
}
if (rtc_disable_trace_events) {
defines += [ "RTC_DISABLE_TRACE_EVENTS" ]
}
if (rtc_disable_metrics) {
defines += [ "RTC_DISABLE_METRICS" ]
}
if (rtc_exclude_audio_processing_module) {
defines += [ "WEBRTC_EXCLUDE_AUDIO_PROCESSING_MODULE" ]
}
if (is_clang) {
cflags += [
# TODO(webrtc:13219): Fix -Wshadow instances and enable.
"-Wno-shadow",
# See https://reviews.llvm.org/D56731 for details about this
# warning.
"-Wctad-maybe-unsupported",
]
}
if (build_with_chromium) {
defines += [ "LOGGING_INSIDE_WEBRTC" ]
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) {
# -Wextra is currently disabled in Chromium"s common.gypi. Enable
# for targets that can handle it. For Android/arm64 right now
# there will be an "enumeral and non-enumeral type in conditional
# expression" warning in android_tools/ndk_experimental"s version
# of stlport.
# See: https://code.google.com/p/chromium/issues/detail?id=379699
if (current_cpu != "arm64" || !is_android) {
cflags = [
"-Wextra",
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.
# We need to repeat some flags from Chromium"s common.gypi
# here that get overridden by -Wextra.
"-Wno-unused-parameter",
"-Wno-missing-field-initializers",
"-Wno-strict-overflow",
]
cflags_cc = [
"-Wnon-virtual-dtor",
# "-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",
# This is enabled for clang; enable for gcc as well.
"-Woverloaded-virtual",
]
}
# "-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 += [ "-Wthread-safety" ]
cflags += [
"-Wc++11-narrowing",
"-Wundef",
"-Wunused-lambda-capture",
]
}
if (is_win && !is_clang) {
# MSVC warning suppressions (needed to use Abseil).
# TODO(bugs.webrtc.org/9274): Remove these warnings as soon as MSVC allows
# external headers warning suppression (or fix them upstream).
cflags += [ "/wd4702" ] # unreachable code
# MSVC 2019 warning suppressions for C++17 compiling
cflags +=
[ "/wd5041" ] # out-of-line definition for constexpr static data
# member is not needed and is deprecated in C++17
}
}
@ -129,8 +450,6 @@ config("common_config") {
defines += [ "WEBRTC_ARCH_ARM_V7" ]
if (arm_use_neon) {
defines += [ "WEBRTC_HAS_NEON" ]
} else if (arm_optionally_use_neon) {
defines += [ "WEBRTC_DETECT_NEON" ]
}
}
}
@ -163,119 +482,385 @@ config("common_config") {
"-fno-builtin-sinf",
]
}
}
source_set("webrtc") {
sources = [
"call.h",
"config.h",
"frame_callback.h",
"transport.h",
]
if (use_fuzzing_engine) {
# Used in Chromium's overrides to disable logging
defines += [ "WEBRTC_UNSAFE_FUZZER_MODE" ]
}
defines = []
configs += [ ":common_config" ]
public_configs = [ ":common_inherited_config" ]
deps = [
"audio",
":webrtc_common",
"base:rtc_base",
"call",
"common_audio",
"common_video",
"modules/audio_coding",
"modules/audio_conference_mixer",
"modules/audio_device",
"modules/audio_processing",
"modules/bitrate_controller",
"modules/desktop_capture",
"modules/media_file",
"modules/rtp_rtcp",
"modules/utility",
"modules/video_coding",
"modules/video_processing",
"system_wrappers",
"tools",
"video",
"voice_engine",
]
if (build_with_chromium) {
deps += [
"modules/video_capture",
"modules/video_render",
if (!build_with_chromium && rtc_win_undef_unicode) {
cflags += [
"/UUNICODE",
"/U_UNICODE",
]
}
if (rtc_enable_protobuf) {
defines += [ "ENABLE_RTC_EVENT_LOG" ]
deps += [ ":rtc_event_log_proto" ]
if (rtc_use_perfetto) {
defines += [ "RTC_USE_PERFETTO" ]
}
}
config("common_objc") {
frameworks = [ "Foundation.framework" ]
}
if (!rtc_build_ssl) {
config("external_ssl_library") {
if (rtc_ssl_root != "") {
include_dirs = [ rtc_ssl_root ]
}
libs = [
"crypto",
"ssl",
]
}
}
if (!build_with_chromium) {
executable("webrtc_tests") {
# Target to build all the WebRTC production code.
rtc_static_library("webrtc") {
# Only the root target and the test should depend on this.
visibility = [
"//:default",
"//:webrtc_lib_link_test",
]
sources = []
complete_static_lib = true
suppressed_configs += [ "//build/config/compiler:thin_archive" ]
defines = []
deps = [
"api:create_peerconnection_factory",
"api:enable_media",
"api:libjingle_peerconnection_api",
"api:rtc_error",
"api:transport_api",
"api/audio_codecs:opus_audio_decoder_factory",
"api/crypto",
"api/rtc_event_log:rtc_event_log_factory",
"api/task_queue",
"api/task_queue:default_task_queue_factory",
"api/test/metrics",
"api/video_codecs:video_decoder_factory_template",
"api/video_codecs:video_decoder_factory_template_dav1d_adapter",
"api/video_codecs:video_decoder_factory_template_libvpx_vp8_adapter",
"api/video_codecs:video_decoder_factory_template_libvpx_vp9_adapter",
"api/video_codecs:video_decoder_factory_template_open_h264_adapter",
"api/video_codecs:video_encoder_factory_template",
"api/video_codecs:video_encoder_factory_template_libaom_av1_adapter",
"api/video_codecs:video_encoder_factory_template_libvpx_vp8_adapter",
"api/video_codecs:video_encoder_factory_template_libvpx_vp9_adapter",
"api/video_codecs:video_encoder_factory_template_open_h264_adapter",
"audio",
"call",
"common_audio",
"common_video",
"logging:rtc_event_log_api",
"media",
"modules",
"modules/video_capture:video_capture_internal_impl",
"p2p:rtc_p2p",
"pc:libjingle_peerconnection",
"pc:rtc_pc",
"sdk",
"video",
]
if (rtc_include_builtin_audio_codecs) {
deps += [
"api/audio_codecs:builtin_audio_decoder_factory",
"api/audio_codecs:builtin_audio_encoder_factory",
]
}
if (build_with_mozilla) {
deps += [
"api/video:video_frame",
"api/video:video_rtp_headers",
]
} else {
deps += [
"api",
"logging",
"p2p",
"pc",
"stats",
]
}
if (rtc_enable_protobuf) {
deps += [ "logging:rtc_event_log_proto" ]
}
}
if (rtc_include_tests && !is_asan) {
rtc_executable("webrtc_lib_link_test") {
testonly = true
# This target is used for checking to link, so do not check dependencies
# on gn check.
check_includes = false # no-presubmit-check TODO(bugs.webrtc.org/12785)
sources = [ "webrtc_lib_link_test.cc" ]
deps = [
# NOTE: Don't add deps here. If this test fails to link, it means you
# need to add stuff to the webrtc static lib target above.
":webrtc",
]
}
}
}
if (use_libfuzzer || use_afl) {
# This target is only here for gn to discover fuzzer build targets under
# webrtc/test/fuzzers/.
group("webrtc_fuzzers_dummy") {
testonly = true
deps = [ "test/fuzzers:webrtc_fuzzer_main" ]
}
}
if (rtc_include_tests && !build_with_chromium) {
rtc_unittests_resources = [ "resources/reference_video_640x360_30fps.y4m" ]
if (is_ios) {
bundle_data("rtc_unittests_bundle_data") {
testonly = true
sources = rtc_unittests_resources
outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
}
}
rtc_test("rtc_unittests") {
testonly = true
deps = [
"api:compile_all_headers",
"api:rtc_api_unittests",
"api/audio/test:audio_api_unittests",
"api/audio_codecs/test:audio_codecs_api_unittests",
"api/numerics:numerics_unittests",
"api/task_queue:pending_task_safety_flag_unittests",
"api/test/metrics:metrics_unittests",
"api/transport:stun_unittest",
"api/video/test:rtc_api_video_unittests",
"api/video_codecs:libaom_av1_encoder_factory_test",
"api/video_codecs:simple_encoder_wrapper_unittests",
"api/video_codecs/test:video_codecs_api_unittests",
"api/voip:compile_all_headers",
"call:fake_network_pipe_unittests",
"p2p:libstunprober_unittests",
"p2p:rtc_p2p_unittests",
"rtc_base:async_dns_resolver_unittests",
"rtc_base:async_packet_socket_unittest",
"rtc_base:callback_list_unittests",
"rtc_base:rtc_base_approved_unittests",
"rtc_base:rtc_base_unittests",
"rtc_base:rtc_json_unittests",
"rtc_base:rtc_numerics_unittests",
"rtc_base:rtc_operations_chain_unittests",
"rtc_base:rtc_task_queue_unittests",
"rtc_base:sigslot_unittest",
"rtc_base:task_queue_stdlib_unittest",
"rtc_base:untyped_function_unittest",
"rtc_base:weak_ptr_unittests",
"rtc_base/experiments:experiments_unittests",
"rtc_base/system:file_wrapper_unittests",
"rtc_base/task_utils:repeating_task_unittests",
"rtc_base/units:units_unittests",
"sdk:sdk_tests",
"test:rtp_test_utils",
"test:test_main",
"test/network:network_emulation_unittests",
]
data = rtc_unittests_resources
if (rtc_enable_protobuf) {
deps += [
"api/test/network_emulation:network_config_schedule_proto",
"logging:rtc_event_log_tests",
]
}
if (is_ios) {
deps += [ ":rtc_unittests_bundle_data" ]
}
if (is_android) {
# Do not use Chromium's launcher. native_unittests defines its own JNI_OnLoad.
use_default_launcher = false
deps += [
"sdk/android:native_unittests",
"sdk/android:native_unittests_java",
"//testing/android/native_test:native_test_support",
]
shard_timeout = 900
}
}
if (rtc_enable_google_benchmarks) {
rtc_test("benchmarks") {
testonly = true
deps = [
"rtc_base/synchronization:mutex_benchmark",
"test:benchmark_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 = [
":webrtc",
"modules/video_render:video_render_internal_impl",
"modules/video_capture:video_capture_internal_impl",
"test",
"audio:audio_tests",
# TODO(eladalon): call_tests aren't actually video-specific, so we
# should move them to a more appropriate test suite.
"call:call_tests",
"call/adaptation:resource_adaptation_tests",
"test:test_common",
"test:test_main",
"test:video_test_common",
"video:video_tests",
"video/adaptation:video_adaptation_tests",
]
data = video_engine_tests_resources
if (is_android) {
use_default_launcher = false
deps += [
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
"//testing/android/native_test:native_test_java",
"//testing/android/native_test:native_test_support",
]
shard_timeout = 900
}
if (is_ios) {
deps += [ ":video_engine_tests_bundle_data" ]
}
}
webrtc_perf_tests_resources = [
"resources/ConferenceMotion_1280_720_50.yuv",
"resources/audio_coding/speech_mono_16kHz.pcm",
"resources/audio_coding/speech_mono_32_48kHz.pcm",
"resources/audio_coding/testfile32kHz.pcm",
"resources/difficult_photo_1850_1110.yuv",
"resources/foreman_cif.yuv",
"resources/paris_qcif.yuv",
"resources/photo_1850_1110.yuv",
"resources/presentation_1850_1110.yuv",
"resources/voice_engine/audio_long16.pcm",
"resources/web_screenshot_1850_1110.yuv",
]
if (is_ios) {
bundle_data("webrtc_perf_tests_bundle_data") {
testonly = true
sources = webrtc_perf_tests_resources
outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
}
}
rtc_test("webrtc_perf_tests") {
testonly = true
deps = [
"call:call_perf_tests",
"modules/audio_coding:audio_coding_perf_tests",
"modules/audio_processing:audio_processing_perf_tests",
"pc:peerconnection_perf_tests",
"test:test_main",
"video:video_full_stack_tests",
"video:video_pc_full_stack_tests",
]
data = webrtc_perf_tests_resources
if (is_android) {
use_default_launcher = false
deps += [
"//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
"//testing/android/native_test:native_test_java",
"//testing/android/native_test:native_test_support",
]
shard_timeout = 4500
}
if (is_ios) {
deps += [ ":webrtc_perf_tests_bundle_data" ]
}
}
rtc_test("webrtc_nonparallel_tests") {
testonly = true
deps = [ "rtc_base:rtc_base_nonparallel_tests" ]
if (is_android) {
deps += [ "//testing/android/native_test:native_test_support" ]
shard_timeout = 900
}
}
rtc_test("voip_unittests") {
testonly = true
deps = [
"api/voip:compile_all_headers",
"api/voip:voip_engine_factory_unittests",
"audio/voip/test:audio_channel_unittests",
"audio/voip/test:audio_egress_unittests",
"audio/voip/test:audio_ingress_unittests",
"audio/voip/test:voip_core_unittests",
"test:test_main",
]
}
}
source_set("webrtc_common") {
sources = [
"common_types.cc",
"common_types.h",
"config.cc",
"config.h",
"engine_configurations.h",
"typedefs.h",
]
configs += [ ":common_config" ]
public_configs = [ ":common_inherited_config" ]
}
source_set("gtest_prod") {
sources = [
"test/testsupport/gtest_prod_util.h",
]
}
if (rtc_enable_protobuf) {
proto_library("rtc_event_log_proto") {
sources = [
"call/rtc_event_log.proto",
]
proto_out_dir = "webrtc/call"
}
}
source_set("rtc_event_log") {
sources = [
"call/rtc_event_log.cc",
"call/rtc_event_log.h",
]
# Build target for standalone dcsctp
rtc_static_library("dcsctp") {
# Only the root target should depend on this.
visibility = [ "//:default" ]
sources = []
complete_static_lib = true
suppressed_configs += [ "//build/config/compiler:thin_archive" ]
defines = []
configs += [ ":common_config" ]
public_configs = [ ":common_inherited_config" ]
deps = [
":webrtc_common",
"net/dcsctp/public:factory",
"net/dcsctp/public:socket",
"net/dcsctp/public:types",
"net/dcsctp/socket:dcsctp_socket",
"net/dcsctp/timer:task_queue_timeout",
]
if (rtc_enable_protobuf) {
defines += [ "ENABLE_RTC_EVENT_LOG" ]
deps += [ ":rtc_event_log_proto" ]
}
if (is_clang && !is_nacl) {
# Suppress warnings from Chrome's Clang plugins.
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
configs -= [ "//build/config/clang:find_bad_constructs" ]
}
}
# ---- Poisons ----
#
# Here is one empty dummy target for each poison type (needed because
# "being poisonous with poison type foo" is implemented as "depends on
# //:poison_foo").
#
# The set of poison_* targets needs to be kept in sync with the
# `all_poison_types` list in webrtc.gni.
#
group("poison_audio_codecs") {
}
group("poison_default_echo_detector") {
}
group("poison_environment_construction") {
}
group("poison_software_video_codecs") {
}

29
webrtc/LICENSE Normal file
View File

@ -0,0 +1,29 @@
Copyright (c) 2011, The WebRTC project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Google nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,419 +0,0 @@
This source tree contains third party source code which is governed by third
party licenses. Paths to the files and associated licenses are collected here.
Files governed by third party licenses:
common_audio/fft4g.c
common_audio/signal_processing/spl_sqrt_floor.c
common_audio/signal_processing/spl_sqrt_floor_arm.S
modules/audio_coding/codecs/g711/main/source/g711.c
modules/audio_coding/codecs/g711/main/source/g711.h
modules/audio_coding/codecs/g722/main/source/g722_decode.c
modules/audio_coding/codecs/g722/main/source/g722_enc_dec.h
modules/audio_coding/codecs/g722/main/source/g722_encode.c
modules/audio_coding/codecs/isac/main/source/fft.c
modules/audio_device/mac/portaudio/pa_memorybarrier.h
modules/audio_device/mac/portaudio/pa_ringbuffer.c
modules/audio_device/mac/portaudio/pa_ringbuffer.h
modules/audio_processing/aec/aec_rdft.c
system_wrappers/source/condition_variable_event_win.cc
system_wrappers/source/set_thread_name_win.h
system_wrappers/source/spreadsortlib/constants.hpp
system_wrappers/source/spreadsortlib/spreadsort.hpp
Individual licenses for each file:
-------------------------------------------------------------------------------
Files:
common_audio/signal_processing/spl_sqrt_floor.c
common_audio/signal_processing/spl_sqrt_floor_arm.S
License:
/*
* Written by Wilco Dijkstra, 1996. The following email exchange establishes the
* license.
*
* From: Wilco Dijkstra <Wilco.Dijkstra@ntlworld.com>
* Date: Fri, Jun 24, 2011 at 3:20 AM
* Subject: Re: sqrt routine
* To: Kevin Ma <kma@google.com>
* Hi Kevin,
* Thanks for asking. Those routines are public domain (originally posted to
* comp.sys.arm a long time ago), so you can use them freely for any purpose.
* Cheers,
* Wilco
*
* ----- Original Message -----
* From: "Kevin Ma" <kma@google.com>
* To: <Wilco.Dijkstra@ntlworld.com>
* Sent: Thursday, June 23, 2011 11:44 PM
* Subject: Fwd: sqrt routine
* Hi Wilco,
* I saw your sqrt routine from several web sites, including
* http://www.finesse.demon.co.uk/steven/sqrt.html.
* Just wonder if there's any copyright information with your Successive
* approximation routines, or if I can freely use it for any purpose.
* Thanks.
* Kevin
*/
-------------------------------------------------------------------------------
Files:
modules/audio_coding/codecs/g711/main/source/g711.c
modules/audio_coding/codecs/g711/main/source/g711.h
License:
/*
* SpanDSP - a series of DSP components for telephony
*
* g711.h - In line A-law and u-law conversion routines
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2001 Steve Underwood
*
* Despite my general liking of the GPL, I place this code in the
* public domain for the benefit of all mankind - even the slimy
* ones who might try to proprietize my work and use it to my
* detriment.
*/
-------------------------------------------------------------------------------
Files:
modules/audio_coding/codecs/g722/main/source/g722_decode.c
modules/audio_coding/codecs/g722/main/source/g722_enc_dec.h
modules/audio_coding/codecs/g722/main/source/g722_encode.c
License:
/*
* SpanDSP - a series of DSP components for telephony
*
* g722_decode.c - The ITU G.722 codec, decode part.
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2005 Steve Underwood
*
* Despite my general liking of the GPL, I place my own contributions
* to this code in the public domain for the benefit of all mankind -
* even the slimy ones who might try to proprietize my work and use it
* to my detriment.
*
* Based in part on a single channel G.722 codec which is:
*
* Copyright (c) CMU 1993
* Computer Science, Speech Group
* Chengxiang Lu and Alex Hauptmann
*/
-------------------------------------------------------------------------------
Files:
modules/audio_coding/codecs/isac/main/source/fft.c
License:
/*
* Copyright(c)1995,97 Mark Olesen <olesen@me.QueensU.CA>
* Queen's Univ at Kingston (Canada)
*
* Permission to use, copy, modify, and distribute this software for
* any purpose without fee is hereby granted, provided that this
* entire notice is included in all copies of any software which is
* or includes a copy or modification of this software and in all
* copies of the supporting documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR QUEEN'S
* UNIVERSITY AT KINGSTON MAKES ANY REPRESENTATION OR WARRANTY OF ANY
* KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
* All of which is to say that you can do what you like with this
* source code provided you don't try to sell it as your own and you
* include an unaltered copy of this message (including the
* copyright).
*
* It is also implicitly understood that bug fixes and improvements
* should make their way back to the general Internet community so
* that everyone benefits.
*/
-------------------------------------------------------------------------------
Files:
modules/audio_device/mac/portaudio/pa_memorybarrier.h
modules/audio_device/mac/portaudio/pa_ringbuffer.c
modules/audio_device/mac/portaudio/pa_ringbuffer.h
License:
/*
* $Id: pa_memorybarrier.h 1240 2007-07-17 13:05:07Z bjornroche $
* Portable Audio I/O Library
* Memory barrier utilities
*
* Author: Bjorn Roche, XO Audio, LLC
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/*
* $Id: pa_ringbuffer.c 1421 2009-11-18 16:09:05Z bjornroche $
* Portable Audio I/O Library
* Ring Buffer utility.
*
* Author: Phil Burk, http://www.softsynth.com
* modified for SMP safety on Mac OS X by Bjorn Roche
* modified for SMP safety on Linux by Leland Lucius
* also, allowed for const where possible
* modified for multiple-byte-sized data elements by Sven Fischer
*
* Note that this is safe only for a single-thread reader and a
* single-thread writer.
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
-------------------------------------------------------------------------------
Files:
common_audio/fft4g.c
modules/audio_processing/aec/aec_rdft.c
License:
/*
* http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html
* Copyright Takuya OOURA, 1996-2001
*
* You may use, copy, modify and distribute this code for any purpose (include
* commercial use) and without fee. Please refer to this package when you modify
* this code.
*/
-------------------------------------------------------------------------------
Files:
system_wrappers/source/condition_variable_event_win.cc
Source:
http://www1.cse.wustl.edu/~schmidt/ACE-copying.html
License:
Copyright and Licensing Information for ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM),
and CoSMIC(TM)
ACE(TM), TAO(TM), CIAO(TM), DAnCE>(TM), and CoSMIC(TM) (henceforth referred to
as "DOC software") are copyrighted by Douglas C. Schmidt and his research
group at Washington University, University of California, Irvine, and
Vanderbilt University, Copyright (c) 1993-2009, all rights reserved. Since DOC
software is open-source, freely available software, you are free to use,
modify, copy, and distribute--perpetually and irrevocably--the DOC software
source code and object code produced from the source, as well as copy and
distribute modified versions of this software. You must, however, include this
copyright statement along with any code built using DOC software that you
release. No copyright statement needs to be provided if you just ship binary
executables of your software products.
You can use DOC software in commercial and/or binary software releases and are
under no obligation to redistribute any of your source code that is built
using DOC software. Note, however, that you may not misappropriate the DOC
software code, such as copyrighting it yourself or claiming authorship of the
DOC software code, in a way that will prevent DOC software from being
distributed freely using an open-source development model. You needn't inform
anyone that you're using DOC software in your software, though we encourage
you to let us know so we can promote your project in the DOC software success
stories.
The ACE, TAO, CIAO, DAnCE, and CoSMIC web sites are maintained by the DOC
Group at the Institute for Software Integrated Systems (ISIS) and the Center
for Distributed Object Computing of Washington University, St. Louis for the
development of open-source software as part of the open-source software
community. Submissions are provided by the submitter ``as is'' with no
warranties whatsoever, including any warranty of merchantability,
noninfringement of third party intellectual property, or fitness for any
particular purpose. In no event shall the submitter be liable for any direct,
indirect, special, exemplary, punitive, or consequential damages, including
without limitation, lost profits, even if advised of the possibility of such
damages. Likewise, DOC software is provided as is with no warranties of any
kind, including the warranties of design, merchantability, and fitness for a
particular purpose, noninfringement, or arising from a course of dealing,
usage or trade practice. Washington University, UC Irvine, Vanderbilt
University, their employees, and students shall have no liability with respect
to the infringement of copyrights, trade secrets or any patents by DOC
software or any part thereof. Moreover, in no event will Washington
University, UC Irvine, or Vanderbilt University, their employees, or students
be liable for any lost revenue or profits or other special, indirect and
consequential damages.
DOC software is provided with no support and without any obligation on the
part of Washington University, UC Irvine, Vanderbilt University, their
employees, or students to assist in its use, correction, modification, or
enhancement. A number of companies around the world provide commercial support
for DOC software, however. DOC software is Y2K-compliant, as long as the
underlying OS platform is Y2K-compliant. Likewise, DOC software is compliant
with the new US daylight savings rule passed by Congress as "The Energy Policy
Act of 2005," which established new daylight savings times (DST) rules for the
United States that expand DST as of March 2007. Since DOC software obtains
time/date and calendaring information from operating systems users will not be
affected by the new DST rules as long as they upgrade their operating systems
accordingly.
The names ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), CoSMIC(TM), Washington
University, UC Irvine, and Vanderbilt University, may not be used to endorse
or promote products or services derived from this source without express
written permission from Washington University, UC Irvine, or Vanderbilt
University. This license grants no permission to call products or services
derived from this source ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), or CoSMIC(TM),
nor does it grant permission for the name Washington University, UC Irvine, or
Vanderbilt University to appear in their names.
-------------------------------------------------------------------------------
Files:
system_wrappers/source/set_thread_name_win.h
Source:
http://msdn.microsoft.com/en-us/cc300389.aspx#P
License:
This license governs use of code marked as “sample” or “example” available on
this web site without a license agreement, as provided under the section above
titled “NOTICE SPECIFIC TO SOFTWARE AVAILABLE ON THIS WEB SITE.” If you use
such code (the “software”), you accept this license. If you do not accept the
license, do not use the software.
1. Definitions
The terms “reproduce,” “reproduction,” “derivative works,” and “distribution”
have the same meaning here as under U.S. copyright law.
A “contribution” is the original software, or any additions or changes to the
software.
A “contributor” is any person that distributes its contribution under this
license.
“Licensed patents” are a contributors patent claims that read directly on its
contribution.
2. Grant of Rights
(A) Copyright Grant - Subject to the terms of this license, including the
license conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free copyright license to reproduce its
contribution, prepare derivative works of its contribution, and distribute its
contribution or any derivative works that you create.
(B) Patent Grant - Subject to the terms of this license, including the license
conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free license under its licensed patents to
make, have made, use, sell, offer for sale, import, and/or otherwise dispose
of its contribution in the software or derivative works of the contribution in
the software.
3. Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use any
contributors name, logo, or trademarks.
(B) If you bring a patent claim against any contributor over patents that you
claim are infringed by the software, your patent license from such contributor
to the software ends automatically.
(C) If you distribute any portion of the software, you must retain all
copyright, patent, trademark, and attribution notices that are present in the
software.
(D) If you distribute any portion of the software in source code form, you may
do so only under this license by including a complete copy of this license
with your distribution. If you distribute any portion of the software in
compiled or object code form, you may only do so under a license that complies
with this license.
(E) The software is licensed “as-is.” You bear the risk of using it. The
contributors give no express warranties, guarantees or conditions. You may
have additional consumer rights under your local laws which this license
cannot change. To the extent permitted under your local laws, the contributors
exclude the implied warranties of merchantability, fitness for a particular
purpose and non-infringement.
(F) Platform Limitation - The licenses granted in sections 2(A) and 2(B)
extend only to the software or derivative works that you create that run on a
Microsoft Windows operating system product.
-------------------------------------------------------------------------------
Files:
system_wrappers/source/spreadsortlib/constants.hpp
system_wrappers/source/spreadsortlib/spreadsort.hpp
License:
/*Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.*/

View File

@ -1,12 +0,0 @@
SUBDIRS = . base common_audio system_wrappers modules
noinst_HEADERS = common.h \
common_types.h \
typedefs.h
noinst_LTLIBRARIES = libwebrtc.la
libwebrtc_la_SOURCES = common_types.cc
libwebrtc_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS)
EXTRA_DIST = BUILD.gn PATENTS LICENSE_THIRD_PARTY

335
webrtc/api/array_view.h Normal file
View File

@ -0,0 +1,335 @@
/*
* Copyright 2015 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_ARRAY_VIEW_H_
#define API_ARRAY_VIEW_H_
#include <algorithm>
#include <array>
#include <cstddef>
#include <iterator>
#include <type_traits>
#include "rtc_base/checks.h"
#include "rtc_base/type_traits.h"
namespace rtc {
// tl;dr: rtc::ArrayView is the same thing as gsl::span from the Guideline
// Support Library.
//
// Many functions read from or write to arrays. The obvious way to do this is
// to use two arguments, a pointer to the first element and an element count:
//
// bool Contains17(const int* arr, size_t size) {
// for (size_t i = 0; i < size; ++i) {
// if (arr[i] == 17)
// return true;
// }
// return false;
// }
//
// This is flexible, since it doesn't matter how the array is stored (C array,
// std::vector, rtc::Buffer, ...), but it's error-prone because the caller has
// to correctly specify the array length:
//
// Contains17(arr, arraysize(arr)); // C array
// Contains17(arr.data(), arr.size()); // std::vector
// Contains17(arr, size); // pointer + size
// ...
//
// It's also kind of messy to have two separate arguments for what is
// conceptually a single thing.
//
// Enter rtc::ArrayView<T>. It contains a T pointer (to an array it doesn't
// own) and a count, and supports the basic things you'd expect, such as
// indexing and iteration. It allows us to write our function like this:
//
// bool Contains17(rtc::ArrayView<const int> arr) {
// for (auto e : arr) {
// if (e == 17)
// return true;
// }
// return false;
// }
//
// And even better, because a bunch of things will implicitly convert to
// ArrayView, we can call it like this:
//
// Contains17(arr); // C array
// Contains17(arr); // std::vector
// Contains17(rtc::ArrayView<int>(arr, size)); // pointer + size
// Contains17(nullptr); // nullptr -> empty ArrayView
// ...
//
// ArrayView<T> stores both a pointer and a size, but you may also use
// ArrayView<T, N>, which has a size that's fixed at compile time (which means
// it only has to store the pointer).
//
// One important point is that ArrayView<T> and ArrayView<const T> are
// different types, which allow and don't allow mutation of the array elements,
// respectively. The implicit conversions work just like you'd hope, so that
// e.g. vector<int> will convert to either ArrayView<int> or ArrayView<const
// int>, but const vector<int> will convert only to ArrayView<const int>.
// (ArrayView itself can be the source type in such conversions, so
// ArrayView<int> will convert to ArrayView<const int>.)
//
// Note: ArrayView is tiny (just a pointer and a count if variable-sized, just
// a pointer if fix-sized) and trivially copyable, so it's probably cheaper to
// pass it by value than by const reference.
namespace array_view_internal {
// Magic constant for indicating that the size of an ArrayView is variable
// instead of fixed.
enum : std::ptrdiff_t { kArrayViewVarSize = -4711 };
// Base class for ArrayViews of fixed nonzero size.
template <typename T, std::ptrdiff_t Size>
class ArrayViewBase {
static_assert(Size > 0, "ArrayView size must be variable or non-negative");
public:
ArrayViewBase(T* data, size_t size) : data_(data) {}
static constexpr size_t size() { return Size; }
static constexpr bool empty() { return false; }
T* data() const { return data_; }
protected:
static constexpr bool fixed_size() { return true; }
private:
T* data_;
};
// Specialized base class for ArrayViews of fixed zero size.
template <typename T>
class ArrayViewBase<T, 0> {
public:
explicit ArrayViewBase(T* data, size_t size) {}
static constexpr size_t size() { return 0; }
static constexpr bool empty() { return true; }
T* data() const { return nullptr; }
protected:
static constexpr bool fixed_size() { return true; }
};
// Specialized base class for ArrayViews of variable size.
template <typename T>
class ArrayViewBase<T, array_view_internal::kArrayViewVarSize> {
public:
ArrayViewBase(T* data, size_t size)
: data_(size == 0 ? nullptr : data), size_(size) {}
size_t size() const { return size_; }
bool empty() const { return size_ == 0; }
T* data() const { return data_; }
protected:
static constexpr bool fixed_size() { return false; }
private:
T* data_;
size_t size_;
};
} // namespace array_view_internal
template <typename T,
std::ptrdiff_t Size = array_view_internal::kArrayViewVarSize>
class ArrayView final : public array_view_internal::ArrayViewBase<T, Size> {
public:
using value_type = T;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
using const_iterator = const T*;
// Construct an ArrayView from a pointer and a length.
template <typename U>
ArrayView(U* data, size_t size)
: array_view_internal::ArrayViewBase<T, Size>::ArrayViewBase(data, size) {
RTC_DCHECK_EQ(size == 0 ? nullptr : data, this->data());
RTC_DCHECK_EQ(size, this->size());
RTC_DCHECK_EQ(!this->data(),
this->size() == 0); // data is null iff size == 0.
}
// Construct an empty ArrayView. Note that fixed-size ArrayViews of size > 0
// cannot be empty.
ArrayView() : ArrayView(nullptr, 0) {}
ArrayView(std::nullptr_t) // NOLINT
: ArrayView() {}
ArrayView(std::nullptr_t, size_t size)
: ArrayView(static_cast<T*>(nullptr), size) {
static_assert(Size == 0 || Size == array_view_internal::kArrayViewVarSize,
"");
RTC_DCHECK_EQ(0, size);
}
// Construct an ArrayView from a C-style array.
template <typename U, size_t N>
ArrayView(U (&array)[N]) // NOLINT
: ArrayView(array, N) {
static_assert(Size == N || Size == array_view_internal::kArrayViewVarSize,
"Array size must match ArrayView size");
}
// (Only if size is fixed.) Construct a fixed size ArrayView<T, N> from a
// non-const std::array instance. For an ArrayView with variable size, the
// used ctor is ArrayView(U& u) instead.
template <typename U,
size_t N,
typename std::enable_if<
Size == static_cast<std::ptrdiff_t>(N)>::type* = nullptr>
ArrayView(std::array<U, N>& u) // NOLINT
: ArrayView(u.data(), u.size()) {}
// (Only if size is fixed.) Construct a fixed size ArrayView<T, N> where T is
// const from a const(expr) std::array instance. For an ArrayView with
// variable size, the used ctor is ArrayView(U& u) instead.
template <typename U,
size_t N,
typename std::enable_if<
Size == static_cast<std::ptrdiff_t>(N)>::type* = nullptr>
ArrayView(const std::array<U, N>& u) // NOLINT
: ArrayView(u.data(), u.size()) {}
// (Only if size is fixed.) Construct an ArrayView from any type U that has a
// static constexpr size() method whose return value is equal to Size, and a
// data() method whose return value converts implicitly to T*. In particular,
// this means we allow conversion from ArrayView<T, N> to ArrayView<const T,
// N>, but not the other way around. We also don't allow conversion from
// ArrayView<T> to ArrayView<T, N>, or from ArrayView<T, M> to ArrayView<T,
// N> when M != N.
template <
typename U,
typename std::enable_if<Size != array_view_internal::kArrayViewVarSize &&
HasDataAndSize<U, T>::value>::type* = nullptr>
ArrayView(U& u) // NOLINT
: ArrayView(u.data(), u.size()) {
static_assert(U::size() == Size, "Sizes must match exactly");
}
template <
typename U,
typename std::enable_if<Size != array_view_internal::kArrayViewVarSize &&
HasDataAndSize<U, T>::value>::type* = nullptr>
ArrayView(const U& u) // NOLINT(runtime/explicit)
: ArrayView(u.data(), u.size()) {
static_assert(U::size() == Size, "Sizes must match exactly");
}
// (Only if size is variable.) Construct an ArrayView from any type U that
// has a size() method whose return value converts implicitly to size_t, and
// a data() method whose return value converts implicitly to T*. In
// particular, this means we allow conversion from ArrayView<T> to
// ArrayView<const T>, but not the other way around. Other allowed
// conversions include
// ArrayView<T, N> to ArrayView<T> or ArrayView<const T>,
// std::vector<T> to ArrayView<T> or ArrayView<const T>,
// const std::vector<T> to ArrayView<const T>,
// rtc::Buffer to ArrayView<uint8_t> or ArrayView<const uint8_t>, and
// const rtc::Buffer to ArrayView<const uint8_t>.
template <
typename U,
typename std::enable_if<Size == array_view_internal::kArrayViewVarSize &&
HasDataAndSize<U, T>::value>::type* = nullptr>
ArrayView(U& u) // NOLINT
: ArrayView(u.data(), u.size()) {}
template <
typename U,
typename std::enable_if<Size == array_view_internal::kArrayViewVarSize &&
HasDataAndSize<U, T>::value>::type* = nullptr>
ArrayView(const U& u) // NOLINT(runtime/explicit)
: ArrayView(u.data(), u.size()) {}
// Indexing and iteration. These allow mutation even if the ArrayView is
// const, because the ArrayView doesn't own the array. (To prevent mutation,
// use a const element type.)
T& operator[](size_t idx) const {
RTC_DCHECK_LT(idx, this->size());
RTC_DCHECK(this->data());
return this->data()[idx];
}
T* begin() const { return this->data(); }
T* end() const { return this->data() + this->size(); }
const T* cbegin() const { return this->data(); }
const T* cend() const { return this->data() + this->size(); }
std::reverse_iterator<T*> rbegin() const {
return std::make_reverse_iterator(end());
}
std::reverse_iterator<T*> rend() const {
return std::make_reverse_iterator(begin());
}
std::reverse_iterator<const T*> crbegin() const {
return std::make_reverse_iterator(cend());
}
std::reverse_iterator<const T*> crend() const {
return std::make_reverse_iterator(cbegin());
}
ArrayView<T> subview(size_t offset, size_t size) const {
return offset < this->size()
? ArrayView<T>(this->data() + offset,
std::min(size, this->size() - offset))
: ArrayView<T>();
}
ArrayView<T> subview(size_t offset) const {
return subview(offset, this->size());
}
};
// Comparing two ArrayViews compares their (pointer,size) pairs; it does *not*
// dereference the pointers.
template <typename T, std::ptrdiff_t Size1, std::ptrdiff_t Size2>
bool operator==(const ArrayView<T, Size1>& a, const ArrayView<T, Size2>& b) {
return a.data() == b.data() && a.size() == b.size();
}
template <typename T, std::ptrdiff_t Size1, std::ptrdiff_t Size2>
bool operator!=(const ArrayView<T, Size1>& a, const ArrayView<T, Size2>& b) {
return !(a == b);
}
// Variable-size ArrayViews are the size of two pointers; fixed-size ArrayViews
// are the size of one pointer. (And as a special case, fixed-size ArrayViews
// of size 0 require no storage.)
static_assert(sizeof(ArrayView<int>) == 2 * sizeof(int*), "");
static_assert(sizeof(ArrayView<int, 17>) == sizeof(int*), "");
static_assert(std::is_empty<ArrayView<int, 0>>::value, "");
template <typename T>
inline ArrayView<T> MakeArrayView(T* data, size_t size) {
return ArrayView<T>(data, size);
}
// Only for primitive types that have the same size and aligment.
// Allow reinterpret cast of the array view to another primitive type of the
// same size.
// Template arguments order is (U, T, Size) to allow deduction of the template
// arguments in client calls: reinterpret_array_view<target_type>(array_view).
template <typename U, typename T, std::ptrdiff_t Size>
inline ArrayView<U, Size> reinterpret_array_view(ArrayView<T, Size> view) {
static_assert(sizeof(U) == sizeof(T) && alignof(U) == alignof(T),
"ArrayView reinterpret_cast is only supported for casting "
"between views that represent the same chunk of memory.");
static_assert(
std::is_fundamental<T>::value && std::is_fundamental<U>::value,
"ArrayView reinterpret_cast is only supported for casting between "
"fundamental types.");
return ArrayView<U, Size>(reinterpret_cast<U*>(view.data()), view.size());
}
} // namespace rtc
#endif // API_ARRAY_VIEW_H_

View File

@ -0,0 +1,235 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/audio/audio_frame.h"
#include <string.h>
#include <cstdint>
#include <optional>
#include "api/array_view.h"
#include "api/audio/audio_view.h"
#include "api/audio/channel_layout.h"
#include "api/rtp_packet_infos.h"
#include "rtc_base/checks.h"
#include "rtc_base/time_utils.h"
namespace webrtc {
AudioFrame::AudioFrame() {
// Visual Studio doesn't like this in the class definition.
static_assert(sizeof(data_) == kMaxDataSizeBytes, "kMaxDataSizeBytes");
}
AudioFrame::AudioFrame(int sample_rate_hz,
size_t num_channels,
ChannelLayout layout /*= CHANNEL_LAYOUT_UNSUPPORTED*/)
: samples_per_channel_(SampleRateToDefaultChannelSize(sample_rate_hz)),
sample_rate_hz_(sample_rate_hz),
num_channels_(num_channels),
channel_layout_(layout == CHANNEL_LAYOUT_UNSUPPORTED
? GuessChannelLayout(num_channels)
: layout) {
RTC_DCHECK_LE(num_channels_, kMaxConcurrentChannels);
RTC_DCHECK_GT(sample_rate_hz_, 0);
RTC_DCHECK_GT(samples_per_channel_, 0u);
}
void AudioFrame::Reset() {
ResetWithoutMuting();
muted_ = true;
}
void AudioFrame::ResetWithoutMuting() {
// TODO(wu): Zero is a valid value for `timestamp_`. We should initialize
// to an invalid value, or add a new member to indicate invalidity.
timestamp_ = 0;
elapsed_time_ms_ = -1;
ntp_time_ms_ = -1;
samples_per_channel_ = 0;
sample_rate_hz_ = 0;
num_channels_ = 0;
channel_layout_ = CHANNEL_LAYOUT_NONE;
speech_type_ = kUndefined;
vad_activity_ = kVadUnknown;
profile_timestamp_ms_ = 0;
packet_infos_ = RtpPacketInfos();
absolute_capture_timestamp_ms_ = std::nullopt;
}
void AudioFrame::UpdateFrame(uint32_t timestamp,
const int16_t* data,
size_t samples_per_channel,
int sample_rate_hz,
SpeechType speech_type,
VADActivity vad_activity,
size_t num_channels) {
RTC_CHECK_LE(num_channels, kMaxConcurrentChannels);
timestamp_ = timestamp;
samples_per_channel_ = samples_per_channel;
sample_rate_hz_ = sample_rate_hz;
speech_type_ = speech_type;
vad_activity_ = vad_activity;
num_channels_ = num_channels;
channel_layout_ = GuessChannelLayout(num_channels);
if (channel_layout_ != CHANNEL_LAYOUT_UNSUPPORTED) {
RTC_DCHECK_EQ(num_channels, ChannelLayoutToChannelCount(channel_layout_));
}
const size_t length = samples_per_channel * num_channels;
RTC_CHECK_LE(length, data_.size());
if (data != nullptr) {
memcpy(data_.data(), data, sizeof(int16_t) * length);
muted_ = false;
} else {
muted_ = true;
}
}
void AudioFrame::CopyFrom(const AudioFrame& src) {
if (this == &src)
return;
if (muted_ && !src.muted()) {
// TODO: bugs.webrtc.org/5647 - Since the default value for `muted_` is
// false and `data_` may still be uninitialized (because we don't initialize
// data_ as part of construction), we clear the full buffer here before
// copying over new values. If we don't, msan might complain in some tests.
// Consider locking down construction, avoiding the default constructor and
// prefering construction that initializes all state.
ClearSamples(data_);
}
timestamp_ = src.timestamp_;
elapsed_time_ms_ = src.elapsed_time_ms_;
ntp_time_ms_ = src.ntp_time_ms_;
packet_infos_ = src.packet_infos_;
muted_ = src.muted();
samples_per_channel_ = src.samples_per_channel_;
sample_rate_hz_ = src.sample_rate_hz_;
speech_type_ = src.speech_type_;
vad_activity_ = src.vad_activity_;
num_channels_ = src.num_channels_;
channel_layout_ = src.channel_layout_;
absolute_capture_timestamp_ms_ = src.absolute_capture_timestamp_ms();
auto data = src.data_view();
RTC_CHECK_LE(data.size(), data_.size());
if (!muted_ && !data.empty()) {
memcpy(&data_[0], &data[0], sizeof(int16_t) * data.size());
}
}
void AudioFrame::UpdateProfileTimeStamp() {
profile_timestamp_ms_ = rtc::TimeMillis();
}
int64_t AudioFrame::ElapsedProfileTimeMs() const {
if (profile_timestamp_ms_ == 0) {
// Profiling has not been activated.
return -1;
}
return rtc::TimeSince(profile_timestamp_ms_);
}
const int16_t* AudioFrame::data() const {
return muted_ ? zeroed_data().begin() : data_.data();
}
InterleavedView<const int16_t> AudioFrame::data_view() const {
// If you get a nullptr from `data_view()`, it's likely because the
// samples_per_channel_ and/or num_channels_ members haven't been properly
// set. Since `data_view()` returns an InterleavedView<> (which internally
// uses rtc::ArrayView<>), we inherit the behavior in InterleavedView when the
// view size is 0 that ArrayView<>::data() returns nullptr. So, even when an
// AudioFrame is muted and we want to return `zeroed_data()`, if
// samples_per_channel_ or num_channels_ is 0, the view will point to
// nullptr.
return InterleavedView<const int16_t>(muted_ ? &zeroed_data()[0] : &data_[0],
samples_per_channel_, num_channels_);
}
int16_t* AudioFrame::mutable_data() {
// TODO: bugs.webrtc.org/5647 - Can we skip zeroing the buffer?
// Consider instead if we should rather zero the buffer when `muted_` is set
// to `true`.
if (muted_) {
ClearSamples(data_);
muted_ = false;
}
return &data_[0];
}
InterleavedView<int16_t> AudioFrame::mutable_data(size_t samples_per_channel,
size_t num_channels) {
const size_t total_samples = samples_per_channel * num_channels;
RTC_CHECK_LE(total_samples, data_.size());
RTC_CHECK_LE(num_channels, kMaxConcurrentChannels);
// Sanity check for valid argument values during development.
// If `samples_per_channel` is < `num_channels` but larger than 0,
// then chances are the order of arguments is incorrect.
RTC_DCHECK((samples_per_channel == 0 && num_channels == 0) ||
num_channels <= samples_per_channel)
<< "samples_per_channel=" << samples_per_channel
<< "num_channels=" << num_channels;
// TODO: bugs.webrtc.org/5647 - Can we skip zeroing the buffer?
// Consider instead if we should rather zero the whole buffer when `muted_` is
// set to `true`.
if (muted_) {
ClearSamples(data_, total_samples);
muted_ = false;
}
samples_per_channel_ = samples_per_channel;
num_channels_ = num_channels;
return InterleavedView<int16_t>(&data_[0], samples_per_channel, num_channels);
}
void AudioFrame::Mute() {
muted_ = true;
}
bool AudioFrame::muted() const {
return muted_;
}
void AudioFrame::SetLayoutAndNumChannels(ChannelLayout layout,
size_t num_channels) {
channel_layout_ = layout;
num_channels_ = num_channels;
#if RTC_DCHECK_IS_ON
// Do a sanity check that the layout and num_channels match.
// If this lookup yield 0u, then the layout is likely CHANNEL_LAYOUT_DISCRETE.
auto expected_num_channels = ChannelLayoutToChannelCount(layout);
if (expected_num_channels) { // If expected_num_channels is 0
RTC_DCHECK_EQ(expected_num_channels, num_channels_);
}
#endif
RTC_CHECK_LE(samples_per_channel_ * num_channels_, data_.size());
}
void AudioFrame::SetSampleRateAndChannelSize(int sample_rate) {
sample_rate_hz_ = sample_rate;
// We could call `AudioProcessing::GetFrameSize()` here, but that requires
// adding a dependency on the ":audio_processing" build target, which can
// complicate the dependency tree. Some refactoring is probably in order to
// get some consistency around this since there are many places across the
// code that assume this default buffer size.
samples_per_channel_ = SampleRateToDefaultChannelSize(sample_rate_hz_);
}
// static
rtc::ArrayView<const int16_t> AudioFrame::zeroed_data() {
static int16_t* null_data = new int16_t[kMaxDataSizeSamples]();
return rtc::ArrayView<const int16_t>(null_data, kMaxDataSizeSamples);
}
} // namespace webrtc

View File

@ -0,0 +1,230 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_AUDIO_AUDIO_FRAME_H_
#define API_AUDIO_AUDIO_FRAME_H_
#include <stddef.h>
#include <stdint.h>
#include <array>
#include <optional>
#include "api/array_view.h"
#include "api/audio/audio_view.h"
#include "api/audio/channel_layout.h"
#include "api/rtp_packet_infos.h"
#include "rtc_base/checks.h"
namespace webrtc {
// Default webrtc buffer size in milliseconds.
constexpr size_t kDefaultAudioBufferLengthMs = 10u;
// Default total number of audio buffers per second based on the default length.
constexpr size_t kDefaultAudioBuffersPerSec =
1000u / kDefaultAudioBufferLengthMs;
// Returns the number of samples a buffer needs to hold for ~10ms of a single
// audio channel at a given sample rate.
// See also `AudioProcessing::GetFrameSize()`.
inline size_t SampleRateToDefaultChannelSize(size_t sample_rate) {
// Basic sanity check. 192kHz is the highest supported input sample rate.
RTC_DCHECK_LE(sample_rate, 192000);
return sample_rate / kDefaultAudioBuffersPerSec;
}
/////////////////////////////////////////////////////////////////////
/* This class holds up to 120 ms of super-wideband (32 kHz) stereo audio. It
* allows for adding and subtracting frames while keeping track of the resulting
* states.
*
* Notes
* - This is a de-facto api, not designed for external use. The AudioFrame class
* is in need of overhaul or even replacement, and anyone depending on it
* should be prepared for that.
* - The total number of samples is samples_per_channel_ * num_channels_.
* - Stereo data is interleaved starting with the left channel.
*/
class AudioFrame {
public:
// Using constexpr here causes linker errors unless the variable also has an
// out-of-class definition, which is impractical in this header-only class.
// (This makes no sense because it compiles as an enum value, which we most
// certainly cannot take the address of, just fine.) C++17 introduces inline
// variables which should allow us to switch to constexpr and keep this a
// header-only class.
enum : size_t {
// Stereo, 32 kHz, 120 ms (2 * 32 * 120)
// Stereo, 192 kHz, 20 ms (2 * 192 * 20)
kMaxDataSizeSamples = 7680,
kMaxDataSizeBytes = kMaxDataSizeSamples * sizeof(int16_t),
};
enum VADActivity { kVadActive = 0, kVadPassive = 1, kVadUnknown = 2 };
enum SpeechType {
kNormalSpeech = 0,
kPLC = 1,
kCNG = 2,
kPLCCNG = 3,
kCodecPLC = 5,
kUndefined = 4
};
AudioFrame();
// Construct an audio frame with frame length properties and channel
// information. `samples_per_channel()` will be initialized to a 10ms buffer
// size and if `layout` is not specified (default value of
// CHANNEL_LAYOUT_UNSUPPORTED is set), then the channel layout is derived
// (guessed) from `num_channels`.
AudioFrame(int sample_rate_hz,
size_t num_channels,
ChannelLayout layout = CHANNEL_LAYOUT_UNSUPPORTED);
AudioFrame(const AudioFrame&) = delete;
AudioFrame& operator=(const AudioFrame&) = delete;
// Resets all members to their default state.
void Reset();
// Same as Reset(), but leaves mute state unchanged. Muting a frame requires
// the buffer to be zeroed on the next call to mutable_data(). Callers
// intending to write to the buffer immediately after Reset() can instead use
// ResetWithoutMuting() to skip this wasteful zeroing.
void ResetWithoutMuting();
// TODO: b/335805780 - Accept InterleavedView.
void UpdateFrame(uint32_t timestamp,
const int16_t* data,
size_t samples_per_channel,
int sample_rate_hz,
SpeechType speech_type,
VADActivity vad_activity,
size_t num_channels = 1);
void CopyFrom(const AudioFrame& src);
// Sets a wall-time clock timestamp in milliseconds to be used for profiling
// of time between two points in the audio chain.
// Example:
// t0: UpdateProfileTimeStamp()
// t1: ElapsedProfileTimeMs() => t1 - t0 [msec]
void UpdateProfileTimeStamp();
// Returns the time difference between now and when UpdateProfileTimeStamp()
// was last called. Returns -1 if UpdateProfileTimeStamp() has not yet been
// called.
int64_t ElapsedProfileTimeMs() const;
// data() returns a zeroed static buffer if the frame is muted.
// TODO: b/335805780 - Return InterleavedView.
const int16_t* data() const;
// Returns a read-only view of all the valid samples held by the AudioFrame.
// For a muted AudioFrame, the samples will all be 0.
InterleavedView<const int16_t> data_view() const;
// mutable_frame() always returns a non-static buffer; the first call to
// mutable_frame() zeros the buffer and marks the frame as unmuted.
// TODO: b/335805780 - Return an InterleavedView.
int16_t* mutable_data();
// Grants write access to the audio buffer. The size of the returned writable
// view is determined by the `samples_per_channel` and `num_channels`
// dimensions which the function checks for correctness and stores in the
// internal member variables; `samples_per_channel()` and `num_channels()`
// respectively.
// If the state is currently muted, the returned view will be zeroed out.
InterleavedView<int16_t> mutable_data(size_t samples_per_channel,
size_t num_channels);
// Prefer to mute frames using AudioFrameOperations::Mute.
void Mute();
// Frame is muted by default.
bool muted() const;
size_t max_16bit_samples() const { return data_.size(); }
size_t samples_per_channel() const { return samples_per_channel_; }
size_t num_channels() const { return num_channels_; }
ChannelLayout channel_layout() const { return channel_layout_; }
// Sets the `channel_layout` property as well as `num_channels`.
void SetLayoutAndNumChannels(ChannelLayout layout, size_t num_channels);
int sample_rate_hz() const { return sample_rate_hz_; }
void set_absolute_capture_timestamp_ms(
int64_t absolute_capture_time_stamp_ms) {
absolute_capture_timestamp_ms_ = absolute_capture_time_stamp_ms;
}
std::optional<int64_t> absolute_capture_timestamp_ms() const {
return absolute_capture_timestamp_ms_;
}
// Sets the sample_rate_hz and samples_per_channel properties based on a
// given sample rate and calculates a default 10ms samples_per_channel value.
void SetSampleRateAndChannelSize(int sample_rate);
// RTP timestamp of the first sample in the AudioFrame.
uint32_t timestamp_ = 0;
// Time since the first frame in milliseconds.
// -1 represents an uninitialized value.
int64_t elapsed_time_ms_ = -1;
// NTP time of the estimated capture time in local timebase in milliseconds.
// -1 represents an uninitialized value.
int64_t ntp_time_ms_ = -1;
size_t samples_per_channel_ = 0;
int sample_rate_hz_ = 0;
size_t num_channels_ = 0;
SpeechType speech_type_ = kUndefined;
VADActivity vad_activity_ = kVadUnknown;
// Monotonically increasing timestamp intended for profiling of audio frames.
// Typically used for measuring elapsed time between two different points in
// the audio path. No lock is used to save resources and we are thread safe
// by design.
// TODO(nisse@webrtc.org): consider using std::optional.
int64_t profile_timestamp_ms_ = 0;
// Information about packets used to assemble this audio frame. This is needed
// by `SourceTracker` when the frame is delivered to the RTCRtpReceiver's
// MediaStreamTrack, in order to implement getContributingSources(). See:
// https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-getcontributingsources
//
// TODO(bugs.webrtc.org/10757):
// Note that this information might not be fully accurate since we currently
// don't have a proper way to track it across the audio sync buffer. The
// sync buffer is the small sample-holding buffer located after the audio
// decoder and before where samples are assembled into output frames.
//
// `RtpPacketInfos` may also be empty if the audio samples did not come from
// RTP packets. E.g. if the audio were locally generated by packet loss
// concealment, comfort noise generation, etc.
RtpPacketInfos packet_infos_;
private:
// A permanently zeroed out buffer to represent muted frames. This is a
// header-only class, so the only way to avoid creating a separate zeroed
// buffer per translation unit is to wrap a static in an inline function.
static rtc::ArrayView<const int16_t> zeroed_data();
std::array<int16_t, kMaxDataSizeSamples> data_;
bool muted_ = true;
ChannelLayout channel_layout_ = CHANNEL_LAYOUT_NONE;
// Absolute capture timestamp when this audio frame was originally captured.
// This is only valid for audio frames captured on this machine. The absolute
// capture timestamp of a received frame is found in `packet_infos_`.
// This timestamp MUST be based on the same clock as rtc::TimeMillis().
std::optional<int64_t> absolute_capture_timestamp_ms_;
};
} // namespace webrtc
#endif // API_AUDIO_AUDIO_FRAME_H_

View File

@ -0,0 +1,211 @@
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/audio/audio_processing.h"
#include <string>
#include "rtc_base/checks.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
namespace {
using Agc1Config = AudioProcessing::Config::GainController1;
using Agc2Config = AudioProcessing::Config::GainController2;
std::string NoiseSuppressionLevelToString(
const AudioProcessing::Config::NoiseSuppression::Level& level) {
switch (level) {
case AudioProcessing::Config::NoiseSuppression::Level::kLow:
return "Low";
case AudioProcessing::Config::NoiseSuppression::Level::kModerate:
return "Moderate";
case AudioProcessing::Config::NoiseSuppression::Level::kHigh:
return "High";
case AudioProcessing::Config::NoiseSuppression::Level::kVeryHigh:
return "VeryHigh";
}
RTC_CHECK_NOTREACHED();
}
std::string GainController1ModeToString(const Agc1Config::Mode& mode) {
switch (mode) {
case Agc1Config::Mode::kAdaptiveAnalog:
return "AdaptiveAnalog";
case Agc1Config::Mode::kAdaptiveDigital:
return "AdaptiveDigital";
case Agc1Config::Mode::kFixedDigital:
return "FixedDigital";
}
RTC_CHECK_NOTREACHED();
}
} // namespace
constexpr int AudioProcessing::kNativeSampleRatesHz[];
void CustomProcessing::SetRuntimeSetting(
AudioProcessing::RuntimeSetting setting) {}
bool Agc1Config::operator==(const Agc1Config& rhs) const {
const auto& analog_lhs = analog_gain_controller;
const auto& analog_rhs = rhs.analog_gain_controller;
return enabled == rhs.enabled && mode == rhs.mode &&
target_level_dbfs == rhs.target_level_dbfs &&
compression_gain_db == rhs.compression_gain_db &&
enable_limiter == rhs.enable_limiter &&
analog_lhs.enabled == analog_rhs.enabled &&
analog_lhs.startup_min_volume == analog_rhs.startup_min_volume &&
analog_lhs.clipped_level_min == analog_rhs.clipped_level_min &&
analog_lhs.enable_digital_adaptive ==
analog_rhs.enable_digital_adaptive &&
analog_lhs.clipped_level_step == analog_rhs.clipped_level_step &&
analog_lhs.clipped_ratio_threshold ==
analog_rhs.clipped_ratio_threshold &&
analog_lhs.clipped_wait_frames == analog_rhs.clipped_wait_frames &&
analog_lhs.clipping_predictor.mode ==
analog_rhs.clipping_predictor.mode &&
analog_lhs.clipping_predictor.window_length ==
analog_rhs.clipping_predictor.window_length &&
analog_lhs.clipping_predictor.reference_window_length ==
analog_rhs.clipping_predictor.reference_window_length &&
analog_lhs.clipping_predictor.reference_window_delay ==
analog_rhs.clipping_predictor.reference_window_delay &&
analog_lhs.clipping_predictor.clipping_threshold ==
analog_rhs.clipping_predictor.clipping_threshold &&
analog_lhs.clipping_predictor.crest_factor_margin ==
analog_rhs.clipping_predictor.crest_factor_margin &&
analog_lhs.clipping_predictor.use_predicted_step ==
analog_rhs.clipping_predictor.use_predicted_step;
}
bool Agc2Config::AdaptiveDigital::operator==(
const Agc2Config::AdaptiveDigital& rhs) const {
return enabled == rhs.enabled && headroom_db == rhs.headroom_db &&
max_gain_db == rhs.max_gain_db &&
initial_gain_db == rhs.initial_gain_db &&
max_gain_change_db_per_second == rhs.max_gain_change_db_per_second &&
max_output_noise_level_dbfs == rhs.max_output_noise_level_dbfs;
}
bool Agc2Config::InputVolumeController::operator==(
const Agc2Config::InputVolumeController& rhs) const {
return enabled == rhs.enabled;
}
bool Agc2Config::operator==(const Agc2Config& rhs) const {
return enabled == rhs.enabled &&
fixed_digital.gain_db == rhs.fixed_digital.gain_db &&
adaptive_digital == rhs.adaptive_digital &&
input_volume_controller == rhs.input_volume_controller;
}
bool AudioProcessing::Config::CaptureLevelAdjustment::operator==(
const AudioProcessing::Config::CaptureLevelAdjustment& rhs) const {
return enabled == rhs.enabled && pre_gain_factor == rhs.pre_gain_factor &&
post_gain_factor == rhs.post_gain_factor &&
analog_mic_gain_emulation == rhs.analog_mic_gain_emulation;
}
bool AudioProcessing::Config::CaptureLevelAdjustment::AnalogMicGainEmulation::
operator==(const AudioProcessing::Config::CaptureLevelAdjustment::
AnalogMicGainEmulation& rhs) const {
return enabled == rhs.enabled && initial_level == rhs.initial_level;
}
std::string AudioProcessing::Config::ToString() const {
char buf[2048];
rtc::SimpleStringBuilder builder(buf);
builder << "AudioProcessing::Config{ "
"pipeline: { "
"maximum_internal_processing_rate: "
<< pipeline.maximum_internal_processing_rate
<< ", multi_channel_render: " << pipeline.multi_channel_render
<< ", multi_channel_capture: " << pipeline.multi_channel_capture
<< " }, pre_amplifier: { enabled: " << pre_amplifier.enabled
<< ", fixed_gain_factor: " << pre_amplifier.fixed_gain_factor
<< " },capture_level_adjustment: { enabled: "
<< capture_level_adjustment.enabled
<< ", pre_gain_factor: " << capture_level_adjustment.pre_gain_factor
<< ", post_gain_factor: " << capture_level_adjustment.post_gain_factor
<< ", analog_mic_gain_emulation: { enabled: "
<< capture_level_adjustment.analog_mic_gain_emulation.enabled
<< ", initial_level: "
<< capture_level_adjustment.analog_mic_gain_emulation.initial_level
<< " }}, high_pass_filter: { enabled: " << high_pass_filter.enabled
<< " }, echo_canceller: { enabled: " << echo_canceller.enabled
<< ", mobile_mode: " << echo_canceller.mobile_mode
<< ", enforce_high_pass_filtering: "
<< echo_canceller.enforce_high_pass_filtering
<< " }, noise_suppression: { enabled: " << noise_suppression.enabled
<< ", level: "
<< NoiseSuppressionLevelToString(noise_suppression.level)
<< " }, transient_suppression: { enabled: "
<< transient_suppression.enabled
<< " }, gain_controller1: { enabled: " << gain_controller1.enabled
<< ", mode: " << GainController1ModeToString(gain_controller1.mode)
<< ", target_level_dbfs: " << gain_controller1.target_level_dbfs
<< ", compression_gain_db: " << gain_controller1.compression_gain_db
<< ", enable_limiter: " << gain_controller1.enable_limiter
<< ", analog_gain_controller { enabled: "
<< gain_controller1.analog_gain_controller.enabled
<< ", startup_min_volume: "
<< gain_controller1.analog_gain_controller.startup_min_volume
<< ", clipped_level_min: "
<< gain_controller1.analog_gain_controller.clipped_level_min
<< ", enable_digital_adaptive: "
<< gain_controller1.analog_gain_controller.enable_digital_adaptive
<< ", clipped_level_step: "
<< gain_controller1.analog_gain_controller.clipped_level_step
<< ", clipped_ratio_threshold: "
<< gain_controller1.analog_gain_controller.clipped_ratio_threshold
<< ", clipped_wait_frames: "
<< gain_controller1.analog_gain_controller.clipped_wait_frames
<< ", clipping_predictor: { enabled: "
<< gain_controller1.analog_gain_controller.clipping_predictor.enabled
<< ", mode: "
<< gain_controller1.analog_gain_controller.clipping_predictor.mode
<< ", window_length: "
<< gain_controller1.analog_gain_controller.clipping_predictor
.window_length
<< ", reference_window_length: "
<< gain_controller1.analog_gain_controller.clipping_predictor
.reference_window_length
<< ", reference_window_delay: "
<< gain_controller1.analog_gain_controller.clipping_predictor
.reference_window_delay
<< ", clipping_threshold: "
<< gain_controller1.analog_gain_controller.clipping_predictor
.clipping_threshold
<< ", crest_factor_margin: "
<< gain_controller1.analog_gain_controller.clipping_predictor
.crest_factor_margin
<< ", use_predicted_step: "
<< gain_controller1.analog_gain_controller.clipping_predictor
.use_predicted_step
<< " }}}, gain_controller2: { enabled: " << gain_controller2.enabled
<< ", fixed_digital: { gain_db: "
<< gain_controller2.fixed_digital.gain_db
<< " }, adaptive_digital: { enabled: "
<< gain_controller2.adaptive_digital.enabled
<< ", headroom_db: " << gain_controller2.adaptive_digital.headroom_db
<< ", max_gain_db: " << gain_controller2.adaptive_digital.max_gain_db
<< ", initial_gain_db: "
<< gain_controller2.adaptive_digital.initial_gain_db
<< ", max_gain_change_db_per_second: "
<< gain_controller2.adaptive_digital.max_gain_change_db_per_second
<< ", max_output_noise_level_dbfs: "
<< gain_controller2.adaptive_digital.max_output_noise_level_dbfs
<< " }, input_volume_control : { enabled "
<< gain_controller2.input_volume_controller.enabled << "}}";
return builder.str();
}
} // namespace webrtc

View File

@ -0,0 +1,944 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_AUDIO_AUDIO_PROCESSING_H_
#define API_AUDIO_AUDIO_PROCESSING_H_
// MSVC++ requires this to be set before any other includes to get M_PI.
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif
#include <math.h>
#include <stddef.h> // size_t
#include <stdio.h> // FILE
#include <string.h>
#include <array>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include "absl/base/nullability.h"
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/audio/audio_processing_statistics.h"
#include "api/audio/echo_control.h"
#include "api/ref_count.h"
#include "api/scoped_refptr.h"
#include "api/task_queue/task_queue_base.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
class AecDump;
class AudioBuffer;
class StreamConfig;
class ProcessingConfig;
class EchoDetector;
// The Audio Processing Module (APM) provides a collection of voice processing
// components designed for real-time communications software.
//
// APM operates on two audio streams on a frame-by-frame basis. Frames of the
// primary stream, on which all processing is applied, are passed to
// `ProcessStream()`. Frames of the reverse direction stream are passed to
// `ProcessReverseStream()`. On the client-side, this will typically be the
// near-end (capture) and far-end (render) streams, respectively. APM should be
// placed in the signal chain as close to the audio hardware abstraction layer
// (HAL) as possible.
//
// On the server-side, the reverse stream will normally not be used, with
// processing occurring on each incoming stream.
//
// Component interfaces follow a similar pattern and are accessed through
// corresponding getters in APM. All components are disabled at create-time,
// with default settings that are recommended for most situations. New settings
// can be applied without enabling a component. Enabling a component triggers
// memory allocation and initialization to allow it to start processing the
// streams.
//
// Thread safety is provided with the following assumptions to reduce locking
// overhead:
// 1. The stream getters and setters are called from the same thread as
// ProcessStream(). More precisely, stream functions are never called
// concurrently with ProcessStream().
// 2. Parameter getters are never called concurrently with the corresponding
// setter.
//
// APM accepts only linear PCM audio data in chunks of ~10 ms (see
// AudioProcessing::GetFrameSize() for details) and sample rates ranging from
// 8000 Hz to 384000 Hz. The int16 interfaces use interleaved data, while the
// float interfaces use deinterleaved data.
//
// Usage example, omitting error checking:
// rtc::scoped_refptr<AudioProcessing> apm = AudioProcessingBuilder().Create();
//
// AudioProcessing::Config config;
// config.echo_canceller.enabled = true;
// config.echo_canceller.mobile_mode = false;
//
// config.gain_controller1.enabled = true;
// config.gain_controller1.mode =
// AudioProcessing::Config::GainController1::kAdaptiveAnalog;
// config.gain_controller1.analog_level_minimum = 0;
// config.gain_controller1.analog_level_maximum = 255;
//
// config.gain_controller2.enabled = true;
//
// config.high_pass_filter.enabled = true;
//
// apm->ApplyConfig(config)
//
// // Start a voice call...
//
// // ... Render frame arrives bound for the audio HAL ...
// apm->ProcessReverseStream(render_frame);
//
// // ... Capture frame arrives from the audio HAL ...
// // Call required set_stream_ functions.
// apm->set_stream_delay_ms(delay_ms);
// apm->set_stream_analog_level(analog_level);
//
// apm->ProcessStream(capture_frame);
//
// // Call required stream_ functions.
// analog_level = apm->recommended_stream_analog_level();
// has_voice = apm->stream_has_voice();
//
// // Repeat render and capture processing for the duration of the call...
// // Start a new call...
// apm->Initialize();
//
// // Close the application...
// apm.reset();
//
class RTC_EXPORT AudioProcessing : public RefCountInterface {
public:
// The struct below constitutes the new parameter scheme for the audio
// processing. It is being introduced gradually and until it is fully
// introduced, it is prone to change.
// TODO(peah): Remove this comment once the new config scheme is fully rolled
// out.
//
// The parameters and behavior of the audio processing module are controlled
// by changing the default values in the AudioProcessing::Config struct.
// The config is applied by passing the struct to the ApplyConfig method.
//
// This config is intended to be used during setup, and to enable/disable
// top-level processing effects. Use during processing may cause undesired
// submodule resets, affecting the audio quality. Use the RuntimeSetting
// construct for runtime configuration.
struct RTC_EXPORT Config {
// Sets the properties of the audio processing pipeline.
struct RTC_EXPORT Pipeline {
// Ways to downmix a multi-channel track to mono.
enum class DownmixMethod {
kAverageChannels, // Average across channels.
kUseFirstChannel // Use the first channel.
};
// Maximum allowed processing rate used internally. May only be set to
// 32000 or 48000 and any differing values will be treated as 48000.
int maximum_internal_processing_rate = 48000;
// Allow multi-channel processing of render audio.
bool multi_channel_render = false;
// Allow multi-channel processing of capture audio when AEC3 is active
// or a custom AEC is injected..
bool multi_channel_capture = false;
// Indicates how to downmix multi-channel capture audio to mono (when
// needed).
DownmixMethod capture_downmix_method = DownmixMethod::kAverageChannels;
} pipeline;
// Enabled the pre-amplifier. It amplifies the capture signal
// before any other processing is done.
// TODO(webrtc:5298): Deprecate and use the pre-gain functionality in
// capture_level_adjustment instead.
struct PreAmplifier {
bool enabled = false;
float fixed_gain_factor = 1.0f;
} pre_amplifier;
// Functionality for general level adjustment in the capture pipeline. This
// should not be used together with the legacy PreAmplifier functionality.
struct CaptureLevelAdjustment {
bool operator==(const CaptureLevelAdjustment& rhs) const;
bool operator!=(const CaptureLevelAdjustment& rhs) const {
return !(*this == rhs);
}
bool enabled = false;
// The `pre_gain_factor` scales the signal before any processing is done.
float pre_gain_factor = 1.0f;
// The `post_gain_factor` scales the signal after all processing is done.
float post_gain_factor = 1.0f;
struct AnalogMicGainEmulation {
bool operator==(const AnalogMicGainEmulation& rhs) const;
bool operator!=(const AnalogMicGainEmulation& rhs) const {
return !(*this == rhs);
}
bool enabled = false;
// Initial analog gain level to use for the emulated analog gain. Must
// be in the range [0...255].
int initial_level = 255;
} analog_mic_gain_emulation;
} capture_level_adjustment;
struct HighPassFilter {
bool enabled = false;
bool apply_in_full_band = true;
} high_pass_filter;
struct EchoCanceller {
bool enabled = false;
bool mobile_mode = false;
bool export_linear_aec_output = false;
// Enforce the highpass filter to be on (has no effect for the mobile
// mode).
bool enforce_high_pass_filtering = true;
} echo_canceller;
// Enables background noise suppression.
struct NoiseSuppression {
bool enabled = false;
enum Level { kLow, kModerate, kHigh, kVeryHigh };
Level level = kModerate;
bool analyze_linear_aec_output_when_available = false;
} noise_suppression;
// TODO(bugs.webrtc.org/357281131): Deprecated. Stop using and remove.
// Enables transient suppression.
struct TransientSuppression {
bool enabled = false;
} transient_suppression;
// Enables automatic gain control (AGC) functionality.
// The automatic gain control (AGC) component brings the signal to an
// appropriate range. This is done by applying a digital gain directly and,
// in the analog mode, prescribing an analog gain to be applied at the audio
// HAL.
// Recommended to be enabled on the client-side.
struct RTC_EXPORT GainController1 {
bool operator==(const GainController1& rhs) const;
bool operator!=(const GainController1& rhs) const {
return !(*this == rhs);
}
bool enabled = false;
enum Mode {
// Adaptive mode intended for use if an analog volume control is
// available on the capture device. It will require the user to provide
// coupling between the OS mixer controls and AGC through the
// stream_analog_level() functions.
// It consists of an analog gain prescription for the audio device and a
// digital compression stage.
kAdaptiveAnalog,
// Adaptive mode intended for situations in which an analog volume
// control is unavailable. It operates in a similar fashion to the
// adaptive analog mode, but with scaling instead applied in the digital
// domain. As with the analog mode, it additionally uses a digital
// compression stage.
kAdaptiveDigital,
// Fixed mode which enables only the digital compression stage also used
// by the two adaptive modes.
// It is distinguished from the adaptive modes by considering only a
// short time-window of the input signal. It applies a fixed gain
// through most of the input level range, and compresses (gradually
// reduces gain with increasing level) the input signal at higher
// levels. This mode is preferred on embedded devices where the capture
// signal level is predictable, so that a known gain can be applied.
kFixedDigital
};
Mode mode = kAdaptiveAnalog;
// Sets the target peak level (or envelope) of the AGC in dBFs (decibels
// from digital full-scale). The convention is to use positive values. For
// instance, passing in a value of 3 corresponds to -3 dBFs, or a target
// level 3 dB below full-scale. Limited to [0, 31].
int target_level_dbfs = 3;
// Sets the maximum gain the digital compression stage may apply, in dB. A
// higher number corresponds to greater compression, while a value of 0
// will leave the signal uncompressed. Limited to [0, 90].
// For updates after APM setup, use a RuntimeSetting instead.
int compression_gain_db = 9;
// When enabled, the compression stage will hard limit the signal to the
// target level. Otherwise, the signal will be compressed but not limited
// above the target level.
bool enable_limiter = true;
// Enables the analog gain controller functionality.
struct AnalogGainController {
bool enabled = true;
// TODO(bugs.webrtc.org/7494): Deprecated. Stop using and remove.
int startup_min_volume = 0;
// Lowest analog microphone level that will be applied in response to
// clipping.
int clipped_level_min = 70;
// If true, an adaptive digital gain is applied.
bool enable_digital_adaptive = true;
// Amount the microphone level is lowered with every clipping event.
// Limited to (0, 255].
int clipped_level_step = 15;
// Proportion of clipped samples required to declare a clipping event.
// Limited to (0.f, 1.f).
float clipped_ratio_threshold = 0.1f;
// Time in frames to wait after a clipping event before checking again.
// Limited to values higher than 0.
int clipped_wait_frames = 300;
// Enables clipping prediction functionality.
struct ClippingPredictor {
bool enabled = false;
enum Mode {
// Clipping event prediction mode with fixed step estimation.
kClippingEventPrediction,
// Clipped peak estimation mode with adaptive step estimation.
kAdaptiveStepClippingPeakPrediction,
// Clipped peak estimation mode with fixed step estimation.
kFixedStepClippingPeakPrediction,
};
Mode mode = kClippingEventPrediction;
// Number of frames in the sliding analysis window.
int window_length = 5;
// Number of frames in the sliding reference window.
int reference_window_length = 5;
// Reference window delay (unit: number of frames).
int reference_window_delay = 5;
// Clipping prediction threshold (dBFS).
float clipping_threshold = -1.0f;
// Crest factor drop threshold (dB).
float crest_factor_margin = 3.0f;
// If true, the recommended clipped level step is used to modify the
// analog gain. Otherwise, the predictor runs without affecting the
// analog gain.
bool use_predicted_step = true;
} clipping_predictor;
} analog_gain_controller;
} gain_controller1;
// Parameters for AGC2, an Automatic Gain Control (AGC) sub-module which
// replaces the AGC sub-module parametrized by `gain_controller1`.
// AGC2 brings the captured audio signal to the desired level by combining
// three different controllers (namely, input volume controller, adapative
// digital controller and fixed digital controller) and a limiter.
// TODO(bugs.webrtc.org:7494): Name `GainController` when AGC1 removed.
struct RTC_EXPORT GainController2 {
bool operator==(const GainController2& rhs) const;
bool operator!=(const GainController2& rhs) const {
return !(*this == rhs);
}
// AGC2 must be created if and only if `enabled` is true.
bool enabled = false;
// Parameters for the input volume controller, which adjusts the input
// volume applied when the audio is captured (e.g., microphone volume on
// a soundcard, input volume on HAL).
struct InputVolumeController {
bool operator==(const InputVolumeController& rhs) const;
bool operator!=(const InputVolumeController& rhs) const {
return !(*this == rhs);
}
bool enabled = false;
} input_volume_controller;
// Parameters for the adaptive digital controller, which adjusts and
// applies a digital gain after echo cancellation and after noise
// suppression.
struct RTC_EXPORT AdaptiveDigital {
bool operator==(const AdaptiveDigital& rhs) const;
bool operator!=(const AdaptiveDigital& rhs) const {
return !(*this == rhs);
}
bool enabled = false;
float headroom_db = 5.0f;
float max_gain_db = 50.0f;
float initial_gain_db = 15.0f;
float max_gain_change_db_per_second = 6.0f;
float max_output_noise_level_dbfs = -50.0f;
} adaptive_digital;
// Parameters for the fixed digital controller, which applies a fixed
// digital gain after the adaptive digital controller and before the
// limiter.
struct FixedDigital {
// By setting `gain_db` to a value greater than zero, the limiter can be
// turned into a compressor that first applies a fixed gain.
float gain_db = 0.0f;
} fixed_digital;
} gain_controller2;
std::string ToString() const;
};
// Specifies the properties of a setting to be passed to AudioProcessing at
// runtime.
class RuntimeSetting {
public:
enum class Type {
kNotSpecified,
kCapturePreGain,
kCaptureCompressionGain,
kCaptureFixedPostGain,
kPlayoutVolumeChange,
kCustomRenderProcessingRuntimeSetting,
kPlayoutAudioDeviceChange,
kCapturePostGain,
kCaptureOutputUsed
};
// Play-out audio device properties.
struct PlayoutAudioDeviceInfo {
int id; // Identifies the audio device.
int max_volume; // Maximum play-out volume.
};
RuntimeSetting() : type_(Type::kNotSpecified), value_(0.0f) {}
~RuntimeSetting() = default;
static RuntimeSetting CreateCapturePreGain(float gain) {
return {Type::kCapturePreGain, gain};
}
static RuntimeSetting CreateCapturePostGain(float gain) {
return {Type::kCapturePostGain, gain};
}
// Corresponds to Config::GainController1::compression_gain_db, but for
// runtime configuration.
static RuntimeSetting CreateCompressionGainDb(int gain_db) {
RTC_DCHECK_GE(gain_db, 0);
RTC_DCHECK_LE(gain_db, 90);
return {Type::kCaptureCompressionGain, static_cast<float>(gain_db)};
}
// Corresponds to Config::GainController2::fixed_digital::gain_db, but for
// runtime configuration.
static RuntimeSetting CreateCaptureFixedPostGain(float gain_db) {
RTC_DCHECK_GE(gain_db, 0.0f);
RTC_DCHECK_LE(gain_db, 90.0f);
return {Type::kCaptureFixedPostGain, gain_db};
}
// Creates a runtime setting to notify play-out (aka render) audio device
// changes.
static RuntimeSetting CreatePlayoutAudioDeviceChange(
PlayoutAudioDeviceInfo audio_device) {
return {Type::kPlayoutAudioDeviceChange, audio_device};
}
// Creates a runtime setting to notify play-out (aka render) volume changes.
// `volume` is the unnormalized volume, the maximum of which
static RuntimeSetting CreatePlayoutVolumeChange(int volume) {
return {Type::kPlayoutVolumeChange, volume};
}
static RuntimeSetting CreateCustomRenderSetting(float payload) {
return {Type::kCustomRenderProcessingRuntimeSetting, payload};
}
static RuntimeSetting CreateCaptureOutputUsedSetting(
bool capture_output_used) {
return {Type::kCaptureOutputUsed, capture_output_used};
}
Type type() const { return type_; }
// Getters do not return a value but instead modify the argument to protect
// from implicit casting.
void GetFloat(float* value) const {
RTC_DCHECK(value);
*value = value_.float_value;
}
void GetInt(int* value) const {
RTC_DCHECK(value);
*value = value_.int_value;
}
void GetBool(bool* value) const {
RTC_DCHECK(value);
*value = value_.bool_value;
}
void GetPlayoutAudioDeviceInfo(PlayoutAudioDeviceInfo* value) const {
RTC_DCHECK(value);
*value = value_.playout_audio_device_info;
}
private:
RuntimeSetting(Type id, float value) : type_(id), value_(value) {}
RuntimeSetting(Type id, int value) : type_(id), value_(value) {}
RuntimeSetting(Type id, PlayoutAudioDeviceInfo value)
: type_(id), value_(value) {}
Type type_;
union U {
U() {}
U(int value) : int_value(value) {}
U(float value) : float_value(value) {}
U(PlayoutAudioDeviceInfo value) : playout_audio_device_info(value) {}
float float_value;
int int_value;
bool bool_value;
PlayoutAudioDeviceInfo playout_audio_device_info;
} value_;
};
~AudioProcessing() override {}
// Initializes internal states, while retaining all user settings. This
// should be called before beginning to process a new audio stream. However,
// it is not necessary to call before processing the first stream after
// creation.
//
// It is also not necessary to call if the audio parameters (sample
// rate and number of channels) have changed. Passing updated parameters
// directly to `ProcessStream()` and `ProcessReverseStream()` is permissible.
// If the parameters are known at init-time though, they may be provided.
// TODO(webrtc:5298): Change to return void.
virtual int Initialize() = 0;
// The int16 interfaces require:
// - only `NativeRate`s be used
// - that the input, output and reverse rates must match
// - that `processing_config.output_stream()` matches
// `processing_config.input_stream()`.
//
// The float interfaces accept arbitrary rates and support differing input and
// output layouts, but the output must have either one channel or the same
// number of channels as the input.
virtual int Initialize(const ProcessingConfig& processing_config) = 0;
// TODO(peah): This method is a temporary solution used to take control
// over the parameters in the audio processing module and is likely to change.
virtual void ApplyConfig(const Config& config) = 0;
// TODO(ajm): Only intended for internal use. Make private and friend the
// necessary classes?
virtual int proc_sample_rate_hz() const = 0;
virtual int proc_split_sample_rate_hz() const = 0;
virtual size_t num_input_channels() const = 0;
virtual size_t num_proc_channels() const = 0;
virtual size_t num_output_channels() const = 0;
virtual size_t num_reverse_channels() const = 0;
// Set to true when the output of AudioProcessing will be muted or in some
// other way not used. Ideally, the captured audio would still be processed,
// but some components may change behavior based on this information.
// Default false. This method takes a lock. To achieve this in a lock-less
// manner the PostRuntimeSetting can instead be used.
virtual void set_output_will_be_muted(bool muted) = 0;
// Enqueues a runtime setting.
virtual void SetRuntimeSetting(RuntimeSetting setting) = 0;
// Enqueues a runtime setting. Returns a bool indicating whether the
// enqueueing was successfull.
virtual bool PostRuntimeSetting(RuntimeSetting setting) = 0;
// Accepts and produces a ~10 ms frame of interleaved 16 bit integer audio as
// specified in `input_config` and `output_config`. `src` and `dest` may use
// the same memory, if desired.
virtual int ProcessStream(const int16_t* const src,
const StreamConfig& input_config,
const StreamConfig& output_config,
int16_t* const dest) = 0;
// Accepts deinterleaved float audio with the range [-1, 1]. Each element of
// `src` points to a channel buffer, arranged according to `input_stream`. At
// output, the channels will be arranged according to `output_stream` in
// `dest`.
//
// The output must have one channel or as many channels as the input. `src`
// and `dest` may use the same memory, if desired.
virtual int ProcessStream(const float* const* src,
const StreamConfig& input_config,
const StreamConfig& output_config,
float* const* dest) = 0;
// Accepts and produces a ~10 ms frame of interleaved 16 bit integer audio for
// the reverse direction audio stream as specified in `input_config` and
// `output_config`. `src` and `dest` may use the same memory, if desired.
virtual int ProcessReverseStream(const int16_t* const src,
const StreamConfig& input_config,
const StreamConfig& output_config,
int16_t* const dest) = 0;
// Accepts deinterleaved float audio with the range [-1, 1]. Each element of
// `data` points to a channel buffer, arranged according to `reverse_config`.
virtual int ProcessReverseStream(const float* const* src,
const StreamConfig& input_config,
const StreamConfig& output_config,
float* const* dest) = 0;
// Accepts deinterleaved float audio with the range [-1, 1]. Each element
// of `data` points to a channel buffer, arranged according to
// `reverse_config`.
virtual int AnalyzeReverseStream(const float* const* data,
const StreamConfig& reverse_config) = 0;
// Returns the most recently produced ~10 ms of the linear AEC output at a
// rate of 16 kHz. If there is more than one capture channel, a mono
// representation of the input is returned. Returns true/false to indicate
// whether an output returned.
virtual bool GetLinearAecOutput(
rtc::ArrayView<std::array<float, 160>> linear_output) const = 0;
// This must be called prior to ProcessStream() if and only if adaptive analog
// gain control is enabled, to pass the current analog level from the audio
// HAL. Must be within the range [0, 255].
virtual void set_stream_analog_level(int level) = 0;
// When an analog mode is set, this should be called after
// `set_stream_analog_level()` and `ProcessStream()` to obtain the recommended
// new analog level for the audio HAL. It is the user's responsibility to
// apply this level.
virtual int recommended_stream_analog_level() const = 0;
// This must be called if and only if echo processing is enabled.
//
// Sets the `delay` in ms between ProcessReverseStream() receiving a far-end
// frame and ProcessStream() receiving a near-end frame containing the
// corresponding echo. On the client-side this can be expressed as
// delay = (t_render - t_analyze) + (t_process - t_capture)
// where,
// - t_analyze is the time a frame is passed to ProcessReverseStream() and
// t_render is the time the first sample of the same frame is rendered by
// the audio hardware.
// - t_capture is the time the first sample of a frame is captured by the
// audio hardware and t_process is the time the same frame is passed to
// ProcessStream().
virtual int set_stream_delay_ms(int delay) = 0;
virtual int stream_delay_ms() const = 0;
// Call to signal that a key press occurred (true) or did not occur (false)
// with this chunk of audio.
virtual void set_stream_key_pressed(bool key_pressed) = 0;
// Creates and attaches an webrtc::AecDump for recording debugging
// information.
// The `worker_queue` may not be null and must outlive the created
// AecDump instance. |max_log_size_bytes == -1| means the log size
// will be unlimited. `handle` may not be null. The AecDump takes
// responsibility for `handle` and closes it in the destructor. A
// return value of true indicates that the file has been
// sucessfully opened, while a value of false indicates that
// opening the file failed.
virtual bool CreateAndAttachAecDump(
absl::string_view file_name,
int64_t max_log_size_bytes,
absl::Nonnull<TaskQueueBase*> worker_queue) = 0;
virtual bool CreateAndAttachAecDump(
absl::Nonnull<FILE*> handle,
int64_t max_log_size_bytes,
absl::Nonnull<TaskQueueBase*> worker_queue) = 0;
// TODO(webrtc:5298) Deprecated variant.
// Attaches provided webrtc::AecDump for recording debugging
// information. Log file and maximum file size logic is supposed to
// be handled by implementing instance of AecDump. Calling this
// method when another AecDump is attached resets the active AecDump
// with a new one. This causes the d-tor of the earlier AecDump to
// be called. The d-tor call may block until all pending logging
// tasks are completed.
virtual void AttachAecDump(std::unique_ptr<AecDump> aec_dump) = 0;
// If no AecDump is attached, this has no effect. If an AecDump is
// attached, it's destructor is called. The d-tor may block until
// all pending logging tasks are completed.
virtual void DetachAecDump() = 0;
// Get audio processing statistics.
virtual AudioProcessingStats GetStatistics() = 0;
// TODO(webrtc:5298) Deprecated variant. The `has_remote_tracks` argument
// should be set if there are active remote tracks (this would usually be true
// during a call). If there are no remote tracks some of the stats will not be
// set by AudioProcessing, because they only make sense if there is at least
// one remote track.
virtual AudioProcessingStats GetStatistics(bool has_remote_tracks) = 0;
// Returns the last applied configuration.
virtual AudioProcessing::Config GetConfig() const = 0;
enum Error {
// Fatal errors.
kNoError = 0,
kUnspecifiedError = -1,
kCreationFailedError = -2,
kUnsupportedComponentError = -3,
kUnsupportedFunctionError = -4,
kNullPointerError = -5,
kBadParameterError = -6,
kBadSampleRateError = -7,
kBadDataLengthError = -8,
kBadNumberChannelsError = -9,
kFileError = -10,
kStreamParameterNotSetError = -11,
kNotEnabledError = -12,
// Warnings are non-fatal.
// This results when a set_stream_ parameter is out of range. Processing
// will continue, but the parameter may have been truncated.
kBadStreamParameterWarning = -13
};
// Native rates supported by the integer interfaces.
enum NativeRate {
kSampleRate8kHz = 8000,
kSampleRate16kHz = 16000,
kSampleRate32kHz = 32000,
kSampleRate48kHz = 48000
};
// TODO(kwiberg): We currently need to support a compiler (Visual C++) that
// complains if we don't explicitly state the size of the array here. Remove
// the size when that's no longer the case.
static constexpr int kNativeSampleRatesHz[4] = {
kSampleRate8kHz, kSampleRate16kHz, kSampleRate32kHz, kSampleRate48kHz};
static constexpr size_t kNumNativeSampleRates =
arraysize(kNativeSampleRatesHz);
static constexpr int kMaxNativeSampleRateHz =
kNativeSampleRatesHz[kNumNativeSampleRates - 1];
// APM processes audio in chunks of about 10 ms. See GetFrameSize() for
// details.
static constexpr int kChunkSizeMs = 10;
// Returns floor(sample_rate_hz/100): the number of samples per channel used
// as input and output to the audio processing module in calls to
// ProcessStream, ProcessReverseStream, AnalyzeReverseStream, and
// GetLinearAecOutput.
//
// This is exactly 10 ms for sample rates divisible by 100. For example:
// - 48000 Hz (480 samples per channel),
// - 44100 Hz (441 samples per channel),
// - 16000 Hz (160 samples per channel).
//
// Sample rates not divisible by 100 are received/produced in frames of
// approximately 10 ms. For example:
// - 22050 Hz (220 samples per channel, or ~9.98 ms per frame),
// - 11025 Hz (110 samples per channel, or ~9.98 ms per frame).
// These nondivisible sample rates yield lower audio quality compared to
// multiples of 100. Internal resampling to 10 ms frames causes a simulated
// clock drift effect which impacts the performance of (for example) echo
// cancellation.
static int GetFrameSize(int sample_rate_hz) { return sample_rate_hz / 100; }
};
// Experimental interface for a custom analysis submodule.
class CustomAudioAnalyzer {
public:
// (Re-) Initializes the submodule.
virtual void Initialize(int sample_rate_hz, int num_channels) = 0;
// Analyzes the given capture or render signal.
virtual void Analyze(const AudioBuffer* audio) = 0;
// Returns a string representation of the module state.
virtual std::string ToString() const = 0;
virtual ~CustomAudioAnalyzer() {}
};
// Interface for a custom processing submodule.
class CustomProcessing {
public:
// (Re-)Initializes the submodule.
virtual void Initialize(int sample_rate_hz, int num_channels) = 0;
// Processes the given capture or render signal.
virtual void Process(AudioBuffer* audio) = 0;
// Returns a string representation of the module state.
virtual std::string ToString() const = 0;
// Handles RuntimeSettings. TODO(webrtc:9262): make pure virtual
// after updating dependencies.
virtual void SetRuntimeSetting(AudioProcessing::RuntimeSetting setting);
virtual ~CustomProcessing() {}
};
class RTC_EXPORT AudioProcessingBuilder {
public:
AudioProcessingBuilder();
AudioProcessingBuilder(const AudioProcessingBuilder&) = delete;
AudioProcessingBuilder& operator=(const AudioProcessingBuilder&) = delete;
~AudioProcessingBuilder();
// Sets the APM configuration.
AudioProcessingBuilder& SetConfig(const AudioProcessing::Config& config) {
config_ = config;
return *this;
}
// Sets the echo controller factory to inject when APM is created.
AudioProcessingBuilder& SetEchoControlFactory(
std::unique_ptr<EchoControlFactory> echo_control_factory) {
echo_control_factory_ = std::move(echo_control_factory);
return *this;
}
// Sets the capture post-processing sub-module to inject when APM is created.
AudioProcessingBuilder& SetCapturePostProcessing(
std::unique_ptr<CustomProcessing> capture_post_processing) {
capture_post_processing_ = std::move(capture_post_processing);
return *this;
}
// Sets the render pre-processing sub-module to inject when APM is created.
AudioProcessingBuilder& SetRenderPreProcessing(
std::unique_ptr<CustomProcessing> render_pre_processing) {
render_pre_processing_ = std::move(render_pre_processing);
return *this;
}
// Sets the echo detector to inject when APM is created.
AudioProcessingBuilder& SetEchoDetector(
rtc::scoped_refptr<EchoDetector> echo_detector) {
echo_detector_ = std::move(echo_detector);
return *this;
}
// Sets the capture analyzer sub-module to inject when APM is created.
AudioProcessingBuilder& SetCaptureAnalyzer(
std::unique_ptr<CustomAudioAnalyzer> capture_analyzer) {
capture_analyzer_ = std::move(capture_analyzer);
return *this;
}
// Creates an APM instance with the specified config or the default one if
// unspecified. Injects the specified components transferring the ownership
// to the newly created APM instance - i.e., except for the config, the
// builder is reset to its initial state.
rtc::scoped_refptr<AudioProcessing> Create();
private:
AudioProcessing::Config config_;
std::unique_ptr<EchoControlFactory> echo_control_factory_;
std::unique_ptr<CustomProcessing> capture_post_processing_;
std::unique_ptr<CustomProcessing> render_pre_processing_;
rtc::scoped_refptr<EchoDetector> echo_detector_;
std::unique_ptr<CustomAudioAnalyzer> capture_analyzer_;
};
class StreamConfig {
public:
// sample_rate_hz: The sampling rate of the stream.
// num_channels: The number of audio channels in the stream.
StreamConfig(int sample_rate_hz = 0,
size_t num_channels = 0) // NOLINT(runtime/explicit)
: sample_rate_hz_(sample_rate_hz),
num_channels_(num_channels),
num_frames_(calculate_frames(sample_rate_hz)) {}
void set_sample_rate_hz(int value) {
sample_rate_hz_ = value;
num_frames_ = calculate_frames(value);
}
void set_num_channels(size_t value) { num_channels_ = value; }
int sample_rate_hz() const { return sample_rate_hz_; }
// The number of channels in the stream.
size_t num_channels() const { return num_channels_; }
size_t num_frames() const { return num_frames_; }
size_t num_samples() const { return num_channels_ * num_frames_; }
bool operator==(const StreamConfig& other) const {
return sample_rate_hz_ == other.sample_rate_hz_ &&
num_channels_ == other.num_channels_;
}
bool operator!=(const StreamConfig& other) const { return !(*this == other); }
private:
static size_t calculate_frames(int sample_rate_hz) {
return static_cast<size_t>(AudioProcessing::GetFrameSize(sample_rate_hz));
}
int sample_rate_hz_;
size_t num_channels_;
size_t num_frames_;
};
class ProcessingConfig {
public:
enum StreamName {
kInputStream,
kOutputStream,
kReverseInputStream,
kReverseOutputStream,
kNumStreamNames,
};
const StreamConfig& input_stream() const {
return streams[StreamName::kInputStream];
}
const StreamConfig& output_stream() const {
return streams[StreamName::kOutputStream];
}
const StreamConfig& reverse_input_stream() const {
return streams[StreamName::kReverseInputStream];
}
const StreamConfig& reverse_output_stream() const {
return streams[StreamName::kReverseOutputStream];
}
StreamConfig& input_stream() { return streams[StreamName::kInputStream]; }
StreamConfig& output_stream() { return streams[StreamName::kOutputStream]; }
StreamConfig& reverse_input_stream() {
return streams[StreamName::kReverseInputStream];
}
StreamConfig& reverse_output_stream() {
return streams[StreamName::kReverseOutputStream];
}
bool operator==(const ProcessingConfig& other) const {
for (int i = 0; i < StreamName::kNumStreamNames; ++i) {
if (this->streams[i] != other.streams[i]) {
return false;
}
}
return true;
}
bool operator!=(const ProcessingConfig& other) const {
return !(*this == other);
}
StreamConfig streams[StreamName::kNumStreamNames];
};
// Interface for an echo detector submodule.
class EchoDetector : public RefCountInterface {
public:
// (Re-)Initializes the submodule.
virtual void Initialize(int capture_sample_rate_hz,
int num_capture_channels,
int render_sample_rate_hz,
int num_render_channels) = 0;
// Analysis (not changing) of the first channel of the render signal.
virtual void AnalyzeRenderAudio(rtc::ArrayView<const float> render_audio) = 0;
// Analysis (not changing) of the capture signal.
virtual void AnalyzeCaptureAudio(
rtc::ArrayView<const float> capture_audio) = 0;
struct Metrics {
std::optional<double> echo_likelihood;
std::optional<double> echo_likelihood_recent_max;
};
// Collect current metrics from the echo detector.
virtual Metrics GetMetrics() const = 0;
};
} // namespace webrtc
#endif // API_AUDIO_AUDIO_PROCESSING_H_

View File

@ -0,0 +1,22 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/audio/audio_processing_statistics.h"
namespace webrtc {
AudioProcessingStats::AudioProcessingStats() = default;
AudioProcessingStats::AudioProcessingStats(const AudioProcessingStats& other) =
default;
AudioProcessingStats::~AudioProcessingStats() = default;
} // namespace webrtc

View File

@ -0,0 +1,68 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_AUDIO_AUDIO_PROCESSING_STATISTICS_H_
#define API_AUDIO_AUDIO_PROCESSING_STATISTICS_H_
#include <stdint.h>
#include <optional>
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
// This version of the stats uses Optionals, it will replace the regular
// AudioProcessingStatistics struct.
struct RTC_EXPORT AudioProcessingStats {
AudioProcessingStats();
AudioProcessingStats(const AudioProcessingStats& other);
~AudioProcessingStats();
// Deprecated.
// TODO(bugs.webrtc.org/11226): Remove.
// True if voice is detected in the last capture frame, after processing.
// It is conservative in flagging audio as speech, with low likelihood of
// incorrectly flagging a frame as voice.
// Only reported if voice detection is enabled in AudioProcessing::Config.
std::optional<bool> voice_detected;
// AEC Statistics.
// ERL = 10log_10(P_far / P_echo)
std::optional<double> echo_return_loss;
// ERLE = 10log_10(P_echo / P_out)
std::optional<double> echo_return_loss_enhancement;
// Fraction of time that the AEC linear filter is divergent, in a 1-second
// non-overlapped aggregation window.
std::optional<double> divergent_filter_fraction;
// The delay metrics consists of the delay median and standard deviation. It
// also consists of the fraction of delay estimates that can make the echo
// cancellation perform poorly. The values are aggregated until the first
// call to `GetStatistics()` and afterwards aggregated and updated every
// second. Note that if there are several clients pulling metrics from
// `GetStatistics()` during a session the first call from any of them will
// change to one second aggregation window for all.
std::optional<int32_t> delay_median_ms;
std::optional<int32_t> delay_standard_deviation_ms;
// Residual echo detector likelihood.
std::optional<double> residual_echo_likelihood;
// Maximum residual echo likelihood from the last time period.
std::optional<double> residual_echo_likelihood_recent_max;
// The instantaneous delay estimate produced in the AEC. The unit is in
// milliseconds and the value is the instantaneous value at the time of the
// call to `GetStatistics()`.
std::optional<int32_t> delay_ms;
};
} // namespace webrtc
#endif // API_AUDIO_AUDIO_PROCESSING_STATISTICS_H_

View File

@ -0,0 +1,269 @@
/*
* Copyright (c) 2024 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_AUDIO_AUDIO_VIEW_H_
#define API_AUDIO_AUDIO_VIEW_H_
#include "api/array_view.h"
#include "api/audio/channel_layout.h"
#include "rtc_base/checks.h"
namespace webrtc {
// This file contains 3 types of view classes:
//
// * MonoView<>: A single channel contiguous buffer of samples.
//
// * InterleavedView<>: Channel samples are interleaved (side-by-side) in
// the buffer. A single channel InterleavedView<> is the same thing as a
// MonoView<>
//
// * DeinterleavedView<>: Each channel's samples are contiguous within the
// buffer. Channels can be enumerated and accessing the individual channel
// data is done via MonoView<>.
//
// The views are comparable to and built on rtc::ArrayView<> but add
// audio specific properties for the dimensions of the buffer and the above
// specialized [de]interleaved support.
//
// There are also a few generic utility functions that can simplify
// generic code for supporting more than one type of view.
// MonoView<> represents a view over a single contiguous, audio buffer. This
// can be either an single channel (mono) interleaved buffer (e.g. AudioFrame),
// or a de-interleaved channel (e.g. from AudioBuffer).
template <typename T>
using MonoView = rtc::ArrayView<T>;
// InterleavedView<> is a view over an interleaved audio buffer (e.g. from
// AudioFrame).
template <typename T>
class InterleavedView {
public:
using value_type = T;
InterleavedView() = default;
template <typename U>
InterleavedView(U* data, size_t samples_per_channel, size_t num_channels)
: num_channels_(num_channels),
samples_per_channel_(samples_per_channel),
data_(data, num_channels * samples_per_channel) {
RTC_DCHECK_LE(num_channels_, kMaxConcurrentChannels);
RTC_DCHECK(num_channels_ == 0u || samples_per_channel_ != 0u);
}
// Construct an InterleavedView from a C-style array. Samples per channels
// is calculated based on the array size / num_channels.
template <typename U, size_t N>
InterleavedView(U (&array)[N], // NOLINT
size_t num_channels)
: InterleavedView(array, N / num_channels, num_channels) {
RTC_DCHECK_EQ(N % num_channels, 0u);
}
template <typename U>
InterleavedView(const InterleavedView<U>& other)
: num_channels_(other.num_channels()),
samples_per_channel_(other.samples_per_channel()),
data_(other.data()) {}
size_t num_channels() const { return num_channels_; }
size_t samples_per_channel() const { return samples_per_channel_; }
rtc::ArrayView<T> data() const { return data_; }
bool empty() const { return data_.empty(); }
size_t size() const { return data_.size(); }
MonoView<T> AsMono() const {
RTC_DCHECK_EQ(num_channels(), 1u);
RTC_DCHECK_EQ(data_.size(), samples_per_channel_);
return data_;
}
// A simple wrapper around memcpy that includes checks for properties.
// TODO(tommi): Consider if this can be utility function for both interleaved
// and deinterleaved views.
template <typename U>
void CopyFrom(const InterleavedView<U>& source) {
static_assert(sizeof(T) == sizeof(U), "");
RTC_DCHECK_EQ(num_channels(), source.num_channels());
RTC_DCHECK_EQ(samples_per_channel(), source.samples_per_channel());
RTC_DCHECK_GE(data_.size(), source.data().size());
const auto data = source.data();
memcpy(&data_[0], &data[0], data.size() * sizeof(U));
}
T& operator[](size_t idx) const { return data_[idx]; }
T* begin() const { return data_.begin(); }
T* end() const { return data_.end(); }
const T* cbegin() const { return data_.cbegin(); }
const T* cend() const { return data_.cend(); }
std::reverse_iterator<T*> rbegin() const { return data_.rbegin(); }
std::reverse_iterator<T*> rend() const { return data_.rend(); }
std::reverse_iterator<const T*> crbegin() const { return data_.crbegin(); }
std::reverse_iterator<const T*> crend() const { return data_.crend(); }
private:
// TODO(tommi): Consider having these both be stored as uint16_t to
// save a few bytes per view. Use `dchecked_cast` to support size_t during
// construction.
size_t num_channels_ = 0u;
size_t samples_per_channel_ = 0u;
rtc::ArrayView<T> data_;
};
template <typename T>
class DeinterleavedView {
public:
using value_type = T;
DeinterleavedView() = default;
template <typename U>
DeinterleavedView(U* data, size_t samples_per_channel, size_t num_channels)
: num_channels_(num_channels),
samples_per_channel_(samples_per_channel),
data_(data, num_channels * samples_per_channel_) {}
template <typename U>
DeinterleavedView(const DeinterleavedView<U>& other)
: num_channels_(other.num_channels()),
samples_per_channel_(other.samples_per_channel()),
data_(other.data()) {}
// Returns a deinterleaved channel where `idx` is the zero based index,
// in the range [0 .. num_channels()-1].
MonoView<T> operator[](size_t idx) const {
RTC_DCHECK_LT(idx, num_channels_);
return MonoView<T>(&data_[idx * samples_per_channel_],
samples_per_channel_);
}
size_t num_channels() const { return num_channels_; }
size_t samples_per_channel() const { return samples_per_channel_; }
rtc::ArrayView<T> data() const { return data_; }
bool empty() const { return data_.empty(); }
size_t size() const { return data_.size(); }
// Returns the first (and possibly only) channel.
MonoView<T> AsMono() const {
RTC_DCHECK_GE(num_channels(), 1u);
return (*this)[0];
}
private:
// TODO(tommi): Consider having these be stored as uint16_t to save a few
// bytes per view. Use `dchecked_cast` to support size_t during construction.
size_t num_channels_ = 0u;
size_t samples_per_channel_ = 0u;
rtc::ArrayView<T> data_;
};
template <typename T>
constexpr size_t NumChannels(const MonoView<T>& view) {
return 1u;
}
template <typename T>
size_t NumChannels(const InterleavedView<T>& view) {
return view.num_channels();
}
template <typename T>
size_t NumChannels(const DeinterleavedView<T>& view) {
return view.num_channels();
}
template <typename T>
constexpr bool IsMono(const MonoView<T>& view) {
return true;
}
template <typename T>
constexpr bool IsInterleavedView(const MonoView<T>& view) {
return true;
}
template <typename T>
constexpr bool IsInterleavedView(const InterleavedView<T>& view) {
return true;
}
template <typename T>
constexpr bool IsInterleavedView(const DeinterleavedView<const T>& view) {
return false;
}
template <typename T>
bool IsMono(const InterleavedView<T>& view) {
return NumChannels(view) == 1u;
}
template <typename T>
bool IsMono(const DeinterleavedView<T>& view) {
return NumChannels(view) == 1u;
}
template <typename T>
size_t SamplesPerChannel(const MonoView<T>& view) {
return view.size();
}
template <typename T>
size_t SamplesPerChannel(const InterleavedView<T>& view) {
return view.samples_per_channel();
}
template <typename T>
size_t SamplesPerChannel(const DeinterleavedView<T>& view) {
return view.samples_per_channel();
}
// A simple wrapper around memcpy that includes checks for properties.
// The parameter order is the same as for memcpy(), first destination then
// source.
template <typename D, typename S>
void CopySamples(D& destination, const S& source) {
static_assert(
sizeof(typename D::value_type) == sizeof(typename S::value_type), "");
// Here we'd really like to do
// static_assert(IsInterleavedView(destination) == IsInterleavedView(source),
// "");
// but the compiler doesn't like it inside this template function for
// some reason. The following check is an approximation but unfortunately
// means that copying between a MonoView and single channel interleaved or
// deinterleaved views wouldn't work.
// static_assert(sizeof(destination) == sizeof(source),
// "Incompatible view types");
RTC_DCHECK_EQ(NumChannels(destination), NumChannels(source));
RTC_DCHECK_EQ(SamplesPerChannel(destination), SamplesPerChannel(source));
RTC_DCHECK_GE(destination.size(), source.size());
memcpy(&destination[0], &source[0],
source.size() * sizeof(typename S::value_type));
}
// Sets all the samples in a view to 0. This template function is a simple
// wrapper around `memset()` but adds the benefit of automatically calculating
// the byte size from the number of samples and sample type.
template <typename T>
void ClearSamples(T& view) {
memset(&view[0], 0, view.size() * sizeof(typename T::value_type));
}
// Same as `ClearSamples()` above but allows for clearing only the first
// `sample_count` number of samples.
template <typename T>
void ClearSamples(T& view, size_t sample_count) {
RTC_DCHECK_LE(sample_count, view.size());
memset(&view[0], 0, sample_count * sizeof(typename T::value_type));
}
} // namespace webrtc
#endif // API_AUDIO_AUDIO_VIEW_H_

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_DCHECK_NOTREACHED() << "Invalid channel layout provided: " << layout;
return "";
}
} // namespace webrtc

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,278 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/audio/echo_canceller3_config.h"
#include <algorithm>
#include <cmath>
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_minmax.h"
namespace webrtc {
namespace {
bool Limit(float* value, float min, float max) {
float clamped = rtc::SafeClamp(*value, min, max);
clamped = std::isfinite(clamped) ? clamped : min;
bool res = *value == clamped;
*value = clamped;
return res;
}
bool Limit(size_t* value, size_t min, size_t max) {
size_t clamped = rtc::SafeClamp(*value, min, max);
bool res = *value == clamped;
*value = clamped;
return res;
}
bool Limit(int* value, int min, int max) {
int clamped = rtc::SafeClamp(*value, min, max);
bool res = *value == clamped;
*value = clamped;
return res;
}
bool FloorLimit(size_t* value, size_t min) {
size_t clamped = *value >= min ? *value : min;
bool res = *value == clamped;
*value = clamped;
return res;
}
} // namespace
EchoCanceller3Config::EchoCanceller3Config() = default;
EchoCanceller3Config::EchoCanceller3Config(const EchoCanceller3Config& e) =
default;
EchoCanceller3Config& EchoCanceller3Config::operator=(
const EchoCanceller3Config& e) = default;
EchoCanceller3Config::Delay::Delay() = default;
EchoCanceller3Config::Delay::Delay(const EchoCanceller3Config::Delay& e) =
default;
EchoCanceller3Config::Delay& EchoCanceller3Config::Delay::operator=(
const Delay& e) = default;
EchoCanceller3Config::EchoModel::EchoModel() = default;
EchoCanceller3Config::EchoModel::EchoModel(
const EchoCanceller3Config::EchoModel& e) = default;
EchoCanceller3Config::EchoModel& EchoCanceller3Config::EchoModel::operator=(
const EchoModel& e) = default;
EchoCanceller3Config::Suppressor::Suppressor() = default;
EchoCanceller3Config::Suppressor::Suppressor(
const EchoCanceller3Config::Suppressor& e) = default;
EchoCanceller3Config::Suppressor& EchoCanceller3Config::Suppressor::operator=(
const Suppressor& e) = default;
EchoCanceller3Config::Suppressor::MaskingThresholds::MaskingThresholds(
float enr_transparent,
float enr_suppress,
float emr_transparent)
: enr_transparent(enr_transparent),
enr_suppress(enr_suppress),
emr_transparent(emr_transparent) {}
EchoCanceller3Config::Suppressor::MaskingThresholds::MaskingThresholds(
const EchoCanceller3Config::Suppressor::MaskingThresholds& e) = default;
EchoCanceller3Config::Suppressor::MaskingThresholds&
EchoCanceller3Config::Suppressor::MaskingThresholds::operator=(
const MaskingThresholds& e) = default;
EchoCanceller3Config::Suppressor::Tuning::Tuning(MaskingThresholds mask_lf,
MaskingThresholds mask_hf,
float max_inc_factor,
float max_dec_factor_lf)
: mask_lf(mask_lf),
mask_hf(mask_hf),
max_inc_factor(max_inc_factor),
max_dec_factor_lf(max_dec_factor_lf) {}
EchoCanceller3Config::Suppressor::Tuning::Tuning(
const EchoCanceller3Config::Suppressor::Tuning& e) = default;
EchoCanceller3Config::Suppressor::Tuning&
EchoCanceller3Config::Suppressor::Tuning::operator=(const Tuning& e) = default;
bool EchoCanceller3Config::Validate(EchoCanceller3Config* config) {
RTC_DCHECK(config);
EchoCanceller3Config* c = config;
bool res = true;
if (c->delay.down_sampling_factor != 4 &&
c->delay.down_sampling_factor != 8) {
c->delay.down_sampling_factor = 4;
res = false;
}
res = res & Limit(&c->delay.default_delay, 0, 5000);
res = res & Limit(&c->delay.num_filters, 0, 5000);
res = res & Limit(&c->delay.delay_headroom_samples, 0, 5000);
res = res & Limit(&c->delay.hysteresis_limit_blocks, 0, 5000);
res = res & Limit(&c->delay.fixed_capture_delay_samples, 0, 5000);
res = res & Limit(&c->delay.delay_estimate_smoothing, 0.f, 1.f);
res = res & Limit(&c->delay.delay_candidate_detection_threshold, 0.f, 1.f);
res = res & Limit(&c->delay.delay_selection_thresholds.initial, 1, 250);
res = res & Limit(&c->delay.delay_selection_thresholds.converged, 1, 250);
res = res & FloorLimit(&c->filter.refined.length_blocks, 1);
res = res & Limit(&c->filter.refined.leakage_converged, 0.f, 1000.f);
res = res & Limit(&c->filter.refined.leakage_diverged, 0.f, 1000.f);
res = res & Limit(&c->filter.refined.error_floor, 0.f, 1000.f);
res = res & Limit(&c->filter.refined.error_ceil, 0.f, 100000000.f);
res = res & Limit(&c->filter.refined.noise_gate, 0.f, 100000000.f);
res = res & FloorLimit(&c->filter.refined_initial.length_blocks, 1);
res = res & Limit(&c->filter.refined_initial.leakage_converged, 0.f, 1000.f);
res = res & Limit(&c->filter.refined_initial.leakage_diverged, 0.f, 1000.f);
res = res & Limit(&c->filter.refined_initial.error_floor, 0.f, 1000.f);
res = res & Limit(&c->filter.refined_initial.error_ceil, 0.f, 100000000.f);
res = res & Limit(&c->filter.refined_initial.noise_gate, 0.f, 100000000.f);
if (c->filter.refined.length_blocks <
c->filter.refined_initial.length_blocks) {
c->filter.refined_initial.length_blocks = c->filter.refined.length_blocks;
res = false;
}
res = res & FloorLimit(&c->filter.coarse.length_blocks, 1);
res = res & Limit(&c->filter.coarse.rate, 0.f, 1.f);
res = res & Limit(&c->filter.coarse.noise_gate, 0.f, 100000000.f);
res = res & FloorLimit(&c->filter.coarse_initial.length_blocks, 1);
res = res & Limit(&c->filter.coarse_initial.rate, 0.f, 1.f);
res = res & Limit(&c->filter.coarse_initial.noise_gate, 0.f, 100000000.f);
if (c->filter.coarse.length_blocks < c->filter.coarse_initial.length_blocks) {
c->filter.coarse_initial.length_blocks = c->filter.coarse.length_blocks;
res = false;
}
res = res & Limit(&c->filter.config_change_duration_blocks, 0, 100000);
res = res & Limit(&c->filter.initial_state_seconds, 0.f, 100.f);
res = res & Limit(&c->filter.coarse_reset_hangover_blocks, 0, 250000);
res = res & Limit(&c->erle.min, 1.f, 100000.f);
res = res & Limit(&c->erle.max_l, 1.f, 100000.f);
res = res & Limit(&c->erle.max_h, 1.f, 100000.f);
if (c->erle.min > c->erle.max_l || c->erle.min > c->erle.max_h) {
c->erle.min = std::min(c->erle.max_l, c->erle.max_h);
res = false;
}
res = res & Limit(&c->erle.num_sections, 1, c->filter.refined.length_blocks);
res = res & Limit(&c->ep_strength.default_gain, 0.f, 1000000.f);
res = res & Limit(&c->ep_strength.default_len, -1.f, 1.f);
res = res & Limit(&c->ep_strength.nearend_len, -1.0f, 1.0f);
res =
res & Limit(&c->echo_audibility.low_render_limit, 0.f, 32768.f * 32768.f);
res = res &
Limit(&c->echo_audibility.normal_render_limit, 0.f, 32768.f * 32768.f);
res = res & Limit(&c->echo_audibility.floor_power, 0.f, 32768.f * 32768.f);
res = res & Limit(&c->echo_audibility.audibility_threshold_lf, 0.f,
32768.f * 32768.f);
res = res & Limit(&c->echo_audibility.audibility_threshold_mf, 0.f,
32768.f * 32768.f);
res = res & Limit(&c->echo_audibility.audibility_threshold_hf, 0.f,
32768.f * 32768.f);
res = res &
Limit(&c->render_levels.active_render_limit, 0.f, 32768.f * 32768.f);
res = res & Limit(&c->render_levels.poor_excitation_render_limit, 0.f,
32768.f * 32768.f);
res = res & Limit(&c->render_levels.poor_excitation_render_limit_ds8, 0.f,
32768.f * 32768.f);
res = res & Limit(&c->echo_model.noise_floor_hold, 0, 1000);
res = res & Limit(&c->echo_model.min_noise_floor_power, 0, 2000000.f);
res = res & Limit(&c->echo_model.stationary_gate_slope, 0, 1000000.f);
res = res & Limit(&c->echo_model.noise_gate_power, 0, 1000000.f);
res = res & Limit(&c->echo_model.noise_gate_slope, 0, 1000000.f);
res = res & Limit(&c->echo_model.render_pre_window_size, 0, 100);
res = res & Limit(&c->echo_model.render_post_window_size, 0, 100);
res = res & Limit(&c->comfort_noise.noise_floor_dbfs, -200.f, 0.f);
res = res & Limit(&c->suppressor.nearend_average_blocks, 1, 5000);
res = res &
Limit(&c->suppressor.normal_tuning.mask_lf.enr_transparent, 0.f, 100.f);
res = res &
Limit(&c->suppressor.normal_tuning.mask_lf.enr_suppress, 0.f, 100.f);
res = res &
Limit(&c->suppressor.normal_tuning.mask_lf.emr_transparent, 0.f, 100.f);
res = res &
Limit(&c->suppressor.normal_tuning.mask_hf.enr_transparent, 0.f, 100.f);
res = res &
Limit(&c->suppressor.normal_tuning.mask_hf.enr_suppress, 0.f, 100.f);
res = res &
Limit(&c->suppressor.normal_tuning.mask_hf.emr_transparent, 0.f, 100.f);
res = res & Limit(&c->suppressor.normal_tuning.max_inc_factor, 0.f, 100.f);
res = res & Limit(&c->suppressor.normal_tuning.max_dec_factor_lf, 0.f, 100.f);
res = res & Limit(&c->suppressor.nearend_tuning.mask_lf.enr_transparent, 0.f,
100.f);
res = res &
Limit(&c->suppressor.nearend_tuning.mask_lf.enr_suppress, 0.f, 100.f);
res = res & Limit(&c->suppressor.nearend_tuning.mask_lf.emr_transparent, 0.f,
100.f);
res = res & Limit(&c->suppressor.nearend_tuning.mask_hf.enr_transparent, 0.f,
100.f);
res = res &
Limit(&c->suppressor.nearend_tuning.mask_hf.enr_suppress, 0.f, 100.f);
res = res & Limit(&c->suppressor.nearend_tuning.mask_hf.emr_transparent, 0.f,
100.f);
res = res & Limit(&c->suppressor.nearend_tuning.max_inc_factor, 0.f, 100.f);
res =
res & Limit(&c->suppressor.nearend_tuning.max_dec_factor_lf, 0.f, 100.f);
res = res & Limit(&c->suppressor.last_permanent_lf_smoothing_band, 0, 64);
res = res & Limit(&c->suppressor.last_lf_smoothing_band, 0, 64);
res = res & Limit(&c->suppressor.last_lf_band, 0, 63);
res = res &
Limit(&c->suppressor.first_hf_band, c->suppressor.last_lf_band + 1, 64);
res = res & Limit(&c->suppressor.dominant_nearend_detection.enr_threshold,
0.f, 1000000.f);
res = res & Limit(&c->suppressor.dominant_nearend_detection.snr_threshold,
0.f, 1000000.f);
res = res & Limit(&c->suppressor.dominant_nearend_detection.hold_duration, 0,
10000);
res = res & Limit(&c->suppressor.dominant_nearend_detection.trigger_threshold,
0, 10000);
res = res &
Limit(&c->suppressor.subband_nearend_detection.nearend_average_blocks,
1, 1024);
res =
res & Limit(&c->suppressor.subband_nearend_detection.subband1.low, 0, 65);
res = res & Limit(&c->suppressor.subband_nearend_detection.subband1.high,
c->suppressor.subband_nearend_detection.subband1.low, 65);
res =
res & Limit(&c->suppressor.subband_nearend_detection.subband2.low, 0, 65);
res = res & Limit(&c->suppressor.subband_nearend_detection.subband2.high,
c->suppressor.subband_nearend_detection.subband2.low, 65);
res = res & Limit(&c->suppressor.subband_nearend_detection.nearend_threshold,
0.f, 1.e24f);
res = res & Limit(&c->suppressor.subband_nearend_detection.snr_threshold, 0.f,
1.e24f);
res = res & Limit(&c->suppressor.high_bands_suppression.enr_threshold, 0.f,
1000000.f);
res = res & Limit(&c->suppressor.high_bands_suppression.max_gain_during_echo,
0.f, 1.f);
res = res & Limit(&c->suppressor.high_bands_suppression
.anti_howling_activation_threshold,
0.f, 32768.f * 32768.f);
res = res & Limit(&c->suppressor.high_bands_suppression.anti_howling_gain,
0.f, 1.f);
res = res & Limit(&c->suppressor.floor_first_increase, 0.f, 1000000.f);
return res;
}
} // namespace webrtc

View File

@ -0,0 +1,250 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_AUDIO_ECHO_CANCELLER3_CONFIG_H_
#define API_AUDIO_ECHO_CANCELLER3_CONFIG_H_
#include <stddef.h> // size_t
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
// Configuration struct for EchoCanceller3
struct RTC_EXPORT EchoCanceller3Config {
// Checks and updates the config parameters to lie within (mostly) reasonable
// ranges. Returns true if and only of the config did not need to be changed.
static bool Validate(EchoCanceller3Config* config);
EchoCanceller3Config();
EchoCanceller3Config(const EchoCanceller3Config& e);
EchoCanceller3Config& operator=(const EchoCanceller3Config& other);
struct Buffering {
size_t excess_render_detection_interval_blocks = 250;
size_t max_allowed_excess_render_blocks = 8;
} buffering;
struct Delay {
Delay();
Delay(const Delay& e);
Delay& operator=(const Delay& e);
size_t default_delay = 5;
size_t down_sampling_factor = 4;
size_t num_filters = 5;
size_t delay_headroom_samples = 32;
size_t hysteresis_limit_blocks = 1;
size_t fixed_capture_delay_samples = 0;
float delay_estimate_smoothing = 0.7f;
float delay_estimate_smoothing_delay_found = 0.7f;
float delay_candidate_detection_threshold = 0.2f;
struct DelaySelectionThresholds {
int initial;
int converged;
} delay_selection_thresholds = {5, 20};
bool use_external_delay_estimator = false;
bool log_warning_on_delay_changes = false;
struct AlignmentMixing {
bool downmix;
bool adaptive_selection;
float activity_power_threshold;
bool prefer_first_two_channels;
};
AlignmentMixing render_alignment_mixing = {false, true, 10000.f, true};
AlignmentMixing capture_alignment_mixing = {false, true, 10000.f, false};
bool detect_pre_echo = true;
} delay;
struct Filter {
struct RefinedConfiguration {
size_t length_blocks;
float leakage_converged;
float leakage_diverged;
float error_floor;
float error_ceil;
float noise_gate;
};
struct CoarseConfiguration {
size_t length_blocks;
float rate;
float noise_gate;
};
RefinedConfiguration refined = {13, 0.00005f, 0.05f,
0.001f, 2.f, 20075344.f};
CoarseConfiguration coarse = {13, 0.7f, 20075344.f};
RefinedConfiguration refined_initial = {12, 0.005f, 0.5f,
0.001f, 2.f, 20075344.f};
CoarseConfiguration coarse_initial = {12, 0.9f, 20075344.f};
size_t config_change_duration_blocks = 250;
float initial_state_seconds = 2.5f;
int coarse_reset_hangover_blocks = 25;
bool conservative_initial_phase = false;
bool enable_coarse_filter_output_usage = true;
bool use_linear_filter = true;
bool high_pass_filter_echo_reference = false;
bool export_linear_aec_output = false;
} filter;
struct Erle {
float min = 1.f;
float max_l = 4.f;
float max_h = 1.5f;
bool onset_detection = true;
size_t num_sections = 1;
bool clamp_quality_estimate_to_zero = true;
bool clamp_quality_estimate_to_one = true;
} erle;
struct EpStrength {
float default_gain = 1.f;
float default_len = 0.83f;
float nearend_len = 0.83f;
bool echo_can_saturate = true;
bool bounded_erl = false;
bool erle_onset_compensation_in_dominant_nearend = false;
bool use_conservative_tail_frequency_response = true;
} ep_strength;
struct EchoAudibility {
float low_render_limit = 4 * 64.f;
float normal_render_limit = 64.f;
float floor_power = 2 * 64.f;
float audibility_threshold_lf = 10;
float audibility_threshold_mf = 10;
float audibility_threshold_hf = 10;
bool use_stationarity_properties = false;
bool use_stationarity_properties_at_init = false;
} echo_audibility;
struct RenderLevels {
float active_render_limit = 100.f;
float poor_excitation_render_limit = 150.f;
float poor_excitation_render_limit_ds8 = 20.f;
float render_power_gain_db = 0.f;
} render_levels;
struct EchoRemovalControl {
bool has_clock_drift = false;
bool linear_and_stable_echo_path = false;
} echo_removal_control;
struct EchoModel {
EchoModel();
EchoModel(const EchoModel& e);
EchoModel& operator=(const EchoModel& e);
size_t noise_floor_hold = 50;
float min_noise_floor_power = 1638400.f;
float stationary_gate_slope = 10.f;
float noise_gate_power = 27509.42f;
float noise_gate_slope = 0.3f;
size_t render_pre_window_size = 1;
size_t render_post_window_size = 1;
bool model_reverb_in_nonlinear_mode = true;
} echo_model;
struct ComfortNoise {
float noise_floor_dbfs = -96.03406f;
} comfort_noise;
struct Suppressor {
Suppressor();
Suppressor(const Suppressor& e);
Suppressor& operator=(const Suppressor& e);
size_t nearend_average_blocks = 4;
struct MaskingThresholds {
MaskingThresholds(float enr_transparent,
float enr_suppress,
float emr_transparent);
MaskingThresholds(const MaskingThresholds& e);
MaskingThresholds& operator=(const MaskingThresholds& e);
float enr_transparent;
float enr_suppress;
float emr_transparent;
};
struct Tuning {
Tuning(MaskingThresholds mask_lf,
MaskingThresholds mask_hf,
float max_inc_factor,
float max_dec_factor_lf);
Tuning(const Tuning& e);
Tuning& operator=(const Tuning& e);
MaskingThresholds mask_lf;
MaskingThresholds mask_hf;
float max_inc_factor;
float max_dec_factor_lf;
};
Tuning normal_tuning = Tuning(MaskingThresholds(.3f, .4f, .3f),
MaskingThresholds(.07f, .1f, .3f),
2.0f,
0.25f);
Tuning nearend_tuning = Tuning(MaskingThresholds(1.09f, 1.1f, .3f),
MaskingThresholds(.1f, .3f, .3f),
2.0f,
0.25f);
bool lf_smoothing_during_initial_phase = true;
int last_permanent_lf_smoothing_band = 0;
int last_lf_smoothing_band = 5;
int last_lf_band = 5;
int first_hf_band = 8;
struct DominantNearendDetection {
float enr_threshold = .25f;
float enr_exit_threshold = 10.f;
float snr_threshold = 30.f;
int hold_duration = 50;
int trigger_threshold = 12;
bool use_during_initial_phase = true;
bool use_unbounded_echo_spectrum = true;
} dominant_nearend_detection;
struct SubbandNearendDetection {
size_t nearend_average_blocks = 1;
struct SubbandRegion {
size_t low;
size_t high;
};
SubbandRegion subband1 = {1, 1};
SubbandRegion subband2 = {1, 1};
float nearend_threshold = 1.f;
float snr_threshold = 1.f;
} subband_nearend_detection;
bool use_subband_nearend_detection = false;
struct HighBandsSuppression {
float enr_threshold = 1.f;
float max_gain_during_echo = 1.f;
float anti_howling_activation_threshold = 400.f;
float anti_howling_gain = 1.f;
} high_bands_suppression;
float floor_first_increase = 0.00001f;
bool conservative_hf_suppression = false;
} suppressor;
struct MultiChannel {
bool detect_stereo_content = true;
float stereo_detection_threshold = 0.0f;
int stereo_detection_timeout_threshold_seconds = 300;
float stereo_detection_hysteresis_seconds = 2.0f;
} multi_channel;
};
} // namespace webrtc
#endif // API_AUDIO_ECHO_CANCELLER3_CONFIG_H_

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_AUDIO_ECHO_CONTROL_H_
#define API_AUDIO_ECHO_CONTROL_H_
#include <memory>
#include "rtc_base/checks.h"
namespace webrtc {
class AudioBuffer;
// Interface for an acoustic echo cancellation (AEC) submodule.
class EchoControl {
public:
// Analysis (not changing) of the render signal.
virtual void AnalyzeRender(AudioBuffer* render) = 0;
// Analysis (not changing) of the capture signal.
virtual void AnalyzeCapture(AudioBuffer* capture) = 0;
// Processes the capture signal in order to remove the echo.
virtual void ProcessCapture(AudioBuffer* capture, bool level_change) = 0;
// As above, but also returns the linear filter output.
virtual void ProcessCapture(AudioBuffer* capture,
AudioBuffer* linear_output,
bool level_change) = 0;
struct Metrics {
double echo_return_loss;
double echo_return_loss_enhancement;
int delay_ms;
};
// Collect current metrics from the echo controller.
virtual Metrics GetMetrics() const = 0;
// Provides an optional external estimate of the audio buffer delay.
virtual void SetAudioBufferDelay(int delay_ms) = 0;
// Specifies whether the capture output will be used. The purpose of this is
// to allow the echo controller to deactivate some of the processing when the
// resulting output is anyway not used, for instance when the endpoint is
// muted.
// TODO(b/177830919): Make pure virtual.
virtual void SetCaptureOutputUsage(bool capture_output_used) {}
// Returns wheter the signal is altered.
virtual bool ActiveProcessing() const = 0;
virtual ~EchoControl() {}
};
// Interface for a factory that creates EchoControllers.
class EchoControlFactory {
public:
virtual std::unique_ptr<EchoControl> Create(int sample_rate_hz,
int num_render_channels,
int num_capture_channels) = 0;
virtual ~EchoControlFactory() = default;
};
} // namespace webrtc
#endif // API_AUDIO_ECHO_CONTROL_H_

131
webrtc/api/function_view.h Normal file
View File

@ -0,0 +1,131 @@
/*
* Copyright 2016 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_FUNCTION_VIEW_H_
#define API_FUNCTION_VIEW_H_
#include <cstddef>
#include <type_traits>
#include <utility>
#include "rtc_base/checks.h"
// Just like std::function, FunctionView will wrap any callable and hide its
// actual type, exposing only its signature. But unlike std::function,
// FunctionView doesn't own its callable---it just points to it. Thus, it's a
// good choice mainly as a function argument when the callable argument will
// not be called again once the function has returned.
//
// Its constructors are implicit, so that callers won't have to convert lambdas
// and other callables to FunctionView<Blah(Blah, Blah)> explicitly. This is
// safe because FunctionView is only a reference to the real callable.
//
// Example use:
//
// void SomeFunction(rtc::FunctionView<int(int)> index_transform);
// ...
// SomeFunction([](int i) { return 2 * i + 1; });
//
// Note: FunctionView is tiny (essentially just two pointers) and trivially
// copyable, so it's probably cheaper to pass it by value than by const
// reference.
namespace rtc {
template <typename T>
class FunctionView; // Undefined.
template <typename RetT, typename... ArgT>
class FunctionView<RetT(ArgT...)> final {
public:
// Constructor for lambdas and other callables; it accepts every type of
// argument except those noted in its enable_if call.
template <
typename F,
typename std::enable_if<
// Not for function pointers; we have another constructor for that
// below.
!std::is_function<typename std::remove_pointer<
typename std::remove_reference<F>::type>::type>::value &&
// Not for nullptr; we have another constructor for that below.
!std::is_same<std::nullptr_t,
typename std::remove_cv<F>::type>::value &&
// Not for FunctionView objects; we have another constructor for that
// (the implicitly declared copy constructor).
!std::is_same<FunctionView,
typename std::remove_cv<typename std::remove_reference<
F>::type>::type>::value>::type* = nullptr>
FunctionView(F&& f)
: call_(CallVoidPtr<typename std::remove_reference<F>::type>) {
f_.void_ptr = &f;
}
// Constructor that accepts function pointers. If the argument is null, the
// result is an empty FunctionView.
template <
typename F,
typename std::enable_if<std::is_function<typename std::remove_pointer<
typename std::remove_reference<F>::type>::type>::value>::type* =
nullptr>
FunctionView(F&& f)
: call_(f ? CallFunPtr<typename std::remove_pointer<F>::type> : nullptr) {
f_.fun_ptr = reinterpret_cast<void (*)()>(f);
}
// Constructor that accepts nullptr. It creates an empty FunctionView.
template <typename F,
typename std::enable_if<std::is_same<
std::nullptr_t,
typename std::remove_cv<F>::type>::value>::type* = nullptr>
FunctionView(F&& f) : call_(nullptr) {}
// Default constructor. Creates an empty FunctionView.
FunctionView() : call_(nullptr) {}
RetT operator()(ArgT... args) const {
RTC_DCHECK(call_);
return call_(f_, std::forward<ArgT>(args)...);
}
// Returns true if we have a function, false if we don't (i.e., we're null).
explicit operator bool() const { return !!call_; }
private:
union VoidUnion {
void* void_ptr;
void (*fun_ptr)();
};
template <typename F>
static RetT CallVoidPtr(VoidUnion vu, ArgT... args) {
return (*static_cast<F*>(vu.void_ptr))(std::forward<ArgT>(args)...);
}
template <typename F>
static RetT CallFunPtr(VoidUnion vu, ArgT... args) {
return (reinterpret_cast<typename std::add_pointer<F>::type>(vu.fun_ptr))(
std::forward<ArgT>(args)...);
}
// A pointer to the callable thing, with type information erased. It's a
// union because we have to use separate types depending on if the callable
// thing is a function pointer or something else.
VoidUnion f_;
// Pointer to a dispatch function that knows the type of the callable thing
// that's stored in f_, and how to call it. A FunctionView object is empty
// (null) iff call_ is null.
RetT (*call_)(VoidUnion, ArgT...);
};
} // namespace rtc
#endif // API_FUNCTION_VIEW_H_

31
webrtc/api/location.h Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright 2023 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_LOCATION_H_
#define API_LOCATION_H_
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
// Location provides basic info where of an object was constructed, or was
// significantly brought to life. This is a stripped down version of
// https://source.chromium.org/chromium/chromium/src/+/main:base/location.h
// that only specifies an interface compatible to how base::Location is
// supposed to be used.
// The declaration is overriden inside the Chromium build.
class RTC_EXPORT Location {
public:
static Location Current() { return Location(); }
};
} // namespace webrtc
#endif // API_LOCATION_H_

View File

@ -0,0 +1,130 @@
/*
* Copyright 2022 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_MAKE_REF_COUNTED_H_
#define API_MAKE_REF_COUNTED_H_
#include <type_traits>
#include <utility>
#include "absl/base/nullability.h"
#include "api/ref_count.h"
#include "api/scoped_refptr.h"
#include "rtc_base/ref_counted_object.h"
namespace webrtc {
namespace webrtc_make_ref_counted_internal {
// Determines if the given class has AddRef and Release methods.
template <typename T>
class HasAddRefAndRelease {
private:
template <typename C,
decltype(std::declval<C>().AddRef())* = nullptr,
decltype(std::declval<C>().Release())* = nullptr>
static int Test(int);
template <typename>
static char Test(...);
public:
static constexpr bool value = std::is_same_v<decltype(Test<T>(0)), int>;
};
} // namespace webrtc_make_ref_counted_internal
// General utilities for constructing a reference counted class and the
// appropriate reference count implementation for that class.
//
// These utilities select either the `RefCountedObject` implementation or
// `FinalRefCountedObject` depending on whether the to-be-shared class is
// derived from the RefCountInterface interface or not (respectively).
// `make_ref_counted`:
//
// Use this when you want to construct a reference counted object of type T and
// get a `scoped_refptr<>` back. Example:
//
// auto p = make_ref_counted<Foo>("bar", 123);
//
// For a class that inherits from RefCountInterface, this is equivalent to:
//
// auto p = scoped_refptr<Foo>(new RefCountedObject<Foo>("bar", 123));
//
// If the class does not inherit from RefCountInterface, but does have
// AddRef/Release methods (so a T* is convertible to rtc::scoped_refptr), this
// is equivalent to just
//
// auto p = scoped_refptr<Foo>(new Foo("bar", 123));
//
// Otherwise, the example is equivalent to:
//
// auto p = scoped_refptr<FinalRefCountedObject<Foo>>(
// new FinalRefCountedObject<Foo>("bar", 123));
//
// In these cases, `make_ref_counted` reduces the amount of boilerplate code but
// also helps with the most commonly intended usage of RefCountedObject whereby
// methods for reference counting, are virtual and designed to satisfy the need
// of an interface. When such a need does not exist, it is more efficient to use
// the `FinalRefCountedObject` template, which does not add the vtable overhead.
//
// Note that in some cases, using RefCountedObject directly may still be what's
// needed.
// `make_ref_counted` for abstract classes that are convertible to
// RefCountInterface. The is_abstract requirement rejects classes that inherit
// both RefCountInterface and RefCounted object, which is a a discouraged
// pattern, and would result in double inheritance of RefCountedObject if this
// template was applied.
template <
typename T,
typename... Args,
typename std::enable_if<std::is_convertible_v<T*, RefCountInterface*> &&
std::is_abstract_v<T>,
T>::type* = nullptr>
absl::Nonnull<scoped_refptr<T>> make_ref_counted(Args&&... args) {
return scoped_refptr<T>(new RefCountedObject<T>(std::forward<Args>(args)...));
}
// `make_ref_counted` for complete classes that are not convertible to
// RefCountInterface and already carry a ref count.
template <
typename T,
typename... Args,
typename std::enable_if<
!std::is_convertible_v<T*, RefCountInterface*> &&
webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value,
T>::type* = nullptr>
absl::Nonnull<scoped_refptr<T>> make_ref_counted(Args&&... args) {
return scoped_refptr<T>(new T(std::forward<Args>(args)...));
}
// `make_ref_counted` for complete classes that are not convertible to
// RefCountInterface and have no ref count of their own.
template <
typename T,
typename... Args,
typename std::enable_if<
!std::is_convertible_v<T*, RefCountInterface*> &&
!webrtc_make_ref_counted_internal::HasAddRefAndRelease<T>::value,
T>::type* = nullptr>
absl::Nonnull<scoped_refptr<FinalRefCountedObject<T>>> make_ref_counted(
Args&&... args) {
return scoped_refptr<FinalRefCountedObject<T>>(
new FinalRefCountedObject<T>(std::forward<Args>(args)...));
}
} // namespace webrtc
namespace rtc {
// Backwards compatibe alias.
// TODO: bugs.webrtc.org/42225969 - deprecate and remove.
using ::webrtc::make_ref_counted;
} // namespace rtc
#endif // API_MAKE_REF_COUNTED_H_

50
webrtc/api/meson.build Normal file
View File

@ -0,0 +1,50 @@
api_sources = [
'audio/audio_frame.cc',
'audio/audio_processing.cc',
'audio/audio_processing_statistics.cc',
'audio/channel_layout.cc',
'audio/echo_canceller3_config.cc',
'rtp_headers.cc',
'rtp_packet_info.cc',
'task_queue/task_queue_base.cc',
'units/frequency.cc',
'units/time_delta.cc',
'units/timestamp.cc',
'video/color_space.cc',
'video/hdr_metadata.cc',
'video/video_content_type.cc',
'video/video_timing.cc',
]
api_headers = [
['', 'array_view.h'],
['', 'location.h'],
['', 'ref_count.h'],
['', 'scoped_refptr.h'],
['audio', 'audio_processing.h'],
['audio', 'audio_processing_statistics.h'],
['audio', 'echo_canceller3_config.h'],
['audio', 'echo_control.h'],
['task_queue', 'task_queue_base.h'],
['units', 'time_delta.h'],
]
foreach h : api_headers
install_headers(
join_paths(h[0], h[1]),
subdir: join_paths(include_subdir, 'api', h[0])
)
endforeach
libapi = static_library('libapi',
api_sources,
dependencies: common_deps,
include_directories: webrtc_inc,
cpp_args : common_cxxflags
)
api_dep = declare_dependency(
link_with: libapi
)

67
webrtc/api/ref_count.h Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_REF_COUNT_H_
#define API_REF_COUNT_H_
namespace webrtc {
// Refcounted objects should implement the following informal interface:
//
// void AddRef() const ;
// RefCountReleaseStatus Release() const;
//
// You may access members of a reference-counted object, including the AddRef()
// and Release() methods, only if you already own a reference to it, or if
// you're borrowing someone else's reference. (A newly created object is a
// special case: the reference count is zero on construction, and the code that
// creates the object should immediately call AddRef(), bringing the reference
// count from zero to one, e.g., by constructing an rtc::scoped_refptr).
//
// AddRef() creates a new reference to the object.
//
// Release() releases a reference to the object; the caller now has one less
// reference than before the call. Returns kDroppedLastRef if the number of
// references dropped to zero because of this (in which case the object destroys
// itself). Otherwise, returns kOtherRefsRemained, to signal that at the precise
// time the caller's reference was dropped, other references still remained (but
// if other threads own references, this may of course have changed by the time
// Release() returns).
//
// The caller of Release() must treat it in the same way as a delete operation:
// Regardless of the return value from Release(), the caller mustn't access the
// object. The object might still be alive, due to references held by other
// users of the object, but the object can go away at any time, e.g., as the
// result of another thread calling Release().
//
// Calling AddRef() and Release() manually is discouraged. It's recommended to
// use rtc::scoped_refptr to manage all pointers to reference counted objects.
// Note that rtc::scoped_refptr depends on compile-time duck-typing; formally
// implementing the below RefCountInterface is not required.
enum class RefCountReleaseStatus { kDroppedLastRef, kOtherRefsRemained };
// Interfaces where refcounting is part of the public api should
// inherit this abstract interface. The implementation of these
// methods is usually provided by the RefCountedObject template class,
// applied as a leaf in the inheritance tree.
class RefCountInterface {
public:
virtual void AddRef() const = 0;
virtual RefCountReleaseStatus Release() const = 0;
// Non-public destructor, because Release() has exclusive responsibility for
// destroying the object.
protected:
virtual ~RefCountInterface() {}
};
} // namespace webrtc
#endif // API_REF_COUNT_H_

View File

@ -0,0 +1,107 @@
/*
* Copyright 2017 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_REF_COUNTED_BASE_H_
#define API_REF_COUNTED_BASE_H_
#include <type_traits>
#include "api/ref_count.h"
#include "rtc_base/ref_counter.h"
namespace webrtc {
class RefCountedBase {
public:
RefCountedBase() = default;
RefCountedBase(const RefCountedBase&) = delete;
RefCountedBase& operator=(const RefCountedBase&) = delete;
void AddRef() const { ref_count_.IncRef(); }
RefCountReleaseStatus Release() const {
const auto status = ref_count_.DecRef();
if (status == RefCountReleaseStatus::kDroppedLastRef) {
delete this;
}
return status;
}
protected:
// Provided for internal webrtc subclasses for corner cases where it's
// necessary to know whether or not a reference is exclusively held.
bool HasOneRef() const { return ref_count_.HasOneRef(); }
virtual ~RefCountedBase() = default;
private:
mutable webrtc::webrtc_impl::RefCounter ref_count_{0};
};
// Template based version of `RefCountedBase` for simple implementations that do
// not need (or want) destruction via virtual destructor or the overhead of a
// vtable.
//
// To use:
// struct MyInt : public rtc::RefCountedNonVirtual<MyInt> {
// int foo_ = 0;
// };
//
// rtc::scoped_refptr<MyInt> my_int(new MyInt());
//
// sizeof(MyInt) on a 32 bit system would then be 8, int + refcount and no
// vtable generated.
template <typename T>
class RefCountedNonVirtual {
public:
RefCountedNonVirtual() = default;
RefCountedNonVirtual(const RefCountedNonVirtual&) = delete;
RefCountedNonVirtual& operator=(const RefCountedNonVirtual&) = delete;
void AddRef() const { ref_count_.IncRef(); }
RefCountReleaseStatus Release() const {
// If you run into this assert, T has virtual methods. There are two
// options:
// 1) The class doesn't actually need virtual methods, the type is complete
// so the virtual attribute(s) can be removed.
// 2) The virtual methods are a part of the design of the class. In this
// case you can consider using `RefCountedBase` instead or alternatively
// use `rtc::RefCountedObject`.
static_assert(!std::is_polymorphic<T>::value,
"T has virtual methods. RefCountedBase is a better fit.");
const auto status = ref_count_.DecRef();
if (status == RefCountReleaseStatus::kDroppedLastRef) {
delete static_cast<const T*>(this);
}
return status;
}
protected:
// Provided for internal webrtc subclasses for corner cases where it's
// necessary to know whether or not a reference is exclusively held.
bool HasOneRef() const { return ref_count_.HasOneRef(); }
~RefCountedNonVirtual() = default;
private:
mutable webrtc::webrtc_impl::RefCounter ref_count_{0};
};
} // namespace webrtc
// Backwards compatibe aliases.
// TODO: https://issues.webrtc.org/42225969 - deprecate and remove.
namespace rtc {
using RefCountedBase = webrtc::RefCountedBase;
template <typename T>
using RefCountedNonVirtual = webrtc::RefCountedNonVirtual<T>;
} // namespace rtc
#endif // API_REF_COUNTED_BASE_H_

62
webrtc/api/rtp_headers.cc Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/rtp_headers.h"
#include "api/video/video_content_type.h"
#include "api/video/video_rotation.h"
#include "rtc_base/checks.h"
namespace webrtc {
AudioLevel::AudioLevel() : voice_activity_(false), audio_level_(0) {}
AudioLevel::AudioLevel(bool voice_activity, int audio_level)
: voice_activity_(voice_activity), audio_level_(audio_level) {
RTC_CHECK_GE(audio_level, 0);
RTC_CHECK_LE(audio_level, 127);
}
RTPHeaderExtension::RTPHeaderExtension()
: hasTransmissionTimeOffset(false),
transmissionTimeOffset(0),
hasAbsoluteSendTime(false),
absoluteSendTime(0),
hasTransportSequenceNumber(false),
transportSequenceNumber(0),
hasVideoRotation(false),
videoRotation(kVideoRotation_0),
hasVideoContentType(false),
videoContentType(VideoContentType::UNSPECIFIED),
has_video_timing(false) {}
RTPHeaderExtension::RTPHeaderExtension(const RTPHeaderExtension& other) =
default;
RTPHeaderExtension& RTPHeaderExtension::operator=(
const RTPHeaderExtension& other) = default;
RTPHeader::RTPHeader()
: markerBit(false),
payloadType(0),
sequenceNumber(0),
timestamp(0),
ssrc(0),
numCSRCs(0),
arrOfCSRCs(),
paddingLength(0),
headerLength(0),
extension() {}
RTPHeader::RTPHeader(const RTPHeader& other) = default;
RTPHeader& RTPHeader::operator=(const RTPHeader& other) = default;
} // namespace webrtc

208
webrtc/api/rtp_headers.h Normal file
View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_RTP_HEADERS_H_
#define API_RTP_HEADERS_H_
#include <stddef.h>
#include <stdint.h>
#include <optional>
#include <string>
#include "api/units/timestamp.h"
#include "api/video/color_space.h"
#include "api/video/video_content_type.h"
#include "api/video/video_rotation.h"
#include "api/video/video_timing.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
struct FeedbackRequest {
// Determines whether the recv delta as specified in
// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01
// should be included.
bool include_timestamps;
// Include feedback of received packets in the range [sequence_number -
// sequence_count + 1, sequence_number]. That is, no feedback will be sent if
// sequence_count is zero.
int sequence_count;
};
// The Absolute Capture Time extension is used to stamp RTP packets with a NTP
// timestamp showing when the first audio or video frame in a packet was
// originally captured. The intent of this extension is to provide a way to
// accomplish audio-to-video synchronization when RTCP-terminating intermediate
// systems (e.g. mixers) are involved. See:
// http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time
struct AbsoluteCaptureTime {
// Absolute capture timestamp is the NTP timestamp of when the first frame in
// a packet was originally captured. This timestamp MUST be based on the same
// clock as the clock used to generate NTP timestamps for RTCP sender reports
// on the capture system.
//
// Its not always possible to do an NTP clock readout at the exact moment of
// when a media frame is captured. A capture system MAY postpone the readout
// until a more convenient time. A capture system SHOULD have known delays
// (e.g. from hardware buffers) subtracted from the readout to make the final
// timestamp as close to the actual capture time as possible.
//
// This field is encoded as a 64-bit unsigned fixed-point number with the high
// 32 bits for the timestamp in seconds and low 32 bits for the fractional
// part. This is also known as the UQ32.32 format and is what the RTP
// specification defines as the canonical format to represent NTP timestamps.
uint64_t absolute_capture_timestamp;
// Estimated capture clock offset is the senders estimate of the offset
// between its own NTP clock and the capture systems NTP clock. The sender is
// here defined as the system that owns the NTP clock used to generate the NTP
// timestamps for the RTCP sender reports on this stream. The sender system is
// typically either the capture system or a mixer.
//
// This field is encoded as a 64-bit twos complement signed fixed-point
// number with the high 32 bits for the seconds and low 32 bits for the
// fractional part. Its intended to make it easy for a receiver, that knows
// how to estimate the sender systems NTP clock, to also estimate the capture
// systems NTP clock:
//
// Capture NTP Clock = Sender NTP Clock + Capture Clock Offset
std::optional<int64_t> estimated_capture_clock_offset;
};
// The audio level extension is used to indicate the voice activity and the
// audio level of the payload in the RTP stream. See:
// https://tools.ietf.org/html/rfc6464#section-3.
class AudioLevel {
public:
AudioLevel();
AudioLevel(bool voice_activity, int audio_level);
AudioLevel(const AudioLevel& other) = default;
AudioLevel& operator=(const AudioLevel& other) = default;
// Flag indicating whether the encoder believes the audio packet contains
// voice activity.
bool voice_activity() const { return voice_activity_; }
// Audio level in -dBov. Values range from 0 to 127, representing 0 to -127
// dBov. 127 represents digital silence.
int level() const { return audio_level_; }
private:
bool voice_activity_;
int audio_level_;
};
inline bool operator==(const AbsoluteCaptureTime& lhs,
const AbsoluteCaptureTime& rhs) {
return (lhs.absolute_capture_timestamp == rhs.absolute_capture_timestamp) &&
(lhs.estimated_capture_clock_offset ==
rhs.estimated_capture_clock_offset);
}
inline bool operator!=(const AbsoluteCaptureTime& lhs,
const AbsoluteCaptureTime& rhs) {
return !(lhs == rhs);
}
struct RTPHeaderExtension {
RTPHeaderExtension();
RTPHeaderExtension(const RTPHeaderExtension& other);
RTPHeaderExtension& operator=(const RTPHeaderExtension& other);
static constexpr int kAbsSendTimeFraction = 18;
Timestamp GetAbsoluteSendTimestamp() const {
RTC_DCHECK(hasAbsoluteSendTime);
RTC_DCHECK(absoluteSendTime < (1ul << 24));
return Timestamp::Micros((absoluteSendTime * 1000000ll) /
(1 << kAbsSendTimeFraction));
}
bool hasTransmissionTimeOffset;
int32_t transmissionTimeOffset;
bool hasAbsoluteSendTime;
uint32_t absoluteSendTime;
std::optional<AbsoluteCaptureTime> absolute_capture_time;
bool hasTransportSequenceNumber;
uint16_t transportSequenceNumber;
std::optional<FeedbackRequest> feedback_request;
// Audio Level includes both level in dBov and voiced/unvoiced bit. See:
// https://tools.ietf.org/html/rfc6464#section-3
std::optional<AudioLevel> audio_level() const { return audio_level_; }
void set_audio_level(std::optional<AudioLevel> audio_level) {
audio_level_ = audio_level;
}
// For Coordination of Video Orientation. See
// http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/
// ts_126114v120700p.pdf
bool hasVideoRotation;
VideoRotation videoRotation;
// TODO(ilnik): Refactor this and one above to be std::optional() and remove
// a corresponding bool flag.
bool hasVideoContentType;
VideoContentType videoContentType;
bool has_video_timing;
VideoSendTiming video_timing;
VideoPlayoutDelay playout_delay;
// For identification of a stream when ssrc is not signaled. See
// https://tools.ietf.org/html/rfc8852
std::string stream_id;
std::string repaired_stream_id;
// For identifying the media section used to interpret this RTP packet. See
// https://tools.ietf.org/html/rfc8843
std::string mid;
std::optional<ColorSpace> color_space;
private:
std::optional<AudioLevel> audio_level_;
};
enum { kRtpCsrcSize = 15 }; // RFC 3550 page 13
struct RTC_EXPORT RTPHeader {
RTPHeader();
RTPHeader(const RTPHeader& other);
RTPHeader& operator=(const RTPHeader& other);
bool markerBit;
uint8_t payloadType;
uint16_t sequenceNumber;
uint32_t timestamp;
uint32_t ssrc;
uint8_t numCSRCs;
uint32_t arrOfCSRCs[kRtpCsrcSize];
size_t paddingLength;
size_t headerLength;
RTPHeaderExtension extension;
};
// RTCP mode to use. Compound mode is described by RFC 4585 and reduced-size
// RTCP mode is described by RFC 5506.
enum class RtcpMode { kOff, kCompound, kReducedSize };
enum NetworkState {
kNetworkUp,
kNetworkDown,
};
} // namespace webrtc
#endif // API_RTP_HEADERS_H_

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/rtp_packet_info.h"
#include <stddef.h>
#include <algorithm>
#include <cstdint>
#include <utility>
#include <vector>
#include "api/rtp_headers.h"
#include "api/units/timestamp.h"
namespace webrtc {
RtpPacketInfo::RtpPacketInfo()
: ssrc_(0), rtp_timestamp_(0), receive_time_(Timestamp::MinusInfinity()) {}
RtpPacketInfo::RtpPacketInfo(uint32_t ssrc,
std::vector<uint32_t> csrcs,
uint32_t rtp_timestamp,
Timestamp receive_time)
: ssrc_(ssrc),
csrcs_(std::move(csrcs)),
rtp_timestamp_(rtp_timestamp),
receive_time_(receive_time) {}
RtpPacketInfo::RtpPacketInfo(const RTPHeader& rtp_header,
Timestamp receive_time)
: ssrc_(rtp_header.ssrc),
rtp_timestamp_(rtp_header.timestamp),
receive_time_(receive_time) {
const auto& extension = rtp_header.extension;
const auto csrcs_count = std::min<size_t>(rtp_header.numCSRCs, kRtpCsrcSize);
csrcs_.assign(&rtp_header.arrOfCSRCs[0], &rtp_header.arrOfCSRCs[csrcs_count]);
if (extension.audio_level()) {
audio_level_ = extension.audio_level()->level();
}
absolute_capture_time_ = extension.absolute_capture_time;
}
bool operator==(const RtpPacketInfo& lhs, const RtpPacketInfo& rhs) {
return (lhs.ssrc() == rhs.ssrc()) && (lhs.csrcs() == rhs.csrcs()) &&
(lhs.rtp_timestamp() == rhs.rtp_timestamp()) &&
(lhs.receive_time() == rhs.receive_time()) &&
(lhs.audio_level() == rhs.audio_level()) &&
(lhs.absolute_capture_time() == rhs.absolute_capture_time()) &&
(lhs.local_capture_clock_offset() == rhs.local_capture_clock_offset());
}
} // namespace webrtc

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_RTP_PACKET_INFO_H_
#define API_RTP_PACKET_INFO_H_
#include <cstdint>
#include <optional>
#include <utility>
#include <vector>
#include "api/rtp_headers.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
//
// Structure to hold information about a received `RtpPacket`. It is primarily
// used to carry per-packet information from when a packet is received until
// the information is passed to `SourceTracker`.
//
class RTC_EXPORT RtpPacketInfo {
public:
RtpPacketInfo();
RtpPacketInfo(uint32_t ssrc,
std::vector<uint32_t> csrcs,
uint32_t rtp_timestamp,
Timestamp receive_time);
RtpPacketInfo(const RTPHeader& rtp_header, Timestamp receive_time);
RtpPacketInfo(const RtpPacketInfo& other) = default;
RtpPacketInfo(RtpPacketInfo&& other) = default;
RtpPacketInfo& operator=(const RtpPacketInfo& other) = default;
RtpPacketInfo& operator=(RtpPacketInfo&& other) = default;
uint32_t ssrc() const { return ssrc_; }
void set_ssrc(uint32_t value) { ssrc_ = value; }
const std::vector<uint32_t>& csrcs() const { return csrcs_; }
void set_csrcs(std::vector<uint32_t> value) { csrcs_ = std::move(value); }
uint32_t rtp_timestamp() const { return rtp_timestamp_; }
void set_rtp_timestamp(uint32_t value) { rtp_timestamp_ = value; }
Timestamp receive_time() const { return receive_time_; }
void set_receive_time(Timestamp value) { receive_time_ = value; }
std::optional<uint8_t> audio_level() const { return audio_level_; }
RtpPacketInfo& set_audio_level(std::optional<uint8_t> value) {
audio_level_ = value;
return *this;
}
const std::optional<AbsoluteCaptureTime>& absolute_capture_time() const {
return absolute_capture_time_;
}
RtpPacketInfo& set_absolute_capture_time(
const std::optional<AbsoluteCaptureTime>& value) {
absolute_capture_time_ = value;
return *this;
}
const std::optional<TimeDelta>& local_capture_clock_offset() const {
return local_capture_clock_offset_;
}
RtpPacketInfo& set_local_capture_clock_offset(
std::optional<TimeDelta> value) {
local_capture_clock_offset_ = value;
return *this;
}
private:
// Fields from the RTP header:
// https://tools.ietf.org/html/rfc3550#section-5.1
uint32_t ssrc_;
std::vector<uint32_t> csrcs_;
uint32_t rtp_timestamp_;
// Local `webrtc::Clock`-based timestamp of when the packet was received.
Timestamp receive_time_;
// Fields from the Audio Level header extension:
// https://tools.ietf.org/html/rfc6464#section-3
std::optional<uint8_t> audio_level_;
// Fields from the Absolute Capture Time header extension:
// http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time
std::optional<AbsoluteCaptureTime> absolute_capture_time_;
// Clock offset between the local clock and the capturer's clock.
// Do not confuse with `AbsoluteCaptureTime::estimated_capture_clock_offset`
// which instead represents the clock offset between a remote sender and the
// capturer. The following holds:
// Capture's NTP Clock = Local NTP Clock + Local-Capture Clock Offset
std::optional<TimeDelta> local_capture_clock_offset_;
};
bool operator==(const RtpPacketInfo& lhs, const RtpPacketInfo& rhs);
inline bool operator!=(const RtpPacketInfo& lhs, const RtpPacketInfo& rhs) {
return !(lhs == rhs);
}
} // namespace webrtc
#endif // API_RTP_PACKET_INFO_H_

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_RTP_PACKET_INFOS_H_
#define API_RTP_PACKET_INFOS_H_
#include <utility>
#include <vector>
#include "api/make_ref_counted.h"
#include "api/ref_counted_base.h"
#include "api/rtp_packet_info.h"
#include "api/scoped_refptr.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
// Semi-immutable structure to hold information about packets used to assemble
// an audio or video frame. Uses internal reference counting to make it very
// cheap to copy.
//
// We should ideally just use `std::vector<RtpPacketInfo>` and have it
// `std::move()`-ed as the per-packet information is transferred from one object
// to another. But moving the info, instead of copying it, is not easily done
// for the current video code.
class RTC_EXPORT RtpPacketInfos {
public:
using vector_type = std::vector<RtpPacketInfo>;
using value_type = vector_type::value_type;
using size_type = vector_type::size_type;
using difference_type = vector_type::difference_type;
using const_reference = vector_type::const_reference;
using const_pointer = vector_type::const_pointer;
using const_iterator = vector_type::const_iterator;
using const_reverse_iterator = vector_type::const_reverse_iterator;
using reference = const_reference;
using pointer = const_pointer;
using iterator = const_iterator;
using reverse_iterator = const_reverse_iterator;
RtpPacketInfos() {}
explicit RtpPacketInfos(const vector_type& entries)
: data_(Data::Create(entries)) {}
explicit RtpPacketInfos(vector_type&& entries)
: data_(Data::Create(std::move(entries))) {}
RtpPacketInfos(const RtpPacketInfos& other) = default;
RtpPacketInfos(RtpPacketInfos&& other) = default;
RtpPacketInfos& operator=(const RtpPacketInfos& other) = default;
RtpPacketInfos& operator=(RtpPacketInfos&& other) = default;
const_reference operator[](size_type pos) const { return entries()[pos]; }
const_reference at(size_type pos) const { return entries().at(pos); }
const_reference front() const { return entries().front(); }
const_reference back() const { return entries().back(); }
const_iterator begin() const { return entries().begin(); }
const_iterator end() const { return entries().end(); }
const_reverse_iterator rbegin() const { return entries().rbegin(); }
const_reverse_iterator rend() const { return entries().rend(); }
const_iterator cbegin() const { return entries().cbegin(); }
const_iterator cend() const { return entries().cend(); }
const_reverse_iterator crbegin() const { return entries().crbegin(); }
const_reverse_iterator crend() const { return entries().crend(); }
bool empty() const { return entries().empty(); }
size_type size() const { return entries().size(); }
private:
class Data final : public rtc::RefCountedNonVirtual<Data> {
public:
static rtc::scoped_refptr<Data> Create(const vector_type& entries) {
// Performance optimization for the empty case.
if (entries.empty()) {
return nullptr;
}
return rtc::make_ref_counted<Data>(entries);
}
static rtc::scoped_refptr<Data> Create(vector_type&& entries) {
// Performance optimization for the empty case.
if (entries.empty()) {
return nullptr;
}
return rtc::make_ref_counted<Data>(std::move(entries));
}
const vector_type& entries() const { return entries_; }
explicit Data(const vector_type& entries) : entries_(entries) {}
explicit Data(vector_type&& entries) : entries_(std::move(entries)) {}
~Data() = default;
private:
const vector_type entries_;
};
static const vector_type& empty_entries() {
static const vector_type& value = *new vector_type();
return value;
}
const vector_type& entries() const {
if (data_ != nullptr) {
return data_->entries();
} else {
return empty_entries();
}
}
rtc::scoped_refptr<Data> data_;
};
} // namespace webrtc
#endif // API_RTP_PACKET_INFOS_H_

229
webrtc/api/scoped_refptr.h Normal file
View File

@ -0,0 +1,229 @@
/*
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Originally these classes are from Chromium.
// http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/ref_counted.h?view=markup
//
// A smart pointer class for reference counted objects. Use this class instead
// of calling AddRef and Release manually on a reference counted object to
// avoid common memory leaks caused by forgetting to Release an object
// reference. Sample usage:
//
// class MyFoo : public RefCounted<MyFoo> {
// ...
// };
//
// void some_function() {
// scoped_refptr<MyFoo> foo = make_ref_counted<MyFoo>();
// foo->Method(param);
// // `foo` is released when this function returns
// }
//
// void some_other_function() {
// scoped_refptr<MyFoo> foo = make_ref_counted<MyFoo>();
// ...
// foo = nullptr; // explicitly releases `foo`
// ...
// if (foo)
// foo->Method(param);
// }
//
// The above examples show how scoped_refptr<T> acts like a pointer to T.
// Given two scoped_refptr<T> classes, it is also possible to exchange
// references between the two objects, like so:
//
// {
// scoped_refptr<MyFoo> a = make_ref_counted<MyFoo>();
// scoped_refptr<MyFoo> b;
//
// b.swap(a);
// // now, `b` references the MyFoo object, and `a` references null.
// }
//
// To make both `a` and `b` in the above example reference the same MyFoo
// object, simply use the assignment operator:
//
// {
// scoped_refptr<MyFoo> a = make_ref_counted<MyFoo>();
// scoped_refptr<MyFoo> b;
//
// b = a;
// // now, `a` and `b` each own a reference to the same MyFoo object.
// }
//
#ifndef API_SCOPED_REFPTR_H_
#define API_SCOPED_REFPTR_H_
#include <cstddef>
#include <utility>
#include "absl/base/nullability.h"
namespace webrtc {
template <class T>
class ABSL_NULLABILITY_COMPATIBLE scoped_refptr {
public:
using absl_nullability_compatible = void;
using element_type = T;
scoped_refptr() : ptr_(nullptr) {}
scoped_refptr(std::nullptr_t) : ptr_(nullptr) {} // NOLINT(runtime/explicit)
explicit scoped_refptr(absl::Nullable<T*> p) : ptr_(p) {
if (ptr_)
ptr_->AddRef();
}
scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
if (ptr_)
ptr_->AddRef();
}
template <typename U>
scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
if (ptr_)
ptr_->AddRef();
}
// Move constructors.
scoped_refptr(scoped_refptr<T>&& r) noexcept : ptr_(r.release()) {}
template <typename U>
scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.release()) {}
~scoped_refptr() {
if (ptr_)
ptr_->Release();
}
T* get() const { return ptr_; }
explicit operator bool() const { return ptr_ != nullptr; }
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
// Returns the (possibly null) raw pointer, and makes the scoped_refptr hold a
// null pointer, all without touching the reference count of the underlying
// pointed-to object. The object is still reference counted, and the caller of
// release() is now the proud owner of one reference, so it is responsible for
// calling Release() once on the object when no longer using it.
T* release() {
T* retVal = ptr_;
ptr_ = nullptr;
return retVal;
}
scoped_refptr<T>& operator=(absl::Nullable<T*> p) {
// AddRef first so that self assignment should work
if (p)
p->AddRef();
if (ptr_)
ptr_->Release();
ptr_ = p;
return *this;
}
scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
return *this = r.ptr_;
}
template <typename U>
scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
return *this = r.get();
}
scoped_refptr<T>& operator=(scoped_refptr<T>&& r) noexcept {
scoped_refptr<T>(std::move(r)).swap(*this);
return *this;
}
template <typename U>
scoped_refptr<T>& operator=(scoped_refptr<U>&& r) noexcept {
scoped_refptr<T>(std::move(r)).swap(*this);
return *this;
}
void swap(absl::Nonnull<T**> pp) noexcept {
T* p = ptr_;
ptr_ = *pp;
*pp = p;
}
void swap(scoped_refptr<T>& r) noexcept { swap(&r.ptr_); }
protected:
T* ptr_;
};
template <typename T, typename U>
bool operator==(const scoped_refptr<T>& a, const scoped_refptr<U>& b) {
return a.get() == b.get();
}
template <typename T, typename U>
bool operator!=(const scoped_refptr<T>& a, const scoped_refptr<U>& b) {
return !(a == b);
}
template <typename T>
bool operator==(const scoped_refptr<T>& a, std::nullptr_t) {
return a.get() == nullptr;
}
template <typename T>
bool operator!=(const scoped_refptr<T>& a, std::nullptr_t) {
return !(a == nullptr);
}
template <typename T>
bool operator==(std::nullptr_t, const scoped_refptr<T>& a) {
return a.get() == nullptr;
}
template <typename T>
bool operator!=(std::nullptr_t, const scoped_refptr<T>& a) {
return !(a == nullptr);
}
// Comparison with raw pointer.
template <typename T, typename U>
bool operator==(const scoped_refptr<T>& a, const U* b) {
return a.get() == b;
}
template <typename T, typename U>
bool operator!=(const scoped_refptr<T>& a, const U* b) {
return !(a == b);
}
template <typename T, typename U>
bool operator==(const T* a, const scoped_refptr<U>& b) {
return a == b.get();
}
template <typename T, typename U>
bool operator!=(const T* a, const scoped_refptr<U>& b) {
return !(a == b);
}
// Ordered comparison, needed for use as a std::map key.
template <typename T, typename U>
bool operator<(const scoped_refptr<T>& a, const scoped_refptr<U>& b) {
return a.get() < b.get();
}
} // namespace webrtc
namespace rtc {
// Backwards compatible alias.
// TODO: bugs.webrtc.org/42225969 - Deprecate and remove.
using ::webrtc::scoped_refptr;
} // namespace rtc
#endif // API_SCOPED_REFPTR_H_

View File

@ -0,0 +1,141 @@
/*
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_SEQUENCE_CHECKER_H_
#define API_SEQUENCE_CHECKER_H_
#include "api/task_queue/task_queue_base.h"
#include "rtc_base/checks.h"
#include "rtc_base/synchronization/sequence_checker_internal.h"
#include "rtc_base/thread_annotations.h"
namespace webrtc {
// SequenceChecker is a helper class used to help verify that some methods
// of a class are called on the same task queue or thread. A
// SequenceChecker is bound to a a task queue if the object is
// created on a task queue, or a thread otherwise.
//
//
// Example:
// class MyClass {
// public:
// void Foo() {
// RTC_DCHECK_RUN_ON(&sequence_checker_);
// ... (do stuff) ...
// }
//
// private:
// SequenceChecker sequence_checker_;
// }
//
// In Release mode, IsCurrent will always return true.
class RTC_LOCKABLE SequenceChecker
#if RTC_DCHECK_IS_ON
: public webrtc_sequence_checker_internal::SequenceCheckerImpl {
using Impl = webrtc_sequence_checker_internal::SequenceCheckerImpl;
#else
: public webrtc_sequence_checker_internal::SequenceCheckerDoNothing {
using Impl = webrtc_sequence_checker_internal::SequenceCheckerDoNothing;
#endif
public:
enum InitialState : bool { kDetached = false, kAttached = true };
// TODO(tommi): We could maybe join these two ctors and have fewer factory
// functions. At the moment they're separate to minimize code changes when
// we added the second ctor as well as avoiding to have unnecessary code at
// the SequenceChecker which much only run for the SequenceCheckerImpl
// implementation.
// In theory we could have something like:
//
// SequenceChecker(InitialState initial_state = kAttached,
// TaskQueueBase* attached_queue = TaskQueueBase::Current());
//
// But the problem with that is having the call to `Current()` exist for
// `SequenceCheckerDoNothing`.
explicit SequenceChecker(InitialState initial_state = kAttached)
: Impl(initial_state) {}
explicit SequenceChecker(TaskQueueBase* attached_queue)
: Impl(attached_queue) {}
// Returns true if sequence checker is attached to the current sequence.
bool IsCurrent() const { return Impl::IsCurrent(); }
// Detaches checker from sequence to which it is attached. Next attempt
// to do a check with this checker will result in attaching this checker
// to the sequence on which check was performed.
void Detach() { Impl::Detach(); }
};
} // namespace webrtc
// RTC_RUN_ON/RTC_GUARDED_BY/RTC_DCHECK_RUN_ON macros allows to annotate
// variables are accessed from same thread/task queue.
// Using tools designed to check mutexes, it checks at compile time everywhere
// variable is access, there is a run-time dcheck thread/task queue is correct.
//
// class SequenceCheckerExample {
// public:
// int CalledFromPacer() RTC_RUN_ON(pacer_sequence_checker_) {
// return var2_;
// }
//
// void CallMeFromPacer() {
// RTC_DCHECK_RUN_ON(&pacer_sequence_checker_)
// << "Should be called from pacer";
// CalledFromPacer();
// }
//
// private:
// int pacer_var_ RTC_GUARDED_BY(pacer_sequence_checker_);
// SequenceChecker pacer_sequence_checker_;
// };
//
// class TaskQueueExample {
// public:
// class Encoder {
// public:
// rtc::TaskQueueBase& Queue() { return encoder_queue_; }
// void Encode() {
// RTC_DCHECK_RUN_ON(&encoder_queue_);
// DoSomething(var_);
// }
//
// private:
// rtc::TaskQueueBase& encoder_queue_;
// Frame var_ RTC_GUARDED_BY(encoder_queue_);
// };
//
// void Encode() {
// // Will fail at runtime when DCHECK is enabled:
// // encoder_->Encode();
// // Will work:
// rtc::scoped_refptr<Encoder> encoder = encoder_;
// encoder_->Queue().PostTask([encoder] { encoder->Encode(); });
// }
//
// private:
// rtc::scoped_refptr<Encoder> encoder_;
// }
// Document if a function expected to be called from same thread/task queue.
#define RTC_RUN_ON(x) \
RTC_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x))
// Checks current code is running on the desired sequence.
//
// First statement validates it is running on the sequence `x`.
// Second statement annotates for the thread safety analyzer the check was done.
// Such annotation has to be attached to a function, and that function has to be
// called. Thus current implementation creates a noop lambda and calls it.
#define RTC_DCHECK_RUN_ON(x) \
RTC_DCHECK((x)->IsCurrent()) \
<< webrtc::webrtc_sequence_checker_internal::ExpectationToString(x); \
[]() RTC_ASSERT_EXCLUSIVE_LOCK(x) {}()
#endif // API_SEQUENCE_CHECKER_H_

View File

@ -0,0 +1,78 @@
/*
* Copyright 2019 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/task_queue/task_queue_base.h"
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#if defined(ABSL_HAVE_THREAD_LOCAL)
namespace webrtc {
namespace {
ABSL_CONST_INIT thread_local TaskQueueBase* current = nullptr;
} // namespace
TaskQueueBase* TaskQueueBase::Current() {
return current;
}
TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(
TaskQueueBase* task_queue)
: previous_(current) {
current = task_queue;
}
TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() {
current = previous_;
}
} // namespace webrtc
#elif defined(WEBRTC_POSIX)
#include <pthread.h>
namespace webrtc {
namespace {
ABSL_CONST_INIT pthread_key_t g_queue_ptr_tls = 0;
void InitializeTls() {
RTC_CHECK(pthread_key_create(&g_queue_ptr_tls, nullptr) == 0);
}
pthread_key_t GetQueuePtrTls() {
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
RTC_CHECK(pthread_once(&init_once, &InitializeTls) == 0);
return g_queue_ptr_tls;
}
} // namespace
TaskQueueBase* TaskQueueBase::Current() {
return static_cast<TaskQueueBase*>(pthread_getspecific(GetQueuePtrTls()));
}
TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(
TaskQueueBase* task_queue)
: previous_(TaskQueueBase::Current()) {
pthread_setspecific(GetQueuePtrTls(), task_queue);
}
TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() {
pthread_setspecific(GetQueuePtrTls(), previous_);
}
} // namespace webrtc
#else
#error Unsupported platform
#endif

View File

@ -0,0 +1,197 @@
/*
* Copyright 2019 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_TASK_QUEUE_TASK_QUEUE_BASE_H_
#define API_TASK_QUEUE_TASK_QUEUE_BASE_H_
#include <utility>
#include "absl/functional/any_invocable.h"
#include "api/location.h"
#include "api/units/time_delta.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/thread_annotations.h"
namespace webrtc {
// Asynchronously executes tasks in a way that guarantees that they're executed
// in FIFO order and that tasks never overlap. Tasks may always execute on the
// same worker thread and they may not. To DCHECK that tasks are executing on a
// known task queue, use IsCurrent().
class RTC_LOCKABLE RTC_EXPORT TaskQueueBase {
public:
enum class DelayPrecision {
// This may include up to a 17 ms leeway in addition to OS timer precision.
// See PostDelayedTask() for more information.
kLow,
// This does not have the additional delay that kLow has, but it is still
// limited by OS timer precision. See PostDelayedHighPrecisionTask() for
// more information.
kHigh,
};
// Starts destruction of the task queue.
// On return ensures no task are running and no new tasks are able to start
// on the task queue.
// Responsible for deallocation. Deallocation may happen synchronously during
// Delete or asynchronously after Delete returns.
// Code not running on the TaskQueue should not make any assumption when
// TaskQueue is deallocated and thus should not call any methods after Delete.
// Code running on the TaskQueue should not call Delete, but can assume
// TaskQueue still exists and may call other methods, e.g. PostTask.
// Should be called on the same task queue or thread that this task queue
// was created on.
virtual void Delete() = 0;
// Schedules a `task` to execute. Tasks are executed in FIFO order.
// When a TaskQueue is deleted, pending tasks will not be executed but they
// will be deleted.
//
// As long as tasks are not posted from task destruction, posted tasks are
// guaranteed to be destroyed with Current() pointing to the task queue they
// were posted to, whether they're executed or not. That means SequenceChecker
// works during task destruction, a fact that can be used to guarantee
// thread-compatible object deletion happening on a particular task queue
// which can simplify class design.
// Note that this guarantee does not apply to delayed tasks.
//
// May be called on any thread or task queue, including this task queue.
void PostTask(absl::AnyInvocable<void() &&> task,
const Location& location = Location::Current()) {
PostTaskImpl(std::move(task), PostTaskTraits{}, location);
}
// Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever
// possible.
//
// Schedules a `task` to execute a specified `delay` from when the call is
// made, using "low" precision. All scheduling is affected by OS-specific
// leeway and current workloads which means that in terms of precision there
// are no hard guarantees, but in addition to the OS induced leeway, "low"
// precision adds up to a 17 ms additional leeway. The purpose of this leeway
// is to achieve more efficient CPU scheduling and reduce Idle Wake Up
// frequency.
//
// The task may execute with [-1, 17 + OS induced leeway) ms additional delay.
//
// Avoid making assumptions about the precision of the OS scheduler. On macOS,
// the OS induced leeway may be 10% of sleep interval. On Windows, 1 ms
// precision timers may be used but there are cases, such as when running on
// battery, when the timer precision can be as poor as 15 ms.
//
// "Low" precision is not implemented everywhere yet. Where not yet
// implemented, PostDelayedTask() has "high" precision. See
// https://crbug.com/webrtc/13583 for more information.
//
// May be called on any thread or task queue, including this task queue.
void PostDelayedTask(absl::AnyInvocable<void() &&> task,
TimeDelta delay,
const Location& location = Location::Current()) {
PostDelayedTaskImpl(std::move(task), delay, PostDelayedTaskTraits{},
location);
}
// Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever
// possible.
//
// Schedules a `task` to execute a specified `delay` from when the call is
// made, using "high" precision. All scheduling is affected by OS-specific
// leeway and current workloads which means that in terms of precision there
// are no hard guarantees.
//
// The task may execute with [-1, OS induced leeway] ms additional delay.
//
// Avoid making assumptions about the precision of the OS scheduler. On macOS,
// the OS induced leeway may be 10% of sleep interval. On Windows, 1 ms
// precision timers may be used but there are cases, such as when running on
// battery, when the timer precision can be as poor as 15 ms.
//
// May be called on any thread or task queue, including this task queue.
void PostDelayedHighPrecisionTask(
absl::AnyInvocable<void() &&> task,
TimeDelta delay,
const Location& location = Location::Current()) {
PostDelayedTaskTraits traits;
traits.high_precision = true;
PostDelayedTaskImpl(std::move(task), delay, traits, location);
}
// As specified by `precision`, calls either PostDelayedTask() or
// PostDelayedHighPrecisionTask().
void PostDelayedTaskWithPrecision(
DelayPrecision precision,
absl::AnyInvocable<void() &&> task,
TimeDelta delay,
const Location& location = Location::Current()) {
switch (precision) {
case DelayPrecision::kLow:
PostDelayedTask(std::move(task), delay, location);
break;
case DelayPrecision::kHigh:
PostDelayedHighPrecisionTask(std::move(task), delay, location);
break;
}
}
// Returns the task queue that is running the current thread.
// Returns nullptr if this thread is not associated with any task queue.
// May be called on any thread or task queue, including this task queue.
static TaskQueueBase* Current();
bool IsCurrent() const { return Current() == this; }
protected:
// This is currently only present here to simplify introduction of future
// planned task queue changes.
struct PostTaskTraits {};
struct PostDelayedTaskTraits {
// If `high_precision` is false, tasks may execute within up to a 17 ms
// leeway in addition to OS timer precision. Otherwise the task should be
// limited to OS timer precision. See PostDelayedTask() and
// PostDelayedHighPrecisionTask() for more information.
bool high_precision = false;
};
class RTC_EXPORT CurrentTaskQueueSetter {
public:
explicit CurrentTaskQueueSetter(TaskQueueBase* task_queue);
CurrentTaskQueueSetter(const CurrentTaskQueueSetter&) = delete;
CurrentTaskQueueSetter& operator=(const CurrentTaskQueueSetter&) = delete;
~CurrentTaskQueueSetter();
private:
TaskQueueBase* const previous_;
};
// Subclasses should implement this method to support the behavior defined in
// the PostTask and PostTaskTraits docs above.
virtual void PostTaskImpl(absl::AnyInvocable<void() &&> task,
const PostTaskTraits& traits,
const Location& location) = 0;
// Subclasses should implement this method to support the behavior defined in
// the PostDelayedTask/PostHighPrecisionDelayedTask and PostDelayedTaskTraits
// docs above.
virtual void PostDelayedTaskImpl(absl::AnyInvocable<void() &&> task,
TimeDelta delay,
const PostDelayedTaskTraits& traits,
const Location& location) = 0;
// Users of the TaskQueue should call Delete instead of directly deleting
// this object.
virtual ~TaskQueueBase() = default;
};
struct TaskQueueDeleter {
void operator()(TaskQueueBase* task_queue) const { task_queue->Delete(); }
};
} // namespace webrtc
#endif // API_TASK_QUEUE_TASK_QUEUE_BASE_H_

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/units/frequency.h"
#include <cstdint>
#include <string>
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
std::string ToString(Frequency value) {
char buf[64];
rtc::SimpleStringBuilder sb(buf);
if (value.IsPlusInfinity()) {
sb << "+inf Hz";
} else if (value.IsMinusInfinity()) {
sb << "-inf Hz";
} else if (value.millihertz<int64_t>() % 1000 != 0) {
sb.AppendFormat("%.3f Hz", value.hertz<double>());
} else {
sb << value.hertz<int64_t>() << " Hz";
}
return sb.str();
}
} // namespace webrtc

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_UNITS_FREQUENCY_H_
#define API_UNITS_FREQUENCY_H_
#include <cstdint>
#include <cstdlib>
#include <limits>
#include <string>
#include <type_traits>
#include "api/units/time_delta.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/units/unit_base.h" // IWYU pragma: export
namespace webrtc {
class Frequency final : public rtc_units_impl::RelativeUnit<Frequency> {
public:
template <typename T>
static constexpr Frequency MilliHertz(T value) {
static_assert(std::is_arithmetic<T>::value, "");
return FromValue(value);
}
template <typename T>
static constexpr Frequency Hertz(T value) {
static_assert(std::is_arithmetic<T>::value, "");
return FromFraction(1'000, value);
}
template <typename T>
static constexpr Frequency KiloHertz(T value) {
static_assert(std::is_arithmetic<T>::value, "");
return FromFraction(1'000'000, value);
}
Frequency() = delete;
template <typename Sink>
friend void AbslStringify(Sink& sink, Frequency value);
template <typename T = int64_t>
constexpr T hertz() const {
return ToFraction<1000, T>();
}
template <typename T = int64_t>
constexpr T millihertz() const {
return ToValue<T>();
}
private:
friend class rtc_units_impl::UnitBase<Frequency>;
using RelativeUnit::RelativeUnit;
static constexpr bool one_sided = true;
};
inline constexpr Frequency operator/(int64_t nominator,
const TimeDelta& interval) {
constexpr int64_t kKiloPerMicro = 1000 * 1000000;
RTC_DCHECK_LE(nominator, std::numeric_limits<int64_t>::max() / kKiloPerMicro);
RTC_CHECK(interval.IsFinite());
RTC_CHECK(!interval.IsZero());
return Frequency::MilliHertz(nominator * kKiloPerMicro / interval.us());
}
inline constexpr TimeDelta operator/(int64_t nominator,
const Frequency& frequency) {
constexpr int64_t kMegaPerMilli = 1000000 * 1000;
RTC_DCHECK_LE(nominator, std::numeric_limits<int64_t>::max() / kMegaPerMilli);
RTC_CHECK(frequency.IsFinite());
RTC_CHECK(!frequency.IsZero());
return TimeDelta::Micros(nominator * kMegaPerMilli / frequency.millihertz());
}
inline constexpr double operator*(Frequency frequency, TimeDelta time_delta) {
return frequency.hertz<double>() * time_delta.seconds<double>();
}
inline constexpr double operator*(TimeDelta time_delta, Frequency frequency) {
return frequency * time_delta;
}
RTC_EXPORT std::string ToString(Frequency value);
inline std::string ToLogString(Frequency value) {
return ToString(value);
}
template <typename Sink>
void AbslStringify(Sink& sink, Frequency value) {
sink.Append(ToString(value));
}
} // namespace webrtc
#endif // API_UNITS_FREQUENCY_H_

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/units/time_delta.h"
#include <string>
#include "api/array_view.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
std::string ToString(TimeDelta value) {
char buf[64];
rtc::SimpleStringBuilder sb(buf);
if (value.IsPlusInfinity()) {
sb << "+inf ms";
} else if (value.IsMinusInfinity()) {
sb << "-inf ms";
} else {
if (value.us() == 0 || (value.us() % 1000) != 0)
sb << value.us() << " us";
else if (value.ms() % 1000 != 0)
sb << value.ms() << " ms";
else
sb << value.seconds() << " s";
}
return sb.str();
}
} // namespace webrtc

View File

@ -0,0 +1,108 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_UNITS_TIME_DELTA_H_
#define API_UNITS_TIME_DELTA_H_
#include <cstdint>
#include <cstdlib>
#include <string>
#include <type_traits>
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/units/unit_base.h" // IWYU pragma: export
namespace webrtc {
// TimeDelta represents the difference between two timestamps. Commonly this can
// be a duration. However since two Timestamps are not guaranteed to have the
// same epoch (they might come from different computers, making exact
// synchronisation infeasible), the duration covered by a TimeDelta can be
// undefined. To simplify usage, it can be constructed and converted to
// different units, specifically seconds (s), milliseconds (ms) and
// microseconds (us).
class TimeDelta final : public rtc_units_impl::RelativeUnit<TimeDelta> {
public:
template <typename T>
static constexpr TimeDelta Minutes(T value) {
static_assert(std::is_arithmetic<T>::value, "");
return Seconds(value * 60);
}
template <typename T>
static constexpr TimeDelta Seconds(T value) {
static_assert(std::is_arithmetic<T>::value, "");
return FromFraction(1'000'000, value);
}
template <typename T>
static constexpr TimeDelta Millis(T value) {
static_assert(std::is_arithmetic<T>::value, "");
return FromFraction(1'000, value);
}
template <typename T>
static constexpr TimeDelta Micros(T value) {
static_assert(std::is_arithmetic<T>::value, "");
return FromValue(value);
}
TimeDelta() = delete;
template <typename Sink>
friend void AbslStringify(Sink& sink, TimeDelta value);
template <typename T = int64_t>
constexpr T seconds() const {
return ToFraction<1000000, T>();
}
template <typename T = int64_t>
constexpr T ms() const {
return ToFraction<1000, T>();
}
template <typename T = int64_t>
constexpr T us() const {
return ToValue<T>();
}
template <typename T = int64_t>
constexpr T ns() const {
return ToMultiple<1000, T>();
}
constexpr int64_t seconds_or(int64_t fallback_value) const {
return ToFractionOr<1000000>(fallback_value);
}
constexpr int64_t ms_or(int64_t fallback_value) const {
return ToFractionOr<1000>(fallback_value);
}
constexpr int64_t us_or(int64_t fallback_value) const {
return ToValueOr(fallback_value);
}
constexpr TimeDelta Abs() const {
return us() < 0 ? TimeDelta::Micros(-us()) : *this;
}
private:
friend class rtc_units_impl::UnitBase<TimeDelta>;
using RelativeUnit::RelativeUnit;
static constexpr bool one_sided = false;
};
RTC_EXPORT std::string ToString(TimeDelta value);
inline std::string ToLogString(TimeDelta value) {
return ToString(value);
}
template <typename Sink>
void AbslStringify(Sink& sink, TimeDelta value) {
sink.Append(ToString(value));
}
} // namespace webrtc
#endif // API_UNITS_TIME_DELTA_H_

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/units/timestamp.h"
#include <string>
#include "api/array_view.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
std::string ToString(Timestamp value) {
char buf[64];
rtc::SimpleStringBuilder sb(buf);
if (value.IsPlusInfinity()) {
sb << "+inf ms";
} else if (value.IsMinusInfinity()) {
sb << "-inf ms";
} else {
if (value.us() == 0 || (value.us() % 1000) != 0)
sb << value.us() << " us";
else if (value.ms() % 1000 != 0)
sb << value.ms() << " ms";
else
sb << value.seconds() << " s";
}
return sb.str();
}
} // namespace webrtc

View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_UNITS_TIMESTAMP_H_
#define API_UNITS_TIMESTAMP_H_
#include <cstdint>
#include <string>
#include <type_traits>
#include "api/units/time_delta.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/units/unit_base.h" // IWYU pragma: export
namespace webrtc {
// Timestamp represents the time that has passed since some unspecified epoch.
// The epoch is assumed to be before any represented timestamps, this means that
// negative values are not valid. The most notable feature is that the
// difference of two Timestamps results in a TimeDelta.
class Timestamp final : public rtc_units_impl::UnitBase<Timestamp> {
public:
template <typename T>
static constexpr Timestamp Seconds(T value) {
static_assert(std::is_arithmetic<T>::value, "");
return FromFraction(1'000'000, value);
}
template <typename T>
static constexpr Timestamp Millis(T value) {
static_assert(std::is_arithmetic<T>::value, "");
return FromFraction(1'000, value);
}
template <typename T>
static constexpr Timestamp Micros(T value) {
static_assert(std::is_arithmetic<T>::value, "");
return FromValue(value);
}
Timestamp() = delete;
template <typename Sink>
friend void AbslStringify(Sink& sink, Timestamp value);
template <typename T = int64_t>
constexpr T seconds() const {
return ToFraction<1000000, T>();
}
template <typename T = int64_t>
constexpr T ms() const {
return ToFraction<1000, T>();
}
template <typename T = int64_t>
constexpr T us() const {
return ToValue<T>();
}
constexpr int64_t seconds_or(int64_t fallback_value) const {
return ToFractionOr<1000000>(fallback_value);
}
constexpr int64_t ms_or(int64_t fallback_value) const {
return ToFractionOr<1000>(fallback_value);
}
constexpr int64_t us_or(int64_t fallback_value) const {
return ToValueOr(fallback_value);
}
constexpr Timestamp operator+(const TimeDelta delta) const {
if (IsPlusInfinity() || delta.IsPlusInfinity()) {
RTC_DCHECK(!IsMinusInfinity());
RTC_DCHECK(!delta.IsMinusInfinity());
return PlusInfinity();
} else if (IsMinusInfinity() || delta.IsMinusInfinity()) {
RTC_DCHECK(!IsPlusInfinity());
RTC_DCHECK(!delta.IsPlusInfinity());
return MinusInfinity();
}
return Timestamp::Micros(us() + delta.us());
}
constexpr Timestamp operator-(const TimeDelta delta) const {
if (IsPlusInfinity() || delta.IsMinusInfinity()) {
RTC_DCHECK(!IsMinusInfinity());
RTC_DCHECK(!delta.IsPlusInfinity());
return PlusInfinity();
} else if (IsMinusInfinity() || delta.IsPlusInfinity()) {
RTC_DCHECK(!IsPlusInfinity());
RTC_DCHECK(!delta.IsMinusInfinity());
return MinusInfinity();
}
return Timestamp::Micros(us() - delta.us());
}
constexpr TimeDelta operator-(const Timestamp other) const {
if (IsPlusInfinity() || other.IsMinusInfinity()) {
RTC_DCHECK(!IsMinusInfinity());
RTC_DCHECK(!other.IsPlusInfinity());
return TimeDelta::PlusInfinity();
} else if (IsMinusInfinity() || other.IsPlusInfinity()) {
RTC_DCHECK(!IsPlusInfinity());
RTC_DCHECK(!other.IsMinusInfinity());
return TimeDelta::MinusInfinity();
}
return TimeDelta::Micros(us() - other.us());
}
constexpr Timestamp& operator-=(const TimeDelta delta) {
*this = *this - delta;
return *this;
}
constexpr Timestamp& operator+=(const TimeDelta delta) {
*this = *this + delta;
return *this;
}
private:
friend class rtc_units_impl::UnitBase<Timestamp>;
using UnitBase::UnitBase;
static constexpr bool one_sided = true;
};
RTC_EXPORT std::string ToString(Timestamp value);
inline std::string ToLogString(Timestamp value) {
return ToString(value);
}
template <typename Sink>
void AbslStringify(Sink& sink, Timestamp value) {
sink.Append(ToString(value));
}
} // namespace webrtc
#endif // API_UNITS_TIMESTAMP_H_

View File

@ -0,0 +1,269 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/video/color_space.h"
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include "api/video/hdr_metadata.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
namespace {
// Try to convert `enum_value` into the enum class T. `enum_bitmask` is created
// by the funciton below. Returns true if conversion was successful, false
// otherwise.
template <typename T>
bool SetFromUint8(uint8_t enum_value, uint64_t enum_bitmask, T* out) {
if ((enum_value < 64) && ((enum_bitmask >> enum_value) & 1)) {
*out = static_cast<T>(enum_value);
return true;
}
return false;
}
// This function serves as an assert for the constexpr function below. It's on
// purpose not declared as constexpr so that it causes a build problem if enum
// values of 64 or above are used. The bitmask and the code generating it would
// have to be extended if the standard is updated to include enum values >= 64.
int EnumMustBeLessThan64() {
return -1;
}
template <typename T, size_t N>
constexpr int MakeMask(const int index, const int length, T (&values)[N]) {
return length > 1
? (MakeMask(index, 1, values) +
MakeMask(index + 1, length - 1, values))
: (static_cast<uint8_t>(values[index]) < 64
? (uint64_t{1} << static_cast<uint8_t>(values[index]))
: EnumMustBeLessThan64());
}
// Create a bitmask where each bit corresponds to one potential enum value.
// `values` should be an array listing all possible enum values. The bit is set
// to one if the corresponding enum exists. Only works for enums with values
// less than 64.
template <typename T, size_t N>
constexpr uint64_t CreateEnumBitmask(T (&values)[N]) {
return MakeMask(0, N, values);
}
bool SetChromaSitingFromUint8(uint8_t enum_value,
ColorSpace::ChromaSiting* chroma_siting) {
constexpr ColorSpace::ChromaSiting kChromaSitings[] = {
ColorSpace::ChromaSiting::kUnspecified,
ColorSpace::ChromaSiting::kCollocated, ColorSpace::ChromaSiting::kHalf};
constexpr uint64_t enum_bitmask = CreateEnumBitmask(kChromaSitings);
return SetFromUint8(enum_value, enum_bitmask, chroma_siting);
}
} // namespace
ColorSpace::ColorSpace() = default;
ColorSpace::ColorSpace(const ColorSpace& other) = default;
ColorSpace::ColorSpace(ColorSpace&& other) = default;
ColorSpace& ColorSpace::operator=(const ColorSpace& other) = default;
ColorSpace::ColorSpace(PrimaryID primaries,
TransferID transfer,
MatrixID matrix,
RangeID range)
: ColorSpace(primaries,
transfer,
matrix,
range,
ChromaSiting::kUnspecified,
ChromaSiting::kUnspecified,
nullptr) {}
ColorSpace::ColorSpace(PrimaryID primaries,
TransferID transfer,
MatrixID matrix,
RangeID range,
ChromaSiting chroma_siting_horz,
ChromaSiting chroma_siting_vert,
const HdrMetadata* hdr_metadata)
: primaries_(primaries),
transfer_(transfer),
matrix_(matrix),
range_(range),
chroma_siting_horizontal_(chroma_siting_horz),
chroma_siting_vertical_(chroma_siting_vert),
hdr_metadata_(hdr_metadata ? std::make_optional(*hdr_metadata)
: std::nullopt) {}
ColorSpace::PrimaryID ColorSpace::primaries() const {
return primaries_;
}
ColorSpace::TransferID ColorSpace::transfer() const {
return transfer_;
}
ColorSpace::MatrixID ColorSpace::matrix() const {
return matrix_;
}
ColorSpace::RangeID ColorSpace::range() const {
return range_;
}
ColorSpace::ChromaSiting ColorSpace::chroma_siting_horizontal() const {
return chroma_siting_horizontal_;
}
ColorSpace::ChromaSiting ColorSpace::chroma_siting_vertical() const {
return chroma_siting_vertical_;
}
const HdrMetadata* ColorSpace::hdr_metadata() const {
return hdr_metadata_ ? &*hdr_metadata_ : nullptr;
}
#define PRINT_ENUM_CASE(TYPE, NAME) \
case TYPE::NAME: \
ss << #NAME; \
break;
std::string ColorSpace::AsString() const {
char buf[1024];
rtc::SimpleStringBuilder ss(buf);
ss << "{primaries:";
switch (primaries_) {
PRINT_ENUM_CASE(PrimaryID, kBT709)
PRINT_ENUM_CASE(PrimaryID, kUnspecified)
PRINT_ENUM_CASE(PrimaryID, kBT470M)
PRINT_ENUM_CASE(PrimaryID, kBT470BG)
PRINT_ENUM_CASE(PrimaryID, kSMPTE170M)
PRINT_ENUM_CASE(PrimaryID, kSMPTE240M)
PRINT_ENUM_CASE(PrimaryID, kFILM)
PRINT_ENUM_CASE(PrimaryID, kBT2020)
PRINT_ENUM_CASE(PrimaryID, kSMPTEST428)
PRINT_ENUM_CASE(PrimaryID, kSMPTEST431)
PRINT_ENUM_CASE(PrimaryID, kSMPTEST432)
PRINT_ENUM_CASE(PrimaryID, kJEDECP22)
}
ss << ", transfer:";
switch (transfer_) {
PRINT_ENUM_CASE(TransferID, kBT709)
PRINT_ENUM_CASE(TransferID, kUnspecified)
PRINT_ENUM_CASE(TransferID, kGAMMA22)
PRINT_ENUM_CASE(TransferID, kGAMMA28)
PRINT_ENUM_CASE(TransferID, kSMPTE170M)
PRINT_ENUM_CASE(TransferID, kSMPTE240M)
PRINT_ENUM_CASE(TransferID, kLINEAR)
PRINT_ENUM_CASE(TransferID, kLOG)
PRINT_ENUM_CASE(TransferID, kLOG_SQRT)
PRINT_ENUM_CASE(TransferID, kIEC61966_2_4)
PRINT_ENUM_CASE(TransferID, kBT1361_ECG)
PRINT_ENUM_CASE(TransferID, kIEC61966_2_1)
PRINT_ENUM_CASE(TransferID, kBT2020_10)
PRINT_ENUM_CASE(TransferID, kBT2020_12)
PRINT_ENUM_CASE(TransferID, kSMPTEST2084)
PRINT_ENUM_CASE(TransferID, kSMPTEST428)
PRINT_ENUM_CASE(TransferID, kARIB_STD_B67)
}
ss << ", matrix:";
switch (matrix_) {
PRINT_ENUM_CASE(MatrixID, kRGB)
PRINT_ENUM_CASE(MatrixID, kBT709)
PRINT_ENUM_CASE(MatrixID, kUnspecified)
PRINT_ENUM_CASE(MatrixID, kFCC)
PRINT_ENUM_CASE(MatrixID, kBT470BG)
PRINT_ENUM_CASE(MatrixID, kSMPTE170M)
PRINT_ENUM_CASE(MatrixID, kSMPTE240M)
PRINT_ENUM_CASE(MatrixID, kYCOCG)
PRINT_ENUM_CASE(MatrixID, kBT2020_NCL)
PRINT_ENUM_CASE(MatrixID, kBT2020_CL)
PRINT_ENUM_CASE(MatrixID, kSMPTE2085)
PRINT_ENUM_CASE(MatrixID, kCDNCLS)
PRINT_ENUM_CASE(MatrixID, kCDCLS)
PRINT_ENUM_CASE(MatrixID, kBT2100_ICTCP)
}
ss << ", range:";
switch (range_) {
PRINT_ENUM_CASE(RangeID, kInvalid)
PRINT_ENUM_CASE(RangeID, kLimited)
PRINT_ENUM_CASE(RangeID, kFull)
PRINT_ENUM_CASE(RangeID, kDerived)
}
ss << "}";
return ss.str();
}
#undef PRINT_ENUM_CASE
bool ColorSpace::set_primaries_from_uint8(uint8_t enum_value) {
constexpr PrimaryID kPrimaryIds[] = {
PrimaryID::kBT709, PrimaryID::kUnspecified, PrimaryID::kBT470M,
PrimaryID::kBT470BG, PrimaryID::kSMPTE170M, PrimaryID::kSMPTE240M,
PrimaryID::kFILM, PrimaryID::kBT2020, PrimaryID::kSMPTEST428,
PrimaryID::kSMPTEST431, PrimaryID::kSMPTEST432, PrimaryID::kJEDECP22};
constexpr uint64_t enum_bitmask = CreateEnumBitmask(kPrimaryIds);
return SetFromUint8(enum_value, enum_bitmask, &primaries_);
}
bool ColorSpace::set_transfer_from_uint8(uint8_t enum_value) {
constexpr TransferID kTransferIds[] = {
TransferID::kBT709, TransferID::kUnspecified,
TransferID::kGAMMA22, TransferID::kGAMMA28,
TransferID::kSMPTE170M, TransferID::kSMPTE240M,
TransferID::kLINEAR, TransferID::kLOG,
TransferID::kLOG_SQRT, TransferID::kIEC61966_2_4,
TransferID::kBT1361_ECG, TransferID::kIEC61966_2_1,
TransferID::kBT2020_10, TransferID::kBT2020_12,
TransferID::kSMPTEST2084, TransferID::kSMPTEST428,
TransferID::kARIB_STD_B67};
constexpr uint64_t enum_bitmask = CreateEnumBitmask(kTransferIds);
return SetFromUint8(enum_value, enum_bitmask, &transfer_);
}
bool ColorSpace::set_matrix_from_uint8(uint8_t enum_value) {
constexpr MatrixID kMatrixIds[] = {
MatrixID::kRGB, MatrixID::kBT709, MatrixID::kUnspecified,
MatrixID::kFCC, MatrixID::kBT470BG, MatrixID::kSMPTE170M,
MatrixID::kSMPTE240M, MatrixID::kYCOCG, MatrixID::kBT2020_NCL,
MatrixID::kBT2020_CL, MatrixID::kSMPTE2085, MatrixID::kCDNCLS,
MatrixID::kCDCLS, MatrixID::kBT2100_ICTCP};
constexpr uint64_t enum_bitmask = CreateEnumBitmask(kMatrixIds);
return SetFromUint8(enum_value, enum_bitmask, &matrix_);
}
bool ColorSpace::set_range_from_uint8(uint8_t enum_value) {
constexpr RangeID kRangeIds[] = {RangeID::kInvalid, RangeID::kLimited,
RangeID::kFull, RangeID::kDerived};
constexpr uint64_t enum_bitmask = CreateEnumBitmask(kRangeIds);
return SetFromUint8(enum_value, enum_bitmask, &range_);
}
bool ColorSpace::set_chroma_siting_horizontal_from_uint8(uint8_t enum_value) {
return SetChromaSitingFromUint8(enum_value, &chroma_siting_horizontal_);
}
bool ColorSpace::set_chroma_siting_vertical_from_uint8(uint8_t enum_value) {
return SetChromaSitingFromUint8(enum_value, &chroma_siting_vertical_);
}
void ColorSpace::set_hdr_metadata(const HdrMetadata* hdr_metadata) {
hdr_metadata_ =
hdr_metadata ? std::make_optional(*hdr_metadata) : std::nullopt;
}
} // namespace webrtc

View File

@ -0,0 +1,181 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_VIDEO_COLOR_SPACE_H_
#define API_VIDEO_COLOR_SPACE_H_
#include <stdint.h>
#include <optional>
#include <string>
#include "api/video/hdr_metadata.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
// This class represents color information as specified in T-REC H.273,
// available from https://www.itu.int/rec/T-REC-H.273.
//
// WebRTC's supported codecs:
// - VP9 supports color profiles, see VP9 Bitstream & Decoding Process
// Specification Version 0.6 Section 7.2.2 "Color config semantics" available
// from https://www.webmproject.org.
// - VP8 only supports BT.601, see
// https://tools.ietf.org/html/rfc6386#section-9.2
// - H264 uses the exact same representation as T-REC H.273. See T-REC-H.264
// E.2.1, "VUI parameters semantics", available from
// https://www.itu.int/rec/T-REC-H.264.
class RTC_EXPORT ColorSpace {
public:
enum class PrimaryID : uint8_t {
// The indices are equal to the values specified in T-REC H.273 Table 2.
kBT709 = 1,
kUnspecified = 2,
kBT470M = 4,
kBT470BG = 5,
kSMPTE170M = 6, // Identical to BT601
kSMPTE240M = 7,
kFILM = 8,
kBT2020 = 9,
kSMPTEST428 = 10,
kSMPTEST431 = 11,
kSMPTEST432 = 12,
kJEDECP22 = 22, // Identical to EBU3213-E
// When adding/removing entries here, please make sure to do the
// corresponding change to kPrimaryIds.
};
enum class TransferID : uint8_t {
// The indices are equal to the values specified in T-REC H.273 Table 3.
kBT709 = 1,
kUnspecified = 2,
kGAMMA22 = 4,
kGAMMA28 = 5,
kSMPTE170M = 6,
kSMPTE240M = 7,
kLINEAR = 8,
kLOG = 9,
kLOG_SQRT = 10,
kIEC61966_2_4 = 11,
kBT1361_ECG = 12,
kIEC61966_2_1 = 13,
kBT2020_10 = 14,
kBT2020_12 = 15,
kSMPTEST2084 = 16,
kSMPTEST428 = 17,
kARIB_STD_B67 = 18,
// When adding/removing entries here, please make sure to do the
// corresponding change to kTransferIds.
};
enum class MatrixID : uint8_t {
// The indices are equal to the values specified in T-REC H.273 Table 4.
kRGB = 0,
kBT709 = 1,
kUnspecified = 2,
kFCC = 4,
kBT470BG = 5,
kSMPTE170M = 6,
kSMPTE240M = 7,
kYCOCG = 8,
kBT2020_NCL = 9,
kBT2020_CL = 10,
kSMPTE2085 = 11,
kCDNCLS = 12,
kCDCLS = 13,
kBT2100_ICTCP = 14,
// When adding/removing entries here, please make sure to do the
// corresponding change to kMatrixIds.
};
enum class RangeID {
// The indices are equal to the values specified at
// https://www.webmproject.org/docs/container/#colour for the element Range.
kInvalid = 0,
// Limited Rec. 709 color range with RGB values ranging from 16 to 235.
kLimited = 1,
// Full RGB color range with RGB values from 0 to 255.
kFull = 2,
// Range is defined by MatrixCoefficients/TransferCharacteristics.
kDerived = 3,
// When adding/removing entries here, please make sure to do the
// corresponding change to kRangeIds.
};
enum class ChromaSiting {
// Chroma siting specifies how chroma is subsampled relative to the luma
// samples in a YUV video frame.
// The indices are equal to the values specified at
// https://www.webmproject.org/docs/container/#colour for the element
// ChromaSitingVert and ChromaSitingHorz.
kUnspecified = 0,
kCollocated = 1,
kHalf = 2,
// When adding/removing entries here, please make sure to do the
// corresponding change to kChromaSitings.
};
ColorSpace();
ColorSpace(const ColorSpace& other);
ColorSpace(ColorSpace&& other);
ColorSpace& operator=(const ColorSpace& other);
ColorSpace(PrimaryID primaries,
TransferID transfer,
MatrixID matrix,
RangeID range);
ColorSpace(PrimaryID primaries,
TransferID transfer,
MatrixID matrix,
RangeID range,
ChromaSiting chroma_siting_horizontal,
ChromaSiting chroma_siting_vertical,
const HdrMetadata* hdr_metadata);
friend bool operator==(const ColorSpace& lhs, const ColorSpace& rhs) {
return lhs.primaries_ == rhs.primaries_ && lhs.transfer_ == rhs.transfer_ &&
lhs.matrix_ == rhs.matrix_ && lhs.range_ == rhs.range_ &&
lhs.chroma_siting_horizontal_ == rhs.chroma_siting_horizontal_ &&
lhs.chroma_siting_vertical_ == rhs.chroma_siting_vertical_ &&
lhs.hdr_metadata_ == rhs.hdr_metadata_;
}
friend bool operator!=(const ColorSpace& lhs, const ColorSpace& rhs) {
return !(lhs == rhs);
}
PrimaryID primaries() const;
TransferID transfer() const;
MatrixID matrix() const;
RangeID range() const;
ChromaSiting chroma_siting_horizontal() const;
ChromaSiting chroma_siting_vertical() const;
const HdrMetadata* hdr_metadata() const;
std::string AsString() const;
bool set_primaries_from_uint8(uint8_t enum_value);
bool set_transfer_from_uint8(uint8_t enum_value);
bool set_matrix_from_uint8(uint8_t enum_value);
bool set_range_from_uint8(uint8_t enum_value);
bool set_chroma_siting_horizontal_from_uint8(uint8_t enum_value);
bool set_chroma_siting_vertical_from_uint8(uint8_t enum_value);
void set_hdr_metadata(const HdrMetadata* hdr_metadata);
private:
PrimaryID primaries_ = PrimaryID::kUnspecified;
TransferID transfer_ = TransferID::kUnspecified;
MatrixID matrix_ = MatrixID::kUnspecified;
RangeID range_ = RangeID::kInvalid;
ChromaSiting chroma_siting_horizontal_ = ChromaSiting::kUnspecified;
ChromaSiting chroma_siting_vertical_ = ChromaSiting::kUnspecified;
std::optional<HdrMetadata> hdr_metadata_;
};
} // namespace webrtc
#endif // API_VIDEO_COLOR_SPACE_H_

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/video/hdr_metadata.h"
namespace webrtc {
HdrMasteringMetadata::Chromaticity::Chromaticity() = default;
HdrMasteringMetadata::HdrMasteringMetadata() = default;
HdrMetadata::HdrMetadata() = default;
} // namespace webrtc

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_VIDEO_HDR_METADATA_H_
#define API_VIDEO_HDR_METADATA_H_
namespace webrtc {
// SMPTE ST 2086 mastering metadata,
// see https://ieeexplore.ieee.org/document/8353899.
struct HdrMasteringMetadata {
struct Chromaticity {
Chromaticity();
bool operator==(const Chromaticity& rhs) const {
return x == rhs.x && y == rhs.y;
}
bool Validate() const {
return x >= 0.0 && x <= 1.0 && y >= 0.0 && y <= 1.0;
}
// xy chromaticity coordinates must be calculated as specified in ISO
// 11664-3:2012 Section 7, and must be specified with four decimal places.
// The x coordinate should be in the range [0.0001, 0.7400] and the y
// coordinate should be in the range [0.0001, 0.8400]. Valid range [0.0000,
// 1.0000].
float x = 0.0f;
float y = 0.0f;
};
HdrMasteringMetadata();
bool operator==(const HdrMasteringMetadata& rhs) const {
return ((primary_r == rhs.primary_r) && (primary_g == rhs.primary_g) &&
(primary_b == rhs.primary_b) && (white_point == rhs.white_point) &&
(luminance_max == rhs.luminance_max) &&
(luminance_min == rhs.luminance_min));
}
bool Validate() const {
return luminance_max >= 0.0 && luminance_max <= 20000.0 &&
luminance_min >= 0.0 && luminance_min <= 5.0 &&
primary_r.Validate() && primary_g.Validate() &&
primary_b.Validate() && white_point.Validate();
}
// The nominal primaries of the mastering display.
Chromaticity primary_r;
Chromaticity primary_g;
Chromaticity primary_b;
// The nominal chromaticity of the white point of the mastering display.
Chromaticity white_point;
// The nominal maximum display luminance of the mastering display. Specified
// in the unit candela/m2. The value should be in the range [5, 10000] with
// zero decimal places. Valid range [0, 20000].
float luminance_max = 0.0f;
// The nominal minimum display luminance of the mastering display. Specified
// in the unit candela/m2. The value should be in the range [0.0001, 5.0000]
// with four decimal places. Valid range [0.0000, 5.0000].
float luminance_min = 0.0f;
};
// High dynamic range (HDR) metadata common for HDR10 and WebM/VP9-based HDR
// formats. This struct replicates the HDRMetadata struct defined in
// https://cs.chromium.org/chromium/src/media/base/hdr_metadata.h
struct HdrMetadata {
HdrMetadata();
bool operator==(const HdrMetadata& rhs) const {
return (
(max_content_light_level == rhs.max_content_light_level) &&
(max_frame_average_light_level == rhs.max_frame_average_light_level) &&
(mastering_metadata == rhs.mastering_metadata));
}
bool Validate() const {
return max_content_light_level >= 0 && max_content_light_level <= 20000 &&
max_frame_average_light_level >= 0 &&
max_frame_average_light_level <= 20000 &&
mastering_metadata.Validate();
}
HdrMasteringMetadata mastering_metadata;
// Max content light level (CLL), i.e. maximum brightness level present in the
// stream, in nits. 1 nit = 1 candela/m2. Valid range [0, 20000].
int max_content_light_level = 0;
// Max frame-average light level (FALL), i.e. maximum average brightness of
// the brightest frame in the stream, in nits. Valid range [0, 20000].
int max_frame_average_light_level = 0;
};
} // namespace webrtc
#endif // API_VIDEO_HDR_METADATA_H_

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/video/video_content_type.h"
#include <cstdint>
#include "rtc_base/checks.h"
namespace webrtc {
namespace videocontenttypehelpers {
namespace {
static constexpr uint8_t kScreenshareBitsSize = 1;
static constexpr uint8_t kScreenshareBitsMask =
(1u << kScreenshareBitsSize) - 1;
} // namespace
bool IsScreenshare(const VideoContentType& content_type) {
// Ensure no bits apart from the screenshare bit is set.
// This CHECK is a temporary measure to detect code that introduces
// values according to old versions.
RTC_CHECK((static_cast<uint8_t>(content_type) & !kScreenshareBitsMask) == 0);
return (static_cast<uint8_t>(content_type) & kScreenshareBitsMask) > 0;
}
bool IsValidContentType(uint8_t value) {
// Only the screenshare bit is allowed.
// However, due to previous usage of the next 5 bits, we allow
// the lower 6 bits to be set.
return value < (1 << 6);
}
const char* ToString(const VideoContentType& content_type) {
return IsScreenshare(content_type) ? "screen" : "realtime";
}
} // namespace videocontenttypehelpers
} // namespace webrtc

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_VIDEO_VIDEO_CONTENT_TYPE_H_
#define API_VIDEO_VIDEO_CONTENT_TYPE_H_
#include <stdint.h>
namespace webrtc {
// VideoContentType stored as a single byte, which is sent over the network
// in the rtp-hdrext/video-content-type extension.
// Only the lowest bit is used, per the enum.
enum class VideoContentType : uint8_t {
UNSPECIFIED = 0,
SCREENSHARE = 1,
};
namespace videocontenttypehelpers {
bool IsScreenshare(const VideoContentType& content_type);
bool IsValidContentType(uint8_t value);
const char* ToString(const VideoContentType& content_type);
} // namespace videocontenttypehelpers
} // namespace webrtc
#endif // API_VIDEO_VIDEO_CONTENT_TYPE_H_

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_VIDEO_VIDEO_ROTATION_H_
#define API_VIDEO_VIDEO_ROTATION_H_
namespace webrtc {
// enum for clockwise rotation.
enum VideoRotation {
kVideoRotation_0 = 0,
kVideoRotation_90 = 90,
kVideoRotation_180 = 180,
kVideoRotation_270 = 270
};
} // namespace webrtc
#endif // API_VIDEO_VIDEO_ROTATION_H_

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/video/video_timing.h"
#include <algorithm>
#include <cstdint>
#include <string>
#include "api/array_view.h"
#include "api/units/time_delta.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
uint16_t VideoSendTiming::GetDeltaCappedMs(int64_t base_ms, int64_t time_ms) {
if (time_ms < base_ms) {
RTC_DLOG(LS_ERROR) << "Delta " << (time_ms - base_ms)
<< "ms expected to be positive";
}
return rtc::saturated_cast<uint16_t>(time_ms - base_ms);
}
uint16_t VideoSendTiming::GetDeltaCappedMs(TimeDelta delta) {
if (delta < TimeDelta::Zero()) {
RTC_DLOG(LS_ERROR) << "Delta " << delta.ms()
<< "ms expected to be positive";
}
return rtc::saturated_cast<uint16_t>(delta.ms());
}
TimingFrameInfo::TimingFrameInfo()
: rtp_timestamp(0),
capture_time_ms(-1),
encode_start_ms(-1),
encode_finish_ms(-1),
packetization_finish_ms(-1),
pacer_exit_ms(-1),
network_timestamp_ms(-1),
network2_timestamp_ms(-1),
receive_start_ms(-1),
receive_finish_ms(-1),
decode_start_ms(-1),
decode_finish_ms(-1),
render_time_ms(-1),
flags(VideoSendTiming::kNotTriggered) {}
int64_t TimingFrameInfo::EndToEndDelay() const {
return capture_time_ms >= 0 ? decode_finish_ms - capture_time_ms : -1;
}
bool TimingFrameInfo::IsLongerThan(const TimingFrameInfo& other) const {
int64_t other_delay = other.EndToEndDelay();
return other_delay == -1 || EndToEndDelay() > other_delay;
}
bool TimingFrameInfo::operator<(const TimingFrameInfo& other) const {
return other.IsLongerThan(*this);
}
bool TimingFrameInfo::operator<=(const TimingFrameInfo& other) const {
return !IsLongerThan(other);
}
bool TimingFrameInfo::IsOutlier() const {
return !IsInvalid() && (flags & VideoSendTiming::kTriggeredBySize);
}
bool TimingFrameInfo::IsTimerTriggered() const {
return !IsInvalid() && (flags & VideoSendTiming::kTriggeredByTimer);
}
bool TimingFrameInfo::IsInvalid() const {
return flags == VideoSendTiming::kInvalid;
}
std::string TimingFrameInfo::ToString() const {
if (IsInvalid()) {
return "";
}
char buf[1024];
rtc::SimpleStringBuilder sb(buf);
sb << rtp_timestamp << ',' << capture_time_ms << ',' << encode_start_ms << ','
<< encode_finish_ms << ',' << packetization_finish_ms << ','
<< pacer_exit_ms << ',' << network_timestamp_ms << ','
<< network2_timestamp_ms << ',' << receive_start_ms << ','
<< receive_finish_ms << ',' << decode_start_ms << ',' << decode_finish_ms
<< ',' << render_time_ms << ',' << IsOutlier() << ','
<< IsTimerTriggered();
return sb.str();
}
VideoPlayoutDelay::VideoPlayoutDelay(TimeDelta min, TimeDelta max)
: min_(std::clamp(min, TimeDelta::Zero(), kMax)),
max_(std::clamp(max, min_, kMax)) {
if (!(TimeDelta::Zero() <= min && min <= max && max <= kMax)) {
RTC_LOG(LS_ERROR) << "Invalid video playout delay: [" << min << "," << max
<< "]. Clamped to [" << this->min() << "," << this->max()
<< "]";
}
}
bool VideoPlayoutDelay::Set(TimeDelta min, TimeDelta max) {
if (TimeDelta::Zero() <= min && min <= max && max <= kMax) {
min_ = min;
max_ = max;
return true;
}
return false;
}
} // namespace webrtc

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_VIDEO_VIDEO_TIMING_H_
#define API_VIDEO_VIDEO_TIMING_H_
#include <stdint.h>
#include <limits>
#include <string>
#include "api/units/time_delta.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
// Video timing timestamps in ms counted from capture_time_ms of a frame.
// This structure represents data sent in video-timing RTP header extension.
struct RTC_EXPORT VideoSendTiming {
enum TimingFrameFlags : uint8_t {
kNotTriggered = 0, // Timing info valid, but not to be transmitted.
// Used on send-side only.
kTriggeredByTimer = 1 << 0, // Frame marked for tracing by periodic timer.
kTriggeredBySize = 1 << 1, // Frame marked for tracing due to size.
kInvalid = std::numeric_limits<uint8_t>::max() // Invalid, ignore!
};
// Returns |time_ms - base_ms| capped at max 16-bit value.
// Used to fill this data structure as per
// https://webrtc.org/experiments/rtp-hdrext/video-timing/ extension stores
// 16-bit deltas of timestamps from packet capture time.
static uint16_t GetDeltaCappedMs(int64_t base_ms, int64_t time_ms);
static uint16_t GetDeltaCappedMs(TimeDelta delta);
uint16_t encode_start_delta_ms;
uint16_t encode_finish_delta_ms;
uint16_t packetization_finish_delta_ms;
uint16_t pacer_exit_delta_ms;
uint16_t network_timestamp_delta_ms;
uint16_t network2_timestamp_delta_ms;
uint8_t flags = TimingFrameFlags::kInvalid;
};
// Used to report precise timings of a 'timing frames'. Contains all important
// timestamps for a lifetime of that specific frame. Reported as a string via
// GetStats(). Only frame which took the longest between two GetStats calls is
// reported.
struct RTC_EXPORT TimingFrameInfo {
TimingFrameInfo();
// Returns end-to-end delay of a frame, if sender and receiver timestamps are
// synchronized, -1 otherwise.
int64_t EndToEndDelay() const;
// Returns true if current frame took longer to process than `other` frame.
// If other frame's clocks are not synchronized, current frame is always
// preferred.
bool IsLongerThan(const TimingFrameInfo& other) const;
// Returns true if flags are set to indicate this frame was marked for tracing
// due to the size being outside some limit.
bool IsOutlier() const;
// Returns true if flags are set to indicate this frame was marked fro tracing
// due to cyclic timer.
bool IsTimerTriggered() const;
// Returns true if the timing data is marked as invalid, in which case it
// should be ignored.
bool IsInvalid() const;
std::string ToString() const;
bool operator<(const TimingFrameInfo& other) const;
bool operator<=(const TimingFrameInfo& other) const;
uint32_t rtp_timestamp; // Identifier of a frame.
// All timestamps below are in local monotonous clock of a receiver.
// If sender clock is not yet estimated, sender timestamps
// (capture_time_ms ... pacer_exit_ms) are negative values, still
// relatively correct.
int64_t capture_time_ms; // Captrue time of a frame.
int64_t encode_start_ms; // Encode start time.
int64_t encode_finish_ms; // Encode completion time.
int64_t packetization_finish_ms; // Time when frame was passed to pacer.
int64_t pacer_exit_ms; // Time when last packet was pushed out of pacer.
// Two in-network RTP processor timestamps: meaning is application specific.
int64_t network_timestamp_ms;
int64_t network2_timestamp_ms;
int64_t receive_start_ms; // First received packet time.
int64_t receive_finish_ms; // Last received packet time.
int64_t decode_start_ms; // Decode start time.
int64_t decode_finish_ms; // Decode completion time.
int64_t render_time_ms; // Proposed render time to insure smooth playback.
uint8_t flags; // Flags indicating validity and/or why tracing was triggered.
};
// Minimum and maximum playout delay values from capture to render.
// These are best effort values.
//
// min = max = 0 indicates that the receiver should try and render
// frame as soon as possible.
//
// min = x, max = y indicates that the receiver is free to adapt
// in the range (x, y) based on network jitter.
// This class ensures invariant 0 <= min <= max <= kMax.
class RTC_EXPORT VideoPlayoutDelay {
public:
// Maximum supported value for the delay limit.
static constexpr TimeDelta kMax = TimeDelta::Millis(10) * 0xFFF;
// Creates delay limits that indicates receiver should try to render frame
// as soon as possible.
static VideoPlayoutDelay Minimal() {
return VideoPlayoutDelay(TimeDelta::Zero(), TimeDelta::Zero());
}
// Creates valid, but unspecified limits.
VideoPlayoutDelay() = default;
VideoPlayoutDelay(const VideoPlayoutDelay&) = default;
VideoPlayoutDelay& operator=(const VideoPlayoutDelay&) = default;
VideoPlayoutDelay(TimeDelta min, TimeDelta max);
bool Set(TimeDelta min, TimeDelta max);
TimeDelta min() const { return min_; }
TimeDelta max() const { return max_; }
friend bool operator==(const VideoPlayoutDelay& lhs,
const VideoPlayoutDelay& rhs) {
return lhs.min_ == rhs.min_ && lhs.max_ == rhs.max_;
}
private:
TimeDelta min_ = TimeDelta::Zero();
TimeDelta max_ = kMax;
};
} // namespace webrtc
#endif // API_VIDEO_VIDEO_TIMING_H_

View File

@ -0,0 +1,55 @@
# Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import("../../webrtc.gni")
group("utility") {
deps = [ ":audio_frame_operations" ]
}
rtc_library("audio_frame_operations") {
visibility = [ "*" ]
sources = [
"audio_frame_operations.cc",
"audio_frame_operations.h",
"channel_mixer.cc",
"channel_mixer.h",
"channel_mixing_matrix.cc",
"channel_mixing_matrix.h",
]
deps = [
"../../api:array_view",
"../../api/audio:audio_frame_api",
"../../common_audio",
"../../rtc_base:checks",
"../../rtc_base:logging",
"../../rtc_base:safe_conversions",
"//third_party/abseil-cpp/absl/base:core_headers",
]
}
if (rtc_include_tests) {
rtc_library("utility_tests") {
testonly = true
sources = [
"audio_frame_operations_unittest.cc",
"channel_mixer_unittest.cc",
"channel_mixing_matrix_unittest.cc",
]
deps = [
":audio_frame_operations",
"../../api/audio:audio_frame_api",
"../../rtc_base:checks",
"../../rtc_base:logging",
"../../rtc_base:macromagic",
"../../rtc_base:stringutils",
"../../test:test_support",
"//testing/gtest",
]
}
}

View File

@ -0,0 +1,216 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "audio/utility/audio_frame_operations.h"
#include <string.h>
#include <algorithm>
#include <cstdint>
#include <utility>
#include "common_audio/include/audio_util.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_conversions.h"
namespace webrtc {
namespace {
// 2.7ms @ 48kHz, 4ms @ 32kHz, 8ms @ 16kHz.
const size_t kMuteFadeFrames = 128;
const float kMuteFadeInc = 1.0f / kMuteFadeFrames;
} // namespace
void AudioFrameOperations::QuadToStereo(
InterleavedView<const int16_t> src_audio,
InterleavedView<int16_t> dst_audio) {
RTC_DCHECK_EQ(NumChannels(src_audio), 4);
RTC_DCHECK_EQ(NumChannels(dst_audio), 2);
RTC_DCHECK_EQ(SamplesPerChannel(src_audio), SamplesPerChannel(dst_audio));
for (size_t i = 0; i < SamplesPerChannel(src_audio); ++i) {
auto dst_frame = i * 2;
dst_audio[dst_frame] =
(static_cast<int32_t>(src_audio[4 * i]) + src_audio[4 * i + 1]) >> 1;
dst_audio[dst_frame + 1] =
(static_cast<int32_t>(src_audio[4 * i + 2]) + src_audio[4 * i + 3]) >>
1;
}
}
int AudioFrameOperations::QuadToStereo(AudioFrame* frame) {
if (frame->num_channels_ != 4) {
return -1;
}
RTC_DCHECK_LE(frame->samples_per_channel_ * 4,
AudioFrame::kMaxDataSizeSamples);
if (!frame->muted()) {
// Note that `src` and `dst` will map in to the same buffer, but the call
// to `mutable_data()` changes the layout of `frame`, so `src` and `dst`
// will have different dimensions (important to call `data_view()` first).
auto src = frame->data_view();
auto dst = frame->mutable_data(frame->samples_per_channel_, 2);
QuadToStereo(src, dst);
} else {
frame->num_channels_ = 2;
}
return 0;
}
void AudioFrameOperations::DownmixChannels(
InterleavedView<const int16_t> src_audio,
InterleavedView<int16_t> dst_audio) {
RTC_DCHECK_EQ(SamplesPerChannel(src_audio), SamplesPerChannel(dst_audio));
if (NumChannels(src_audio) > 1 && IsMono(dst_audio)) {
// TODO(tommi): change DownmixInterleavedToMono to support InterleavedView
// and MonoView.
DownmixInterleavedToMono(&src_audio.data()[0], SamplesPerChannel(src_audio),
NumChannels(src_audio), &dst_audio.data()[0]);
} else if (NumChannels(src_audio) == 4 && NumChannels(dst_audio) == 2) {
QuadToStereo(src_audio, dst_audio);
} else {
RTC_DCHECK_NOTREACHED() << "src_channels: " << NumChannels(src_audio)
<< ", dst_channels: " << NumChannels(dst_audio);
}
}
void AudioFrameOperations::DownmixChannels(size_t dst_channels,
AudioFrame* frame) {
RTC_DCHECK_LE(frame->samples_per_channel_ * frame->num_channels_,
AudioFrame::kMaxDataSizeSamples);
if (frame->num_channels_ > 1 && dst_channels == 1) {
if (!frame->muted()) {
DownmixInterleavedToMono(frame->data(), frame->samples_per_channel_,
frame->num_channels_, frame->mutable_data());
}
frame->num_channels_ = 1;
} else if (frame->num_channels_ == 4 && dst_channels == 2) {
int err = QuadToStereo(frame);
RTC_DCHECK_EQ(err, 0);
} else {
RTC_DCHECK_NOTREACHED() << "src_channels: " << frame->num_channels_
<< ", dst_channels: " << dst_channels;
}
}
void AudioFrameOperations::UpmixChannels(size_t target_number_of_channels,
AudioFrame* frame) {
RTC_DCHECK_EQ(frame->num_channels_, 1);
RTC_DCHECK_LE(frame->samples_per_channel_ * target_number_of_channels,
AudioFrame::kMaxDataSizeSamples);
if (frame->num_channels_ != 1 ||
frame->samples_per_channel_ * target_number_of_channels >
AudioFrame::kMaxDataSizeSamples) {
return;
}
if (!frame->muted()) {
// Up-mixing done in place. Going backwards through the frame ensure nothing
// is irrevocably overwritten.
auto frame_data = frame->mutable_data(frame->samples_per_channel_,
target_number_of_channels);
for (int i = frame->samples_per_channel_ - 1; i >= 0; --i) {
for (size_t j = 0; j < target_number_of_channels; ++j) {
frame_data[target_number_of_channels * i + j] = frame_data[i];
}
}
} else {
frame->num_channels_ = target_number_of_channels;
}
}
void AudioFrameOperations::SwapStereoChannels(AudioFrame* frame) {
RTC_DCHECK(frame);
if (frame->num_channels_ != 2 || frame->muted()) {
return;
}
int16_t* frame_data = frame->mutable_data();
for (size_t i = 0; i < frame->samples_per_channel_ * 2; i += 2) {
std::swap(frame_data[i], frame_data[i + 1]);
}
}
void AudioFrameOperations::Mute(AudioFrame* frame,
bool previous_frame_muted,
bool current_frame_muted) {
RTC_DCHECK(frame);
if (!previous_frame_muted && !current_frame_muted) {
// Not muted, don't touch.
} else if (previous_frame_muted && current_frame_muted) {
// Frame fully muted.
size_t total_samples = frame->samples_per_channel_ * frame->num_channels_;
RTC_DCHECK_GE(AudioFrame::kMaxDataSizeSamples, total_samples);
frame->Mute();
} else {
// Fade is a no-op on a muted frame.
if (frame->muted()) {
return;
}
// Limit number of samples to fade, if frame isn't long enough.
size_t count = kMuteFadeFrames;
float inc = kMuteFadeInc;
if (frame->samples_per_channel_ < kMuteFadeFrames) {
count = frame->samples_per_channel_;
if (count > 0) {
inc = 1.0f / count;
}
}
size_t start = 0;
size_t end = count;
float start_g = 0.0f;
if (current_frame_muted) {
// Fade out the last `count` samples of frame.
RTC_DCHECK(!previous_frame_muted);
start = frame->samples_per_channel_ - count;
end = frame->samples_per_channel_;
start_g = 1.0f;
inc = -inc;
} else {
// Fade in the first `count` samples of frame.
RTC_DCHECK(previous_frame_muted);
}
// Perform fade.
int16_t* frame_data = frame->mutable_data();
size_t channels = frame->num_channels_;
for (size_t j = 0; j < channels; ++j) {
float g = start_g;
for (size_t i = start * channels; i < end * channels; i += channels) {
g += inc;
frame_data[i + j] *= g;
}
}
}
}
void AudioFrameOperations::Mute(AudioFrame* frame) {
Mute(frame, true, true);
}
int AudioFrameOperations::ScaleWithSat(float scale, AudioFrame* frame) {
if (frame->muted()) {
return 0;
}
int16_t* frame_data = frame->mutable_data();
for (size_t i = 0; i < frame->samples_per_channel_ * frame->num_channels_;
i++) {
frame_data[i] = rtc::saturated_cast<int16_t>(scale * frame_data[i]);
}
return 0;
}
} // namespace webrtc

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef AUDIO_UTILITY_AUDIO_FRAME_OPERATIONS_H_
#define AUDIO_UTILITY_AUDIO_FRAME_OPERATIONS_H_
#include <stddef.h>
#include <stdint.h>
#include "absl/base/attributes.h"
#include "api/array_view.h"
#include "api/audio/audio_frame.h"
namespace webrtc {
// TODO(andrew): consolidate this with utility.h and audio_frame_manipulator.h.
// Change reference parameters to pointers. Consider using a namespace rather
// than a class.
class AudioFrameOperations {
public:
// Downmixes 4 channels `src_audio` to stereo `dst_audio`. This is an in-place
// operation, meaning `src_audio` and `dst_audio` may point to the same
// buffer.
static void QuadToStereo(InterleavedView<const int16_t> src_audio,
InterleavedView<int16_t> dst_audio);
// `frame.num_channels_` will be updated. This version checks that
// `num_channels_` is 4 channels.
static int QuadToStereo(AudioFrame* frame);
// Downmixes `src_channels` `src_audio` to `dst_channels` `dst_audio`.
// This is an in-place operation, meaning `src_audio` and `dst_audio`
// may point to the same buffer. Supported channel combinations are
// Stereo to Mono, Quad to Mono, and Quad to Stereo.
static void DownmixChannels(InterleavedView<const int16_t> src_audio,
InterleavedView<int16_t> dst_audio);
// `frame.num_channels_` will be updated. This version checks that
// `num_channels_` and `dst_channels` are valid and performs relevant downmix.
// Supported channel combinations are N channels to Mono, and Quad to Stereo.
static void DownmixChannels(size_t dst_channels, AudioFrame* frame);
// `frame.num_channels_` will be updated. This version checks that
// `num_channels_` and `dst_channels` are valid and performs relevant
// downmix. Supported channel combinations are Mono to N
// channels. The single channel is replicated.
static void UpmixChannels(size_t target_number_of_channels,
AudioFrame* frame);
// Swap the left and right channels of `frame`. Fails silently if `frame` is
// not stereo.
static void SwapStereoChannels(AudioFrame* frame);
// Conditionally zero out contents of `frame` for implementing audio mute:
// `previous_frame_muted` && `current_frame_muted` - Zero out whole frame.
// `previous_frame_muted` && !`current_frame_muted` - Fade-in at frame start.
// !`previous_frame_muted` && `current_frame_muted` - Fade-out at frame end.
// !`previous_frame_muted` && !`current_frame_muted` - Leave frame untouched.
static void Mute(AudioFrame* frame,
bool previous_frame_muted,
bool current_frame_muted);
// Zero out contents of frame.
static void Mute(AudioFrame* frame);
static int ScaleWithSat(float scale, AudioFrame* frame);
};
} // namespace webrtc
#endif // AUDIO_UTILITY_AUDIO_FRAME_OPERATIONS_H_

View File

@ -1,596 +0,0 @@
# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import("//build/config/crypto.gni")
import("//build/config/ui.gni")
import("../build/webrtc.gni")
config("rtc_base_config") {
include_dirs = [
"//third_party/jsoncpp/overrides/include",
"//third_party/jsoncpp/source/include",
]
defines = [
"FEATURE_ENABLE_SSL",
"LOGGING=1",
]
if (is_posix) {
# TODO(henrike): issue 3307, make rtc_base build without disabling
# these flags.
cflags_cc = [ "-Wno-non-virtual-dtor" ]
}
}
config("rtc_base_chromium_config") {
defines = [ "NO_MAIN_THREAD_WRAPPING" ]
}
config("openssl_config") {
defines = [
"SSL_USE_OPENSSL",
"HAVE_OPENSSL_SSL_H",
]
}
config("ios_config") {
libs = [
"CFNetwork.framework",
#"Foundation.framework", # Already included in //build/config:default_libs.
"Security.framework",
"SystemConfiguration.framework",
#"UIKit.framework", # Already included in //build/config:default_libs.
]
}
config("mac_config") {
libs = [
"Cocoa.framework",
#"Foundation.framework", # Already included in //build/config:default_libs.
#"IOKit.framework", # Already included in //build/config:default_libs.
#"Security.framework", # Already included in //build/config:default_libs.
"SystemConfiguration.framework",
]
}
config("mac_x86_config") {
libs = [
#"Carbon.framework", # Already included in //build/config:default_libs.
]
}
if (is_linux && !build_with_chromium) {
# Provides the same functionality as the //crypto:platform target, which
# WebRTC cannot use as we don't sync src/crypto from Chromium.
group("linux_system_ssl") {
if (use_openssl) {
deps = [
"//third_party/boringssl",
]
}
}
}
if (rtc_build_ssl == 0) {
config("external_ssl_library") {
assert(rtc_ssl_root != "",
"You must specify rtc_ssl_root when rtc_build_ssl==0.")
include_dirs = [ rtc_ssl_root ]
}
}
# The subset of rtc_base approved for use outside of libjingle.
static_library("rtc_base_approved") {
configs += [ "..:common_config" ]
public_configs = [ "..:common_inherited_config" ]
sources = [
"array_view.h",
"atomicops.h",
"bitbuffer.cc",
"bitbuffer.h",
"buffer.cc",
"buffer.h",
"bufferqueue.cc",
"bufferqueue.h",
"bytebuffer.cc",
"bytebuffer.h",
"byteorder.h",
"checks.cc",
"checks.h",
"criticalsection.cc",
"criticalsection.h",
"event.cc",
"event.h",
"event_tracer.cc",
"event_tracer.h",
"exp_filter.cc",
"exp_filter.h",
"maybe.h",
"md5.cc",
"md5.h",
"md5digest.cc",
"md5digest.h",
"platform_file.cc",
"platform_file.h",
"platform_thread.cc",
"platform_thread.h",
"safe_conversions.h",
"safe_conversions_impl.h",
"scoped_ptr.h",
"stringencode.cc",
"stringencode.h",
"stringutils.cc",
"stringutils.h",
"systeminfo.cc",
"systeminfo.h",
"template_util.h",
"thread_annotations.h",
"thread_checker.h",
"thread_checker_impl.cc",
"thread_checker_impl.h",
"timeutils.cc",
"timeutils.h",
"trace_event.h",
]
if (!build_with_chromium) {
sources += [
"basictypes.h",
"constructormagic.h",
"logging.cc",
"logging.h",
]
}
}
static_library("rtc_base") {
cflags = []
cflags_cc = []
libs = []
deps = [
":rtc_base_approved",
]
configs += [
"..:common_config",
":rtc_base_config",
]
public_configs = [
"..:common_inherited_config",
":rtc_base_config",
]
defines = [ "LOGGING=1" ]
sources = [
"arraysize.h",
"asyncfile.cc",
"asyncfile.h",
"asyncinvoker-inl.h",
"asyncinvoker.cc",
"asyncinvoker.h",
"asyncpacketsocket.cc",
"asyncpacketsocket.h",
"asyncresolverinterface.cc",
"asyncresolverinterface.h",
"asyncsocket.cc",
"asyncsocket.h",
"asynctcpsocket.cc",
"asynctcpsocket.h",
"asyncudpsocket.cc",
"asyncudpsocket.h",
"autodetectproxy.cc",
"autodetectproxy.h",
"base64.cc",
"base64.h",
"basicdefs.h",
"common.cc",
"common.h",
"crc32.cc",
"crc32.h",
"cryptstring.cc",
"cryptstring.h",
"diskcache.cc",
"diskcache.h",
"filerotatingstream.cc",
"filerotatingstream.h",
"fileutils.cc",
"fileutils.h",
"firewallsocketserver.cc",
"firewallsocketserver.h",
"flags.cc",
"flags.h",
"format_macros.h",
"gunit_prod.h",
"helpers.cc",
"helpers.h",
"httpbase.cc",
"httpbase.h",
"httpclient.cc",
"httpclient.h",
"httpcommon-inl.h",
"httpcommon.cc",
"httpcommon.h",
"httprequest.cc",
"httprequest.h",
"iosfilesystem.mm",
"ipaddress.cc",
"ipaddress.h",
"linked_ptr.h",
"mathutils.h",
"messagedigest.cc",
"messagedigest.h",
"messagehandler.cc",
"messagehandler.h",
"messagequeue.cc",
"messagequeue.h",
"nethelpers.cc",
"nethelpers.h",
"network.cc",
"network.h",
"networkmonitor.cc",
"networkmonitor.h",
"nullsocketserver.h",
"pathutils.cc",
"pathutils.h",
"physicalsocketserver.cc",
"physicalsocketserver.h",
"proxydetect.cc",
"proxydetect.h",
"proxyinfo.cc",
"proxyinfo.h",
"ratelimiter.cc",
"ratelimiter.h",
"ratetracker.cc",
"ratetracker.h",
"rtccertificate.cc",
"rtccertificate.h",
"scoped_autorelease_pool.h",
"scoped_autorelease_pool.mm",
"sha1.cc",
"sha1.h",
"sha1digest.cc",
"sha1digest.h",
"signalthread.cc",
"signalthread.h",
"sigslot.cc",
"sigslot.h",
"sigslotrepeater.h",
"socket.h",
"socketadapters.cc",
"socketadapters.h",
"socketaddress.cc",
"socketaddress.h",
"socketaddresspair.cc",
"socketaddresspair.h",
"socketfactory.h",
"socketpool.cc",
"socketpool.h",
"socketserver.h",
"socketstream.cc",
"socketstream.h",
"ssladapter.cc",
"ssladapter.h",
"sslfingerprint.cc",
"sslfingerprint.h",
"sslidentity.cc",
"sslidentity.h",
"sslsocketfactory.cc",
"sslsocketfactory.h",
"sslstreamadapter.cc",
"sslstreamadapter.h",
"sslstreamadapterhelper.cc",
"sslstreamadapterhelper.h",
"stream.cc",
"stream.h",
"task.cc",
"task.h",
"taskparent.cc",
"taskparent.h",
"taskrunner.cc",
"taskrunner.h",
"thread.cc",
"thread.h",
"timing.cc",
"timing.h",
"urlencode.cc",
"urlencode.h",
"worker.cc",
"worker.h",
]
if (is_posix) {
sources += [
"unixfilesystem.cc",
"unixfilesystem.h",
]
}
if (build_with_chromium) {
sources += [
"../../webrtc_overrides/webrtc/base/logging.cc",
"../../webrtc_overrides/webrtc/base/logging.h",
]
deps += [ "..:webrtc_common" ]
if (is_win) {
sources += [ "../../webrtc_overrides/webrtc/base/win32socketinit.cc" ]
}
include_dirs = [
"../../webrtc_overrides",
"../../boringssl/src/include",
]
public_configs += [ ":rtc_base_chromium_config" ]
} else {
sources += [
"bandwidthsmoother.cc",
"bandwidthsmoother.h",
"bind.h",
"bind.h.pump",
"callback.h",
"callback.h.pump",
"fileutils_mock.h",
"genericslot.h",
"genericslot.h.pump",
"httpserver.cc",
"httpserver.h",
"json.cc",
"json.h",
"logsinks.cc",
"logsinks.h",
"mathutils.h",
"multipart.cc",
"multipart.h",
"natserver.cc",
"natserver.h",
"natsocketfactory.cc",
"natsocketfactory.h",
"nattypes.cc",
"nattypes.h",
"optionsfile.cc",
"optionsfile.h",
"profiler.cc",
"profiler.h",
"proxyserver.cc",
"proxyserver.h",
"refcount.h",
"referencecountedsingletonfactory.h",
"rollingaccumulator.h",
"scoped_ref_ptr.h",
"scopedptrcollection.h",
"sec_buffer.h",
"sharedexclusivelock.cc",
"sharedexclusivelock.h",
"sslconfig.h",
"sslroots.h",
"testclient.cc",
"testclient.h",
"transformadapter.cc",
"transformadapter.h",
"versionparsing.cc",
"versionparsing.h",
"virtualsocketserver.cc",
"virtualsocketserver.h",
"window.h",
"windowpicker.h",
"windowpickerfactory.h",
]
deps += [ "..:webrtc_common" ]
if (is_posix) {
sources += [
"latebindingsymboltable.cc",
"latebindingsymboltable.cc.def",
"latebindingsymboltable.h",
"latebindingsymboltable.h.def",
"posix.cc",
"posix.h",
]
}
if (is_linux) {
sources += [
"dbus.cc",
"dbus.h",
"libdbusglibsymboltable.cc",
"libdbusglibsymboltable.h",
"linuxfdwalk.c",
"linuxfdwalk.h",
]
}
if (is_mac) {
sources += [
"macasyncsocket.cc",
"macasyncsocket.h",
"maccocoasocketserver.h",
"maccocoasocketserver.mm",
"macsocketserver.cc",
"macsocketserver.h",
"macwindowpicker.cc",
"macwindowpicker.h",
]
}
if (is_win) {
sources += [
"diskcache_win32.cc",
"diskcache_win32.h",
"win32regkey.cc",
"win32regkey.h",
"win32socketinit.cc",
"win32socketinit.h",
"win32socketserver.cc",
"win32socketserver.h",
]
}
if (rtc_build_json) {
deps += [ "//third_party/jsoncpp" ]
} else {
include_dirs += [ rtc_jsoncpp_root ]
# When defined changes the include path for json.h to where it is
# expected to be when building json outside of the standalone build.
defines += [ "WEBRTC_EXTERNAL_JSON" ]
}
} # !build_with_chromium
# TODO(henrike): issue 3307, make rtc_base build with the Chromium default
# compiler settings.
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
if (!is_win) {
cflags += [ "-Wno-uninitialized" ]
cflags_cc += [ "-Wno-non-virtual-dtor" ]
}
if (use_openssl) {
public_configs += [ ":openssl_config" ]
if (rtc_build_ssl) {
deps += [ "//third_party/boringssl" ]
} else {
configs += [ "external_ssl_library" ]
}
sources += [
"openssl.h",
"openssladapter.cc",
"openssladapter.h",
"openssldigest.cc",
"openssldigest.h",
"opensslidentity.cc",
"opensslidentity.h",
"opensslstreamadapter.cc",
"opensslstreamadapter.h",
]
}
if (is_android) {
sources += [
"ifaddrs-android.cc",
"ifaddrs-android.h",
]
libs += [
"log",
"GLESv2",
]
}
if (is_ios) {
all_dependent_configs = [ ":ios_config" ]
sources += [
"macconversion.cc",
"macconversion.h",
]
}
if (use_x11) {
sources += [
"x11windowpicker.cc",
"x11windowpicker.h",
]
libs += [
"dl",
"rt",
"Xext",
"X11",
"Xcomposite",
"Xrender",
]
}
if (is_linux) {
libs += [
"dl",
"rt",
]
}
if (is_mac) {
sources += [
"maccocoathreadhelper.h",
"maccocoathreadhelper.mm",
"macconversion.cc",
"macconversion.h",
"macutils.cc",
"macutils.h",
]
all_dependent_configs = [ ":mac_config" ]
if (current_cpu == "x86") {
all_dependent_configs += [ ":mac_x86_config" ]
}
}
if (is_win) {
sources += [
"win32.cc",
"win32.h",
"win32filesystem.cc",
"win32filesystem.h",
"win32securityerrors.cc",
"win32window.cc",
"win32window.h",
"win32windowpicker.cc",
"win32windowpicker.h",
"winfirewall.cc",
"winfirewall.h",
"winping.cc",
"winping.h",
]
libs += [
"crypt32.lib",
"iphlpapi.lib",
"secur32.lib",
]
cflags += [
# Suppress warnings about WIN32_LEAN_AND_MEAN.
"/wd4005",
"/wd4703",
]
defines += [ "_CRT_NONSTDC_NO_DEPRECATE" ]
}
if (is_posix && is_debug) {
# The Chromium build/common.gypi defines this for all posix
# _except_ for ios & mac. We want it there as well, e.g.
# because ASSERT and friends trigger off of it.
defines += [ "_DEBUG" ]
}
if (is_ios || (is_mac && current_cpu != "x86")) {
defines += [ "CARBON_DEPRECATED=YES" ]
}
if (is_linux || is_android) {
sources += [
"linux.cc",
"linux.h",
]
}
if (is_nacl) {
deps += [ "//native_client_sdk/src/libraries/nacl_io" ]
defines += [ "timezone=_timezone" ]
}
}

View File

@ -1,31 +0,0 @@
noinst_LTLIBRARIES = libbase.la
noinst_HEADERS = arraysize.h \
atomicops.h \
basictypes.h \
constructormagic.h \
safe_conversions.h \
safe_conversions_impl.h \
scoped_ptr.h \
template_util.h \
thread_annotations.h
libbase_la_SOURCES = criticalsection.cc \
criticalsection.h \
checks.cc \
checks.h \
event.cc \
event.h \
platform_thread.cc \
platform_thread.h \
platform_file.cc \
platform_file.h \
stringutils.cc \
stringutils.h \
thread_checker.h \
thread_checker_impl.cc \
thread_checker_impl.h
libbase_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS)
EXTRA_DIST = BUILD.gn

View File

@ -1,68 +0,0 @@
/*
* Copyright 2011 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_ATOMICOPS_H_
#define WEBRTC_BASE_ATOMICOPS_H_
#if defined(WEBRTC_WIN)
// Include winsock2.h before including <windows.h> to maintain consistency with
// win32.h. We can't include win32.h directly here since it pulls in
// headers such as basictypes.h which causes problems in Chromium where webrtc
// exists as two separate projects, webrtc and libjingle.
#include <winsock2.h>
#include <windows.h>
#endif // defined(WEBRTC_WIN)
namespace rtc {
class AtomicOps {
public:
#if defined(WEBRTC_WIN)
// Assumes sizeof(int) == sizeof(LONG), which it is on Win32 and Win64.
static int Increment(volatile int* i) {
return ::InterlockedIncrement(reinterpret_cast<volatile LONG*>(i));
}
static int Decrement(volatile int* i) {
return ::InterlockedDecrement(reinterpret_cast<volatile LONG*>(i));
}
static int AcquireLoad(volatile const int* i) {
return *i;
}
static void ReleaseStore(volatile int* i, int value) {
*i = value;
}
static int CompareAndSwap(volatile int* i, int old_value, int new_value) {
return ::InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(i),
new_value,
old_value);
}
#else
static int Increment(volatile int* i) {
return __sync_add_and_fetch(i, 1);
}
static int Decrement(volatile int* i) {
return __sync_sub_and_fetch(i, 1);
}
static int AcquireLoad(volatile const int* i) {
return __atomic_load_n(i, __ATOMIC_ACQUIRE);
}
static void ReleaseStore(volatile int* i, int value) {
__atomic_store_n(i, value, __ATOMIC_RELEASE);
}
static int CompareAndSwap(volatile int* i, int old_value, int new_value) {
return __sync_val_compare_and_swap(i, old_value, new_value);
}
#endif
};
}
#endif // WEBRTC_BASE_ATOMICOPS_H_

View File

@ -1,74 +0,0 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_BASICTYPES_H_
#define WEBRTC_BASE_BASICTYPES_H_
#include <stddef.h> // for NULL, size_t
#include <stdint.h> // for uintptr_t and (u)int_t types.
#ifdef HAVE_CONFIG_H
#include "config.h" // NOLINT
#endif
// Detect compiler is for x86 or x64.
#if defined(__x86_64__) || defined(_M_X64) || \
defined(__i386__) || defined(_M_IX86)
#define CPU_X86 1
#endif
// Detect compiler is for arm.
#if defined(__arm__) || defined(_M_ARM)
#define CPU_ARM 1
#endif
#if defined(CPU_X86) && defined(CPU_ARM)
#error CPU_X86 and CPU_ARM both defined.
#endif
#if !defined(RTC_ARCH_CPU_BIG_ENDIAN) && !defined(RTC_ARCH_CPU_LITTLE_ENDIAN)
// x86, arm or GCC provided __BYTE_ORDER__ macros
#if CPU_X86 || CPU_ARM || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define RTC_ARCH_CPU_LITTLE_ENDIAN
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define RTC_ARCH_CPU_BIG_ENDIAN
#else
#error RTC_ARCH_CPU_BIG_ENDIAN or RTC_ARCH_CPU_LITTLE_ENDIAN should be defined.
#endif
#endif
#if defined(RTC_ARCH_CPU_BIG_ENDIAN) && defined(RTC_ARCH_CPU_LITTLE_ENDIAN)
#error RTC_ARCH_CPU_BIG_ENDIAN and RTC_ARCH_CPU_LITTLE_ENDIAN both defined.
#endif
#if defined(WEBRTC_WIN)
typedef int socklen_t;
#endif
// The following only works for C++
#ifdef __cplusplus
#ifndef ALIGNP
#define ALIGNP(p, t) \
(reinterpret_cast<uint8_t*>(((reinterpret_cast<uintptr_t>(p) + \
((t) - 1)) & ~((t) - 1))))
#endif
#define RTC_IS_ALIGNED(p, a) (!((uintptr_t)(p) & ((a) - 1)))
// Use these to declare and define a static local variable that gets leaked so
// that its destructors are not called at exit.
#define RTC_DEFINE_STATIC_LOCAL(type, name, arguments) \
static type& name = *new type arguments
#endif // __cplusplus
#endif // WEBRTC_BASE_BASICTYPES_H_

View File

@ -1,127 +0,0 @@
/*
* Copyright 2006 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Most of this was borrowed (with minor modifications) from V8's and Chromium's
// src/base/logging.cc.
// Use the C++ version to provide __GLIBCXX__.
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#if defined(__GLIBCXX__) && !defined(__UCLIBC__)
#include <cxxabi.h>
#include <execinfo.h>
#endif
#if defined(WEBRTC_ANDROID)
#define LOG_TAG "rtc"
#include <android/log.h> // NOLINT
#endif
#include "webrtc/base/checks.h"
#if defined(_MSC_VER)
// Warning C4722: destructor never returns, potential memory leak.
// FatalMessage's dtor very intentionally aborts.
#pragma warning(disable:4722)
#endif
namespace rtc {
void VPrintError(const char* format, va_list args) {
#if defined(WEBRTC_ANDROID)
__android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args);
#else
vfprintf(stderr, format, args);
#endif
}
void PrintError(const char* format, ...) {
va_list args;
va_start(args, format);
VPrintError(format, args);
va_end(args);
}
// TODO(ajm): This works on Mac (although the parsing fails) but I don't seem
// to get usable symbols on Linux. This is copied from V8. Chromium has a more
// advanced stace trace system; also more difficult to copy.
void DumpBacktrace() {
#if defined(__GLIBCXX__) && !defined(__UCLIBC__)
void* trace[100];
int size = backtrace(trace, sizeof(trace) / sizeof(*trace));
char** symbols = backtrace_symbols(trace, size);
PrintError("\n==== C stack trace ===============================\n\n");
if (size == 0) {
PrintError("(empty)\n");
} else if (symbols == NULL) {
PrintError("(no symbols)\n");
} else {
for (int i = 1; i < size; ++i) {
char mangled[201];
if (sscanf(symbols[i], "%*[^(]%*[(]%200[^)+]", mangled) == 1) { // NOLINT
PrintError("%2d: ", i);
int status;
size_t length;
char* demangled = abi::__cxa_demangle(mangled, NULL, &length, &status);
PrintError("%s\n", demangled != NULL ? demangled : mangled);
free(demangled);
} else {
// If parsing failed, at least print the unparsed symbol.
PrintError("%s\n", symbols[i]);
}
}
}
free(symbols);
#endif
}
FatalMessage::FatalMessage(const char* file, int line) {
Init(file, line);
}
FatalMessage::FatalMessage(const char* file, int line, std::string* result) {
Init(file, line);
stream_ << "Check failed: " << *result << std::endl << "# ";
delete result;
}
NO_RETURN FatalMessage::~FatalMessage() {
fflush(stdout);
fflush(stderr);
stream_ << std::endl << "#" << std::endl;
PrintError(stream_.str().c_str());
DumpBacktrace();
fflush(stderr);
abort();
}
void FatalMessage::Init(const char* file, int line) {
stream_ << std::endl << std::endl << "#" << std::endl << "# Fatal error in "
<< file << ", line " << line << std::endl << "# ";
}
// MSVC doesn't like complex extern templates and DLLs.
#if !defined(COMPILER_MSVC)
// Explicit instantiations for commonly used comparisons.
template std::string* MakeCheckOpString<int, int>(
const int&, const int&, const char* names);
template std::string* MakeCheckOpString<unsigned long, unsigned long>(
const unsigned long&, const unsigned long&, const char* names);
template std::string* MakeCheckOpString<unsigned long, unsigned int>(
const unsigned long&, const unsigned int&, const char* names);
template std::string* MakeCheckOpString<unsigned int, unsigned long>(
const unsigned int&, const unsigned long&, const char* names);
template std::string* MakeCheckOpString<std::string, std::string>(
const std::string&, const std::string&, const char* name);
#endif
} // namespace rtc

View File

@ -1,229 +0,0 @@
/*
* Copyright 2006 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_CHECKS_H_
#define WEBRTC_BASE_CHECKS_H_
#include <sstream>
#include <string>
#include "webrtc/typedefs.h"
// The macros here print a message to stderr and abort under various
// conditions. All will accept additional stream messages. For example:
// RTC_DCHECK_EQ(foo, bar) << "I'm printed when foo != bar.";
//
// - RTC_CHECK(x) is an assertion that x is always true, and that if it isn't,
// it's better to terminate the process than to continue. During development,
// the reason that it's better to terminate might simply be that the error
// handling code isn't in place yet; in production, the reason might be that
// the author of the code truly believes that x will always be true, but that
// she recognizes that if she is wrong, abrupt and unpleasant process
// termination is still better than carrying on with the assumption violated.
//
// RTC_CHECK always evaluates its argument, so it's OK for x to have side
// effects.
//
// - RTC_DCHECK(x) is the same as RTC_CHECK(x)---an assertion that x is always
// true---except that x will only be evaluated in debug builds; in production
// builds, x is simply assumed to be true. This is useful if evaluating x is
// expensive and the expected cost of failing to detect the violated
// assumption is acceptable. You should not handle cases where a production
// build fails to spot a violated condition, even those that would result in
// crashes. If the code needs to cope with the error, make it cope, but don't
// call RTC_DCHECK; if the condition really can't occur, but you'd sleep
// better at night knowing that the process will suicide instead of carrying
// on in case you were wrong, use RTC_CHECK instead of RTC_DCHECK.
//
// RTC_DCHECK only evaluates its argument in debug builds, so if x has visible
// side effects, you need to write e.g.
// bool w = x; RTC_DCHECK(w);
//
// - RTC_CHECK_EQ, _NE, _GT, ..., and RTC_DCHECK_EQ, _NE, _GT, ... are
// specialized variants of RTC_CHECK and RTC_DCHECK that print prettier
// messages if the condition doesn't hold. Prefer them to raw RTC_CHECK and
// RTC_DCHECK.
//
// - FATAL() aborts unconditionally.
//
// TODO(ajm): Ideally, checks.h would be combined with logging.h, but
// consolidation with system_wrappers/logging.h should happen first.
namespace rtc {
// Helper macro which avoids evaluating the arguments to a stream if
// the condition doesn't hold.
#define RTC_LAZY_STREAM(stream, condition) \
!(condition) ? static_cast<void>(0) : rtc::FatalMessageVoidify() & (stream)
// The actual stream used isn't important. We reference condition in the code
// but don't evaluate it; this is to avoid "unused variable" warnings (we do so
// in a particularly convoluted way with an extra ?: because that appears to be
// the simplest construct that keeps Visual Studio from complaining about
// condition being unused).
#define RTC_EAT_STREAM_PARAMETERS(condition) \
(true ? true : !(condition)) \
? static_cast<void>(0) \
: rtc::FatalMessageVoidify() & rtc::FatalMessage("", 0).stream()
// RTC_CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode.
//
// We make sure RTC_CHECK et al. always evaluates their arguments, as
// doing RTC_CHECK(FunctionWithSideEffect()) is a common idiom.
#define RTC_CHECK(condition) \
RTC_LAZY_STREAM(rtc::FatalMessage(__FILE__, __LINE__).stream(), \
!(condition)) \
<< "Check failed: " #condition << std::endl << "# "
// Helper macro for binary operators.
// Don't use this macro directly in your code, use RTC_CHECK_EQ et al below.
//
// TODO(akalin): Rewrite this so that constructs like if (...)
// RTC_CHECK_EQ(...) else { ... } work properly.
#define RTC_CHECK_OP(name, op, val1, val2) \
if (std::string* _result = \
rtc::Check##name##Impl((val1), (val2), #val1 " " #op " " #val2)) \
rtc::FatalMessage(__FILE__, __LINE__, _result).stream()
// Build the error message string. This is separate from the "Impl"
// function template because it is not performance critical and so can
// be out of line, while the "Impl" code should be inline. Caller
// takes ownership of the returned string.
template<class t1, class t2>
std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
std::ostringstream ss;
ss << names << " (" << v1 << " vs. " << v2 << ")";
std::string* msg = new std::string(ss.str());
return msg;
}
// MSVC doesn't like complex extern templates and DLLs.
#if !defined(COMPILER_MSVC)
// Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated
// in logging.cc.
extern template std::string* MakeCheckOpString<int, int>(
const int&, const int&, const char* names);
extern template
std::string* MakeCheckOpString<unsigned long, unsigned long>(
const unsigned long&, const unsigned long&, const char* names);
extern template
std::string* MakeCheckOpString<unsigned long, unsigned int>(
const unsigned long&, const unsigned int&, const char* names);
extern template
std::string* MakeCheckOpString<unsigned int, unsigned long>(
const unsigned int&, const unsigned long&, const char* names);
extern template
std::string* MakeCheckOpString<std::string, std::string>(
const std::string&, const std::string&, const char* name);
#endif
// Helper functions for RTC_CHECK_OP macro.
// The (int, int) specialization works around the issue that the compiler
// will not instantiate the template version of the function on values of
// unnamed enum type - see comment below.
#define DEFINE_RTC_CHECK_OP_IMPL(name, op) \
template <class t1, class t2> \
inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
const char* names) { \
if (v1 op v2) \
return NULL; \
else \
return rtc::MakeCheckOpString(v1, v2, names); \
} \
inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \
if (v1 op v2) \
return NULL; \
else \
return rtc::MakeCheckOpString(v1, v2, names); \
}
DEFINE_RTC_CHECK_OP_IMPL(EQ, ==)
DEFINE_RTC_CHECK_OP_IMPL(NE, !=)
DEFINE_RTC_CHECK_OP_IMPL(LE, <=)
DEFINE_RTC_CHECK_OP_IMPL(LT, < )
DEFINE_RTC_CHECK_OP_IMPL(GE, >=)
DEFINE_RTC_CHECK_OP_IMPL(GT, > )
#undef DEFINE_RTC_CHECK_OP_IMPL
#define RTC_CHECK_EQ(val1, val2) RTC_CHECK_OP(EQ, ==, val1, val2)
#define RTC_CHECK_NE(val1, val2) RTC_CHECK_OP(NE, !=, val1, val2)
#define RTC_CHECK_LE(val1, val2) RTC_CHECK_OP(LE, <=, val1, val2)
#define RTC_CHECK_LT(val1, val2) RTC_CHECK_OP(LT, < , val1, val2)
#define RTC_CHECK_GE(val1, val2) RTC_CHECK_OP(GE, >=, val1, val2)
#define RTC_CHECK_GT(val1, val2) RTC_CHECK_OP(GT, > , val1, val2)
// The RTC_DCHECK macro is equivalent to RTC_CHECK except that it only generates
// code in debug builds. It does reference the condition parameter in all cases,
// though, so callers won't risk getting warnings about unused variables.
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
#define RTC_DCHECK_IS_ON 1
#define RTC_DCHECK(condition) RTC_CHECK(condition)
#define RTC_DCHECK_EQ(v1, v2) RTC_CHECK_EQ(v1, v2)
#define RTC_DCHECK_NE(v1, v2) RTC_CHECK_NE(v1, v2)
#define RTC_DCHECK_LE(v1, v2) RTC_CHECK_LE(v1, v2)
#define RTC_DCHECK_LT(v1, v2) RTC_CHECK_LT(v1, v2)
#define RTC_DCHECK_GE(v1, v2) RTC_CHECK_GE(v1, v2)
#define RTC_DCHECK_GT(v1, v2) RTC_CHECK_GT(v1, v2)
#else
#define RTC_DCHECK_IS_ON 0
#define RTC_DCHECK(condition) RTC_EAT_STREAM_PARAMETERS(condition)
#define RTC_DCHECK_EQ(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) == (v2))
#define RTC_DCHECK_NE(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) != (v2))
#define RTC_DCHECK_LE(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) <= (v2))
#define RTC_DCHECK_LT(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) < (v2))
#define RTC_DCHECK_GE(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) >= (v2))
#define RTC_DCHECK_GT(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) > (v2))
#endif
// This is identical to LogMessageVoidify but in name.
class FatalMessageVoidify {
public:
FatalMessageVoidify() { }
// This has to be an operator with a precedence lower than << but
// higher than ?:
void operator&(std::ostream&) { }
};
#define RTC_UNREACHABLE_CODE_HIT false
#define RTC_NOTREACHED() RTC_DCHECK(RTC_UNREACHABLE_CODE_HIT)
#define FATAL() rtc::FatalMessage(__FILE__, __LINE__).stream()
// TODO(ajm): Consider adding RTC_NOTIMPLEMENTED macro when
// base/logging.h and system_wrappers/logging.h are consolidated such that we
// can match the Chromium behavior.
// Like a stripped-down LogMessage from logging.h, except that it aborts.
class FatalMessage {
public:
FatalMessage(const char* file, int line);
// Used for RTC_CHECK_EQ(), etc. Takes ownership of the given string.
FatalMessage(const char* file, int line, std::string* result);
NO_RETURN ~FatalMessage();
std::ostream& stream() { return stream_; }
private:
void Init(const char* file, int line);
std::ostringstream stream_;
};
// Performs the integer division a/b and returns the result. CHECKs that the
// remainder is zero.
template <typename T>
inline T CheckedDivExact(T a, T b) {
RTC_CHECK_EQ(a % b, static_cast<T>(0));
return a / b;
}
} // namespace rtc
#endif // WEBRTC_BASE_CHECKS_H_

View File

@ -1,34 +0,0 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_CONSTRUCTORMAGIC_H_
#define WEBRTC_BASE_CONSTRUCTORMAGIC_H_
// Put this in the declarations for a class to be unassignable.
#define RTC_DISALLOW_ASSIGN(TypeName) \
void operator=(const TypeName&) = delete
// A macro to disallow the copy constructor and operator= functions. This should
// be used in the declarations for a class.
#define RTC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
RTC_DISALLOW_ASSIGN(TypeName)
// A macro to disallow all the implicit constructors, namely the default
// constructor, copy constructor and operator= functions.
//
// This should be used in the declarations for a class that wants to prevent
// anyone from instantiating it. This is especially useful for classes
// containing only static methods.
#define RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName() = delete; \
RTC_DISALLOW_COPY_AND_ASSIGN(TypeName)
#endif // WEBRTC_BASE_CONSTRUCTORMAGIC_H_

View File

@ -1,169 +0,0 @@
/*
* Copyright 2015 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/checks.h"
namespace rtc {
CriticalSection::CriticalSection() {
#if defined(WEBRTC_WIN)
InitializeCriticalSection(&crit_);
#else
pthread_mutexattr_t mutex_attribute;
pthread_mutexattr_init(&mutex_attribute);
pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex_, &mutex_attribute);
pthread_mutexattr_destroy(&mutex_attribute);
CS_DEBUG_CODE(thread_ = 0);
CS_DEBUG_CODE(recursion_count_ = 0);
#endif
}
CriticalSection::~CriticalSection() {
#if defined(WEBRTC_WIN)
DeleteCriticalSection(&crit_);
#else
pthread_mutex_destroy(&mutex_);
#endif
}
void CriticalSection::Enter() EXCLUSIVE_LOCK_FUNCTION() {
#if defined(WEBRTC_WIN)
EnterCriticalSection(&crit_);
#else
pthread_mutex_lock(&mutex_);
#if CS_DEBUG_CHECKS
if (!recursion_count_) {
RTC_DCHECK(!thread_);
thread_ = pthread_self();
} else {
RTC_DCHECK(CurrentThreadIsOwner());
}
++recursion_count_;
#endif
#endif
}
bool CriticalSection::TryEnter() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
#if defined(WEBRTC_WIN)
return TryEnterCriticalSection(&crit_) != FALSE;
#else
if (pthread_mutex_trylock(&mutex_) != 0)
return false;
#if CS_DEBUG_CHECKS
if (!recursion_count_) {
RTC_DCHECK(!thread_);
thread_ = pthread_self();
} else {
RTC_DCHECK(CurrentThreadIsOwner());
}
++recursion_count_;
#endif
return true;
#endif
}
void CriticalSection::Leave() UNLOCK_FUNCTION() {
RTC_DCHECK(CurrentThreadIsOwner());
#if defined(WEBRTC_WIN)
LeaveCriticalSection(&crit_);
#else
#if CS_DEBUG_CHECKS
--recursion_count_;
RTC_DCHECK(recursion_count_ >= 0);
if (!recursion_count_)
thread_ = 0;
#endif
pthread_mutex_unlock(&mutex_);
#endif
}
bool CriticalSection::CurrentThreadIsOwner() const {
#if defined(WEBRTC_WIN)
// OwningThread has type HANDLE but actually contains the Thread ID:
// http://stackoverflow.com/questions/12675301/why-is-the-owningthread-member-of-critical-section-of-type-handle-when-it-is-de
// Converting through size_t avoids the VS 2015 warning C4312: conversion from
// 'type1' to 'type2' of greater size
return crit_.OwningThread ==
reinterpret_cast<HANDLE>(static_cast<size_t>(GetCurrentThreadId()));
#else
#if CS_DEBUG_CHECKS
return pthread_equal(thread_, pthread_self());
#else
return true;
#endif // CS_DEBUG_CHECKS
#endif
}
bool CriticalSection::IsLocked() const {
#if defined(WEBRTC_WIN)
return crit_.LockCount != -1;
#else
#if CS_DEBUG_CHECKS
return thread_ != 0;
#else
return true;
#endif
#endif
}
CritScope::CritScope(CriticalSection* cs) : cs_(cs) { cs_->Enter(); }
CritScope::~CritScope() { cs_->Leave(); }
TryCritScope::TryCritScope(CriticalSection* cs)
: cs_(cs), locked_(cs->TryEnter()) {
CS_DEBUG_CODE(lock_was_called_ = false);
}
TryCritScope::~TryCritScope() {
CS_DEBUG_CODE(RTC_DCHECK(lock_was_called_));
if (locked_)
cs_->Leave();
}
bool TryCritScope::locked() const {
CS_DEBUG_CODE(lock_was_called_ = true);
return locked_;
}
void GlobalLockPod::Lock() {
#if !defined(WEBRTC_WIN)
const struct timespec ts_null = {0};
#endif
while (AtomicOps::CompareAndSwap(&lock_acquired, 0, 1)) {
#if defined(WEBRTC_WIN)
::Sleep(0);
#else
nanosleep(&ts_null, nullptr);
#endif
}
}
void GlobalLockPod::Unlock() {
int old_value = AtomicOps::CompareAndSwap(&lock_acquired, 1, 0);
RTC_DCHECK_EQ(1, old_value) << "Unlock called without calling Lock first";
}
GlobalLock::GlobalLock() {
lock_acquired = 0;
}
GlobalLockScope::GlobalLockScope(GlobalLockPod* lock)
: lock_(lock) {
lock_->Lock();
}
GlobalLockScope::~GlobalLockScope() {
lock_->Unlock();
}
} // namespace rtc

View File

@ -1,129 +0,0 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_CRITICALSECTION_H_
#define WEBRTC_BASE_CRITICALSECTION_H_
#include "webrtc/base/atomicops.h"
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/thread_annotations.h"
#if defined(WEBRTC_WIN)
// Include winsock2.h before including <windows.h> to maintain consistency with
// win32.h. We can't include win32.h directly here since it pulls in
// headers such as basictypes.h which causes problems in Chromium where webrtc
// exists as two separate projects, webrtc and libjingle.
#include <winsock2.h>
#include <windows.h>
#include <sal.h> // must come after windows headers.
#endif // defined(WEBRTC_WIN)
#if defined(WEBRTC_POSIX)
#include <pthread.h>
#endif
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
#define CS_DEBUG_CHECKS 1
#endif
#if CS_DEBUG_CHECKS
#define CS_DEBUG_CODE(x) x
#else // !CS_DEBUG_CHECKS
#define CS_DEBUG_CODE(x)
#endif // !CS_DEBUG_CHECKS
namespace rtc {
class LOCKABLE CriticalSection {
public:
CriticalSection();
~CriticalSection();
void Enter() EXCLUSIVE_LOCK_FUNCTION();
bool TryEnter() EXCLUSIVE_TRYLOCK_FUNCTION(true);
void Leave() UNLOCK_FUNCTION();
// Use only for RTC_DCHECKing.
bool CurrentThreadIsOwner() const;
// Use only for RTC_DCHECKing.
bool IsLocked() const;
private:
#if defined(WEBRTC_WIN)
CRITICAL_SECTION crit_;
#elif defined(WEBRTC_POSIX)
pthread_mutex_t mutex_;
CS_DEBUG_CODE(pthread_t thread_);
CS_DEBUG_CODE(int recursion_count_);
#endif
};
// CritScope, for serializing execution through a scope.
class SCOPED_LOCKABLE CritScope {
public:
explicit CritScope(CriticalSection* cs) EXCLUSIVE_LOCK_FUNCTION(cs);
~CritScope() UNLOCK_FUNCTION();
private:
CriticalSection* const cs_;
RTC_DISALLOW_COPY_AND_ASSIGN(CritScope);
};
// Tries to lock a critical section on construction via
// CriticalSection::TryEnter, and unlocks on destruction if the
// lock was taken. Never blocks.
//
// IMPORTANT: Unlike CritScope, the lock may not be owned by this thread in
// subsequent code. Users *must* check locked() to determine if the
// lock was taken. If you're not calling locked(), you're doing it wrong!
class TryCritScope {
public:
explicit TryCritScope(CriticalSection* cs);
~TryCritScope();
#if defined(WEBRTC_WIN)
_Check_return_ bool locked() const;
#else
bool locked() const __attribute__((warn_unused_result));
#endif
private:
CriticalSection* const cs_;
const bool locked_;
CS_DEBUG_CODE(mutable bool lock_was_called_);
RTC_DISALLOW_COPY_AND_ASSIGN(TryCritScope);
};
// A POD lock used to protect global variables. Do NOT use for other purposes.
// No custom constructor or private data member should be added.
class LOCKABLE GlobalLockPod {
public:
void Lock() EXCLUSIVE_LOCK_FUNCTION();
void Unlock() UNLOCK_FUNCTION();
volatile int lock_acquired;
};
class GlobalLock : public GlobalLockPod {
public:
GlobalLock();
};
// GlobalLockScope, for serializing execution through a scope.
class SCOPED_LOCKABLE GlobalLockScope {
public:
explicit GlobalLockScope(GlobalLockPod* lock) EXCLUSIVE_LOCK_FUNCTION(lock);
~GlobalLockScope() UNLOCK_FUNCTION();
private:
GlobalLockPod* const lock_;
RTC_DISALLOW_COPY_AND_ASSIGN(GlobalLockScope);
};
} // namespace rtc
#endif // WEBRTC_BASE_CRITICALSECTION_H_

View File

@ -1,135 +0,0 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/event.h"
#if defined(WEBRTC_WIN)
#include <windows.h>
#elif defined(WEBRTC_POSIX)
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#else
#error "Must define either WEBRTC_WIN or WEBRTC_POSIX."
#endif
#include "webrtc/base/checks.h"
namespace rtc {
#if defined(WEBRTC_WIN)
Event::Event(bool manual_reset, bool initially_signaled) {
event_handle_ = ::CreateEvent(NULL, // Security attributes.
manual_reset,
initially_signaled,
NULL); // Name.
RTC_CHECK(event_handle_);
}
Event::~Event() {
CloseHandle(event_handle_);
}
void Event::Set() {
SetEvent(event_handle_);
}
void Event::Reset() {
ResetEvent(event_handle_);
}
bool Event::Wait(int milliseconds) {
DWORD ms = (milliseconds == kForever) ? INFINITE : milliseconds;
return (WaitForSingleObject(event_handle_, ms) == WAIT_OBJECT_0);
}
#elif defined(WEBRTC_POSIX)
Event::Event(bool manual_reset, bool initially_signaled)
: is_manual_reset_(manual_reset),
event_status_(initially_signaled) {
RTC_CHECK(pthread_mutex_init(&event_mutex_, NULL) == 0);
RTC_CHECK(pthread_cond_init(&event_cond_, NULL) == 0);
}
Event::~Event() {
pthread_mutex_destroy(&event_mutex_);
pthread_cond_destroy(&event_cond_);
}
void Event::Set() {
pthread_mutex_lock(&event_mutex_);
event_status_ = true;
pthread_cond_broadcast(&event_cond_);
pthread_mutex_unlock(&event_mutex_);
}
void Event::Reset() {
pthread_mutex_lock(&event_mutex_);
event_status_ = false;
pthread_mutex_unlock(&event_mutex_);
}
bool Event::Wait(int milliseconds) {
pthread_mutex_lock(&event_mutex_);
int error = 0;
if (milliseconds != kForever) {
// Converting from seconds and microseconds (1e-6) plus
// milliseconds (1e-3) to seconds and nanoseconds (1e-9).
struct timespec ts;
#if HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
// Use relative time version, which tends to be more efficient for
// pthread implementations where provided (like on Android).
ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = (milliseconds % 1000) * 1000000;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
ts.tv_sec = tv.tv_sec + (milliseconds / 1000);
ts.tv_nsec = tv.tv_usec * 1000 + (milliseconds % 1000) * 1000000;
// Handle overflow.
if (ts.tv_nsec >= 1000000000) {
ts.tv_sec++;
ts.tv_nsec -= 1000000000;
}
#endif
while (!event_status_ && error == 0) {
#if HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
error = pthread_cond_timedwait_relative_np(
&event_cond_, &event_mutex_, &ts);
#else
error = pthread_cond_timedwait(&event_cond_, &event_mutex_, &ts);
#endif
}
} else {
while (!event_status_ && error == 0)
error = pthread_cond_wait(&event_cond_, &event_mutex_);
}
// NOTE(liulk): Exactly one thread will auto-reset this event. All
// the other threads will think it's unsignaled. This seems to be
// consistent with auto-reset events in WEBRTC_WIN
if (error == 0 && !is_manual_reset_)
event_status_ = false;
pthread_mutex_unlock(&event_mutex_);
return (error == 0);
}
#endif
} // namespace rtc

View File

@ -1,53 +0,0 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_EVENT_H__
#define WEBRTC_BASE_EVENT_H__
#if defined(WEBRTC_WIN)
#include "webrtc/base/win32.h" // NOLINT: consider this a system header.
#elif defined(WEBRTC_POSIX)
#include <pthread.h>
#else
#error "Must define either WEBRTC_WIN or WEBRTC_POSIX."
#endif
#include "webrtc/base/basictypes.h"
namespace rtc {
class Event {
public:
static const int kForever = -1;
Event(bool manual_reset, bool initially_signaled);
~Event();
void Set();
void Reset();
// Wait for the event to become signaled, for the specified number of
// |milliseconds|. To wait indefinetly, pass kForever.
bool Wait(int milliseconds);
private:
#if defined(WEBRTC_WIN)
HANDLE event_handle_;
#elif defined(WEBRTC_POSIX)
pthread_mutex_t event_mutex_;
pthread_cond_t event_cond_;
const bool is_manual_reset_;
bool event_status_;
#endif
};
} // namespace rtc
#endif // WEBRTC_BASE_EVENT_H__

View File

@ -1,110 +0,0 @@
/*
* Copyright 2015 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_MAYBE_H_
#define WEBRTC_BASE_MAYBE_H_
#include <algorithm>
#include <utility>
#include "webrtc/base/checks.h"
namespace rtc {
// Simple std::experimental::optional-wannabe. It either contains a T or not.
// In order to keep the implementation simple and portable, this implementation
// actually contains a (default-constructed) T even when it supposedly doesn't
// contain a value; use e.g. rtc::scoped_ptr<T> instead if that's too
// expensive.
//
// A moved-from Maybe<T> may only be destroyed, and assigned to if T allows
// being assigned to after having been moved from. Specifically, you may not
// assume that it just doesn't contain a value anymore.
//
// TODO(kwiberg): Get rid of this class when the standard library has
// std::optional (and we're allowed to use it).
template <typename T>
class Maybe final {
public:
// Construct an empty Maybe.
Maybe() : has_value_(false) {}
// Construct a Maybe that contains a value.
explicit Maybe(const T& val) : value_(val), has_value_(true) {}
explicit Maybe(T&& val) : value_(static_cast<T&&>(val)), has_value_(true) {}
// Copy and move constructors.
// TODO(kwiberg): =default the move constructor when MSVC supports it.
Maybe(const Maybe&) = default;
Maybe(Maybe&& m)
: value_(static_cast<T&&>(m.value_)), has_value_(m.has_value_) {}
// Assignment.
// TODO(kwiberg): =default the move assignment op when MSVC supports it.
Maybe& operator=(const Maybe&) = default;
Maybe& operator=(Maybe&& m) {
value_ = static_cast<T&&>(m.value_);
has_value_ = m.has_value_;
return *this;
}
friend void swap(Maybe& m1, Maybe& m2) {
using std::swap;
swap(m1.value_, m2.value_);
swap(m1.has_value_, m2.has_value_);
}
// Conversion to bool to test if we have a value.
explicit operator bool() const { return has_value_; }
// Dereferencing. Only allowed if we have a value.
const T* operator->() const {
RTC_DCHECK(has_value_);
return &value_;
}
T* operator->() {
RTC_DCHECK(has_value_);
return &value_;
}
const T& operator*() const {
RTC_DCHECK(has_value_);
return value_;
}
T& operator*() {
RTC_DCHECK(has_value_);
return value_;
}
// Dereference with a default value in case we don't have a value.
const T& value_or(const T& default_val) const {
return has_value_ ? value_ : default_val;
}
// Equality tests. Two Maybes are equal if they contain equivalent values, or
// if they're both empty.
friend bool operator==(const Maybe& m1, const Maybe& m2) {
return m1.has_value_ && m2.has_value_ ? m1.value_ == m2.value_
: m1.has_value_ == m2.has_value_;
}
friend bool operator!=(const Maybe& m1, const Maybe& m2) {
return m1.has_value_ && m2.has_value_ ? m1.value_ != m2.value_
: m1.has_value_ != m2.has_value_;
}
private:
// Invariant: Unless *this has been moved from, value_ is default-initialized
// (or copied or moved from a default-initialized T) if !has_value_.
T value_;
bool has_value_;
};
} // namespace rtc
#endif // WEBRTC_BASE_MAYBE_H_

View File

@ -1,49 +0,0 @@
/*
* Copyright 2014 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/platform_file.h"
#if defined(WEBRTC_WIN)
#include <io.h>
#else
#include <unistd.h>
#endif
namespace rtc {
#if defined(WEBRTC_WIN)
const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE;
FILE* FdopenPlatformFileForWriting(PlatformFile file) {
if (file == kInvalidPlatformFileValue)
return NULL;
int fd = _open_osfhandle(reinterpret_cast<intptr_t>(file), 0);
if (fd < 0)
return NULL;
return _fdopen(fd, "w");
}
bool ClosePlatformFile(PlatformFile file) {
return CloseHandle(file) != 0;
}
#else
const PlatformFile kInvalidPlatformFileValue = -1;
FILE* FdopenPlatformFileForWriting(PlatformFile file) {
return fdopen(file, "w");
}
bool ClosePlatformFile(PlatformFile file) {
return close(file);
}
#endif
} // namespace rtc

View File

@ -1,44 +0,0 @@
/*
* Copyright 2014 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_PLATFORM_FILE_H_
#define WEBRTC_BASE_PLATFORM_FILE_H_
#include <stdio.h>
#if defined(WEBRTC_WIN)
#include <windows.h>
#endif
namespace rtc {
#if defined(WEBRTC_WIN)
typedef HANDLE PlatformFile;
#elif defined(WEBRTC_POSIX)
typedef int PlatformFile;
#else
#error Unsupported platform
#endif
extern const PlatformFile kInvalidPlatformFileValue;
// Associates a standard FILE stream with an existing PlatformFile.
// Note that after this function has returned a valid FILE stream,
// the PlatformFile should no longer be used.
FILE* FdopenPlatformFileForWriting(PlatformFile file);
// Closes a PlatformFile.
// Don't use ClosePlatformFile to close a file opened with FdopenPlatformFile.
// Use fclose instead.
bool ClosePlatformFile(PlatformFile file);
} // namespace rtc
#endif // WEBRTC_BASE_PLATFORM_FILE_H_

View File

@ -1,82 +0,0 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/platform_thread.h"
#include <string.h>
#include "webrtc/base/checks.h"
#if defined(WEBRTC_LINUX)
#include <sys/prctl.h>
#include <sys/syscall.h>
#endif
namespace rtc {
PlatformThreadId CurrentThreadId() {
PlatformThreadId ret;
#if defined(WEBRTC_WIN)
ret = GetCurrentThreadId();
#elif defined(WEBRTC_POSIX)
#if defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
ret = pthread_mach_thread_np(pthread_self());
#elif defined(WEBRTC_LINUX)
ret = syscall(__NR_gettid);
#elif defined(WEBRTC_ANDROID)
ret = gettid();
#else
// Default implementation for nacl and solaris.
ret = reinterpret_cast<pid_t>(pthread_self());
#endif
#endif // defined(WEBRTC_POSIX)
RTC_DCHECK(ret);
return ret;
}
PlatformThreadRef CurrentThreadRef() {
#if defined(WEBRTC_WIN)
return GetCurrentThreadId();
#elif defined(WEBRTC_POSIX)
return pthread_self();
#endif
}
bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) {
#if defined(WEBRTC_WIN)
return a == b;
#elif defined(WEBRTC_POSIX)
return pthread_equal(a, b);
#endif
}
void SetCurrentThreadName(const char* name) {
RTC_DCHECK(strlen(name) < 64);
#if defined(WEBRTC_WIN)
struct {
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
} threadname_info = {0x1000, name, static_cast<DWORD>(-1), 0};
__try {
::RaiseException(0x406D1388, 0, sizeof(threadname_info) / sizeof(DWORD),
reinterpret_cast<ULONG_PTR*>(&threadname_info));
} __except (EXCEPTION_EXECUTE_HANDLER) {
}
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name));
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
pthread_setname_np(name);
#endif
}
} // namespace rtc

View File

@ -1,636 +0,0 @@
/*
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Borrowed from Chromium's src/base/memory/scoped_ptr.h.
// Scopers help you manage ownership of a pointer, helping you easily manage a
// pointer within a scope, and automatically destroying the pointer at the end
// of a scope. There are two main classes you will use, which correspond to the
// operators new/delete and new[]/delete[].
//
// Example usage (scoped_ptr<T>):
// {
// scoped_ptr<Foo> foo(new Foo("wee"));
// } // foo goes out of scope, releasing the pointer with it.
//
// {
// scoped_ptr<Foo> foo; // No pointer managed.
// foo.reset(new Foo("wee")); // Now a pointer is managed.
// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
// foo->Method(); // Foo::Method() called.
// foo.get()->Method(); // Foo::Method() called.
// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer
// // manages a pointer.
// foo.reset(new Foo("wee4")); // foo manages a pointer again.
// foo.reset(); // Foo("wee4") destroyed, foo no longer
// // manages a pointer.
// } // foo wasn't managing a pointer, so nothing was destroyed.
//
// Example usage (scoped_ptr<T[]>):
// {
// scoped_ptr<Foo[]> foo(new Foo[100]);
// foo.get()->Method(); // Foo::Method on the 0th element.
// foo[10].Method(); // Foo::Method on the 10th element.
// }
//
// These scopers also implement part of the functionality of C++11 unique_ptr
// in that they are "movable but not copyable." You can use the scopers in
// the parameter and return types of functions to signify ownership transfer
// in to and out of a function. When calling a function that has a scoper
// as the argument type, it must be called with the result of an analogous
// scoper's Pass() function or another function that generates a temporary;
// passing by copy will NOT work. Here is an example using scoped_ptr:
//
// void TakesOwnership(scoped_ptr<Foo> arg) {
// // Do something with arg
// }
// scoped_ptr<Foo> CreateFoo() {
// // No need for calling Pass() because we are constructing a temporary
// // for the return value.
// return scoped_ptr<Foo>(new Foo("new"));
// }
// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
// return arg.Pass();
// }
//
// {
// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay").
// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay").
// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo.
// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2.
// PassThru(ptr2.Pass()); // ptr2 is correspondingly nullptr.
// }
//
// Notice that if you do not call Pass() when returning from PassThru(), or
// when invoking TakesOwnership(), the code will not compile because scopers
// are not copyable; they only implement move semantics which require calling
// the Pass() function to signify a destructive transfer of state. CreateFoo()
// is different though because we are constructing a temporary on the return
// line and thus can avoid needing to call Pass().
//
// Pass() properly handles upcast in initialization, i.e. you can use a
// scoped_ptr<Child> to initialize a scoped_ptr<Parent>:
//
// scoped_ptr<Foo> foo(new Foo());
// scoped_ptr<FooParent> parent(foo.Pass());
//
// PassAs<>() should be used to upcast return value in return statement:
//
// scoped_ptr<Foo> CreateFoo() {
// scoped_ptr<FooChild> result(new FooChild());
// return result.PassAs<Foo>();
// }
//
// Note that PassAs<>() is implemented only for scoped_ptr<T>, but not for
// scoped_ptr<T[]>. This is because casting array pointers may not be safe.
#ifndef WEBRTC_BASE_SCOPED_PTR_H__
#define WEBRTC_BASE_SCOPED_PTR_H__
// This is an implementation designed to match the anticipated future TR2
// implementation of the scoped_ptr class.
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <algorithm> // For std::swap().
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/template_util.h"
#include "webrtc/typedefs.h"
namespace rtc {
// Function object which deletes its parameter, which must be a pointer.
// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
// invokes 'delete'. The default deleter for scoped_ptr<T>.
template <class T>
struct DefaultDeleter {
DefaultDeleter() {}
template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
// IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
// if U* is implicitly convertible to T* and U is not an array type.
//
// Correct implementation should use SFINAE to disable this
// constructor. However, since there are no other 1-argument constructors,
// using a static_assert based on is_convertible<> and requiring
// complete types is simpler and will cause compile failures for equivalent
// misuses.
//
// Note, the is_convertible<U*, T*> check also ensures that U is not an
// array. T is guaranteed to be a non-array, so any U* where U is an array
// cannot convert to T*.
enum { T_must_be_complete = sizeof(T) };
enum { U_must_be_complete = sizeof(U) };
static_assert(rtc::is_convertible<U*, T*>::value,
"U* must implicitly convert to T*");
}
inline void operator()(T* ptr) const {
enum { type_must_be_complete = sizeof(T) };
delete ptr;
}
};
// Specialization of DefaultDeleter for array types.
template <class T>
struct DefaultDeleter<T[]> {
inline void operator()(T* ptr) const {
enum { type_must_be_complete = sizeof(T) };
delete[] ptr;
}
private:
// Disable this operator for any U != T because it is undefined to execute
// an array delete when the static type of the array mismatches the dynamic
// type.
//
// References:
// C++98 [expr.delete]p3
// http://cplusplus.github.com/LWG/lwg-defects.html#938
template <typename U> void operator()(U* array) const;
};
template <class T, int n>
struct DefaultDeleter<T[n]> {
// Never allow someone to declare something like scoped_ptr<int[10]>.
static_assert(sizeof(T) == -1, "do not use array with size as type");
};
// Function object which invokes 'free' on its parameter, which must be
// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
//
// scoped_ptr<int, rtc::FreeDeleter> foo_ptr(
// static_cast<int*>(malloc(sizeof(int))));
struct FreeDeleter {
inline void operator()(void* ptr) const {
free(ptr);
}
};
namespace internal {
template <typename T>
struct ShouldAbortOnSelfReset {
template <typename U>
static rtc::internal::NoType Test(const typename U::AllowSelfReset*);
template <typename U>
static rtc::internal::YesType Test(...);
static const bool value =
sizeof(Test<T>(0)) == sizeof(rtc::internal::YesType);
};
// Minimal implementation of the core logic of scoped_ptr, suitable for
// reuse in both scoped_ptr and its specializations.
template <class T, class D>
class scoped_ptr_impl {
public:
explicit scoped_ptr_impl(T* p) : data_(p) {}
// Initializer for deleters that have data parameters.
scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
// Templated constructor that destructively takes the value from another
// scoped_ptr_impl.
template <typename U, typename V>
scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
: data_(other->release(), other->get_deleter()) {
// We do not support move-only deleters. We could modify our move
// emulation to have rtc::subtle::move() and rtc::subtle::forward()
// functions that are imperfect emulations of their C++11 equivalents,
// but until there's a requirement, just assume deleters are copyable.
}
template <typename U, typename V>
void TakeState(scoped_ptr_impl<U, V>* other) {
// See comment in templated constructor above regarding lack of support
// for move-only deleters.
reset(other->release());
get_deleter() = other->get_deleter();
}
~scoped_ptr_impl() {
if (data_.ptr != nullptr) {
// Not using get_deleter() saves one function call in non-optimized
// builds.
static_cast<D&>(data_)(data_.ptr);
}
}
void reset(T* p) {
// This is a self-reset, which is no longer allowed for default deleters:
// https://crbug.com/162971
assert(!ShouldAbortOnSelfReset<D>::value || p == nullptr || p != data_.ptr);
// Note that running data_.ptr = p can lead to undefined behavior if
// get_deleter()(get()) deletes this. In order to prevent this, reset()
// should update the stored pointer before deleting its old value.
//
// However, changing reset() to use that behavior may cause current code to
// break in unexpected ways. If the destruction of the owned object
// dereferences the scoped_ptr when it is destroyed by a call to reset(),
// then it will incorrectly dispatch calls to |p| rather than the original
// value of |data_.ptr|.
//
// During the transition period, set the stored pointer to nullptr while
// deleting the object. Eventually, this safety check will be removed to
// prevent the scenario initially described from occurring and
// http://crbug.com/176091 can be closed.
T* old = data_.ptr;
data_.ptr = nullptr;
if (old != nullptr)
static_cast<D&>(data_)(old);
data_.ptr = p;
}
T* get() const { return data_.ptr; }
D& get_deleter() { return data_; }
const D& get_deleter() const { return data_; }
void swap(scoped_ptr_impl& p2) {
// Standard swap idiom: 'using std::swap' ensures that std::swap is
// present in the overload set, but we call swap unqualified so that
// any more-specific overloads can be used, if available.
using std::swap;
swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
swap(data_.ptr, p2.data_.ptr);
}
T* release() {
T* old_ptr = data_.ptr;
data_.ptr = nullptr;
return old_ptr;
}
T** accept() {
reset(nullptr);
return &(data_.ptr);
}
T** use() {
return &(data_.ptr);
}
private:
// Needed to allow type-converting constructor.
template <typename U, typename V> friend class scoped_ptr_impl;
// Use the empty base class optimization to allow us to have a D
// member, while avoiding any space overhead for it when D is an
// empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
// discussion of this technique.
struct Data : public D {
explicit Data(T* ptr_in) : ptr(ptr_in) {}
Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
T* ptr;
};
Data data_;
RTC_DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
};
} // namespace internal
// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
// automatically deletes the pointer it holds (if any).
// That is, scoped_ptr<T> owns the T object that it points to.
// Like a T*, a scoped_ptr<T> may hold either nullptr or a pointer to a T
// object. Also like T*, scoped_ptr<T> is thread-compatible, and once you
// dereference it, you get the thread safety guarantees of T.
//
// The size of scoped_ptr is small. On most compilers, when using the
// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
// increase the size proportional to whatever state they need to have. See
// comments inside scoped_ptr_impl<> for details.
//
// Current implementation targets having a strict subset of C++11's
// unique_ptr<> features. Known deficiencies include not supporting move-only
// deleters, function pointers as deleters, and deleters with reference
// types.
template <class T, class D = rtc::DefaultDeleter<T> >
class scoped_ptr {
// TODO(ajm): If we ever import RefCountedBase, this check needs to be
// enabled.
//static_assert(rtc::internal::IsNotRefCounted<T>::value,
// "T is refcounted type and needs scoped refptr");
public:
// The element and deleter types.
typedef T element_type;
typedef D deleter_type;
// Constructor. Defaults to initializing with nullptr.
scoped_ptr() : impl_(nullptr) {}
// Constructor. Takes ownership of p.
explicit scoped_ptr(element_type* p) : impl_(p) {}
// Constructor. Allows initialization of a stateful deleter.
scoped_ptr(element_type* p, const D& d) : impl_(p, d) {}
// Constructor. Allows construction from a nullptr.
scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
// Constructor. Allows construction from a scoped_ptr rvalue for a
// convertible type and deleter.
//
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
// from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
// has different post-conditions if D is a reference type. Since this
// implementation does not support deleters with reference type,
// we do not need a separate move constructor allowing us to avoid one
// use of SFINAE. You only need to care about this if you modify the
// implementation of scoped_ptr.
template <typename U, typename V>
scoped_ptr(scoped_ptr<U, V>&& other)
: impl_(&other.impl_) {
static_assert(!rtc::is_array<U>::value, "U cannot be an array");
}
// operator=. Allows assignment from a scoped_ptr rvalue for a convertible
// type and deleter.
//
// IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
// the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
// form has different requirements on for move-only Deleters. Since this
// implementation does not support move-only Deleters, we do not need a
// separate move assignment operator allowing us to avoid one use of SFINAE.
// You only need to care about this if you modify the implementation of
// scoped_ptr.
template <typename U, typename V>
scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) {
static_assert(!rtc::is_array<U>::value, "U cannot be an array");
impl_.TakeState(&rhs.impl_);
return *this;
}
// operator=. Allows assignment from a nullptr. Deletes the currently owned
// object, if any.
scoped_ptr& operator=(decltype(nullptr)) {
reset();
return *this;
}
// Deleted copy constructor and copy assignment, to make the type move-only.
scoped_ptr(const scoped_ptr& other) = delete;
scoped_ptr& operator=(const scoped_ptr& other) = delete;
// Get an rvalue reference. (sp.Pass() does the same thing as std::move(sp).)
scoped_ptr&& Pass() { return static_cast<scoped_ptr&&>(*this); }
// Reset. Deletes the currently owned object, if any.
// Then takes ownership of a new object, if given.
void reset(element_type* p = nullptr) { impl_.reset(p); }
// Accessors to get the owned object.
// operator* and operator-> will assert() if there is no current object.
element_type& operator*() const {
assert(impl_.get() != nullptr);
return *impl_.get();
}
element_type* operator->() const {
assert(impl_.get() != nullptr);
return impl_.get();
}
element_type* get() const { return impl_.get(); }
// Access to the deleter.
deleter_type& get_deleter() { return impl_.get_deleter(); }
const deleter_type& get_deleter() const { return impl_.get_deleter(); }
// Allow scoped_ptr<element_type> to be used in boolean expressions, but not
// implicitly convertible to a real bool (which is dangerous).
//
// Note that this trick is only safe when the == and != operators
// are declared explicitly, as otherwise "scoped_ptr1 ==
// scoped_ptr2" will compile but do the wrong thing (i.e., convert
// to Testable and then do the comparison).
private:
typedef rtc::internal::scoped_ptr_impl<element_type, deleter_type>
scoped_ptr::*Testable;
public:
operator Testable() const {
return impl_.get() ? &scoped_ptr::impl_ : nullptr;
}
// Comparison operators.
// These return whether two scoped_ptr refer to the same object, not just to
// two different but equal objects.
bool operator==(const element_type* p) const { return impl_.get() == p; }
bool operator!=(const element_type* p) const { return impl_.get() != p; }
// Swap two scoped pointers.
void swap(scoped_ptr& p2) {
impl_.swap(p2.impl_);
}
// Release a pointer.
// The return value is the current pointer held by this object. If this object
// holds a nullptr, the return value is nullptr. After this operation, this
// object will hold a nullptr, and will not own the object any more.
element_type* release() WARN_UNUSED_RESULT {
return impl_.release();
}
// Delete the currently held pointer and return a pointer
// to allow overwriting of the current pointer address.
element_type** accept() WARN_UNUSED_RESULT {
return impl_.accept();
}
// Return a pointer to the current pointer address.
element_type** use() WARN_UNUSED_RESULT {
return impl_.use();
}
private:
// Needed to reach into |impl_| in the constructor.
template <typename U, typename V> friend class scoped_ptr;
rtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
// Forbidden for API compatibility with std::unique_ptr.
explicit scoped_ptr(int disallow_construction_from_null);
// Forbid comparison of scoped_ptr types. If U != T, it totally
// doesn't make sense, and if U == T, it still doesn't make sense
// because you should never have the same object owned by two different
// scoped_ptrs.
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
};
template <class T, class D>
class scoped_ptr<T[], D> {
public:
// The element and deleter types.
typedef T element_type;
typedef D deleter_type;
// Constructor. Defaults to initializing with nullptr.
scoped_ptr() : impl_(nullptr) {}
// Constructor. Stores the given array. Note that the argument's type
// must exactly match T*. In particular:
// - it cannot be a pointer to a type derived from T, because it is
// inherently unsafe in the general case to access an array through a
// pointer whose dynamic type does not match its static type (eg., if
// T and the derived types had different sizes access would be
// incorrectly calculated). Deletion is also always undefined
// (C++98 [expr.delete]p3). If you're doing this, fix your code.
// - it cannot be const-qualified differently from T per unique_ptr spec
// (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
// to work around this may use implicit_cast<const T*>().
// However, because of the first bullet in this comment, users MUST
// NOT use implicit_cast<Base*>() to upcast the static type of the array.
explicit scoped_ptr(element_type* array) : impl_(array) {}
// Constructor. Allows construction from a nullptr.
scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
// Constructor. Allows construction from a scoped_ptr rvalue.
scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {}
// operator=. Allows assignment from a scoped_ptr rvalue.
scoped_ptr& operator=(scoped_ptr&& rhs) {
impl_.TakeState(&rhs.impl_);
return *this;
}
// operator=. Allows assignment from a nullptr. Deletes the currently owned
// array, if any.
scoped_ptr& operator=(decltype(nullptr)) {
reset();
return *this;
}
// Deleted copy constructor and copy assignment, to make the type move-only.
scoped_ptr(const scoped_ptr& other) = delete;
scoped_ptr& operator=(const scoped_ptr& other) = delete;
// Get an rvalue reference. (sp.Pass() does the same thing as std::move(sp).)
scoped_ptr&& Pass() { return static_cast<scoped_ptr&&>(*this); }
// Reset. Deletes the currently owned array, if any.
// Then takes ownership of a new object, if given.
void reset(element_type* array = nullptr) { impl_.reset(array); }
// Accessors to get the owned array.
element_type& operator[](size_t i) const {
assert(impl_.get() != nullptr);
return impl_.get()[i];
}
element_type* get() const { return impl_.get(); }
// Access to the deleter.
deleter_type& get_deleter() { return impl_.get_deleter(); }
const deleter_type& get_deleter() const { return impl_.get_deleter(); }
// Allow scoped_ptr<element_type> to be used in boolean expressions, but not
// implicitly convertible to a real bool (which is dangerous).
private:
typedef rtc::internal::scoped_ptr_impl<element_type, deleter_type>
scoped_ptr::*Testable;
public:
operator Testable() const {
return impl_.get() ? &scoped_ptr::impl_ : nullptr;
}
// Comparison operators.
// These return whether two scoped_ptr refer to the same object, not just to
// two different but equal objects.
bool operator==(element_type* array) const { return impl_.get() == array; }
bool operator!=(element_type* array) const { return impl_.get() != array; }
// Swap two scoped pointers.
void swap(scoped_ptr& p2) {
impl_.swap(p2.impl_);
}
// Release a pointer.
// The return value is the current pointer held by this object. If this object
// holds a nullptr, the return value is nullptr. After this operation, this
// object will hold a nullptr, and will not own the object any more.
element_type* release() WARN_UNUSED_RESULT {
return impl_.release();
}
// Delete the currently held pointer and return a pointer
// to allow overwriting of the current pointer address.
element_type** accept() WARN_UNUSED_RESULT {
return impl_.accept();
}
// Return a pointer to the current pointer address.
element_type** use() WARN_UNUSED_RESULT {
return impl_.use();
}
private:
// Force element_type to be a complete type.
enum { type_must_be_complete = sizeof(element_type) };
// Actually hold the data.
rtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
// Disable initialization from any type other than element_type*, by
// providing a constructor that matches such an initialization, but is
// private and has no definition. This is disabled because it is not safe to
// call delete[] on an array whose static type does not match its dynamic
// type.
template <typename U> explicit scoped_ptr(U* array);
explicit scoped_ptr(int disallow_construction_from_null);
// Disable reset() from any type other than element_type*, for the same
// reasons as the constructor above.
template <typename U> void reset(U* array);
void reset(int disallow_reset_from_null);
// Forbid comparison of scoped_ptr types. If U != T, it totally
// doesn't make sense, and if U == T, it still doesn't make sense
// because you should never have the same object owned by two different
// scoped_ptrs.
template <class U> bool operator==(scoped_ptr<U> const& p2) const;
template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
};
template <class T, class D>
void swap(rtc::scoped_ptr<T, D>& p1, rtc::scoped_ptr<T, D>& p2) {
p1.swap(p2);
}
} // namespace rtc
template <class T, class D>
bool operator==(T* p1, const rtc::scoped_ptr<T, D>& p2) {
return p1 == p2.get();
}
template <class T, class D>
bool operator!=(T* p1, const rtc::scoped_ptr<T, D>& p2) {
return p1 != p2.get();
}
// A function to convert T* into scoped_ptr<T>
// Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
// for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
template <typename T>
rtc::scoped_ptr<T> rtc_make_scoped_ptr(T* ptr) {
return rtc::scoped_ptr<T>(ptr);
}
#endif // #ifndef WEBRTC_BASE_SCOPED_PTR_H__

View File

@ -1,133 +0,0 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/base/checks.h"
#include "webrtc/base/stringutils.h"
namespace rtc {
bool memory_check(const void* memory, int c, size_t count) {
const char* char_memory = static_cast<const char*>(memory);
char char_c = static_cast<char>(c);
for (size_t i = 0; i < count; ++i) {
if (char_memory[i] != char_c) {
return false;
}
}
return true;
}
bool string_match(const char* target, const char* pattern) {
while (*pattern) {
if (*pattern == '*') {
if (!*++pattern) {
return true;
}
while (*target) {
if ((toupper(*pattern) == toupper(*target))
&& string_match(target + 1, pattern + 1)) {
return true;
}
++target;
}
return false;
} else {
if (toupper(*pattern) != toupper(*target)) {
return false;
}
++target;
++pattern;
}
}
return !*target;
}
#if defined(WEBRTC_WIN)
int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n,
CharacterTransformation transformation) {
wchar_t c1, c2;
while (true) {
if (n-- == 0) return 0;
c1 = transformation(*s1);
// Double check that characters are not UTF-8
RTC_DCHECK_LT(static_cast<unsigned char>(*s2), 128);
// Note: *s2 gets implicitly promoted to wchar_t
c2 = transformation(*s2);
if (c1 != c2) return (c1 < c2) ? -1 : 1;
if (!c1) return 0;
++s1;
++s2;
}
}
size_t asccpyn(wchar_t* buffer, size_t buflen,
const char* source, size_t srclen) {
if (buflen <= 0)
return 0;
if (srclen == SIZE_UNKNOWN) {
srclen = strlenn(source, buflen - 1);
} else if (srclen >= buflen) {
srclen = buflen - 1;
}
#if !defined(NDEBUG)
// Double check that characters are not UTF-8
for (size_t pos = 0; pos < srclen; ++pos)
RTC_DCHECK_LT(static_cast<unsigned char>(source[pos]), 128);
#endif
std::copy(source, source + srclen, buffer);
buffer[srclen] = 0;
return srclen;
}
#endif // WEBRTC_WIN
void replace_substrs(const char *search,
size_t search_len,
const char *replace,
size_t replace_len,
std::string *s) {
size_t pos = 0;
while ((pos = s->find(search, pos, search_len)) != std::string::npos) {
s->replace(pos, search_len, replace, replace_len);
pos += replace_len;
}
}
bool starts_with(const char *s1, const char *s2) {
return strncmp(s1, s2, strlen(s2)) == 0;
}
bool ends_with(const char *s1, const char *s2) {
size_t s1_length = strlen(s1);
size_t s2_length = strlen(s2);
if (s2_length > s1_length) {
return false;
}
const char* start = s1 + (s1_length - s2_length);
return strncmp(start, s2, s2_length) == 0;
}
static const char kWhitespace[] = " \n\r\t";
std::string string_trim(const std::string& s) {
std::string::size_type first = s.find_first_not_of(kWhitespace);
std::string::size_type last = s.find_last_not_of(kWhitespace);
if (first == std::string::npos || last == std::string::npos) {
return std::string("");
}
return s.substr(first, last - first + 1);
}
} // namespace rtc

View File

@ -1,318 +0,0 @@
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_BASE_STRINGUTILS_H__
#define WEBRTC_BASE_STRINGUTILS_H__
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#if defined(WEBRTC_WIN)
#include <malloc.h>
#include <wchar.h>
#define alloca _alloca
#endif // WEBRTC_WIN
#if defined(WEBRTC_POSIX)
#ifdef BSD
#include <stdlib.h>
#else // BSD
#include <alloca.h>
#endif // !BSD
#endif // WEBRTC_POSIX
#include <string>
#include "webrtc/base/basictypes.h"
///////////////////////////////////////////////////////////////////////////////
// Generic string/memory utilities
///////////////////////////////////////////////////////////////////////////////
#define STACK_ARRAY(TYPE, LEN) static_cast<TYPE*>(::alloca((LEN)*sizeof(TYPE)))
namespace rtc {
// Complement to memset. Verifies memory consists of count bytes of value c.
bool memory_check(const void* memory, int c, size_t count);
// Determines whether the simple wildcard pattern matches target.
// Alpha characters in pattern match case-insensitively.
// Asterisks in pattern match 0 or more characters.
// Ex: string_match("www.TEST.GOOGLE.COM", "www.*.com") -> true
bool string_match(const char* target, const char* pattern);
} // namespace rtc
///////////////////////////////////////////////////////////////////////////////
// Rename a bunch of common string functions so they are consistent across
// platforms and between char and wchar_t variants.
// Here is the full list of functions that are unified:
// strlen, strcmp, stricmp, strncmp, strnicmp
// strchr, vsnprintf, strtoul, tolowercase
// tolowercase is like tolower, but not compatible with end-of-file value
//
// It's not clear if we will ever use wchar_t strings on unix. In theory,
// all strings should be Utf8 all the time, except when interfacing with Win32
// APIs that require Utf16.
///////////////////////////////////////////////////////////////////////////////
inline char tolowercase(char c) {
return static_cast<char>(tolower(c));
}
#if defined(WEBRTC_WIN)
inline size_t strlen(const wchar_t* s) {
return wcslen(s);
}
inline int strcmp(const wchar_t* s1, const wchar_t* s2) {
return wcscmp(s1, s2);
}
inline int stricmp(const wchar_t* s1, const wchar_t* s2) {
return _wcsicmp(s1, s2);
}
inline int strncmp(const wchar_t* s1, const wchar_t* s2, size_t n) {
return wcsncmp(s1, s2, n);
}
inline int strnicmp(const wchar_t* s1, const wchar_t* s2, size_t n) {
return _wcsnicmp(s1, s2, n);
}
inline const wchar_t* strchr(const wchar_t* s, wchar_t c) {
return wcschr(s, c);
}
inline const wchar_t* strstr(const wchar_t* haystack, const wchar_t* needle) {
return wcsstr(haystack, needle);
}
#ifndef vsnprintf
inline int vsnprintf(wchar_t* buf, size_t n, const wchar_t* fmt, va_list args) {
return _vsnwprintf(buf, n, fmt, args);
}
#endif // !vsnprintf
inline unsigned long strtoul(const wchar_t* snum, wchar_t** end, int base) {
return wcstoul(snum, end, base);
}
inline wchar_t tolowercase(wchar_t c) {
return static_cast<wchar_t>(towlower(c));
}
#endif // WEBRTC_WIN
#if defined(WEBRTC_POSIX)
inline int _stricmp(const char* s1, const char* s2) {
return strcasecmp(s1, s2);
}
inline int _strnicmp(const char* s1, const char* s2, size_t n) {
return strncasecmp(s1, s2, n);
}
#endif // WEBRTC_POSIX
///////////////////////////////////////////////////////////////////////////////
// Traits simplifies porting string functions to be CTYPE-agnostic
///////////////////////////////////////////////////////////////////////////////
namespace rtc {
const size_t SIZE_UNKNOWN = static_cast<size_t>(-1);
template<class CTYPE>
struct Traits {
// STL string type
//typedef XXX string;
// Null-terminated string
//inline static const CTYPE* empty_str();
};
///////////////////////////////////////////////////////////////////////////////
// String utilities which work with char or wchar_t
///////////////////////////////////////////////////////////////////////////////
template<class CTYPE>
inline const CTYPE* nonnull(const CTYPE* str, const CTYPE* def_str = NULL) {
return str ? str : (def_str ? def_str : Traits<CTYPE>::empty_str());
}
template<class CTYPE>
const CTYPE* strchr(const CTYPE* str, const CTYPE* chs) {
for (size_t i=0; str[i]; ++i) {
for (size_t j=0; chs[j]; ++j) {
if (str[i] == chs[j]) {
return str + i;
}
}
}
return 0;
}
template<class CTYPE>
const CTYPE* strchrn(const CTYPE* str, size_t slen, CTYPE ch) {
for (size_t i=0; i<slen && str[i]; ++i) {
if (str[i] == ch) {
return str + i;
}
}
return 0;
}
template<class CTYPE>
size_t strlenn(const CTYPE* buffer, size_t buflen) {
size_t bufpos = 0;
while (buffer[bufpos] && (bufpos < buflen)) {
++bufpos;
}
return bufpos;
}
// Safe versions of strncpy, strncat, snprintf and vsnprintf that always
// null-terminate.
template<class CTYPE>
size_t strcpyn(CTYPE* buffer, size_t buflen,
const CTYPE* source, size_t srclen = SIZE_UNKNOWN) {
if (buflen <= 0)
return 0;
if (srclen == SIZE_UNKNOWN) {
srclen = strlenn(source, buflen - 1);
} else if (srclen >= buflen) {
srclen = buflen - 1;
}
memcpy(buffer, source, srclen * sizeof(CTYPE));
buffer[srclen] = 0;
return srclen;
}
template<class CTYPE>
size_t strcatn(CTYPE* buffer, size_t buflen,
const CTYPE* source, size_t srclen = SIZE_UNKNOWN) {
if (buflen <= 0)
return 0;
size_t bufpos = strlenn(buffer, buflen - 1);
return bufpos + strcpyn(buffer + bufpos, buflen - bufpos, source, srclen);
}
// Some compilers (clang specifically) require vsprintfn be defined before
// sprintfn.
template<class CTYPE>
size_t vsprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format,
va_list args) {
int len = vsnprintf(buffer, buflen, format, args);
if ((len < 0) || (static_cast<size_t>(len) >= buflen)) {
len = static_cast<int>(buflen - 1);
buffer[len] = 0;
}
return len;
}
template<class CTYPE>
size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...);
template<class CTYPE>
size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...) {
va_list args;
va_start(args, format);
size_t len = vsprintfn(buffer, buflen, format, args);
va_end(args);
return len;
}
///////////////////////////////////////////////////////////////////////////////
// Allow safe comparing and copying ascii (not UTF-8) with both wide and
// non-wide character strings.
///////////////////////////////////////////////////////////////////////////////
inline int asccmp(const char* s1, const char* s2) {
return strcmp(s1, s2);
}
inline int ascicmp(const char* s1, const char* s2) {
return _stricmp(s1, s2);
}
inline int ascncmp(const char* s1, const char* s2, size_t n) {
return strncmp(s1, s2, n);
}
inline int ascnicmp(const char* s1, const char* s2, size_t n) {
return _strnicmp(s1, s2, n);
}
inline size_t asccpyn(char* buffer, size_t buflen,
const char* source, size_t srclen = SIZE_UNKNOWN) {
return strcpyn(buffer, buflen, source, srclen);
}
#if defined(WEBRTC_WIN)
typedef wchar_t(*CharacterTransformation)(wchar_t);
inline wchar_t identity(wchar_t c) { return c; }
int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n,
CharacterTransformation transformation);
inline int asccmp(const wchar_t* s1, const char* s2) {
return ascii_string_compare(s1, s2, static_cast<size_t>(-1), identity);
}
inline int ascicmp(const wchar_t* s1, const char* s2) {
return ascii_string_compare(s1, s2, static_cast<size_t>(-1), tolowercase);
}
inline int ascncmp(const wchar_t* s1, const char* s2, size_t n) {
return ascii_string_compare(s1, s2, n, identity);
}
inline int ascnicmp(const wchar_t* s1, const char* s2, size_t n) {
return ascii_string_compare(s1, s2, n, tolowercase);
}
size_t asccpyn(wchar_t* buffer, size_t buflen,
const char* source, size_t srclen = SIZE_UNKNOWN);
#endif // WEBRTC_WIN
///////////////////////////////////////////////////////////////////////////////
// Traits<char> specializations
///////////////////////////////////////////////////////////////////////////////
template<>
struct Traits<char> {
typedef std::string string;
inline static const char* empty_str() { return ""; }
};
///////////////////////////////////////////////////////////////////////////////
// Traits<wchar_t> specializations (Windows only, currently)
///////////////////////////////////////////////////////////////////////////////
#if defined(WEBRTC_WIN)
template<>
struct Traits<wchar_t> {
typedef std::wstring string;
inline static const wchar_t* empty_str() { return L""; }
};
#endif // WEBRTC_WIN
// Replaces all occurrences of "search" with "replace".
void replace_substrs(const char *search,
size_t search_len,
const char *replace,
size_t replace_len,
std::string *s);
// True iff s1 starts with s2.
bool starts_with(const char *s1, const char *s2);
// True iff s1 ends with s2.
bool ends_with(const char *s1, const char *s2);
// Remove leading and trailing whitespaces.
std::string string_trim(const std::string& s);
} // namespace rtc
#endif // WEBRTC_BASE_STRINGUTILS_H__

View File

@ -1,127 +0,0 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Borrowed from Chromium's src/base/template_util.h.
#ifndef WEBRTC_BASE_TEMPLATE_UTIL_H_
#define WEBRTC_BASE_TEMPLATE_UTIL_H_
#include <stddef.h> // For size_t.
namespace rtc {
// Template definitions from tr1.
template<class T, T v>
struct integral_constant {
static const T value = v;
typedef T value_type;
typedef integral_constant<T, v> type;
};
template <class T, T v> const T integral_constant<T, v>::value;
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
template <class T> struct is_pointer : false_type {};
template <class T> struct is_pointer<T*> : true_type {};
template <class T, class U> struct is_same : public false_type {};
template <class T> struct is_same<T, T> : true_type {};
template<class> struct is_array : public false_type {};
template<class T, size_t n> struct is_array<T[n]> : public true_type {};
template<class T> struct is_array<T[]> : public true_type {};
template <class T> struct is_non_const_reference : false_type {};
template <class T> struct is_non_const_reference<T&> : true_type {};
template <class T> struct is_non_const_reference<const T&> : false_type {};
template <class T> struct is_void : false_type {};
template <> struct is_void<void> : true_type {};
template <class T>
struct remove_reference {
typedef T type;
};
template <class T>
struct remove_reference<T&> {
typedef T type;
};
template <class T>
struct remove_reference<T&&> {
typedef T type;
};
namespace internal {
// Types YesType and NoType are guaranteed such that sizeof(YesType) <
// sizeof(NoType).
typedef char YesType;
struct NoType {
YesType dummy[2];
};
// This class is an implementation detail for is_convertible, and you
// don't need to know how it works to use is_convertible. For those
// who care: we declare two different functions, one whose argument is
// of type To and one with a variadic argument list. We give them
// return types of different size, so we can use sizeof to trick the
// compiler into telling us which function it would have chosen if we
// had called it with an argument of type From. See Alexandrescu's
// _Modern C++ Design_ for more details on this sort of trick.
struct ConvertHelper {
template <typename To>
static YesType Test(To);
template <typename To>
static NoType Test(...);
template <typename From>
static From& Create();
};
// Used to determine if a type is a struct/union/class. Inspired by Boost's
// is_class type_trait implementation.
struct IsClassHelper {
template <typename C>
static YesType Test(void(C::*)(void));
template <typename C>
static NoType Test(...);
};
} // namespace internal
// Inherits from true_type if From is convertible to To, false_type otherwise.
//
// Note that if the type is convertible, this will be a true_type REGARDLESS
// of whether or not the conversion would emit a warning.
template <typename From, typename To>
struct is_convertible
: integral_constant<bool,
sizeof(internal::ConvertHelper::Test<To>(
internal::ConvertHelper::Create<From>())) ==
sizeof(internal::YesType)> {
};
template <typename T>
struct is_class
: integral_constant<bool,
sizeof(internal::IsClassHelper::Test<T>(0)) ==
sizeof(internal::YesType)> {
};
} // namespace rtc
#endif // WEBRTC_BASE_TEMPLATE_UTIL_H_

View File

@ -1,99 +0,0 @@
//
// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//
// Borrowed from
// https://code.google.com/p/gperftools/source/browse/src/base/thread_annotations.h
// but adapted for clang attributes instead of the gcc.
//
// This header file contains the macro definitions for thread safety
// annotations that allow the developers to document the locking policies
// of their multi-threaded code. The annotations can also help program
// analysis tools to identify potential thread safety issues.
#ifndef BASE_THREAD_ANNOTATIONS_H_
#define BASE_THREAD_ANNOTATIONS_H_
#if defined(__clang__) && (!defined(SWIG))
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
#endif
// Document if a shared variable/field needs to be protected by a lock.
// GUARDED_BY allows the user to specify a particular lock that should be
// held when accessing the annotated variable, while GUARDED_VAR only
// indicates a shared variable should be guarded (by any lock). GUARDED_VAR
// is primarily used when the client cannot express the name of the lock.
#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
#define GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(guarded)
// Document if the memory location pointed to by a pointer should be guarded
// by a lock when dereferencing the pointer. Similar to GUARDED_VAR,
// PT_GUARDED_VAR is primarily used when the client cannot express the name
// of the lock. Note that a pointer variable to a shared memory location
// could itself be a shared variable. For example, if a shared global pointer
// q, which is guarded by mu1, points to a shared memory location that is
// guarded by mu2, q should be annotated as follows:
// int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded_by(x))
#define PT_GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded)
// Document the acquisition order between locks that can be held
// simultaneously by a thread. For any two locks that need to be annotated
// to establish an acquisition order, only one of them needs the annotation.
// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER
// and ACQUIRED_BEFORE.)
#define ACQUIRED_AFTER(x) THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(x))
#define ACQUIRED_BEFORE(x) THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(x))
// The following three annotations document the lock requirements for
// functions/methods.
// Document if a function expects certain locks to be held before it is called
#define EXCLUSIVE_LOCKS_REQUIRED(...) \
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
#define SHARED_LOCKS_REQUIRED(...) \
THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
// Document the locks acquired in the body of the function. These locks
// cannot be held when calling this function (as google3's Mutex locks are
// non-reentrant).
#define LOCKS_EXCLUDED(x) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(x))
// Document the lock the annotated function returns without acquiring it.
#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
// Document if a class/type is a lockable type (such as the Mutex class).
#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable)
// Document if a class is a scoped lockable type (such as the MutexLock class).
#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
// The following annotations specify lock and unlock primitives.
#define EXCLUSIVE_LOCK_FUNCTION(...) \
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
#define SHARED_LOCK_FUNCTION(...) \
THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
#define SHARED_TRYLOCK_FUNCTION(...) \
THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
#define UNLOCK_FUNCTION(...) \
THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
// An escape hatch for thread safety analysis to ignore the annotated function.
#define NO_THREAD_SAFETY_ANALYSIS \
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
#endif // BASE_THREAD_ANNOTATIONS_H_

View File

@ -1,91 +0,0 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Borrowed from Chromium's src/base/threading/thread_checker.h.
#ifndef WEBRTC_BASE_THREAD_CHECKER_H_
#define WEBRTC_BASE_THREAD_CHECKER_H_
// Apart from debug builds, we also enable the thread checker in
// builds with DCHECK_ALWAYS_ON so that trybots and waterfall bots
// with this define will get the same level of thread checking as
// debug bots.
//
// Note that this does not perfectly match situations where RTC_DCHECK is
// enabled. For example a non-official release build may have
// DCHECK_ALWAYS_ON undefined (and therefore ThreadChecker would be
// disabled) but have RTC_DCHECKs enabled at runtime.
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
#define ENABLE_THREAD_CHECKER 1
#else
#define ENABLE_THREAD_CHECKER 0
#endif
#include "webrtc/base/thread_checker_impl.h"
namespace rtc {
// Do nothing implementation, for use in release mode.
//
// Note: You should almost always use the ThreadChecker class to get the
// right version for your build configuration.
class ThreadCheckerDoNothing {
public:
bool CalledOnValidThread() const {
return true;
}
void DetachFromThread() {}
};
// ThreadChecker is a helper class used to help verify that some methods of a
// class are called from the same thread. It provides identical functionality to
// base::NonThreadSafe, but it is meant to be held as a member variable, rather
// than inherited from base::NonThreadSafe.
//
// While inheriting from base::NonThreadSafe may give a clear indication about
// the thread-safety of a class, it may also lead to violations of the style
// guide with regard to multiple inheritance. The choice between having a
// ThreadChecker member and inheriting from base::NonThreadSafe should be based
// on whether:
// - Derived classes need to know the thread they belong to, as opposed to
// having that functionality fully encapsulated in the base class.
// - Derived classes should be able to reassign the base class to another
// thread, via DetachFromThread.
//
// If neither of these are true, then having a ThreadChecker member and calling
// CalledOnValidThread is the preferable solution.
//
// Example:
// class MyClass {
// public:
// void Foo() {
// RTC_DCHECK(thread_checker_.CalledOnValidThread());
// ... (do stuff) ...
// }
//
// private:
// ThreadChecker thread_checker_;
// }
//
// In Release mode, CalledOnValidThread will always return true.
#if ENABLE_THREAD_CHECKER
class ThreadChecker : public ThreadCheckerImpl {
};
#else
class ThreadChecker : public ThreadCheckerDoNothing {
};
#endif // ENABLE_THREAD_CHECKER
#undef ENABLE_THREAD_CHECKER
} // namespace rtc
#endif // WEBRTC_BASE_THREAD_CHECKER_H_

View File

@ -1,36 +0,0 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Borrowed from Chromium's src/base/threading/thread_checker_impl.cc.
#include "webrtc/base/thread_checker_impl.h"
namespace rtc {
ThreadCheckerImpl::ThreadCheckerImpl() : valid_thread_(CurrentThreadRef()) {
}
ThreadCheckerImpl::~ThreadCheckerImpl() {
}
bool ThreadCheckerImpl::CalledOnValidThread() const {
const PlatformThreadRef current_thread = CurrentThreadRef();
CritScope scoped_lock(&lock_);
if (!valid_thread_) // Set if previously detached.
valid_thread_ = current_thread;
return IsThreadRefEqual(valid_thread_, current_thread);
}
void ThreadCheckerImpl::DetachFromThread() {
CritScope scoped_lock(&lock_);
valid_thread_ = 0;
}
} // namespace rtc

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Borrowed from Chromium's src/base/threading/thread_checker_impl.h.
#ifndef WEBRTC_BASE_THREAD_CHECKER_IMPL_H_
#define WEBRTC_BASE_THREAD_CHECKER_IMPL_H_
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/platform_thread.h"
namespace rtc {
// Real implementation of ThreadChecker, for use in debug mode, or
// for temporary use in release mode (e.g. to RTC_CHECK on a threading issue
// seen only in the wild).
//
// Note: You should almost always use the ThreadChecker class to get the
// right version for your build configuration.
class ThreadCheckerImpl {
public:
ThreadCheckerImpl();
~ThreadCheckerImpl();
bool CalledOnValidThread() const;
// Changes the thread that is checked for in CalledOnValidThread. This may
// be useful when an object may be created on one thread and then used
// exclusively on another thread.
void DetachFromThread();
private:
mutable CriticalSection lock_;
// This is mutable so that CalledOnValidThread can set it.
// It's guarded by |lock_|.
mutable PlatformThreadRef valid_thread_;
};
} // namespace rtc
#endif // WEBRTC_BASE_THREAD_CHECKER_IMPL_H_

View File

@ -1,124 +0,0 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_COMMON_H_
#define WEBRTC_COMMON_H_
#include <map>
#include "webrtc/base/basictypes.h"
namespace webrtc {
// Class Config is designed to ease passing a set of options across webrtc code.
// Options are identified by typename in order to avoid incorrect casts.
//
// Usage:
// * declaring an option:
// struct Algo1_CostFunction {
// virtual float cost(int x) const { return x; }
// virtual ~Algo1_CostFunction() {}
// };
//
// * accessing an option:
// config.Get<Algo1_CostFunction>().cost(value);
//
// * setting an option:
// struct SqrCost : Algo1_CostFunction {
// virtual float cost(int x) const { return x*x; }
// };
// config.Set<Algo1_CostFunction>(new SqrCost());
//
// Note: This class is thread-compatible (like STL containers).
class Config {
public:
// Returns the option if set or a default constructed one.
// Callers that access options too often are encouraged to cache the result.
// Returned references are owned by this.
//
// Requires std::is_default_constructible<T>
template<typename T> const T& Get() const;
// Set the option, deleting any previous instance of the same.
// This instance gets ownership of the newly set value.
template<typename T> void Set(T* value);
Config() {}
~Config() {
// Note: this method is inline so webrtc public API depends only
// on the headers.
for (OptionMap::iterator it = options_.begin();
it != options_.end(); ++it) {
delete it->second;
}
}
private:
typedef void* OptionIdentifier;
struct BaseOption {
virtual ~BaseOption() {}
};
template<typename T>
struct Option : BaseOption {
explicit Option(T* v): value(v) {}
~Option() {
delete value;
}
T* value;
};
// Own implementation of rtti-subset to avoid depending on rtti and its costs.
template<typename T>
static OptionIdentifier identifier() {
static char id_placeholder;
return &id_placeholder;
}
// Used to instantiate a default constructed object that doesn't needs to be
// owned. This allows Get<T> to be implemented without requiring explicitly
// locks.
template<typename T>
static const T& default_value() {
RTC_DEFINE_STATIC_LOCAL(const T, def, ());
return def;
}
typedef std::map<OptionIdentifier, BaseOption*> OptionMap;
OptionMap options_;
// RTC_DISALLOW_COPY_AND_ASSIGN
Config(const Config&);
void operator=(const Config&);
};
template<typename T>
const T& Config::Get() const {
OptionMap::const_iterator it = options_.find(identifier<T>());
if (it != options_.end()) {
const T* t = static_cast<Option<T>*>(it->second)->value;
if (t) {
return *t;
}
}
return default_value<T>();
}
template<typename T>
void Config::Set(T* value) {
BaseOption*& it = options_[identifier<T>()];
delete it;
it = new Option<T>(value);
}
} // namespace webrtc
#endif // WEBRTC_COMMON_H_

View File

@ -6,37 +6,19 @@
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import("//build/config/arm.gni")
import("../build/webrtc.gni")
import("../webrtc.gni")
config("common_audio_config") {
include_dirs = [
"resampler/include",
"signal_processing/include",
"vad/include",
]
}
visibility = [ ":*" ]
source_set("common_audio") {
rtc_library("common_audio") {
visibility += [ "*" ]
sources = [
"audio_converter.cc",
"audio_converter.h",
"audio_ring_buffer.cc",
"audio_ring_buffer.h",
"audio_util.cc",
"blocker.cc",
"blocker.h",
"channel_buffer.cc",
"channel_buffer.h",
"fft4g.c",
"fft4g.h",
"fir_filter.cc",
"fir_filter.h",
"fir_filter_neon.h",
"fir_filter_sse.h",
"include/audio_util.h",
"lapped_transform.cc",
"lapped_transform.h",
"real_fourier.cc",
"real_fourier.h",
"real_fourier_ooura.cc",
@ -48,7 +30,79 @@ source_set("common_audio") {
"resampler/push_sinc_resampler.h",
"resampler/resampler.cc",
"resampler/sinc_resampler.cc",
"resampler/sinc_resampler.h",
"smoothing_filter.cc",
"smoothing_filter.h",
"vad/include/vad.h",
"vad/vad.cc",
"wav_file.cc",
"wav_file.h",
"wav_header.cc",
"wav_header.h",
"window_generator.cc",
"window_generator.h",
]
deps = [
":common_audio_c",
":sinc_resampler",
"../api:array_view",
"../api/audio:audio_frame_api",
"../rtc_base:checks",
"../rtc_base:gtest_prod",
"../rtc_base:logging",
"../rtc_base:safe_conversions",
"../rtc_base:sanitizer",
"../rtc_base:timeutils",
"../rtc_base/memory:aligned_malloc",
"../rtc_base/system:arch",
"../rtc_base/system:file_wrapper",
"../system_wrappers",
"third_party/ooura:fft_size_256",
]
defines = []
if (rtc_build_with_neon) {
deps += [ ":common_audio_neon" ]
}
if (current_cpu == "x86" || current_cpu == "x64") {
deps += [ ":common_audio_sse2" ]
deps += [ ":common_audio_avx2" ]
}
}
rtc_source_set("mock_common_audio") {
visibility += webrtc_default_visibility
testonly = true
sources = [
"mocks/mock_smoothing_filter.h",
"vad/mock/mock_vad.h",
]
deps = [
":common_audio",
"../test:test_support",
]
}
rtc_source_set("common_audio_c_arm_asm") {
sources = []
deps = []
if (current_cpu == "arm") {
sources += [ "signal_processing/complex_bit_reverse_arm.S" ]
if (arm_version >= 7) {
sources += [ "signal_processing/filter_ar_fast_q12_armv7.S" ]
} else {
sources += [ "signal_processing/filter_ar_fast_q12.c" ]
}
deps += [ "../rtc_base/system:asm_defines" ]
}
}
rtc_library("common_audio_c") {
visibility += webrtc_default_visibility
sources = [
"ring_buffer.c",
"ring_buffer.h",
"signal_processing/auto_corr_to_refl_coef.c",
@ -57,7 +111,6 @@ source_set("common_audio") {
"signal_processing/copy_set_operations.c",
"signal_processing/cross_correlation.c",
"signal_processing/division_operations.c",
"signal_processing/dot_product_with_scale.c",
"signal_processing/downsample_fast.c",
"signal_processing/energy.c",
"signal_processing/filter_ar.c",
@ -68,6 +121,7 @@ source_set("common_audio") {
"signal_processing/include/real_fft.h",
"signal_processing/include/signal_processing_library.h",
"signal_processing/include/spl_inl.h",
"signal_processing/include/spl_inl_armv7.h",
"signal_processing/levinson_durbin.c",
"signal_processing/lpc_to_refl_coef.c",
"signal_processing/min_max_operations.c",
@ -81,15 +135,12 @@ source_set("common_audio") {
"signal_processing/resample_by_2_internal.h",
"signal_processing/resample_fractional.c",
"signal_processing/spl_init.c",
"signal_processing/spl_inl.c",
"signal_processing/spl_sqrt.c",
"signal_processing/splitting_filter.c",
"signal_processing/sqrt_of_one_minus_x_squared.c",
"signal_processing/vector_scaling_operations.c",
"sparse_fir_filter.cc",
"sparse_fir_filter.h",
"vad/include/vad.h",
"vad/include/webrtc_vad.h",
"vad/vad.cc",
"vad/vad_core.c",
"vad/vad_core.h",
"vad/vad_filterbank.c",
@ -99,47 +150,8 @@ source_set("common_audio") {
"vad/vad_sp.c",
"vad/vad_sp.h",
"vad/webrtc_vad.c",
"wav_file.cc",
"wav_file.h",
"wav_header.cc",
"wav_header.h",
"window_generator.cc",
"window_generator.h",
]
deps = [
"../system_wrappers",
]
defines = []
if (rtc_use_openmax_dl) {
sources += [
"real_fourier_openmax.cc",
"real_fourier_openmax.h",
]
defines += [ "RTC_USE_OPENMAX_DL" ]
if (rtc_build_openmax_dl) {
deps += [ "//third_party/openmax_dl/dl" ]
}
}
if (current_cpu == "arm") {
sources += [
"signal_processing/complex_bit_reverse_arm.S",
"signal_processing/spl_sqrt_floor_arm.S",
]
if (arm_version >= 7) {
sources += [ "signal_processing/filter_ar_fast_q12_armv7.S" ]
} else {
sources += [ "signal_processing/filter_ar_fast_q12.c" ]
}
}
if (rtc_build_with_neon) {
deps += [ ":common_audio_neon" ]
}
if (current_cpu == "mipsel") {
sources += [
"signal_processing/complex_bit_reverse_mips.c",
@ -150,7 +162,6 @@ source_set("common_audio") {
"signal_processing/include/spl_inl_mips.h",
"signal_processing/min_max_operations_mips.c",
"signal_processing/resample_by_2_mips.c",
"signal_processing/spl_sqrt_floor_mips.c",
]
if (mips_dsp_rev > 0) {
sources += [ "signal_processing/vector_scaling_operations_mips.c" ]
@ -163,81 +174,222 @@ source_set("common_audio") {
sources += [
"signal_processing/complex_bit_reverse.c",
"signal_processing/filter_ar_fast_q12.c",
"signal_processing/spl_sqrt_floor.c",
]
}
if (is_win) {
cflags = [ "/wd4334" ] # Ignore warning on shift operator promotion.
}
deps = [
":common_audio_c_arm_asm",
":common_audio_cc",
"../rtc_base:checks",
"../rtc_base:compile_assert_c",
"../rtc_base:sanitizer",
"../rtc_base/system:arch",
"../system_wrappers",
"third_party/ooura:fft_size_256",
"third_party/spl_sqrt_floor",
]
}
configs += [ "..:common_config" ]
public_configs = [
"..:common_inherited_config",
":common_audio_config",
rtc_library("common_audio_cc") {
sources = [
"signal_processing/dot_product_with_scale.cc",
"signal_processing/dot_product_with_scale.h",
]
if (is_clang) {
# Suppress warnings from Chrome's Clang plugins.
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
configs -= [ "//build/config/clang:find_bad_constructs" ]
}
deps = [
"../rtc_base:safe_conversions",
"../system_wrappers",
]
}
rtc_source_set("sinc_resampler") {
sources = [ "resampler/sinc_resampler.h" ]
deps = [
"../rtc_base:gtest_prod",
"../rtc_base/memory:aligned_malloc",
"../rtc_base/system:arch",
"../system_wrappers",
]
}
rtc_source_set("fir_filter") {
visibility += webrtc_default_visibility
sources = [ "fir_filter.h" ]
}
rtc_library("fir_filter_factory") {
visibility += webrtc_default_visibility
sources = [
"fir_filter_c.cc",
"fir_filter_c.h",
"fir_filter_factory.cc",
"fir_filter_factory.h",
]
deps = [
":fir_filter",
"../rtc_base:checks",
"../rtc_base/system:arch",
"../system_wrappers",
]
if (current_cpu == "x86" || current_cpu == "x64") {
deps += [ ":common_audio_sse2" ]
deps += [ ":common_audio_avx2" ]
}
if (rtc_build_with_neon) {
deps += [ ":common_audio_neon" ]
}
}
if (current_cpu == "x86" || current_cpu == "x64") {
source_set("common_audio_sse2") {
rtc_library("common_audio_sse2") {
sources = [
"fir_filter_sse.cc",
"fir_filter_sse.h",
"resampler/sinc_resampler_sse.cc",
]
if (is_posix) {
if (is_posix || is_fuchsia) {
cflags = [ "-msse2" ]
}
configs += [ "..:common_inherited_config" ]
deps = [
":fir_filter",
":sinc_resampler",
"../rtc_base:checks",
"../rtc_base/memory:aligned_malloc",
]
}
if (is_clang) {
# Suppress warnings from Chrome's Clang plugins.
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
configs -= [ "//build/config/clang:find_bad_constructs" ]
rtc_library("common_audio_avx2") {
sources = [
"fir_filter_avx2.cc",
"fir_filter_avx2.h",
"resampler/sinc_resampler_avx2.cc",
]
if (is_win) {
cflags = [ "/arch:AVX2" ]
} else {
cflags = [
"-mavx2",
"-mfma",
]
}
deps = [
":fir_filter",
":sinc_resampler",
"../rtc_base:checks",
"../rtc_base/memory:aligned_malloc",
]
}
}
if (rtc_build_with_neon) {
source_set("common_audio_neon") {
rtc_library("common_audio_neon") {
sources = [
"fir_filter_neon.cc",
"fir_filter_neon.h",
"resampler/sinc_resampler_neon.cc",
]
if (current_cpu != "arm64") {
# Enable compilation for the NEON instruction set.
suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
cflags = [ "-mfpu=neon" ]
}
deps = [
":common_audio_neon_c",
":fir_filter",
":sinc_resampler",
"../rtc_base:checks",
"../rtc_base/memory:aligned_malloc",
]
}
rtc_library("common_audio_neon_c") {
visibility += webrtc_default_visibility
sources = [
"signal_processing/cross_correlation_neon.c",
"signal_processing/downsample_fast_neon.c",
"signal_processing/min_max_operations_neon.c",
]
if (current_cpu != "arm64") {
# Enable compilation for the NEON instruction set. This is needed
# since //build/config/arm.gni only enables NEON for iOS, not Android.
# This provides the same functionality as webrtc/build/arm_neon.gypi.
configs -= [ "//build/config/compiler:compiler_arm_fpu" ]
# Enable compilation for the NEON instruction set.
suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
cflags = [ "-mfpu=neon" ]
}
# Disable LTO on NEON targets due to compiler bug.
# TODO(fdegans): Enable this. See crbug.com/408997.
if (rtc_use_lto) {
cflags -= [
"-flto",
"-ffat-lto-objects",
]
}
configs += [ "..:common_config" ]
public_configs = [ "..:common_inherited_config" ]
deps = [
":common_audio_c",
"../rtc_base:checks",
"../rtc_base/system:arch",
]
}
}
if (rtc_include_tests && !build_with_chromium) {
rtc_test("common_audio_unittests") {
visibility += webrtc_default_visibility
testonly = true
sources = [
"audio_converter_unittest.cc",
"audio_util_unittest.cc",
"channel_buffer_unittest.cc",
"fir_filter_unittest.cc",
"real_fourier_unittest.cc",
"resampler/push_resampler_unittest.cc",
"resampler/push_sinc_resampler_unittest.cc",
"resampler/resampler_unittest.cc",
"resampler/sinusoidal_linear_chirp_source.cc",
"resampler/sinusoidal_linear_chirp_source.h",
"ring_buffer_unittest.cc",
"signal_processing/real_fft_unittest.cc",
"signal_processing/signal_processing_unittest.cc",
"smoothing_filter_unittest.cc",
"vad/vad_core_unittest.cc",
"vad/vad_filterbank_unittest.cc",
"vad/vad_gmm_unittest.cc",
"vad/vad_sp_unittest.cc",
"vad/vad_unittest.cc",
"vad/vad_unittest.h",
"wav_file_unittest.cc",
"wav_header_unittest.cc",
"window_generator_unittest.cc",
]
# Does not compile on iOS for arm: webrtc:5544.
if (!is_ios || target_cpu != "arm") {
sources += [ "resampler/sinc_resampler_unittest.cc" ]
}
deps = [
":common_audio",
":common_audio_c",
":fir_filter",
":fir_filter_factory",
":sinc_resampler",
"../rtc_base:checks",
"../rtc_base:macromagic",
"../rtc_base:rtc_base_tests_utils",
"../rtc_base:stringutils",
"../rtc_base:timeutils",
"../rtc_base/system:arch",
"../system_wrappers",
"../test:fileutils",
"../test:rtc_expect_death",
"../test:test_main",
"../test:test_support",
"//testing/gtest",
]
if (is_android) {
deps += [ "//testing/android/native_test:native_test_support" ]
shard_timeout = 900
}
}
}

View File

@ -1,153 +0,0 @@
noinst_LTLIBRARIES = libcommon_audio.la
noinst_HEADERS = include/audio_util.h
libcommon_audio_la_SOURCES = resampler/include/push_resampler.h \
resampler/include/resampler.h \
resampler/push_sinc_resampler.h \
resampler/sinc_resampler.h \
resampler/sinusoidal_linear_chirp_source.h \
resampler/push_resampler.cc \
resampler/push_sinc_resampler.cc \
resampler/resampler.cc \
resampler/sinc_resampler.cc \
resampler/sinusoidal_linear_chirp_source.cc \
signal_processing/include/real_fft.h \
signal_processing/include/signal_processing_library.h \
signal_processing/include/spl_inl.h \
signal_processing/include/spl_inl_armv7.h \
signal_processing/include/spl_inl_mips.h \
signal_processing/auto_corr_to_refl_coef.c \
signal_processing/auto_correlation.c \
signal_processing/complex_fft.c \
signal_processing/complex_fft_tables.h \
signal_processing/copy_set_operations.c \
signal_processing/cross_correlation.c \
signal_processing/division_operations.c \
signal_processing/dot_product_with_scale.c \
signal_processing/downsample_fast.c \
signal_processing/energy.c \
signal_processing/filter_ar.c \
signal_processing/filter_ma_fast_q12.c \
signal_processing/get_hanning_window.c \
signal_processing/get_scaling_square.c \
signal_processing/ilbc_specific_functions.c \
signal_processing/levinson_durbin.c \
signal_processing/lpc_to_refl_coef.c \
signal_processing/min_max_operations.c \
signal_processing/randomization_functions.c \
signal_processing/real_fft.c \
signal_processing/refl_coef_to_lpc.c \
signal_processing/resample.c \
signal_processing/resample_48khz.c \
signal_processing/resample_by_2.c \
signal_processing/resample_by_2_internal.c \
signal_processing/resample_by_2_internal.h \
signal_processing/resample_fractional.c \
signal_processing/spl_init.c \
signal_processing/spl_sqrt.c \
signal_processing/splitting_filter.c \
signal_processing/sqrt_of_one_minus_x_squared.c \
signal_processing/vector_scaling_operations.c \
vad/include/vad.h \
vad/include/webrtc_vad.h \
vad/vad.cc \
vad/vad_core.c \
vad/vad_core.h \
vad/vad_filterbank.c \
vad/vad_filterbank.h \
vad/vad_gmm.c \
vad/vad_gmm.h \
vad/vad_sp.c \
vad/vad_sp.h \
vad/webrtc_vad.c \
audio_converter.cc \
audio_converter.h \
audio_ring_buffer.cc \
audio_ring_buffer.h \
audio_util.cc \
blocker.cc \
blocker.h \
channel_buffer.cc \
channel_buffer.h \
fft4g.c \
fft4g.h \
fir_filter.cc \
fir_filter.h \
lapped_transform.cc \
lapped_transform.h \
real_fourier.cc \
real_fourier.h \
real_fourier_ooura.cc \
real_fourier_ooura.h \
real_fourier_openmax.h \
ring_buffer.h \
ring_buffer.c \
sparse_fir_filter.cc \
sparse_fir_filter.h \
wav_file.h \
wav_file.cc \
wav_header.h \
wav_header.cc \
window_generator.h \
window_generator.cc
if HAVE_X86
noinst_LTLIBRARIES += libcommon_audio_sse2.la
libcommon_audio_sse2_la_SOURCES = \
resampler/sinc_resampler_sse.cc \
fir_filter_sse.cc \
fir_filter_sse.h
libcommon_audio_sse2_la_CFLAGS = $(AM_CFLAGS) $(COMMON_CFLAGS) -msse2
libcommon_audio_sse2_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS) -msse2
libcommon_audio_sse2_la_LDFLAGS = $(AM_LDFLAGS)
libcommon_audio_la_LIBADD = libcommon_audio_sse2.la
endif
if HAVE_ARM
libcommon_audio_la_SOURCES += \
signal_processing/complex_bit_reverse_arm.S \
signal_processing/spl_sqrt_floor_arm.S
endif
if HAVE_ARMV7
libcommon_audio_la_SOURCES += \
signal_processing/filter_ar_fast_q12_armv7.S
endif
if HAVE_NEON
libcommon_audio_la_SOURCES += \
resampler/sinc_resampler_neon.cc \
signal_processing/cross_correlation_neon.c \
signal_processing/downsample_fast_neon.c \
signal_processing/min_max_operations_neon.c \
fir_filter_neon.cc \
fir_filter_neon.h
endif
if !HAVE_ARM
# FIXME: This condition will also hold for !HAVE_MIPS
libcommon_audio_la_SOURCES += \
signal_processing/complex_bit_reverse.c \
signal_processing/filter_ar_fast_q12.c \
signal_processing/spl_sqrt_floor.c
endif
libcommon_audio_la_CCASFLAGS = $(AM_CCASFLAGS) $(COMMON_CFLAGS)
libcommon_audio_la_CFLAGS = $(AM_CFLAGS) $(COMMON_CFLAGS)
libcommon_audio_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS)
# FIXME: The MIPS optimisations need to be hooked up once we have the
# autotools conditionals in place
EXTRA_DIST = BUILD.gn \
signal_processing/complex_bit_reverse_mips.c \
signal_processing/complex_fft_mips.c \
signal_processing/cross_correlation_mips.c \
signal_processing/downsample_fast_mips.c \
signal_processing/filter_ar_fast_q12_mips.c \
signal_processing/min_max_operations_mips.c \
signal_processing/resample_by_2_mips.c \
signal_processing/spl_sqrt_floor_mips.c \
signal_processing/vector_scaling_operations_mips.c

View File

@ -8,32 +8,36 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/common_audio/audio_converter.h"
#include "common_audio/audio_converter.h"
#include <cstring>
#include <memory>
#include <utility>
#include <vector>
#include "webrtc/base/checks.h"
#include "webrtc/base/safe_conversions.h"
#include "webrtc/common_audio/channel_buffer.h"
#include "webrtc/common_audio/resampler/push_sinc_resampler.h"
#include "webrtc/system_wrappers/include/scoped_vector.h"
using rtc::checked_cast;
#include "common_audio/channel_buffer.h"
#include "common_audio/resampler/push_sinc_resampler.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_conversions.h"
namespace webrtc {
class CopyConverter : public AudioConverter {
public:
CopyConverter(int src_channels, size_t src_frames, int dst_channels,
CopyConverter(size_t src_channels,
size_t src_frames,
size_t dst_channels,
size_t dst_frames)
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
~CopyConverter() override {};
~CopyConverter() override {}
void Convert(const float* const* src, size_t src_size, float* const* dst,
void Convert(const float* const* src,
size_t src_size,
float* const* dst,
size_t dst_capacity) override {
CheckSizes(src_size, dst_capacity);
if (src != dst) {
for (int i = 0; i < src_channels(); ++i)
for (size_t i = 0; i < src_channels(); ++i)
std::memcpy(dst[i], src[i], dst_frames() * sizeof(*dst[i]));
}
}
@ -41,17 +45,21 @@ class CopyConverter : public AudioConverter {
class UpmixConverter : public AudioConverter {
public:
UpmixConverter(int src_channels, size_t src_frames, int dst_channels,
UpmixConverter(size_t src_channels,
size_t src_frames,
size_t dst_channels,
size_t dst_frames)
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
~UpmixConverter() override {};
~UpmixConverter() override {}
void Convert(const float* const* src, size_t src_size, float* const* dst,
void Convert(const float* const* src,
size_t src_size,
float* const* dst,
size_t dst_capacity) override {
CheckSizes(src_size, dst_capacity);
for (size_t i = 0; i < dst_frames(); ++i) {
const float value = src[0][i];
for (int j = 0; j < dst_channels(); ++j)
for (size_t j = 0; j < dst_channels(); ++j)
dst[j][i] = value;
}
}
@ -59,19 +67,22 @@ class UpmixConverter : public AudioConverter {
class DownmixConverter : public AudioConverter {
public:
DownmixConverter(int src_channels, size_t src_frames, int dst_channels,
DownmixConverter(size_t src_channels,
size_t src_frames,
size_t dst_channels,
size_t dst_frames)
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {
}
~DownmixConverter() override {};
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
~DownmixConverter() override {}
void Convert(const float* const* src, size_t src_size, float* const* dst,
void Convert(const float* const* src,
size_t src_size,
float* const* dst,
size_t dst_capacity) override {
CheckSizes(src_size, dst_capacity);
float* dst_mono = dst[0];
for (size_t i = 0; i < src_frames(); ++i) {
float sum = 0;
for (int j = 0; j < src_channels(); ++j)
for (size_t j = 0; j < src_channels(); ++j)
sum += src[j][i];
dst_mono[i] = sum / src_channels();
}
@ -80,16 +91,21 @@ class DownmixConverter : public AudioConverter {
class ResampleConverter : public AudioConverter {
public:
ResampleConverter(int src_channels, size_t src_frames, int dst_channels,
ResampleConverter(size_t src_channels,
size_t src_frames,
size_t dst_channels,
size_t dst_frames)
: AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {
resamplers_.reserve(src_channels);
for (int i = 0; i < src_channels; ++i)
resamplers_.push_back(new PushSincResampler(src_frames, dst_frames));
for (size_t i = 0; i < src_channels; ++i)
resamplers_.push_back(std::unique_ptr<PushSincResampler>(
new PushSincResampler(src_frames, dst_frames)));
}
~ResampleConverter() override {};
~ResampleConverter() override {}
void Convert(const float* const* src, size_t src_size, float* const* dst,
void Convert(const float* const* src,
size_t src_size,
float* const* dst,
size_t dst_capacity) override {
CheckSizes(src_size, dst_capacity);
for (size_t i = 0; i < resamplers_.size(); ++i)
@ -97,69 +113,73 @@ class ResampleConverter : public AudioConverter {
}
private:
ScopedVector<PushSincResampler> resamplers_;
std::vector<std::unique_ptr<PushSincResampler>> resamplers_;
};
// Apply a vector of converters in serial, in the order given. At least two
// converters must be provided.
class CompositionConverter : public AudioConverter {
public:
CompositionConverter(ScopedVector<AudioConverter> converters)
: converters_(converters.Pass()) {
RTC_CHECK_GE(converters_.size(), 2u);
explicit CompositionConverter(
std::vector<std::unique_ptr<AudioConverter>> converters)
: converters_(std::move(converters)) {
RTC_CHECK_GE(converters_.size(), 2);
// We need an intermediate buffer after every converter.
for (auto it = converters_.begin(); it != converters_.end() - 1; ++it)
buffers_.push_back(new ChannelBuffer<float>((*it)->dst_frames(),
(*it)->dst_channels()));
buffers_.push_back(
std::unique_ptr<ChannelBuffer<float>>(new ChannelBuffer<float>(
(*it)->dst_frames(), (*it)->dst_channels())));
}
~CompositionConverter() override {};
~CompositionConverter() override {}
void Convert(const float* const* src, size_t src_size, float* const* dst,
void Convert(const float* const* src,
size_t src_size,
float* const* dst,
size_t dst_capacity) override {
converters_.front()->Convert(src, src_size, buffers_.front()->channels(),
buffers_.front()->size());
for (size_t i = 2; i < converters_.size(); ++i) {
auto src_buffer = buffers_[i - 2];
auto dst_buffer = buffers_[i - 1];
converters_[i]->Convert(src_buffer->channels(),
src_buffer->size(),
dst_buffer->channels(),
dst_buffer->size());
auto& src_buffer = buffers_[i - 2];
auto& dst_buffer = buffers_[i - 1];
converters_[i]->Convert(src_buffer->channels(), src_buffer->size(),
dst_buffer->channels(), dst_buffer->size());
}
converters_.back()->Convert(buffers_.back()->channels(),
buffers_.back()->size(), dst, dst_capacity);
}
private:
ScopedVector<AudioConverter> converters_;
ScopedVector<ChannelBuffer<float>> buffers_;
std::vector<std::unique_ptr<AudioConverter>> converters_;
std::vector<std::unique_ptr<ChannelBuffer<float>>> buffers_;
};
rtc::scoped_ptr<AudioConverter> AudioConverter::Create(int src_channels,
std::unique_ptr<AudioConverter> AudioConverter::Create(size_t src_channels,
size_t src_frames,
int dst_channels,
size_t dst_channels,
size_t dst_frames) {
rtc::scoped_ptr<AudioConverter> sp;
std::unique_ptr<AudioConverter> sp;
if (src_channels > dst_channels) {
if (src_frames != dst_frames) {
ScopedVector<AudioConverter> converters;
converters.push_back(new DownmixConverter(src_channels, src_frames,
dst_channels, src_frames));
converters.push_back(new ResampleConverter(dst_channels, src_frames,
dst_channels, dst_frames));
sp.reset(new CompositionConverter(converters.Pass()));
std::vector<std::unique_ptr<AudioConverter>> converters;
converters.push_back(std::unique_ptr<AudioConverter>(new DownmixConverter(
src_channels, src_frames, dst_channels, src_frames)));
converters.push_back(
std::unique_ptr<AudioConverter>(new ResampleConverter(
dst_channels, src_frames, dst_channels, dst_frames)));
sp.reset(new CompositionConverter(std::move(converters)));
} else {
sp.reset(new DownmixConverter(src_channels, src_frames, dst_channels,
dst_frames));
}
} else if (src_channels < dst_channels) {
if (src_frames != dst_frames) {
ScopedVector<AudioConverter> converters;
converters.push_back(new ResampleConverter(src_channels, src_frames,
src_channels, dst_frames));
converters.push_back(new UpmixConverter(src_channels, dst_frames,
dst_channels, dst_frames));
sp.reset(new CompositionConverter(converters.Pass()));
std::vector<std::unique_ptr<AudioConverter>> converters;
converters.push_back(
std::unique_ptr<AudioConverter>(new ResampleConverter(
src_channels, src_frames, src_channels, dst_frames)));
converters.push_back(std::unique_ptr<AudioConverter>(new UpmixConverter(
src_channels, dst_frames, dst_channels, dst_frames)));
sp.reset(new CompositionConverter(std::move(converters)));
} else {
sp.reset(new UpmixConverter(src_channels, src_frames, dst_channels,
dst_frames));
@ -168,22 +188,21 @@ rtc::scoped_ptr<AudioConverter> AudioConverter::Create(int src_channels,
sp.reset(new ResampleConverter(src_channels, src_frames, dst_channels,
dst_frames));
} else {
sp.reset(new CopyConverter(src_channels, src_frames, dst_channels,
dst_frames));
sp.reset(
new CopyConverter(src_channels, src_frames, dst_channels, dst_frames));
}
return sp.Pass();
return sp;
}
// For CompositionConverter.
AudioConverter::AudioConverter()
: src_channels_(0),
src_frames_(0),
dst_channels_(0),
dst_frames_(0) {}
: src_channels_(0), src_frames_(0), dst_channels_(0), dst_frames_(0) {}
AudioConverter::AudioConverter(int src_channels, size_t src_frames,
int dst_channels, size_t dst_frames)
AudioConverter::AudioConverter(size_t src_channels,
size_t src_frames,
size_t dst_channels,
size_t dst_frames)
: src_channels_(src_channels),
src_frames_(src_frames),
dst_channels_(dst_channels),

View File

@ -8,16 +8,17 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_COMMON_AUDIO_AUDIO_CONVERTER_H_
#define WEBRTC_COMMON_AUDIO_AUDIO_CONVERTER_H_
#ifndef COMMON_AUDIO_AUDIO_CONVERTER_H_
#define COMMON_AUDIO_AUDIO_CONVERTER_H_
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/scoped_ptr.h"
#include <stddef.h>
#include <memory>
namespace webrtc {
// Format conversion (remixing and resampling) for audio. Only simple remixing
// conversions are supported: downmix to mono (i.e. |dst_channels| == 1) or
// conversions are supported: downmix to mono (i.e. `dst_channels` == 1) or
// upmix from mono (i.e. |src_channels == 1|).
//
// The source and destination chunks have the same duration in time; specifying
@ -26,41 +27,46 @@ class AudioConverter {
public:
// Returns a new AudioConverter, which will use the supplied format for its
// lifetime. Caller is responsible for the memory.
static rtc::scoped_ptr<AudioConverter> Create(int src_channels,
static std::unique_ptr<AudioConverter> Create(size_t src_channels,
size_t src_frames,
int dst_channels,
size_t dst_channels,
size_t dst_frames);
virtual ~AudioConverter() {};
virtual ~AudioConverter() {}
// Convert |src|, containing |src_size| samples, to |dst|, having a sample
// capacity of |dst_capacity|. Both point to a series of buffers containing
AudioConverter(const AudioConverter&) = delete;
AudioConverter& operator=(const AudioConverter&) = delete;
// Convert `src`, containing `src_size` samples, to `dst`, having a sample
// capacity of `dst_capacity`. Both point to a series of buffers containing
// the samples for each channel. The sizes must correspond to the format
// passed to Create().
virtual void Convert(const float* const* src, size_t src_size,
float* const* dst, size_t dst_capacity) = 0;
virtual void Convert(const float* const* src,
size_t src_size,
float* const* dst,
size_t dst_capacity) = 0;
int src_channels() const { return src_channels_; }
size_t src_channels() const { return src_channels_; }
size_t src_frames() const { return src_frames_; }
int dst_channels() const { return dst_channels_; }
size_t dst_channels() const { return dst_channels_; }
size_t dst_frames() const { return dst_frames_; }
protected:
AudioConverter();
AudioConverter(int src_channels, size_t src_frames, int dst_channels,
AudioConverter(size_t src_channels,
size_t src_frames,
size_t dst_channels,
size_t dst_frames);
// Helper to RTC_CHECK that inputs are correctly sized.
void CheckSizes(size_t src_size, size_t dst_capacity) const;
private:
const int src_channels_;
const size_t src_channels_;
const size_t src_frames_;
const int dst_channels_;
const size_t dst_channels_;
const size_t dst_frames_;
RTC_DISALLOW_COPY_AND_ASSIGN(AudioConverter);
};
} // namespace webrtc
#endif // WEBRTC_COMMON_AUDIO_AUDIO_CONVERTER_H_
#endif // COMMON_AUDIO_AUDIO_CONVERTER_H_

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