summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Chromium Automerger <chromium-automerger@android>2014-06-19 21:56:31 +0000
committerAndroid Chromium Automerger <chromium-automerger@android>2014-06-19 21:56:31 +0000
commitc497bcd46d65650cbafb85ae4e71db44cd656b08 (patch)
treea38edd8a90c7ca5474ea1165100e59ac82a5a5cb
parentad3bcf43404f06080840b0787fad7a394e7925d8 (diff)
parent68f4c7b51ec6434b302de9e97ee01f5ccdb48aa2 (diff)
downloadwebrtc-c497bcd46d65650cbafb85ae4e71db44cd656b08.tar.gz
Merge third_party/webrtc from https://chromium.googlesource.com/external/webrtc/trunk/webrtc.git at 68f4c7b51ec6434b302de9e97ee01f5ccdb48aa2
This commit was generated by merge_from_chromium.py. Change-Id: Iedf6d850648d6a5904340109e1f71ce52d44113b
-rw-r--r--BUILD.gn174
-rw-r--r--base/BUILD.gn723
-rw-r--r--base/base.gyp70
-rw-r--r--base/json.h2
-rw-r--r--base/profiler_unittest.cc8
-rw-r--r--build/common.gypi8
-rw-r--r--build/webrtc.gni57
-rw-r--r--modules/audio_coding/codecs/isac/fix/source/isacfix.c19
-rw-r--r--modules/audio_coding/codecs/isac/fix/source/structs.h2
-rw-r--r--modules/audio_coding/neteq/neteq.gypi3
-rw-r--r--modules/audio_coding/neteq/tools/audio_checksum.h60
-rw-r--r--modules/audio_coding/neteq/tools/audio_sink.h46
-rw-r--r--modules/audio_coding/neteq/tools/output_audio_file.h50
-rw-r--r--modules/audio_coding/neteq/tools/packet_source.h3
-rw-r--r--modules/audio_coding/neteq/tools/rtp_file_source.cc87
-rw-r--r--modules/audio_coding/neteq/tools/rtp_file_source.h3
-rw-r--r--modules/audio_processing/aec/aec_core_neon.c81
-rw-r--r--modules/audio_processing/aec/system_delay_unittest.cc16
-rw-r--r--modules/audio_processing/test/audio_processing_unittest.cc5
-rw-r--r--modules/audio_processing/test/process_test.cc6
-rw-r--r--modules/bitrate_controller/bitrate_controller_impl.cc17
-rw-r--r--modules/bitrate_controller/bitrate_controller_unittest.cc18
-rw-r--r--modules/rtp_rtcp/source/rtp_rtcp_impl.cc70
-rw-r--r--modules/rtp_rtcp/source/rtp_rtcp_impl.h11
-rw-r--r--modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc250
-rw-r--r--modules/rtp_rtcp/source/rtp_sender.cc63
-rw-r--r--modules/rtp_rtcp/source/rtp_sender.h8
-rw-r--r--modules/rtp_rtcp/source/rtp_sender_unittest.cc8
-rw-r--r--modules/video_coding/codecs/vp8/vp8_impl.cc5
-rw-r--r--test/w3c/getusermedia_conformance_test.html11
-rw-r--r--test/w3c/getusermedia_conformance_test.js296
-rw-r--r--video_engine/overuse_frame_detector.cc22
-rw-r--r--video_engine/overuse_frame_detector.h1
33 files changed, 1930 insertions, 273 deletions
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 00000000..a86c8a76
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,174 @@
+# 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/arm.gni")
+import("//build/config/crypto.gni")
+import("//build/config/linux/pkg_config.gni")
+import("build/webrtc.gni")
+
+# 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" ]
+ }
+ if (build_with_chromium) {
+ defines = [
+ "WEBRTC_CHROMIUM_BUILD",
+ "LOGGING_INSIDE_WEBRTC",
+ ]
+ include_dirs = [
+ # overrides must be included first as that is the mechanism for
+ # selecting the override headers in Chromium.
+ "overrides",
+ # Allow includes to be prefixed with webrtc/ in case it is not an
+ # immediate subdirectory of the top-level.
+ "..",
+ ]
+ }
+ if (is_posix) {
+ defines += [ "WEBRTC_POSIX" ]
+ }
+ if (is_ios) {
+ defines += [
+ "WEBRTC_MAC",
+ "WEBRTC_IOS",
+ ]
+ }
+ if (is_linux) {
+ defines += [ "WEBRTC_LINUX" ]
+ }
+ if (is_mac) {
+ defines += [ "WEBRTC_MAC" ]
+ }
+ if (is_win) {
+ defines += [ "WEBRTC_WIN" ]
+ }
+ if (is_android) {
+ defines += [
+ "WEBRTC_LINUX",
+ "WEBRTC_ANDROID",
+ ]
+ if (enable_android_opensl) {
+ defines += [ "WEBRTC_ANDROID_OPENSLES" ]
+ }
+ }
+}
+
+pkg_config("dbus-glib") {
+ packages = [ "dbus-glib-1" ]
+}
+
+config("common_config") {
+ if (restrict_webrtc_logging) {
+ defines = [ "WEBRTC_RESTRICT_LOGGING" ]
+ }
+
+ if (have_dbus_glib) {
+ defines += [ "HAVE_DBUS_GLIB" ]
+ # 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 (enable_video) {
+ defines += [ "WEBRTC_MODULE_UTILITY_VIDEO" ]
+ }
+
+ if (!build_with_chromium) {
+ 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 (cpu_arch != "arm64" || !is_android) {
+ cflags = [
+ "-Wextra",
+ # We need to repeat some flags from Chromium"s common.gypi
+ # here that get overridden by -Wextra.
+ "-Wno-unused-parameter",
+ "-Wno-missing-field-initializers",
+ "-Wno-strict-overflow",
+ ]
+ cflags_cc = [
+ "-Wnon-virtual-dtor",
+ # This is enabled for clang; enable for gcc as well.
+ "-Woverloaded-virtual",
+ ]
+ }
+ }
+
+ if (is_clang) {
+ cflags += [ "-Wthread-safety" ]
+ }
+ }
+
+ if (cpu_arch == "arm") {
+ defines += [ "WEBRTC_ARCH_ARM" ]
+ if (arm_version == 7) {
+ defines += [ "WEBRTC_ARCH_ARM_V7" ]
+ if (arm_use_neon) {
+ defines += [ "WEBRTC_ARCH_ARM_NEON" ]
+ } else {
+ defines += [ "WEBRTC_DETECT_ARM_NEON" ]
+ }
+ }
+ }
+
+ if (cpu_arch == "mipsel") {
+ defines += [ "MIPS32_LE" ]
+ if (mips_fpu) {
+ defines += [ "MIPS_FPU_LE" ]
+ cflags += [ "-mhard-float" ]
+ } else {
+ cflags += [ "-msoft-float" ]
+ }
+ if (mips_arch_variant == "mips32r2") {
+ defines += [ "MIPS32_R2_LE" ]
+ cflags += [ "-mips32r2" ]
+ cflags_cc += [ "-mips32r2" ]
+ }
+ if (mips_dsp_rev == 1) {
+ defines += [ "MIPS_DSP_R1_LE" ]
+ cflags += [ "-mdsp" ]
+ cflags_cc += [ "-mdsp" ]
+ } else if (mips_dsp_rev == 2) {
+ defines += [
+ "MIPS_DSP_R1_LE",
+ "MIPS_DSP_R2_LE",
+ ]
+ cflags += [ "-mdspr2" ]
+ cflags_cc += [ "-mdspr2" ]
+ }
+ }
+
+ # TODO(kjellander): Handle warnings on Windows where WebRTC differ from the
+ # default warnings set in build/config/compiler/BUILD.gn.
+
+ if (is_android && is_clang) {
+ # The Android NDK doesn"t provide optimized versions of these
+ # functions. Ensure they are disabled for all compilers.
+ cflags += [
+ "-fno-builtin-cos",
+ "-fno-builtin-sin",
+ "-fno-builtin-cosf",
+ "-fno-builtin-sinf",
+ ]
+ }
+}
+
+static_library("webrtc") {
+ deps = [
+ "base:webrtc_base",
+ ]
+}
diff --git a/base/BUILD.gn b/base/BUILD.gn
new file mode 100644
index 00000000..41180901
--- /dev/null
+++ b/base/BUILD.gn
@@ -0,0 +1,723 @@
+# 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/webrtc.gni")
+
+config("webrtc_base_config") {
+ include_dirs = [
+ "//third_party/jsoncpp/overrides/include",
+ "//third_party/jsoncpp/source/include",
+ ]
+
+ defines = [
+ "FEATURE_ENABLE_SSL",
+ "GTEST_RELATIVE_PATH",
+ ]
+
+ # TODO(henrike): issue 3307, make webrtc_base build without disabling
+ # these flags.
+ cflags_cc = [ "-Wno-non-virtual-dtor" ]
+}
+
+config("webrtc_base_chromium_config") {
+ defines = [
+ "NO_MAIN_THREAD_WRAPPING",
+ "SSL_USE_NSS",
+ ]
+}
+
+config("openssl_config") {
+ defines = [
+ "SSL_USE_OPENSSL",
+ "HAVE_OPENSSL_SSL_H",
+ ]
+}
+
+config("no_openssl_config") {
+ defines = [
+ "SSL_USE_NSS",
+ "HAVE_NSS_SSL_H",
+ "SSL_USE_NSS_RNG",
+ ]
+}
+
+config("android_config") {
+ defines = [ "HAVE_OPENSSL_SSL_H" ]
+}
+
+config("no_android_config") {
+ defines = [
+ "HAVE_NSS_SSL_H",
+ "SSL_USE_NSS_RNG",
+ ]
+}
+
+config("ios_config") {
+ ldflags = [
+ #"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") {
+ ldflags = [
+ "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.
+ ]
+}
+
+config("linux_system_ssl_config") {
+ visibility = ":*" # Only targets in this file can depend on this.
+
+ # TODO(kjellander): Find out how to convert GYP include_dirs+ (i.e. insert
+ # first in the include path?).
+ include_dirs = [ "//net/third_party/nss/ssl" ]
+
+ configs = [ "//third_party/nss:system_nss_no_ssl_config" ]
+}
+
+# Provides the same functionality as the build/linux/system.gyp:ssl GYP target.
+# This cannot be in build/linux/BUILD.gn since targets in build/ are not allowed
+# to depend on targets outside of it. This could be replaced by the Chromium
+# //crypto:platform target, but as WebRTC currently don't sync src/crypto from
+# Chromium, it is not possible today.
+config("linux_system_ssl") {
+ if (use_openssl) {
+ deps = [ "//third_party/openssl" ]
+ } else {
+ deps = [ "//net/third_party/nss/ssl:libssl" ]
+
+ direct_dependent_configs = [
+ ":linux_system_ssl_config",
+ ]
+
+ if (is_clang) {
+ cflags = [
+ # There is a broken header guard in /usr/include/nss/secmod.h:
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=884072
+ "-Wno-header-guard",
+ ]
+ }
+ }
+}
+
+static_library("webrtc_base") {
+ cflags = []
+ cflags_cc = []
+
+ configs -= [ "//build/config/compiler:chromium_code" ]
+ configs += [ "//build/config/compiler:no_chromium_code" ]
+ configs += [
+ "..:common_inherited_config",
+ "..:common_config",
+ ":webrtc_base_config",
+ ]
+
+ direct_dependent_configs = [
+ "..:common_inherited_config",
+ ":webrtc_base_config",
+ ]
+
+ defines = [
+ "LOGGING=1",
+ "USE_WEBRTC_DEV_BRANCH",
+ ]
+
+ sources = [
+ "asyncfile.cc",
+ "asyncfile.h",
+ "asynchttprequest.cc",
+ "asynchttprequest.h",
+ "asyncinvoker.cc",
+ "asyncinvoker.h",
+ "asyncinvoker-inl.h",
+ "asyncpacketsocket.h",
+ "asyncresolverinterface.h",
+ "asyncsocket.cc",
+ "asyncsocket.h",
+ "asynctcpsocket.cc",
+ "asynctcpsocket.h",
+ "asyncudpsocket.cc",
+ "asyncudpsocket.h",
+ "atomicops.h",
+ "autodetectproxy.cc",
+ "autodetectproxy.h",
+ "bandwidthsmoother.cc",
+ "bandwidthsmoother.h",
+ "base64.cc",
+ "base64.h",
+ "basicdefs.h",
+ "basictypes.h",
+ "bind.h",
+ "bind.h.pump",
+ "buffer.h",
+ "bytebuffer.cc",
+ "bytebuffer.h",
+ "byteorder.h",
+ "callback.h",
+ "callback.h.pump",
+ "checks.cc",
+ "checks.h",
+ "common.cc",
+ "common.h",
+ "constructormagic.h",
+ "cpumonitor.cc",
+ "cpumonitor.h",
+ "crc32.cc",
+ "crc32.h",
+ "criticalsection.h",
+ "cryptstring.h",
+ "dbus.cc",
+ "dbus.h",
+ "diskcache.cc",
+ "diskcache.h",
+ "event.cc",
+ "event.h",
+ "filelock.cc",
+ "filelock.h",
+ "fileutils.cc",
+ "fileutils.h",
+ "fileutils_mock.h",
+ "firewallsocketserver.cc",
+ "firewallsocketserver.h",
+ "flags.cc",
+ "flags.h",
+ "genericslot.h",
+ "genericslot.h.pump",
+ "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",
+ "httpserver.cc",
+ "httpserver.h",
+ "ifaddrs-android.cc",
+ "ifaddrs-android.h",
+ "iosfilesystem.mm",
+ "ipaddress.cc",
+ "ipaddress.h",
+ "json.cc",
+ "json.h",
+ "latebindingsymboltable.cc",
+ "latebindingsymboltable.cc.def",
+ "latebindingsymboltable.h",
+ "latebindingsymboltable.h.def",
+ "libdbusglibsymboltable.cc",
+ "libdbusglibsymboltable.h",
+ "linux.cc",
+ "linux.h",
+ "linuxfdwalk.c",
+ "linuxfdwalk.h",
+ "linuxwindowpicker.cc",
+ "linuxwindowpicker.h",
+ "linked_ptr.h",
+ "logging.cc",
+ "logging.h",
+ "macasyncsocket.cc",
+ "macasyncsocket.h",
+ "maccocoasocketserver.h",
+ "maccocoasocketserver.mm",
+ "maccocoathreadhelper.h",
+ "maccocoathreadhelper.mm",
+ "macconversion.cc",
+ "macconversion.h",
+ "macsocketserver.cc",
+ "macsocketserver.h",
+ "macutils.cc",
+ "macutils.h",
+ "macwindowpicker.cc",
+ "macwindowpicker.h",
+ "mathutils.h",
+ "md5.cc",
+ "md5.h",
+ "md5digest.h",
+ "messagedigest.cc",
+ "messagedigest.h",
+ "messagehandler.cc",
+ "messagehandler.h",
+ "messagequeue.cc",
+ "messagequeue.h",
+ "multipart.cc",
+ "multipart.h",
+ "natserver.cc",
+ "natserver.h",
+ "natsocketfactory.cc",
+ "natsocketfactory.h",
+ "nattypes.cc",
+ "nattypes.h",
+ "nethelpers.cc",
+ "nethelpers.h",
+ "network.cc",
+ "network.h",
+ "nssidentity.cc",
+ "nssidentity.h",
+ "nssstreamadapter.cc",
+ "nssstreamadapter.h",
+ "nullsocketserver.h",
+ "openssl.h",
+ "openssladapter.cc",
+ "openssladapter.h",
+ "openssldigest.cc",
+ "openssldigest.h",
+ "opensslidentity.cc",
+ "opensslidentity.h",
+ "opensslstreamadapter.cc",
+ "opensslstreamadapter.h",
+ "optionsfile.cc",
+ "optionsfile.h",
+ "pathutils.cc",
+ "pathutils.h",
+ "physicalsocketserver.cc",
+ "physicalsocketserver.h",
+ "posix.cc",
+ "posix.h",
+ "profiler.cc",
+ "profiler.h",
+ "proxydetect.cc",
+ "proxydetect.h",
+ "proxyinfo.cc",
+ "proxyinfo.h",
+ "proxyserver.cc",
+ "proxyserver.h",
+ "ratelimiter.cc",
+ "ratelimiter.h",
+ "ratetracker.cc",
+ "ratetracker.h",
+ "refcount.h",
+ "referencecountedsingletonfactory.h",
+ "rollingaccumulator.h",
+ "schanneladapter.cc",
+ "schanneladapter.h",
+ "scoped_autorelease_pool.h",
+ "scoped_autorelease_pool.mm",
+ "scoped_ptr.h",
+ "scoped_ref_ptr.h",
+ "scopedptrcollection.h",
+ "sec_buffer.h",
+ "sha1.cc",
+ "sha1.h",
+ "sha1digest.h",
+ "sharedexclusivelock.cc",
+ "sharedexclusivelock.h",
+ "signalthread.cc",
+ "signalthread.h",
+ "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",
+ "sslconfig.h",
+ "sslfingerprint.cc",
+ "sslfingerprint.h",
+ "sslidentity.cc",
+ "sslidentity.h",
+ "sslroots.h",
+ "sslsocketfactory.cc",
+ "sslsocketfactory.h",
+ "sslstreamadapter.cc",
+ "sslstreamadapter.h",
+ "sslstreamadapterhelper.cc",
+ "sslstreamadapterhelper.h",
+ "stream.cc",
+ "stream.h",
+ "stringdigest.h",
+ "stringencode.cc",
+ "stringencode.h",
+ "stringutils.cc",
+ "stringutils.h",
+ "systeminfo.cc",
+ "systeminfo.h",
+ "task.cc",
+ "task.h",
+ "taskparent.cc",
+ "taskparent.h",
+ "taskrunner.cc",
+ "taskrunner.h",
+ "testclient.cc",
+ "testclient.h",
+ "thread.cc",
+ "thread.h",
+ "timeutils.cc",
+ "timeutils.h",
+ "timing.cc",
+ "timing.h",
+ "transformadapter.cc",
+ "transformadapter.h",
+ "unixfilesystem.cc",
+ "unixfilesystem.h",
+ "urlencode.cc",
+ "urlencode.h",
+ "versionparsing.cc",
+ "versionparsing.h",
+ "virtualsocketserver.cc",
+ "virtualsocketserver.h",
+ "win32.cc",
+ "win32.h",
+ "win32filesystem.cc",
+ "win32filesystem.h",
+ "win32regkey.cc",
+ "win32regkey.h",
+ "win32securityerrors.cc",
+ "win32socketinit.cc",
+ "win32socketinit.h",
+ "win32socketserver.cc",
+ "win32socketserver.h",
+ "win32window.cc",
+ "win32window.h",
+ "win32windowpicker.cc",
+ "win32windowpicker.h",
+ "window.h",
+ "windowpicker.h",
+ "windowpickerfactory.h",
+ "winfirewall.cc",
+ "winfirewall.h",
+ "winping.cc",
+ "winping.h",
+ "worker.cc",
+ "worker.h",
+ ]
+
+ if (build_with_chromium) {
+ sources += [
+ "../overrides/webrtc/base/basictypes.h",
+ "../overrides/webrtc/base/constructormagic.h",
+ "../overrides/webrtc/base/logging.cc",
+ "../overrides/webrtc/base/logging.h",
+ ]
+ if (is_win) {
+ sources += [ "../overrides/webrtc/base/win32socketinit.cc" ]
+ }
+ sources -= [
+ "asyncinvoker.cc",
+ "asyncinvoker.h",
+ "asyncinvoker-inl.h",
+ "asyncresolverinterface.h",
+ "atomicops.h",
+ "bandwidthsmoother.cc",
+ "bandwidthsmoother.h",
+ "basictypes.h",
+ "bind.h",
+ "bind.h.pump",
+ "buffer.h",
+ "callback.h",
+ "callback.h.pump",
+ "constructormagic.h",
+ "dbus.cc",
+ "dbus.h",
+ "filelock.cc",
+ "filelock.h",
+ "fileutils_mock.h",
+ "genericslot.h",
+ "genericslot.h.pump",
+ "httpserver.cc",
+ "httpserver.h",
+ "json.cc",
+ "json.h",
+ "latebindingsymboltable.cc",
+ "latebindingsymboltable.cc.def",
+ "latebindingsymboltable.h",
+ "latebindingsymboltable.h.def",
+ "libdbusglibsymboltable.cc",
+ "libdbusglibsymboltable.h",
+ "linuxfdwalk.c",
+ "linuxfdwalk.h",
+ "linuxwindowpicker.cc",
+ "linuxwindowpicker.h",
+ "logging.cc",
+ "logging.h",
+ #"macasyncsocket.cc",
+ #"macasyncsocket.h",
+ #"maccocoasocketserver.h",
+ #"maccocoasocketserver.mm",
+ #"macsocketserver.cc",
+ #"macsocketserver.h",
+ #"macwindowpicker.cc",
+ #"macwindowpicker.h",
+ "mathutils.h",
+ "multipart.cc",
+ "multipart.h",
+ "natserver.cc",
+ "natserver.h",
+ "natsocketfactory.cc",
+ "natsocketfactory.h",
+ "nattypes.cc",
+ "nattypes.h",
+ "openssl.h",
+ "optionsfile.cc",
+ "optionsfile.h",
+ "posix.cc",
+ "posix.h",
+ "profiler.cc",
+ "profiler.h",
+ "proxyserver.cc",
+ "proxyserver.h",
+ "refcount.h",
+ "referencecountedsingletonfactory.h",
+ "rollingaccumulator.h",
+ #"safe_conversions.h",
+ #"safe_conversions_impl.h",
+ "scopedptrcollection.h",
+ "scoped_ref_ptr.h",
+ "sec_buffer.h",
+ "sharedexclusivelock.cc",
+ "sharedexclusivelock.h",
+ "sslconfig.h",
+ "sslroots.h",
+ "stringdigest.h",
+ #"testbase64.h",
+ "testclient.cc",
+ "testclient.h",
+ #"testutils.h",
+ "transformadapter.cc",
+ "transformadapter.h",
+ "versionparsing.cc",
+ "versionparsing.h",
+ "virtualsocketserver.cc",
+ "virtualsocketserver.h",
+ #"win32regkey.cc",
+ #"win32regkey.h",
+ #"win32socketinit.cc",
+ #"win32socketinit.h",
+ #"win32socketserver.cc",
+ #"win32socketserver.h",
+ #"win32toolhelp.h",
+ "window.h",
+ "windowpickerfactory.h",
+ "windowpicker.h",
+ ]
+
+ include_dirs = [
+ "../overrides",
+ "../../openssl/openssl/include",
+ ]
+
+ direct_dependent_configs += [ ":webrtc_base_chromium_config" ]
+ } else {
+ if (is_win) {
+ sources += [
+ "diskcache_win32.cc",
+ "diskcache_win32.h",
+ ]
+ }
+
+ deps = [ "//third_party/jsoncpp" ]
+ }
+
+ # TODO(henrike): issue 3307, make webrtc_base build without disabling
+ # these flags.
+ cflags += [
+ "-Wno-extra",
+ "-Wno-all",
+ ]
+ cflags_cc += [ "-Wno-non-virtual-dtor" ]
+
+ if (use_openssl) {
+ direct_dependent_configs += [ ":openssl_config" ]
+
+ deps = [ "//third_party/openssl" ]
+ } else {
+ direct_dependent_configs += [ ":no_openssl_config" ]
+ }
+
+ if (is_android) {
+ direct_dependent_configs += [ ":android_config" ]
+
+ libs = [
+ "log",
+ "GLESv2"
+ ]
+ } else {
+ direct_dependent_configs += [ ":no_android_config" ]
+
+ sources -= [
+ "ifaddrs-android.cc",
+ "ifaddrs-android.h",
+ ]
+ }
+
+ if (is_ios) {
+ all_dependent_configs += [ ":ios_config" ]
+
+ deps = [ "//net/third_party/nss/ssl:libssl" ]
+ }
+
+ if (is_linux) {
+ libs = [
+ "crypto",
+ "dl",
+ "rt",
+ "Xext",
+ "X11",
+ "Xcomposite",
+ "Xrender",
+ ]
+ configs += [ "//third_party/nss:system_nss_no_ssl_config" ]
+ } else {
+ sources -= [
+ "dbus.cc",
+ "dbus.h",
+ "libdbusglibsymboltable.cc",
+ "libdbusglibsymboltable.h",
+ "linuxfdwalk.c",
+ "linuxfdwalk.h",
+ "linuxwindowpicker.cc",
+ "linuxwindowpicker.h",
+ ]
+ }
+
+ if (is_mac) {
+ all_dependent_configs = [ ":mac_config" ]
+
+ libs = [
+ "crypto", # $(SDKROOT)/usr/lib/libcrypto.dylib
+ "ssl", # $(SDKROOT)/usr/lib/libssl.dylib
+ ]
+ if (cpu_arch == "x86") {
+ all_dependent_configs += [ ":mac_x86_config" ]
+ }
+ } else {
+ sources -= [
+ "macasyncsocket.cc",
+ "macasyncsocket.h",
+ "maccocoasocketserver.h",
+ #"maccocoasocketserver.mm", # Seems to be excluded by default with GN.
+ "macconversion.cc",
+ "macconversion.h",
+ "macsocketserver.cc",
+ "macsocketserver.h",
+ "macutils.cc",
+ "macutils.h",
+ "macwindowpicker.cc",
+ "macwindowpicker.h",
+ ]
+ }
+
+ if (is_win) {
+ libs = [
+ "crypt32.lib",
+ "iphlpapi.lib",
+ "secur32.lib",
+ ]
+
+ cflags += [
+ # Suppress warnings about WIN32_LEAN_AND_MEAN.
+ "/wd4005",
+ "/wd4703",
+ ]
+
+ defines += [ "_CRT_NONSTDC_NO_DEPRECATE" ]
+ } else {
+ sources -= [
+ "schanneladapter.cc",
+ "schanneladapter.h",
+ "winping.cc",
+ "winping.h",
+ "winfirewall.cc",
+ "winfirewall.h",
+ # The files below were covered by a regex exclude in GYP.
+ "win32.cc",
+ "win32.h",
+ "win32filesystem.cc",
+ "win32filesystem.h",
+ "win32regkey.cc",
+ "win32regkey.h",
+ "win32securityerrors.cc",
+ "win32socketinit.cc",
+ "win32socketinit.h",
+ "win32socketserver.cc",
+ "win32socketserver.h",
+ "win32window.cc",
+ "win32window.h",
+ "win32windowpicker.cc",
+ "win32windowpicker.h",
+ ]
+ }
+
+ if (is_posix) {
+ if (is_debug) {
+ defines += [ "_DEBUG" ]
+ }
+ } else {
+ sources -= [
+ "latebindingsymboltable.cc",
+ "latebindingsymboltable.h",
+ "posix.cc",
+ "posix.h",
+ "unixfilesystem.cc",
+ "unixfilesystem.h",
+ ]
+ }
+
+ if (is_ios || (is_mac && cpu_arch != "x86")) {
+ defines += [ "CARBON_DEPRECATED=YES" ]
+ }
+
+ if (is_ios || !is_posix) {
+ sources -= [
+ "openssl.h",
+ "openssladapter.cc",
+ "openssladapter.h",
+ "openssldigest.cc",
+ "openssldigest.h",
+ "opensslidentity.cc",
+ "opensslidentity.h",
+ "opensslstreamadapter.cc",
+ "opensslstreamadapter.h",
+ ]
+ }
+
+ if (!is_linux && !is_android) {
+ sources -= [
+ "linux.cc",
+ "linux.h",
+ ]
+ }
+
+ if (is_mac || is_ios || is_win) {
+ deps += [
+ "//net/third_party/nss/ssl:libssl",
+ "//third_party/nss:nspr",
+ "//third_party/nss:nss",
+ ]
+ }
+
+ if (is_posix && !is_mac && !is_ios && !is_android) {
+ configs += [ ":linux_system_ssl" ]
+ }
+}
diff --git a/base/base.gyp b/base/base.gyp
index 5cb1fd9b..330ea82a 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -452,8 +452,22 @@
],
},
}, {
- 'dependencies': [
- '<(DEPTH)/third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
+ 'conditions': [
+ ['build_json==1', {
+ 'dependencies': [
+ '<(DEPTH)/third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
+ ],
+ }, {
+ 'include_dirs': [
+ '<(json_root)',
+ ],
+ 'defines': [
+ # When defined changes the include path for json.h to where it
+ # is expected to be when building json outside of the standalone
+ # build.
+ 'WEBRTC_EXTERNAL_JSON',
+ ],
+ }],
],
'sources!': [
'../overrides/webrtc/base/basictypes.h',
@@ -474,8 +488,16 @@
'HAVE_OPENSSL_SSL_H',
],
},
- 'dependencies': [
- '<(DEPTH)/third_party/openssl/openssl.gyp:openssl',
+ 'conditions': [
+ ['build_ssl==1', {
+ 'dependencies': [
+ '<(DEPTH)/third_party/openssl/openssl.gyp:openssl',
+ ],
+ }, {
+ 'include_dirs': [
+ '<(ssl_root)',
+ ],
+ }],
],
}, {
'defines': [
@@ -533,8 +555,16 @@
],
},
},
- 'dependencies': [
- '<(DEPTH)/net/third_party/nss/ssl.gyp:libssl',
+ 'conditions': [
+ ['build_ssl==1', {
+ 'dependencies': [
+ '<(DEPTH)/net/third_party/nss/ssl.gyp:libssl',
+ ]
+ }, {
+ 'include_dirs': [
+ '<(ssl_root)',
+ ],
+ }],
],
}],
['OS=="linux"', {
@@ -693,15 +723,31 @@
],
}],
['OS == "mac" or OS == "ios" or OS == "win"', {
- 'dependencies': [
- '<(DEPTH)/net/third_party/nss/ssl.gyp:libssl',
- '<(DEPTH)/third_party/nss/nss.gyp:nspr',
- '<(DEPTH)/third_party/nss/nss.gyp:nss',
+ 'conditions': [
+ ['build_ssl==1', {
+ 'dependencies': [
+ '<(DEPTH)/net/third_party/nss/ssl.gyp:libssl',
+ '<(DEPTH)/third_party/nss/nss.gyp:nspr',
+ '<(DEPTH)/third_party/nss/nss.gyp:nss',
+ ],
+ }, {
+ 'include_dirs': [
+ '<(ssl_root)',
+ ],
+ }],
],
}],
['os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', {
- 'dependencies': [
- '<(DEPTH)/build/linux/system.gyp:ssl',
+ 'conditions': [
+ ['build_ssl==1', {
+ 'dependencies': [
+ '<(DEPTH)/build/linux/system.gyp:ssl',
+ ],
+ }, {
+ 'include_dirs': [
+ '<(ssl_root)',
+ ],
+ }],
],
}],
],
diff --git a/base/json.h b/base/json.h
index a8f76be1..9d45ded9 100644
--- a/base/json.h
+++ b/base/json.h
@@ -14,7 +14,7 @@
#include <string>
#include <vector>
-#if !defined(WEBRTC_EXTERNAL)
+#if !defined(WEBRTC_EXTERNAL_JSON)
#include "json/json.h"
#else
#include "third_party/jsoncpp/json.h"
diff --git a/base/profiler_unittest.cc b/base/profiler_unittest.cc
index 5a607914..8f4421e9 100644
--- a/base/profiler_unittest.cc
+++ b/base/profiler_unittest.cc
@@ -30,13 +30,15 @@ namespace rtc {
TEST(ProfilerTest, TestFunction) {
ASSERT_TRUE(Profiler::Instance()->Clear());
+
// Profile a long-running function.
const char* function_name = TestFunc();
const ProfilerEvent* event = Profiler::Instance()->GetEvent(function_name);
ASSERT_TRUE(event != NULL);
EXPECT_FALSE(event->is_started());
EXPECT_EQ(1, event->event_count());
- EXPECT_NEAR(kWaitSec, event->mean(), kTolerance);
+ EXPECT_NEAR(kWaitSec, event->mean(), kTolerance * 3);
+
// Run it a second time.
TestFunc();
EXPECT_FALSE(event->is_started());
@@ -78,7 +80,9 @@ TEST(ProfilerTest, TestScopedEvents) {
// Check the result.
EXPECT_FALSE(event2->is_started());
EXPECT_EQ(1, event2->event_count());
- EXPECT_NEAR(kEvent2WaitSec, event2->mean(), kTolerance);
+
+ // The difference here can be as much as 0.33, so we need high tolerance.
+ EXPECT_NEAR(kEvent2WaitSec, event2->mean(), kTolerance * 4);
// Make sure event1 is unchanged.
EXPECT_FALSE(event1->is_started());
EXPECT_EQ(1, event1->event_count());
diff --git a/build/common.gypi b/build/common.gypi
index da96c1d3..cbc398e4 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -54,6 +54,12 @@
'webrtc_vp8_dir%': '<(webrtc_vp8_dir)',
'include_opus%': '<(include_opus)',
'rbe_components_path%': '<(rbe_components_path)',
+ 'external_libraries%': '0',
+ 'json_root%': '<(DEPTH)/third_party/jsoncpp/source/include/',
+ # openssl needs to be defined or gyp will complain. Is is only used when
+ # when providing external libraries so just use current directory as a
+ # placeholder.
+ 'ssl_root%': '.',
# The Chromium common.gypi we use treats all gyp files without
# chromium_code==1 as third party code. This disables many of the
@@ -85,9 +91,11 @@
'enable_protobuf%': 1,
# Disable these to not build components which can be externally provided.
+ 'build_json%': 1,
'build_libjpeg%': 1,
'build_libyuv%': 1,
'build_libvpx%': 1,
+ 'build_ssl%': 1,
# Disable by default
'have_dbus_glib%': 0,
diff --git a/build/webrtc.gni b/build/webrtc.gni
new file mode 100644
index 00000000..e269a262
--- /dev/null
+++ b/build/webrtc.gni
@@ -0,0 +1,57 @@
+# 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.
+
+declare_args() {
+ # Assume Chromium build for now, since that's the priority case for getting GN
+ # up and running with WebRTC.
+ build_with_chromium = true
+ build_with_libjingle = true
+
+ if (build_with_libjingle) {
+ include_tests = false
+ restrict_webrtc_logging = true
+ } else {
+ include_tests = true
+ restrict_webrtc_logging = false
+ }
+
+ # Adds video support to dependencies shared by voice and video engine.
+ # This should normally be enabled; the intended use is to disable only
+ # when building voice engine exclusively.
+ enable_video = true
+
+ # Selects fixed-point code where possible.
+ prefer_fixed_point = false
+
+ build_libjpeg = true
+ # Enables the use of protocol buffers for debug recordings.
+ enable_protobuf = true
+
+ # Disable by default.
+ have_dbus_glib = false
+
+ # Enable to use the Mozilla internal settings.
+ build_with_mozilla = false
+
+ # Define MIPS architecture variant, MIPS DSP variant and MIPS FPU
+ # This may be subject to change in accordance to Chromium's MIPS flags
+ mips_arch_variant = "mips32r1"
+ mips_dsp_rev = 0
+ mips_fpu = true
+
+ enable_android_opensl = true
+
+ if (is_ios) {
+ build_libjpeg = false
+ enable_protobuf = false
+ }
+
+ if (cpu_arch == "arm") {
+ prefer_fixed_point = true
+ }
+}
diff --git a/modules/audio_coding/codecs/isac/fix/source/isacfix.c b/modules/audio_coding/codecs/isac/fix/source/isacfix.c
index 688ec07a..76359080 100644
--- a/modules/audio_coding/codecs/isac/fix/source/isacfix.c
+++ b/modules/audio_coding/codecs/isac/fix/source/isacfix.c
@@ -608,15 +608,11 @@ int16_t WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_MainStruct *ISAC_main_inst,
{
ISACFIX_SubStruct *ISAC_inst;
Bitstr_dec streamdata;
- uint16_t partOfStream[5];
#ifndef WEBRTC_ARCH_BIG_ENDIAN
int k;
#endif
int16_t err;
- /* Set stream pointer to point at partOfStream */
- streamdata.stream = (uint16_t *)partOfStream;
-
/* typecast pointer to real structure */
ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
@@ -696,15 +692,11 @@ int16_t WebRtcIsacfix_UpdateBwEstimate(ISACFIX_MainStruct *ISAC_main_inst,
{
ISACFIX_SubStruct *ISAC_inst;
Bitstr_dec streamdata;
- uint16_t partOfStream[5];
#ifndef WEBRTC_ARCH_BIG_ENDIAN
int k;
#endif
int16_t err;
- /* Set stream pointer to point at partOfStream */
- streamdata.stream = (uint16_t *)partOfStream;
-
/* typecast pointer to real structure */
ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
@@ -811,7 +803,6 @@ int16_t WebRtcIsacfix_Decode(ISACFIX_MainStruct *ISAC_main_inst,
return -1;
}
- (ISAC_inst->ISACdec_obj.bitstr_obj).stream = (uint16_t *)encoded;
ISAC_inst->ISACdec_obj.bitstr_obj.stream_size = (len + 1) >> 1;
/* convert bitstream from int16_t to bytes */
@@ -913,7 +904,7 @@ int16_t WebRtcIsacfix_DecodeNb(ISACFIX_MainStruct *ISAC_main_inst,
return -1;
}
- (ISAC_inst->ISACdec_obj.bitstr_obj).stream = (uint16_t *)encoded;
+ ISAC_inst->ISACdec_obj.bitstr_obj.stream_size = (len + 1) >> 1;
/* convert bitstream from int16_t to bytes */
#ifndef WEBRTC_ARCH_BIG_ENDIAN
@@ -1288,15 +1279,11 @@ int16_t WebRtcIsacfix_ReadFrameLen(const int16_t* encoded,
int16_t* frameLength)
{
Bitstr_dec streamdata;
- uint16_t partOfStream[5];
#ifndef WEBRTC_ARCH_BIG_ENDIAN
int k;
#endif
int16_t err;
- /* Set stream pointer to point at partOfStream */
- streamdata.stream = (uint16_t *)partOfStream;
-
streamdata.W_upper = 0xFFFFFFFF;
streamdata.streamval = 0;
streamdata.stream_index = 0;
@@ -1337,15 +1324,11 @@ int16_t WebRtcIsacfix_ReadBwIndex(const int16_t* encoded,
int16_t* rateIndex)
{
Bitstr_dec streamdata;
- uint16_t partOfStream[5];
#ifndef WEBRTC_ARCH_BIG_ENDIAN
int k;
#endif
int16_t err;
- /* Set stream pointer to point at partOfStream */
- streamdata.stream = (uint16_t *)partOfStream;
-
streamdata.W_upper = 0xFFFFFFFF;
streamdata.streamval = 0;
streamdata.stream_index = 0;
diff --git a/modules/audio_coding/codecs/isac/fix/source/structs.h b/modules/audio_coding/codecs/isac/fix/source/structs.h
index b4d2bd89..bd20ba01 100644
--- a/modules/audio_coding/codecs/isac/fix/source/structs.h
+++ b/modules/audio_coding/codecs/isac/fix/source/structs.h
@@ -26,7 +26,7 @@
/* Bitstream struct for decoder */
typedef struct Bitstreamstruct_dec {
- uint16_t *stream; /* Pointer to bytestream to decode */
+ uint16_t stream[STREAM_MAXW16_60MS]; /* Array bytestream to decode */
uint32_t W_upper; /* Upper boundary of interval W */
uint32_t streamval;
uint16_t stream_index; /* Index to the current position in bytestream */
diff --git a/modules/audio_coding/neteq/neteq.gypi b/modules/audio_coding/neteq/neteq.gypi
index ccdc9f5d..21ccee41 100644
--- a/modules/audio_coding/neteq/neteq.gypi
+++ b/modules/audio_coding/neteq/neteq.gypi
@@ -182,10 +182,13 @@
'tools',
],
'sources': [
+ 'tools/audio_checksum.h',
'tools/audio_loop.cc',
'tools/audio_loop.h',
+ 'tools/audio_sink.h',
'tools/input_audio_file.cc',
'tools/input_audio_file.h',
+ 'tools/output_audio_file.h',
'tools/packet.cc',
'tools/packet.h',
'tools/packet_source.h',
diff --git a/modules/audio_coding/neteq/tools/audio_checksum.h b/modules/audio_coding/neteq/tools/audio_checksum.h
new file mode 100644
index 00000000..ac568265
--- /dev/null
+++ b/modules/audio_coding/neteq/tools/audio_checksum.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_AUDIO_CHECKSUM_H_
+#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_AUDIO_CHECKSUM_H_
+
+#include <string>
+
+#include "webrtc/base/constructormagic.h"
+#include "webrtc/base/md5digest.h"
+#include "webrtc/base/stringencode.h"
+#include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h"
+#include "webrtc/system_wrappers/interface/compile_assert.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+namespace test {
+
+class AudioChecksum : public AudioSink {
+ public:
+ AudioChecksum() : finished_(false) {}
+
+ virtual bool WriteArray(const int16_t* audio, size_t num_samples) OVERRIDE {
+ if (finished_)
+ return false;
+
+#ifndef WEBRTC_ARCH_LITTLE_ENDIAN
+#error "Big-endian gives a different checksum"
+#endif
+ checksum_.Update(audio, num_samples * sizeof(*audio));
+ return true;
+ }
+
+ // Finalizes the computations, and returns the checksum.
+ std::string Finish() {
+ if (!finished_) {
+ finished_ = true;
+ checksum_.Finish(checksum_result_, rtc::Md5Digest::kSize);
+ }
+ return rtc::hex_encode(checksum_result_, rtc::Md5Digest::kSize);
+ }
+
+ private:
+ rtc::Md5Digest checksum_;
+ char checksum_result_[rtc::Md5Digest::kSize];
+ bool finished_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioChecksum);
+};
+
+} // namespace test
+} // namespace webrtc
+#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_AUDIO_CHECKSUM_H_
diff --git a/modules/audio_coding/neteq/tools/audio_sink.h b/modules/audio_coding/neteq/tools/audio_sink.h
new file mode 100644
index 00000000..5743c364
--- /dev/null
+++ b/modules/audio_coding/neteq/tools/audio_sink.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_AUDIO_SINK_H_
+#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_AUDIO_SINK_H_
+
+#include "webrtc/base/constructormagic.h"
+#include "webrtc/modules/interface/module_common_types.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+namespace test {
+
+// Interface class for an object receiving raw output audio from test
+// applications.
+class AudioSink {
+ public:
+ AudioSink() {}
+ virtual ~AudioSink() {}
+
+ // Writes |num_samples| from |audio| to the AudioSink. Returns true if
+ // successful, otherwise false.
+ virtual bool WriteArray(const int16_t* audio, size_t num_samples) = 0;
+
+ // Writes |audio_frame| to the AudioSink. Returns true if successful,
+ // otherwise false.
+ bool WriteAudioFrame(const AudioFrame& audio_frame) {
+ return WriteArray(
+ audio_frame.data_,
+ audio_frame.samples_per_channel_ * audio_frame.num_channels_);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AudioSink);
+};
+
+} // namespace test
+} // namespace webrtc
+#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_AUDIO_SINK_H_
diff --git a/modules/audio_coding/neteq/tools/output_audio_file.h b/modules/audio_coding/neteq/tools/output_audio_file.h
new file mode 100644
index 00000000..1d612807
--- /dev/null
+++ b/modules/audio_coding/neteq/tools/output_audio_file.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_OUTPUT_AUDIO_FILE_H_
+#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_OUTPUT_AUDIO_FILE_H_
+
+#include <assert.h>
+#include <stdio.h>
+#include <string>
+
+#include "webrtc/base/constructormagic.h"
+#include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h"
+
+namespace webrtc {
+namespace test {
+
+class OutputAudioFile : public AudioSink {
+ public:
+ // Creates an OutputAudioFile, opening a file named |file_name| for writing.
+ // The file format is 16-bit signed host-endian PCM.
+ explicit OutputAudioFile(const std::string& file_name) {
+ out_file_ = fopen(file_name.c_str(), "wb");
+ }
+
+ virtual ~OutputAudioFile() {
+ if (out_file_)
+ fclose(out_file_);
+ }
+
+ virtual bool WriteArray(const int16_t* audio, size_t num_samples) OVERRIDE {
+ assert(out_file_);
+ return fwrite(audio, sizeof(*audio), num_samples, out_file_) == num_samples;
+ }
+
+ private:
+ FILE* out_file_;
+
+ DISALLOW_COPY_AND_ASSIGN(OutputAudioFile);
+};
+
+} // namespace test
+} // namespace webrtc
+#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_OUTPUT_AUDIO_FILE_H_
diff --git a/modules/audio_coding/neteq/tools/packet_source.h b/modules/audio_coding/neteq/tools/packet_source.h
index c539b8e8..669bc14e 100644
--- a/modules/audio_coding/neteq/tools/packet_source.h
+++ b/modules/audio_coding/neteq/tools/packet_source.h
@@ -24,7 +24,8 @@ class PacketSource {
PacketSource() {}
virtual ~PacketSource() {}
- // Returns a pointer to the next packet.
+ // Returns a pointer to the next packet. Returns NULL if the source is
+ // depleted, or if an error occurred.
virtual Packet* NextPacket() = 0;
private:
diff --git a/modules/audio_coding/neteq/tools/rtp_file_source.cc b/modules/audio_coding/neteq/tools/rtp_file_source.cc
index 82786353..6490d468 100644
--- a/modules/audio_coding/neteq/tools/rtp_file_source.cc
+++ b/modules/audio_coding/neteq/tools/rtp_file_source.cc
@@ -47,47 +47,54 @@ bool RtpFileSource::RegisterRtpHeaderExtension(RTPExtensionType type,
}
Packet* RtpFileSource::NextPacket() {
- uint16_t length;
- if (fread(&length, sizeof(uint16_t), 1, in_file_) == 0) {
- assert(false);
- return NULL;
- }
- length = ntohs(length);
-
- uint16_t plen;
- if (fread(&plen, sizeof(uint16_t), 1, in_file_) == 0) {
- assert(false);
- return NULL;
- }
- plen = ntohs(plen);
-
- uint32_t offset;
- if (fread(&offset, sizeof(uint32_t), 1, in_file_) == 0) {
- assert(false);
- return NULL;
- }
-
- // Use length here because a plen of 0 specifies RTCP.
- size_t packet_size_bytes = length - kPacketHeaderSize;
- if (packet_size_bytes <= 0) {
- // May be an RTCP packet.
- return NULL;
- }
- uint8_t* packet_memory = new uint8_t[packet_size_bytes];
- if (fread(packet_memory, 1, packet_size_bytes, in_file_) !=
- packet_size_bytes) {
- assert(false);
- delete[] packet_memory;
- return NULL;
- }
- Packet* packet = new Packet(
- packet_memory, packet_size_bytes, plen, ntohl(offset), *parser_.get());
- if (!packet->valid_header()) {
- assert(false);
- delete packet;
- return NULL;
+ while (!EndOfFile()) {
+ uint16_t length;
+ if (fread(&length, sizeof(length), 1, in_file_) == 0) {
+ assert(false);
+ return NULL;
+ }
+ length = ntohs(length);
+
+ uint16_t plen;
+ if (fread(&plen, sizeof(plen), 1, in_file_) == 0) {
+ assert(false);
+ return NULL;
+ }
+ plen = ntohs(plen);
+
+ uint32_t offset;
+ if (fread(&offset, sizeof(offset), 1, in_file_) == 0) {
+ assert(false);
+ return NULL;
+ }
+ offset = ntohl(offset);
+
+ // Use length here because a plen of 0 specifies RTCP.
+ assert(length >= kPacketHeaderSize);
+ size_t packet_size_bytes = length - kPacketHeaderSize;
+ if (packet_size_bytes == 0) {
+ // May be an RTCP packet.
+ // Read the next one.
+ continue;
+ }
+ scoped_ptr<uint8_t> packet_memory(new uint8_t[packet_size_bytes]);
+ if (fread(packet_memory.get(), 1, packet_size_bytes, in_file_) !=
+ packet_size_bytes) {
+ assert(false);
+ return NULL;
+ }
+ scoped_ptr<Packet> packet(new Packet(packet_memory.release(),
+ packet_size_bytes,
+ plen,
+ offset,
+ *parser_.get()));
+ if (!packet->valid_header()) {
+ assert(false);
+ return NULL;
+ }
+ return packet.release();
}
- return packet;
+ return NULL;
}
bool RtpFileSource::EndOfFile() const {
diff --git a/modules/audio_coding/neteq/tools/rtp_file_source.h b/modules/audio_coding/neteq/tools/rtp_file_source.h
index 527018e1..6b92a886 100644
--- a/modules/audio_coding/neteq/tools/rtp_file_source.h
+++ b/modules/audio_coding/neteq/tools/rtp_file_source.h
@@ -37,7 +37,8 @@ class RtpFileSource : public PacketSource {
// Registers an RTP header extension and binds it to |id|.
virtual bool RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id);
- // Returns a pointer to the next packet.
+ // Returns a pointer to the next packet. Returns NULL if end of file was
+ // reached, or if a the data was corrupt.
virtual Packet* NextPacket();
// Returns true if the end of file has been reached.
diff --git a/modules/audio_processing/aec/aec_core_neon.c b/modules/audio_processing/aec/aec_core_neon.c
index d751a4b1..cec0a7e3 100644
--- a/modules/audio_processing/aec/aec_core_neon.c
+++ b/modules/audio_processing/aec/aec_core_neon.c
@@ -18,6 +18,7 @@
#include <arm_neon.h>
#include <math.h>
+#include <string.h> // memset
#include "webrtc/modules/audio_processing/aec/aec_core_internal.h"
#include "webrtc/modules/audio_processing/aec/aec_rdft.h"
@@ -25,6 +26,85 @@
enum { kShiftExponentIntoTopMantissa = 8 };
enum { kFloatExponentShift = 23 };
+__inline static float MulRe(float aRe, float aIm, float bRe, float bIm) {
+ return aRe * bRe - aIm * bIm;
+}
+
+static void FilterAdaptationNEON(AecCore* aec,
+ float* fft,
+ float ef[2][PART_LEN1]) {
+ int i;
+ const int num_partitions = aec->num_partitions;
+ for (i = 0; i < num_partitions; i++) {
+ int xPos = (i + aec->xfBufBlockPos) * PART_LEN1;
+ int pos = i * PART_LEN1;
+ int j;
+ // Check for wrap
+ if (i + aec->xfBufBlockPos >= num_partitions) {
+ xPos -= num_partitions * PART_LEN1;
+ }
+
+ // Process the whole array...
+ for (j = 0; j < PART_LEN; j += 4) {
+ // Load xfBuf and ef.
+ const float32x4_t xfBuf_re = vld1q_f32(&aec->xfBuf[0][xPos + j]);
+ const float32x4_t xfBuf_im = vld1q_f32(&aec->xfBuf[1][xPos + j]);
+ const float32x4_t ef_re = vld1q_f32(&ef[0][j]);
+ const float32x4_t ef_im = vld1q_f32(&ef[1][j]);
+ // Calculate the product of conjugate(xfBuf) by ef.
+ // re(conjugate(a) * b) = aRe * bRe + aIm * bIm
+ // im(conjugate(a) * b)= aRe * bIm - aIm * bRe
+ const float32x4_t a = vmulq_f32(xfBuf_re, ef_re);
+ const float32x4_t e = vmlaq_f32(a, xfBuf_im, ef_im);
+ const float32x4_t c = vmulq_f32(xfBuf_re, ef_im);
+ const float32x4_t f = vmlsq_f32(c, xfBuf_im, ef_re);
+ // Interleave real and imaginary parts.
+ const float32x4x2_t g_n_h = vzipq_f32(e, f);
+ // Store
+ vst1q_f32(&fft[2 * j + 0], g_n_h.val[0]);
+ vst1q_f32(&fft[2 * j + 4], g_n_h.val[1]);
+ }
+ // ... and fixup the first imaginary entry.
+ fft[1] = MulRe(aec->xfBuf[0][xPos + PART_LEN],
+ -aec->xfBuf[1][xPos + PART_LEN],
+ ef[0][PART_LEN],
+ ef[1][PART_LEN]);
+
+ aec_rdft_inverse_128(fft);
+ memset(fft + PART_LEN, 0, sizeof(float) * PART_LEN);
+
+ // fft scaling
+ {
+ const float scale = 2.0f / PART_LEN2;
+ const float32x4_t scale_ps = vmovq_n_f32(scale);
+ for (j = 0; j < PART_LEN; j += 4) {
+ const float32x4_t fft_ps = vld1q_f32(&fft[j]);
+ const float32x4_t fft_scale = vmulq_f32(fft_ps, scale_ps);
+ vst1q_f32(&fft[j], fft_scale);
+ }
+ }
+ aec_rdft_forward_128(fft);
+
+ {
+ const float wt1 = aec->wfBuf[1][pos];
+ aec->wfBuf[0][pos + PART_LEN] += fft[1];
+ for (j = 0; j < PART_LEN; j += 4) {
+ float32x4_t wtBuf_re = vld1q_f32(&aec->wfBuf[0][pos + j]);
+ float32x4_t wtBuf_im = vld1q_f32(&aec->wfBuf[1][pos + j]);
+ const float32x4_t fft0 = vld1q_f32(&fft[2 * j + 0]);
+ const float32x4_t fft4 = vld1q_f32(&fft[2 * j + 4]);
+ const float32x4x2_t fft_re_im = vuzpq_f32(fft0, fft4);
+ wtBuf_re = vaddq_f32(wtBuf_re, fft_re_im.val[0]);
+ wtBuf_im = vaddq_f32(wtBuf_im, fft_re_im.val[1]);
+
+ vst1q_f32(&aec->wfBuf[0][pos + j], wtBuf_re);
+ vst1q_f32(&aec->wfBuf[1][pos + j], wtBuf_im);
+ }
+ aec->wfBuf[1][pos] = wt1;
+ }
+ }
+}
+
extern const float WebRtcAec_weightCurve[65];
extern const float WebRtcAec_overDriveCurve[65];
@@ -218,6 +298,7 @@ static void OverdriveAndSuppressNEON(AecCore* aec,
}
void WebRtcAec_InitAec_neon(void) {
+ WebRtcAec_FilterAdaptation = FilterAdaptationNEON;
WebRtcAec_OverdriveAndSuppress = OverdriveAndSuppressNEON;
}
diff --git a/modules/audio_processing/aec/system_delay_unittest.cc b/modules/audio_processing/aec/system_delay_unittest.cc
index e85fc28f..a13d4762 100644
--- a/modules/audio_processing/aec/system_delay_unittest.cc
+++ b/modules/audio_processing/aec/system_delay_unittest.cc
@@ -248,12 +248,14 @@ TEST_F(SystemDelayTest, CorrectDelayAfterUnstableStartup) {
}
}
-TEST_F(SystemDelayTest,
- DISABLED_ON_ANDROID(CorrectDelayAfterStableBufferBuildUp)) {
+TEST_F(SystemDelayTest, CorrectDelayAfterStableBufferBuildUp) {
// In this test we start by establishing the device buffer size during stable
// conditions, but with an empty internal far-end buffer. Once that is done we
// verify that the system delay is increased correctly until we have reach an
// internal buffer size of 75% of what's been reported.
+
+ // This test assumes the reported delays are used.
+ WebRtcAec_enable_reported_delay(WebRtcAec_aec_core(handle_), 1);
for (size_t i = 0; i < kNumSampleRates; i++) {
Init(kSampleRateHz[i]);
@@ -330,11 +332,14 @@ TEST_F(SystemDelayTest, CorrectDelayWhenBufferUnderrun) {
}
}
-TEST_F(SystemDelayTest, DISABLED_ON_ANDROID(CorrectDelayDuringDrift)) {
+TEST_F(SystemDelayTest, CorrectDelayDuringDrift) {
// This drift test should verify that the system delay is never exceeding the
// device buffer. The drift is simulated by decreasing the reported device
// buffer size by 1 ms every 100 ms. If the device buffer size goes below 30
// ms we jump (add) 10 ms to give a repeated pattern.
+
+ // This test assumes the reported delays are used.
+ WebRtcAec_enable_reported_delay(WebRtcAec_aec_core(handle_), 1);
for (size_t i = 0; i < kNumSampleRates; i++) {
Init(kSampleRateHz[i]);
RunStableStartup();
@@ -361,13 +366,16 @@ TEST_F(SystemDelayTest, DISABLED_ON_ANDROID(CorrectDelayDuringDrift)) {
}
}
-TEST_F(SystemDelayTest, DISABLED_ON_ANDROID(ShouldRecoverAfterGlitch)) {
+TEST_F(SystemDelayTest, ShouldRecoverAfterGlitch) {
// This glitch test should verify that the system delay recovers if there is
// a glitch in data. The data glitch is constructed as 200 ms of buffering
// after which the stable procedure continues. The glitch is never reported by
// the device.
// The system is said to be in a non-causal state if the difference between
// the device buffer and system delay is less than a block (64 samples).
+
+ // This test assumes the reported delays are used.
+ WebRtcAec_enable_reported_delay(WebRtcAec_aec_core(handle_), 1);
for (size_t i = 0; i < kNumSampleRates; i++) {
Init(kSampleRateHz[i]);
RunStableStartup();
diff --git a/modules/audio_processing/test/audio_processing_unittest.cc b/modules/audio_processing/test/audio_processing_unittest.cc
index 406c3de5..65c2d8d4 100644
--- a/modules/audio_processing/test/audio_processing_unittest.cc
+++ b/modules/audio_processing/test/audio_processing_unittest.cc
@@ -827,7 +827,7 @@ TEST_F(ApmTest, EchoCancellation) {
EXPECT_FALSE(apm_->echo_cancellation()->aec_core() != NULL);
}
-TEST_F(ApmTest, DISABLED_ON_ANDROID(EchoCancellationReportsCorrectDelays)) {
+TEST_F(ApmTest, DISABLED_EchoCancellationReportsCorrectDelays) {
// Enable AEC only.
EXPECT_EQ(apm_->kNoError,
apm_->echo_cancellation()->enable_drift_compensation(false));
@@ -836,6 +836,9 @@ TEST_F(ApmTest, DISABLED_ON_ANDROID(EchoCancellationReportsCorrectDelays)) {
EXPECT_EQ(apm_->kNoError,
apm_->echo_cancellation()->enable_delay_logging(true));
EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
+ Config config;
+ config.Set<ReportedDelay>(new ReportedDelay(true));
+ apm_->SetExtraOptions(config);
// Internally in the AEC the amount of lookahead the delay estimation can
// handle is 15 blocks and the maximum delay is set to 60 blocks.
diff --git a/modules/audio_processing/test/process_test.cc b/modules/audio_processing/test/process_test.cc
index 01f9dcec..a36a072c 100644
--- a/modules/audio_processing/test/process_test.cc
+++ b/modules/audio_processing/test/process_test.cc
@@ -78,6 +78,7 @@ void usage() {
printf(" --no_delay_logging\n");
printf(" --aec_suppression_level LEVEL [0 - 2]\n");
printf(" --extended_filter\n");
+ printf(" --no_reported_delay\n");
printf("\n -aecm Echo control mobile\n");
printf(" --aecm_echo_path_in_file FILE\n");
printf(" --aecm_echo_path_out_file FILE\n");
@@ -257,6 +258,11 @@ void void_main(int argc, char* argv[]) {
config.Set<DelayCorrection>(new DelayCorrection(true));
apm->SetExtraOptions(config);
+ } else if (strcmp(argv[i], "--no_reported_delay") == 0) {
+ Config config;
+ config.Set<ReportedDelay>(new ReportedDelay(false));
+ apm->SetExtraOptions(config);
+
} else if (strcmp(argv[i], "-aecm") == 0) {
ASSERT_EQ(apm->kNoError, apm->echo_control_mobile()->Enable(true));
diff --git a/modules/bitrate_controller/bitrate_controller_impl.cc b/modules/bitrate_controller/bitrate_controller_impl.cc
index 48f59b85..cff5dd18 100644
--- a/modules/bitrate_controller/bitrate_controller_impl.cc
+++ b/modules/bitrate_controller/bitrate_controller_impl.cc
@@ -139,6 +139,21 @@ void BitrateControllerImpl::SetBitrateObserver(
it->second->start_bitrate_ = start_bitrate;
it->second->min_bitrate_ = min_bitrate;
it->second->max_bitrate_ = max_bitrate;
+ // Set the send-side bandwidth to the max of the sum of start bitrates and
+ // the current estimate, so that if the user wants to immediately use more
+ // bandwidth, that can be enforced.
+ uint32_t sum_start_bitrate = 0;
+ BitrateObserverConfList::iterator it;
+ for (it = bitrate_observers_.begin(); it != bitrate_observers_.end();
+ ++it) {
+ sum_start_bitrate += it->second->start_bitrate_;
+ }
+ uint32_t current_estimate;
+ uint8_t loss;
+ uint32_t rtt;
+ bandwidth_estimation_.CurrentEstimate(&current_estimate, &loss, &rtt);
+ bandwidth_estimation_.SetSendBitrate(std::max(sum_start_bitrate,
+ current_estimate));
} else {
// Add new settings.
bitrate_observers_.push_back(BitrateObserverConfiguration(observer,
@@ -159,12 +174,10 @@ void BitrateControllerImpl::SetBitrateObserver(
}
void BitrateControllerImpl::UpdateMinMaxBitrate() {
- uint32_t sum_start_bitrate = 0;
uint32_t sum_min_bitrate = 0;
uint32_t sum_max_bitrate = 0;
BitrateObserverConfList::iterator it;
for (it = bitrate_observers_.begin(); it != bitrate_observers_.end(); ++it) {
- sum_start_bitrate += it->second->start_bitrate_;
sum_min_bitrate += it->second->min_bitrate_;
sum_max_bitrate += it->second->max_bitrate_;
}
diff --git a/modules/bitrate_controller/bitrate_controller_unittest.cc b/modules/bitrate_controller/bitrate_controller_unittest.cc
index b15eb29d..8523d505 100644
--- a/modules/bitrate_controller/bitrate_controller_unittest.cc
+++ b/modules/bitrate_controller/bitrate_controller_unittest.cc
@@ -83,6 +83,24 @@ TEST_F(BitrateControllerTest, Basic) {
controller_->RemoveBitrateObserver(&bitrate_observer);
}
+TEST_F(BitrateControllerTest, UpdatingBitrateObserver) {
+ TestBitrateObserver bitrate_observer;
+ controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 1500000);
+ clock_.AdvanceTimeMilliseconds(25);
+ controller_->Process();
+ EXPECT_EQ(200000u, bitrate_observer.last_bitrate_);
+
+ controller_->SetBitrateObserver(&bitrate_observer, 1500000, 100000, 1500000);
+ clock_.AdvanceTimeMilliseconds(25);
+ controller_->Process();
+ EXPECT_EQ(1500000u, bitrate_observer.last_bitrate_);
+
+ controller_->SetBitrateObserver(&bitrate_observer, 500000, 100000, 1500000);
+ clock_.AdvanceTimeMilliseconds(25);
+ controller_->Process();
+ EXPECT_EQ(1500000u, bitrate_observer.last_bitrate_);
+}
+
TEST_F(BitrateControllerTest, OneBitrateObserverOneRtcpObserver) {
TestBitrateObserver bitrate_observer;
controller_->SetBitrateObserver(&bitrate_observer, 200000, 100000, 300000);
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index fe33e1b7..70fe7174 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -17,11 +17,6 @@
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/system_wrappers/interface/trace.h"
-#ifdef MATLAB
-#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.h"
-extern MatlabEngine eng; // Global variable defined elsewhere.
-#endif
-
#ifdef _WIN32
// Disable warning C4355: 'this' : used in base member initializer list.
#pragma warning(disable : 4355)
@@ -66,7 +61,9 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
configuration.outgoing_transport,
configuration.audio_messages,
configuration.paced_sender),
- rtcp_sender_(configuration.id, configuration.audio, configuration.clock,
+ rtcp_sender_(configuration.id,
+ configuration.audio,
+ configuration.clock,
configuration.receive_statistics),
rtcp_receiver_(configuration.id, configuration.clock, this),
clock_(configuration.clock),
@@ -83,15 +80,13 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
CriticalSectionWrapper::CreateCriticalSection()),
default_module_(
static_cast<ModuleRtpRtcpImpl*>(configuration.default_module)),
+ padding_index_(-1), // Start padding at the first child module.
nack_method_(kNackOff),
nack_last_time_sent_full_(0),
nack_last_seq_number_sent_(0),
simulcast_(false),
key_frame_req_method_(kKeyFrameReqFirRtp),
remote_bitrate_(configuration.remote_bitrate_estimator),
-#ifdef MATLAB
- , plot1_(NULL),
-#endif
rtt_stats_(configuration.rtt_stats),
critical_section_rtt_(CriticalSectionWrapper::CreateCriticalSection()),
rtt_ms_(0) {
@@ -121,12 +116,6 @@ ModuleRtpRtcpImpl::~ModuleRtpRtcpImpl() {
if (default_module_) {
default_module_->DeRegisterChildModule(this);
}
-#ifdef MATLAB
- if (plot1_) {
- eng.DeletePlot(plot1_);
- plot1_ = NULL;
- }
-#endif
}
void ModuleRtpRtcpImpl::RegisterChildModule(RtpRtcp* module) {
@@ -148,7 +137,7 @@ void ModuleRtpRtcpImpl::DeRegisterChildModule(RtpRtcp* remove_module) {
CriticalSectionScoped double_lock(
critical_section_module_ptrs_feedback_.get());
- std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
while (it != child_modules_.end()) {
RtpRtcp* module = *it;
if (module == remove_module) {
@@ -252,8 +241,9 @@ void ModuleRtpRtcpImpl::SetRTXSendStatus(int mode) {
rtp_sender_.SetRTXStatus(mode);
}
-void ModuleRtpRtcpImpl::RTXSendStatus(int* mode, uint32_t* ssrc,
- int* payload_type) const {
+void ModuleRtpRtcpImpl::RTXSendStatus(int* mode,
+ uint32_t* ssrc,
+ int* payload_type) const {
rtp_sender_.RTXStatus(mode, ssrc, payload_type);
}
@@ -372,7 +362,7 @@ int32_t ModuleRtpRtcpImpl::SetCSRCs(
// For default we need to update all child modules too.
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
- std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
while (it != child_modules_.end()) {
RtpRtcp* module = *it;
if (module) {
@@ -443,7 +433,7 @@ bool ModuleRtpRtcpImpl::SendingMedia() const {
}
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
- std::list<ModuleRtpRtcpImpl*>::const_iterator it = child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::const_iterator it = child_modules_.begin();
while (it != child_modules_.end()) {
RTPSender& rtp_sender = (*it)->rtp_sender_;
if (rtp_sender.SendingMedia()) {
@@ -488,7 +478,7 @@ int32_t ModuleRtpRtcpImpl::SendOutgoingData(
return -1;
}
int idx = 0;
- std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
for (; idx < rtp_video_hdr->simulcastIdx; ++it) {
if (it == child_modules_.end()) {
return -1;
@@ -515,7 +505,7 @@ int32_t ModuleRtpRtcpImpl::SendOutgoingData(
fragmentation,
rtp_video_hdr);
} else {
- std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
// Send to all "child" modules
while (it != child_modules_.end()) {
if ((*it)->SendingMedia()) {
@@ -546,7 +536,7 @@ bool ModuleRtpRtcpImpl::TimeToSendPacket(uint32_t ssrc,
}
} else {
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
- std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
while (it != child_modules_.end()) {
if ((*it)->SendingMedia() && ssrc == (*it)->rtp_sender_.SSRC()) {
return (*it)->rtp_sender_.TimeToSendPacket(sequence_number,
@@ -568,13 +558,15 @@ int ModuleRtpRtcpImpl::TimeToSendPadding(int bytes) {
}
} else {
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
- std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
- while (it != child_modules_.end()) {
+ // Decide what media stream to pad on based on a round-robin scheme.
+ for (size_t i = 0; i < child_modules_.size(); ++i) {
+ padding_index_ = (padding_index_ + 1) % child_modules_.size();
// Send padding on one of the modules sending media.
- if ((*it)->SendingMedia()) {
- return (*it)->rtp_sender_.TimeToSendPadding(bytes);
+ if (child_modules_[padding_index_]->SendingMedia() &&
+ child_modules_[padding_index_]->rtp_sender_.GetTargetBitrate() > 0) {
+ return child_modules_[padding_index_]->rtp_sender_.TimeToSendPadding(
+ bytes);
}
- ++it;
}
}
return 0;
@@ -603,8 +595,7 @@ uint16_t ModuleRtpRtcpImpl::MaxDataPayloadLength() const {
if (IsDefaultModule()) {
// For default we need to update all child modules too.
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
- std::list<ModuleRtpRtcpImpl*>::const_iterator it =
- child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::const_iterator it = child_modules_.begin();
while (it != child_modules_.end()) {
RtpRtcp* module = *it;
if (module) {
@@ -1001,28 +992,28 @@ void ModuleRtpRtcpImpl::SetTargetSendBitrate(
if (IsDefaultModule()) {
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
if (simulcast_) {
- std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
for (size_t i = 0;
it != child_modules_.end() && i < stream_bitrates.size(); ++it) {
if ((*it)->SendingMedia()) {
RTPSender& rtp_sender = (*it)->rtp_sender_;
- rtp_sender.SetTargetSendBitrate(stream_bitrates[i]);
+ rtp_sender.SetTargetBitrate(stream_bitrates[i]);
++i;
}
}
} else {
if (stream_bitrates.size() > 1)
return;
- std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
for (; it != child_modules_.end(); ++it) {
RTPSender& rtp_sender = (*it)->rtp_sender_;
- rtp_sender.SetTargetSendBitrate(stream_bitrates[0]);
+ rtp_sender.SetTargetBitrate(stream_bitrates[0]);
}
}
} else {
if (stream_bitrates.size() > 1)
return;
- rtp_sender_.SetTargetSendBitrate(stream_bitrates[0]);
+ rtp_sender_.SetTargetBitrate(stream_bitrates[0]);
}
}
@@ -1054,7 +1045,7 @@ int32_t ModuleRtpRtcpImpl::SendRTCPSliceLossIndication(
int32_t ModuleRtpRtcpImpl::SetCameraDelay(const int32_t delay_ms) {
if (IsDefaultModule()) {
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
- std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
while (it != child_modules_.end()) {
RtpRtcp* module = *it;
if (module) {
@@ -1084,7 +1075,7 @@ int32_t ModuleRtpRtcpImpl::GenericFECStatus(
if (IsDefaultModule()) {
// For default we need to check all child modules too.
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
- std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
while (it != child_modules_.end()) {
RtpRtcp* module = *it;
if (module) {
@@ -1118,7 +1109,7 @@ int32_t ModuleRtpRtcpImpl::SetFecParameters(
// For default we need to update all child modules too.
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
- std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
while (it != child_modules_.end()) {
RtpRtcp* module = *it;
if (module) {
@@ -1172,8 +1163,7 @@ void ModuleRtpRtcpImpl::BitrateSent(uint32_t* total_rate,
if (nack_rate != NULL)
*nack_rate = 0;
- std::list<ModuleRtpRtcpImpl*>::const_iterator it =
- child_modules_.begin();
+ std::vector<ModuleRtpRtcpImpl*>::const_iterator it = child_modules_.begin();
while (it != child_modules_.end()) {
RtpRtcp* module = *it;
if (module) {
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/modules/rtp_rtcp/source/rtp_rtcp_impl.h
index ef00a461..55826b6f 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.h
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.h
@@ -21,10 +21,6 @@
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/test/testsupport/gtest_prod_util.h"
-#ifdef MATLAB
-class MatlabPlot;
-#endif
-
namespace webrtc {
class ModuleRtpRtcpImpl : public RtpRtcp {
@@ -426,7 +422,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
scoped_ptr<CriticalSectionWrapper> critical_section_module_ptrs_;
scoped_ptr<CriticalSectionWrapper> critical_section_module_ptrs_feedback_;
ModuleRtpRtcpImpl* default_module_;
- std::list<ModuleRtpRtcpImpl*> child_modules_;
+ std::vector<ModuleRtpRtcpImpl*> child_modules_;
+ size_t padding_index_;
// Send side
NACKMethod nack_method_;
@@ -439,10 +436,6 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
RemoteBitrateEstimator* remote_bitrate_;
-#ifdef MATLAB
- MatlabPlot* plot1_;
-#endif
-
RtcpRttStats* rtt_stats_;
// The processed RTT from RtcpRttStats.
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
index 4b6fa32f..eb76cfe7 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
@@ -12,13 +12,22 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/common_types.h"
+#include "webrtc/modules/pacing/include/mock/mock_paced_sender.h"
+#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
+#include "webrtc/system_wrappers/interface/scoped_vector.h"
+
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::SaveArg;
namespace webrtc {
namespace {
const uint32_t kSenderSsrc = 0x12345;
const uint32_t kReceiverSsrc = 0x23456;
+const uint32_t kSenderRtxSsrc = 0x32345;
const uint32_t kOneWayNetworkDelayMs = 100;
class RtcpRttStatsTestImpl : public RtcpRttStats {
@@ -215,4 +224,245 @@ TEST_F(RtpRtcpImplTest, RtcpPacketTypeCounter_FirAndPli) {
EXPECT_EQ(2U, sender_.RtcpReceived().fir_packets);
EXPECT_EQ(1U, sender_.RtcpReceived().pli_packets);
}
+
+class RtpSendingTestTransport : public Transport {
+ public:
+ void ResetCounters() { bytes_received_.clear(); }
+
+ virtual int SendPacket(int channel, const void* data, int length) {
+ RTPHeader header;
+ scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
+ EXPECT_TRUE(
+ parser->Parse(static_cast<const uint8_t*>(data), length, &header));
+ bytes_received_[header.ssrc] += length;
+ ++packets_received_[header.ssrc];
+ return length;
+ }
+
+ virtual int SendRTCPPacket(int channel, const void* data, int length) {
+ return length;
+ }
+
+ int GetPacketsReceived(uint32_t ssrc) const {
+ std::map<uint32_t, int>::const_iterator it = packets_received_.find(ssrc);
+ if (it == packets_received_.end())
+ return 0;
+ return it->second;
+ }
+
+ int GetBytesReceived(uint32_t ssrc) const {
+ std::map<uint32_t, int>::const_iterator it = bytes_received_.find(ssrc);
+ if (it == bytes_received_.end())
+ return 0;
+ return it->second;
+ }
+
+ int GetTotalBytesReceived() const {
+ int sum = 0;
+ for (std::map<uint32_t, int>::const_iterator it = bytes_received_.begin();
+ it != bytes_received_.end();
+ ++it) {
+ sum += it->second;
+ }
+ return sum;
+ }
+
+ private:
+ std::map<uint32_t, int> bytes_received_;
+ std::map<uint32_t, int> packets_received_;
+};
+
+class RtpSendingTest : public ::testing::Test {
+ protected:
+ // Map from SSRC to number of received packets and bytes.
+ typedef std::map<uint32_t, std::pair<int, int> > PaddingMap;
+
+ RtpSendingTest() {
+ // Send module.
+ RtpRtcp::Configuration config;
+ config.audio = false;
+ config.clock = Clock::GetRealTimeClock();
+ config.outgoing_transport = &transport_;
+ config.receive_statistics = receive_statistics_.get();
+ config.rtt_stats = &rtt_stats_;
+ config.paced_sender = &pacer_;
+ memset(&codec_, 0, sizeof(VideoCodec));
+ codec_.plType = 100;
+ strncpy(codec_.plName, "VP8", 3);
+ codec_.numberOfSimulcastStreams = 3;
+ codec_.simulcastStream[0].width = 320;
+ codec_.simulcastStream[0].height = 180;
+ codec_.simulcastStream[0].maxBitrate = 300;
+ codec_.simulcastStream[1].width = 640;
+ codec_.simulcastStream[1].height = 360;
+ codec_.simulcastStream[1].maxBitrate = 600;
+ codec_.simulcastStream[2].width = 1280;
+ codec_.simulcastStream[2].height = 720;
+ codec_.simulcastStream[2].maxBitrate = 1200;
+ // We need numberOfSimulcastStreams + 1 RTP modules since we need one
+ // default module.
+ for (int i = 0; i < codec_.numberOfSimulcastStreams + 1; ++i) {
+ RtpRtcp* sender = RtpRtcp::CreateRtpRtcp(config);
+ EXPECT_EQ(0, sender->RegisterSendPayload(codec_));
+ EXPECT_EQ(0, sender->SetSendingStatus(true));
+ EXPECT_EQ(0, sender->SetSendingMediaStatus(true));
+ sender->SetSSRC(kSenderSsrc + i);
+ sender->SetRemoteSSRC(kReceiverSsrc + i);
+ senders_.push_back(sender);
+ config.default_module = senders_[0];
+ }
+ std::vector<uint32_t> bitrates;
+ bitrates.push_back(codec_.simulcastStream[0].maxBitrate);
+ bitrates.push_back(codec_.simulcastStream[1].maxBitrate);
+ bitrates.push_back(codec_.simulcastStream[2].maxBitrate);
+ senders_[0]->SetTargetSendBitrate(bitrates);
+ }
+
+ ~RtpSendingTest() {
+ for (int i = senders_.size() - 1; i >= 0; --i) {
+ delete senders_[i];
+ }
+ }
+
+ void SendFrameOnSender(int sender_index,
+ const uint8_t* payload,
+ size_t length) {
+ RTPVideoHeader rtp_video_header = {
+ codec_.simulcastStream[sender_index].width,
+ codec_.simulcastStream[sender_index].height,
+ true,
+ 0,
+ kRtpVideoVp8,
+ {}};
+ uint32_t seq_num = 0;
+ uint32_t ssrc = 0;
+ int64_t capture_time_ms = 0;
+ bool retransmission = false;
+ EXPECT_CALL(pacer_, SendPacket(_, _, _, _, _, _))
+ .WillRepeatedly(DoAll(SaveArg<1>(&ssrc),
+ SaveArg<2>(&seq_num),
+ SaveArg<3>(&capture_time_ms),
+ SaveArg<5>(&retransmission),
+ Return(true)));
+ EXPECT_EQ(0,
+ senders_[sender_index]->SendOutgoingData(kVideoFrameKey,
+ codec_.plType,
+ 0,
+ 0,
+ payload,
+ length,
+ NULL,
+ &rtp_video_header));
+ EXPECT_TRUE(senders_[sender_index]->TimeToSendPacket(
+ ssrc, seq_num, capture_time_ms, retransmission));
+ }
+
+ void ExpectPadding(const PaddingMap& expected_padding) {
+ int expected_total_bytes = 0;
+ for (PaddingMap::const_iterator it = expected_padding.begin();
+ it != expected_padding.end();
+ ++it) {
+ int packets_received = transport_.GetBytesReceived(it->first);
+ if (it->second.first > 0) {
+ EXPECT_GE(packets_received, it->second.first)
+ << "On SSRC: " << it->first;
+ }
+ int bytes_received = transport_.GetBytesReceived(it->first);
+ expected_total_bytes += bytes_received;
+ if (it->second.second > 0) {
+ EXPECT_GE(bytes_received, it->second.second)
+ << "On SSRC: " << it->first;
+ } else {
+ EXPECT_EQ(0, bytes_received) << "On SSRC: " << it->first;
+ }
+ }
+ EXPECT_EQ(expected_total_bytes, transport_.GetTotalBytesReceived());
+ }
+
+ scoped_ptr<ReceiveStatistics> receive_statistics_;
+ RtcpRttStatsTestImpl rtt_stats_;
+ std::vector<RtpRtcp*> senders_;
+ RtpSendingTestTransport transport_;
+ NiceMock<MockPacedSender> pacer_;
+ VideoCodec codec_;
+};
+
+TEST_F(RtpSendingTest, RoundRobinPadding) {
+ // We have to send on an SSRC to be allowed to pad, since a marker bit must
+ // be sent prior to padding packets.
+ const uint8_t payload[200] = {0};
+ for (int i = 0; i < codec_.numberOfSimulcastStreams; ++i) {
+ SendFrameOnSender(i + 1, payload, sizeof(payload));
+ }
+ transport_.ResetCounters();
+ senders_[0]->TimeToSendPadding(500);
+ PaddingMap expected_padding;
+ expected_padding[kSenderSsrc + 1] = std::make_pair(2, 500);
+ expected_padding[kSenderSsrc + 2] = std::make_pair(0, 0);
+ expected_padding[kSenderSsrc + 3] = std::make_pair(0, 0);
+ ExpectPadding(expected_padding);
+ senders_[0]->TimeToSendPadding(1000);
+ expected_padding[kSenderSsrc + 2] = std::make_pair(4, 1000);
+ ExpectPadding(expected_padding);
+ senders_[0]->TimeToSendPadding(1500);
+ expected_padding[kSenderSsrc + 3] = std::make_pair(6, 1500);
+ ExpectPadding(expected_padding);
+}
+
+TEST_F(RtpSendingTest, RoundRobinPaddingRtx) {
+ // Enable RTX to allow padding to be sent prior to media.
+ for (int i = 1; i < codec_.numberOfSimulcastStreams + 1; ++i) {
+ senders_[i]->SetRtxSendPayloadType(96);
+ senders_[i]->SetRtxSsrc(kSenderRtxSsrc + i);
+ senders_[i]->SetRTXSendStatus(kRtxRetransmitted);
+ }
+ transport_.ResetCounters();
+ senders_[0]->TimeToSendPadding(500);
+ PaddingMap expected_padding;
+ expected_padding[kSenderSsrc + 1] = std::make_pair(0, 0);
+ expected_padding[kSenderSsrc + 2] = std::make_pair(0, 0);
+ expected_padding[kSenderSsrc + 3] = std::make_pair(0, 0);
+ expected_padding[kSenderRtxSsrc + 1] = std::make_pair(2, 500);
+ expected_padding[kSenderRtxSsrc + 2] = std::make_pair(0, 0);
+ expected_padding[kSenderRtxSsrc + 3] = std::make_pair(0, 0);
+ ExpectPadding(expected_padding);
+ senders_[0]->TimeToSendPadding(1000);
+ expected_padding[kSenderRtxSsrc + 2] = std::make_pair(4, 500);
+ ExpectPadding(expected_padding);
+ senders_[0]->TimeToSendPadding(1500);
+
+ expected_padding[kSenderRtxSsrc + 3] = std::make_pair(6, 500);
+ ExpectPadding(expected_padding);
+}
+
+TEST_F(RtpSendingTest, RoundRobinPaddingRtxRedundantPayloads) {
+ for (int i = 1; i < codec_.numberOfSimulcastStreams + 1; ++i) {
+ senders_[i]->SetRtxSendPayloadType(96);
+ senders_[i]->SetRtxSsrc(kSenderRtxSsrc + i);
+ senders_[i]->SetRTXSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
+ senders_[i]->SetStorePacketsStatus(true, 100);
+ }
+ // First send payloads so that we have something to retransmit.
+ const size_t kPayloadSize = 500;
+ const uint8_t payload[kPayloadSize] = {0};
+ for (int i = 0; i < codec_.numberOfSimulcastStreams; ++i) {
+ SendFrameOnSender(i + 1, payload, sizeof(payload));
+ }
+ transport_.ResetCounters();
+ senders_[0]->TimeToSendPadding(500);
+ PaddingMap expected_padding;
+ expected_padding[kSenderSsrc + 1] = std::make_pair<int, int>(0, 0);
+ expected_padding[kSenderSsrc + 2] = std::make_pair<int, int>(0, 0);
+ expected_padding[kSenderSsrc + 3] = std::make_pair<int, int>(0, 0);
+ expected_padding[kSenderRtxSsrc + 1] = std::make_pair<int, int>(1, 500);
+ expected_padding[kSenderRtxSsrc + 2] = std::make_pair<int, int>(0, 0);
+ expected_padding[kSenderRtxSsrc + 3] = std::make_pair<int, int>(0, 0);
+ ExpectPadding(expected_padding);
+ senders_[0]->TimeToSendPadding(1000);
+ expected_padding[kSenderRtxSsrc + 2] = std::make_pair<int, int>(2, 1000);
+ ExpectPadding(expected_padding);
+ senders_[0]->TimeToSendPadding(1500);
+ expected_padding[kSenderRtxSsrc + 3] = std::make_pair<int, int>(3, 1500);
+ ExpectPadding(expected_padding);
+}
} // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc
index 6e59a2d7..7cfcd722 100644
--- a/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/modules/rtp_rtcp/source/rtp_sender.cc
@@ -89,7 +89,7 @@ RTPSender::RTPSender(const int32_t id,
rtx_(kRtxOff),
payload_type_rtx_(-1),
target_bitrate_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
- target_bitrate_kbps_(0) {
+ target_bitrate_(0) {
memset(nack_byte_count_times_, 0, sizeof(nack_byte_count_times_));
memset(nack_byte_count_, 0, sizeof(nack_byte_count_));
memset(csrcs_, 0, sizeof(csrcs_));
@@ -127,8 +127,14 @@ RTPSender::~RTPSender() {
delete video_;
}
-void RTPSender::SetTargetSendBitrate(const uint32_t bits) {
- SetTargetBitrateKbps(static_cast<uint16_t>(bits / 1000));
+void RTPSender::SetTargetBitrate(uint32_t bitrate) {
+ CriticalSectionScoped cs(target_bitrate_critsect_.get());
+ target_bitrate_ = bitrate;
+}
+
+uint32_t RTPSender::GetTargetBitrate() {
+ CriticalSectionScoped cs(target_bitrate_critsect_.get());
+ return target_bitrate_;
}
uint16_t RTPSender::ActualSendBitrateKbit() const {
@@ -330,7 +336,6 @@ void RTPSender::RTXStatus(int* mode, uint32_t* ssrc,
*payload_type = payload_type_rtx_;
}
-
void RTPSender::SetRtxPayloadType(int payload_type) {
CriticalSectionScoped cs(send_critsect_);
payload_type_rtx_ = payload_type;
@@ -465,8 +470,8 @@ bool RTPSender::SendPaddingAccordingToBitrate(
// Current bitrate since last estimate(1 second) averaged with the
// estimate since then, to get the most up to date bitrate.
uint32_t current_bitrate = bitrate_sent_.BitrateNow();
- uint16_t target_bitrate_kbps = GetTargetBitrateKbps();
- int bitrate_diff = target_bitrate_kbps * 1000 - current_bitrate;
+ uint32_t target_bitrate = GetTargetBitrate();
+ int bitrate_diff = target_bitrate - current_bitrate;
if (bitrate_diff <= 0) {
return true;
}
@@ -477,7 +482,7 @@ bool RTPSender::SendPaddingAccordingToBitrate(
} else {
bytes = (bitrate_diff / 8);
// Cap at 200 ms of target send data.
- int bytes_cap = target_bitrate_kbps * 25; // 1000 / 8 / 5.
+ int bytes_cap = target_bitrate / 1000 * 25; // 1000 / 8 / 5.
if (bytes > bytes_cap) {
bytes = bytes_cap;
}
@@ -656,12 +661,12 @@ void RTPSender::OnReceivedNACK(
"num_seqnum", nack_sequence_numbers.size(), "avg_rtt", avg_rtt);
const int64_t now = clock_->TimeInMilliseconds();
uint32_t bytes_re_sent = 0;
- uint16_t target_bitrate_kbps = GetTargetBitrateKbps();
+ uint32_t target_bitrate = GetTargetBitrate();
// Enough bandwidth to send NACK?
if (!ProcessNACKBitRate(now)) {
LOG(LS_INFO) << "NACK bitrate reached. Skip sending NACK response. Target "
- << target_bitrate_kbps;
+ << target_bitrate;
return;
}
@@ -681,10 +686,10 @@ void RTPSender::OnReceivedNACK(
break;
}
// Delay bandwidth estimate (RTT * BW).
- if (target_bitrate_kbps != 0 && avg_rtt) {
+ if (target_bitrate != 0 && avg_rtt) {
// kbits/s * ms = bits => bits/8 = bytes
uint32_t target_bytes =
- (static_cast<uint32_t>(target_bitrate_kbps) * avg_rtt) >> 3;
+ (static_cast<uint32_t>(target_bitrate / 1000) * avg_rtt) >> 3;
if (bytes_re_sent > target_bytes) {
break; // Ignore the rest of the packets in the list.
}
@@ -699,33 +704,34 @@ void RTPSender::OnReceivedNACK(
bool RTPSender::ProcessNACKBitRate(const uint32_t now) {
uint32_t num = 0;
- int32_t byte_count = 0;
- const uint32_t avg_interval = 1000;
- uint16_t target_bitrate_kbps = GetTargetBitrateKbps();
+ int byte_count = 0;
+ const int kAvgIntervalMs = 1000;
+ uint32_t target_bitrate = GetTargetBitrate();
CriticalSectionScoped cs(send_critsect_);
- if (target_bitrate_kbps == 0) {
+ if (target_bitrate == 0) {
return true;
}
for (num = 0; num < NACK_BYTECOUNT_SIZE; ++num) {
- if ((now - nack_byte_count_times_[num]) > avg_interval) {
+ if ((now - nack_byte_count_times_[num]) > kAvgIntervalMs) {
// Don't use data older than 1sec.
break;
} else {
byte_count += nack_byte_count_[num];
}
}
- int32_t time_interval = avg_interval;
+ int time_interval = kAvgIntervalMs;
if (num == NACK_BYTECOUNT_SIZE) {
// More than NACK_BYTECOUNT_SIZE nack messages has been received
// during the last msg_interval.
time_interval = now - nack_byte_count_times_[num - 1];
if (time_interval < 0) {
- time_interval = avg_interval;
+ time_interval = kAvgIntervalMs;
}
}
- return (byte_count * 8) < (target_bitrate_kbps * time_interval);
+ return (byte_count * 8) <
+ static_cast<int>(target_bitrate / 1000 * time_interval);
}
void RTPSender::UpdateNACKBitRate(const uint32_t bytes,
@@ -882,8 +888,13 @@ int RTPSender::TimeToSendPadding(int bytes) {
int bytes_sent = SendRedundantPayloads(payload_type, bytes);
bytes -= bytes_sent;
if (bytes > 0) {
- int padding_sent = SendPadData(payload_type, timestamp, capture_time_ms,
- bytes, kDontStore, true, true);
+ int padding_sent = SendPadData(payload_type,
+ timestamp,
+ capture_time_ms,
+ bytes,
+ kDontStore,
+ true,
+ rtx_ == kRtxOff);
bytes_sent += padding_sent;
}
return bytes_sent;
@@ -1659,14 +1670,4 @@ void RTPSender::BitrateUpdated(const BitrateStatistics& stats) {
bitrate_callback_->Notify(stats, ssrc_);
}
}
-
-void RTPSender::SetTargetBitrateKbps(uint16_t bitrate_kbps) {
- CriticalSectionScoped cs(target_bitrate_critsect_.get());
- target_bitrate_kbps_ = bitrate_kbps;
-}
-
-uint16_t RTPSender::GetTargetBitrateKbps() {
- CriticalSectionScoped cs(target_bitrate_critsect_.get());
- return target_bitrate_kbps_;
-}
} // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_sender.h b/modules/rtp_rtcp/source/rtp_sender.h
index 17457ff2..17b026ca 100644
--- a/modules/rtp_rtcp/source/rtp_sender.h
+++ b/modules/rtp_rtcp/source/rtp_sender.h
@@ -83,7 +83,8 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
// was sent within the statistics window.
bool GetSendSideDelay(int* avg_send_delay_ms, int* max_send_delay_ms) const;
- void SetTargetSendBitrate(const uint32_t bits);
+ void SetTargetBitrate(uint32_t bitrate);
+ uint32_t GetTargetBitrate();
virtual uint16_t MaxDataPayloadLength() const
OVERRIDE; // with RTP and FEC headers.
@@ -329,9 +330,6 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
bool is_retransmit);
bool IsFecPacket(const uint8_t* buffer, const RTPHeader& header) const;
- void SetTargetBitrateKbps(uint16_t bitrate_kbps);
- uint16_t GetTargetBitrateKbps();
-
Clock* clock_;
Bitrate bitrate_sent_;
@@ -399,7 +397,7 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
// that by the time the function returns there is no guarantee
// that the target bitrate is still valid.
scoped_ptr<CriticalSectionWrapper> target_bitrate_critsect_;
- uint16_t target_bitrate_kbps_ GUARDED_BY(target_bitrate_critsect_);
+ uint16_t target_bitrate_ GUARDED_BY(target_bitrate_critsect_);
};
} // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
index 67a4a57d..18482890 100644
--- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -444,7 +444,7 @@ TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId));
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
- rtp_sender_->SetTargetSendBitrate(300000);
+ rtp_sender_->SetTargetBitrate(300000);
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
int32_t rtp_length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
@@ -498,7 +498,7 @@ TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) {
kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId));
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
- rtp_sender_->SetTargetSendBitrate(300000);
+ rtp_sender_->SetTargetBitrate(300000);
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
int32_t rtp_length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
@@ -580,7 +580,7 @@ TEST_F(RtpSenderTest, SendPadding) {
kAbsoluteSendTimeExtensionId);
webrtc::RTPHeader rtp_header;
- rtp_sender_->SetTargetSendBitrate(300000);
+ rtp_sender_->SetTargetBitrate(300000);
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
int32_t rtp_length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
@@ -698,7 +698,7 @@ TEST_F(RtpSenderTest, SendRedundantPayloads) {
kTransmissionTimeOffsetExtensionId);
rtp_parser->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
kAbsoluteSendTimeExtensionId);
- rtp_sender_->SetTargetSendBitrate(300000);
+ rtp_sender_->SetTargetBitrate(300000);
const size_t kNumPayloadSizes = 10;
const int kPayloadSizes[kNumPayloadSizes] = {500, 550, 600, 650, 700, 750,
800, 850, 900, 950};
diff --git a/modules/video_coding/codecs/vp8/vp8_impl.cc b/modules/video_coding/codecs/vp8/vp8_impl.cc
index dfe76e01..4901edff 100644
--- a/modules/video_coding/codecs/vp8/vp8_impl.cc
+++ b/modules/video_coding/codecs/vp8/vp8_impl.cc
@@ -214,7 +214,10 @@ int VP8EncoderImpl::InitEncode(const VideoCodec* inst,
}
config_->g_lag_in_frames = 0; // 0- no frame lagging
- if (codec_.width * codec_.height > 1280 * 960 && number_of_cores >= 6) {
+ if (codec_.width * codec_.height >= 1920 * 1080 && number_of_cores > 8) {
+ config_->g_threads = 8; // 8 threads for 1080p on high perf machines.
+ } else if (codec_.width * codec_.height > 1280 * 960 &&
+ number_of_cores >= 6) {
config_->g_threads = 3; // 3 threads for 1080p.
} else if (codec_.width * codec_.height > 640 * 480 && number_of_cores >= 3) {
config_->g_threads = 2; // 2 threads for qHD/HD.
diff --git a/test/w3c/getusermedia_conformance_test.html b/test/w3c/getusermedia_conformance_test.html
index 6ddb6030..7b724a93 100644
--- a/test/w3c/getusermedia_conformance_test.html
+++ b/test/w3c/getusermedia_conformance_test.html
@@ -52,15 +52,16 @@ Notice that this requires the site you're browsing to use HTTPS.
</p>
<div id="log"></div>
- <video id="local-view" autoplay="autoplay" muted="true"></video>
-
<!-- These files are in place when executing on W3C. -->
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/vendor-prefix.js"
- data-prefixed-objects= '[{"ancestors":["navigator"], "name":"getUserMedia"},
- {"ancestors":["window"], "name":"RTCPeerConnection"}]'
- data-prefixed-prototypes='[{"ancestors":["HTMLMediaElement"],"name":"srcObject"}]'></script>
+ data-prefixed-objects=
+ '[{"ancestors":["navigator"], "name":"getUserMedia"},
+ {"ancestors":["window"], "name":"RTCPeerConnection"}]'
+ data-prefixed-prototypes=
+ '[{"ancestors":["HTMLMediaElement"],"name":"srcObject"}]'>
+ </script>
<script src="getusermedia_conformance_test.js"></script>
</body>
diff --git a/test/w3c/getusermedia_conformance_test.js b/test/w3c/getusermedia_conformance_test.js
index fe1dcc8c..d7c78280 100644
--- a/test/w3c/getusermedia_conformance_test.js
+++ b/test/w3c/getusermedia_conformance_test.js
@@ -6,7 +6,7 @@
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
-setup({timeout:10000});
+setup({timeout:5000});
// Helper functions to minimize code duplication.
function failedCallback(test) {
@@ -19,6 +19,14 @@ function invokeGetUserMedia(test, okCallback) {
failedCallback(test));
}
+function createInvisibleVideoTag() {
+ var video = document.createElement('video');
+ video.autoplay = true;
+ video.style.display = 'none';
+ document.body.appendChild(video);
+ return video;
+}
+
// 4.2 MediaStream.
var mediaStreamTest = async_test('4.2 MediaStream');
@@ -56,21 +64,25 @@ function verifyMediaStream(stream) {
}, '[MediaStream] removeTrack function');
test(function () {
- // Missing in Chrome.
assert_inherits(stream, 'clone');
assert_true(typeof stream.clone === 'function');
}, '[MediaStream] clone function');
test(function () {
- assert_own_property(stream, 'ended');
- assert_true(typeof stream.ended === 'boolean');
- assert_readonly(stream, 'ended');
- }, '[MediaStream] ended attribute');
+ assert_own_property(stream, 'active');
+ assert_true(typeof stream.active === 'boolean');
+ assert_readonly(stream, 'active');
+ }, '[MediaStream] active attribute');
+
+ test(function () {
+ assert_own_property(stream, 'onactive');
+ assert_true(stream.onactive === null);
+ }, '[MediaStream] onactive EventHandler');
test(function () {
- assert_own_property(stream, 'onended');
- assert_true(stream.onended === null);
- }, '[MediaStream] onended EventHandler');
+ assert_own_property(stream, 'oninactive');
+ assert_true(stream.oninactive === null);
+ }, '[MediaStream] oninactive EventHandler');
test(function () {
assert_own_property(stream, 'onaddtrack');
@@ -86,28 +98,43 @@ function verifyMediaStream(stream) {
mediaStreamTest.step(function() {
var okCallback = mediaStreamTest.step_func(function (stream) {
verifyMediaStream(stream);
-
var videoTracks = stream.getVideoTracks();
assert_true(videoTracks.length > 0);
+ mediaStreamTest.done();
+ });
+
+ invokeGetUserMedia(mediaStreamTest, okCallback);
+});
+
+var mediaStreamCallbacksTest = async_test('4.2.2 MediaStream callbacks');
+
+mediaStreamCallbacksTest.step(function() {
+ var addCallbackCalled = false;
+ var onAddTrackCallback = mediaStreamCallbacksTest.step_func(function (event) {
+ assert_true(event.track instanceof MediaStreamTrack);
+ addCallbackCalled = true;
+ });
+ var onRemoveTrackCallback =
+ mediaStreamCallbacksTest.step_func(function (event) {
+ assert_true(event.track instanceof MediaStreamTrack);
+ assert_true(addCallbackCalled, 'Add should have been called after remove.');
+ mediaStreamCallbacksTest.done();
+ });
+ var okCallback = mediaStreamCallbacksTest.step_func(function (stream) {
+ var videoTracks = stream.getVideoTracks();
// Verify event handlers are working.
- stream.onaddtrack = onAddTrackCallback
- stream.onremovetrack = onRemoveTrackCallback
+ stream.onaddtrack = onAddTrackCallback;
+ stream.onremovetrack = onRemoveTrackCallback;
stream.removeTrack(videoTracks[0]);
stream.addTrack(videoTracks[0]);
- mediaStreamTest.done();
- });
- var onAddTrackCallback = mediaStreamTest.step_func(function () {
- // TODO(kjellander): verify number of tracks.
- mediaStreamTest.done();
});
- var onRemoveTrackCallback = mediaStreamTest.step_func(function () {
- // TODO(kjellander): verify number of tracks.
- mediaStreamTest.done();
- });
- invokeGetUserMedia(mediaStreamTest, okCallback);
+
+ invokeGetUserMedia(mediaStreamCallbacksTest, okCallback);
});
+// TODO(phoglund): add test for onactive/oninactive.
+
// 4.3 MediaStreamTrack.
var mediaStreamTrackTest = async_test('4.3 MediaStreamTrack');
@@ -140,7 +167,6 @@ function verifyTrack(type, track) {
}, '[MediaStreamTrack (' + type + ')] enabled attribute');
test(function () {
- // Missing in Chrome.
assert_own_property(track, 'muted');
assert_readonly(track, 'muted');
assert_true(typeof track.muted === 'boolean');
@@ -250,59 +276,113 @@ mediaStreamTrackTest.step(function() {
var mediaStreamTrackEventTest = async_test('4.4 MediaStreamTrackEvent');
mediaStreamTrackEventTest.step(function() {
var okCallback = mediaStreamTrackEventTest.step_func(function (stream) {
- // TODO(kjellander): verify attributes
+ // TODO(kjellander): verify attributes.
mediaStreamTrackEventTest.done();
});
invokeGetUserMedia(mediaStreamTrackEventTest, okCallback);
});
-// 4.5 Video and Audio Tracks tests.
-var avTracksTest = async_test('4.5 Video and Audio Tracks');
-avTracksTest.step(function() {
- var okCallback = avTracksTest.step_func(function (stream) {
- // TODO(kjellander): verify attributes
- avTracksTest.done();
- });
- invokeGetUserMedia(avTracksTest, okCallback);
-});
+// 6. Media streams as media elements.
-// 5. The model: sources, sinks, constraints, and states
+var playingInMediaElementTest = async_test(
+ '6.2 Loading and Playing a MediaStream in a Media Element');
+playingInMediaElementTest.step(function() {
+ var video = createInvisibleVideoTag();
-// 6. Source states
-// 6.1 Dictionary MediaSourceStates Members
+ var okCallback = playingInMediaElementTest.step_func(function (stream) {
+ video.onplay = playingInMediaElementTest.step_func(function() {
+ // This depends on what webcam we're actually running with, but the
+ // resolution should at least be greater than or equal to QVGA.
+ assert_greater_than_equal(video.videoWidth, 320);
+ assert_greater_than_equal(video.videoHeight, 240);
-// 7. Source capabilities
-// 7.1 Dictionary CapabilityRange Members
-// 7.2 CapabilityList array
-// 7.3 Dictionary AllVideoCapabilities Members
-// 7.4 Dictionary AllAudioCapabilities Members
+ playingInMediaElementTest.done();
+ });
+ video.srcObject = stream;
+ });
+ invokeGetUserMedia(playingInMediaElementTest, okCallback);
+});
-// 8. URL tests.
-var createObjectURLTest = async_test('8.1 URL createObjectURL method');
-createObjectURLTest.step(function() {
- var okCallback = createObjectURLTest.step_func(function (stream) {
- var url = URL.createObjectURL(stream);
- assert_true(typeof url === 'string');
- createObjectURLTest.done();
+// Verifies a media element track (for instance belonging to a video tag)
+// after it has been assigned a media stream.
+function verifyOneMediaElementTrack(track, correspondingMediaStreamTrack) {
+ assert_equals(track.id, correspondingMediaStreamTrack.id);
+ assert_equals(track.kind, 'main');
+ assert_equals(track.label, correspondingMediaStreamTrack.label);
+ assert_equals(track.language, '');
+}
+
+var setsUpMediaTracksRightTest = async_test(
+ '6.2 Sets up <video> audio and video tracks right');
+setsUpMediaTracksRightTest.step(function() {
+ var video = createInvisibleVideoTag();
+
+ var okCallback = setsUpMediaTracksRightTest.step_func(function (stream) {
+ video.onplay = setsUpMediaTracksRightTest.step_func(function() {
+ // Verify the requirements on the video tag's streams as outlined in 6.2.
+ // There could be any number of tracks depending on what device we have
+ // connected, so verify all of them. There should be at least one of audio
+ // and video each though.
+ assert_inherits(video, 'videoTracks',
+ 'Browser missing videoTracks support on media elements.');
+ assert_readonly(video, 'videoTracks');
+ assert_greater_than_equal(video.videoTracks.length, 1);
+ assert_equals(video.videoTracks.length, stream.getVideoTracks().length);
+
+ for (var i = 0; i < video.videoTracks.length; i++) {
+ verifyOneMediaElementTrack(video.videoTracks[i],
+ stream.getVideoTracks()[i]);
+ }
+
+ assert_inherits(video, 'audioTracks',
+ 'Browser missing audioTracks support on media elements.');
+ assert_readonly(video, 'audioTracks');
+ assert_greater_than_equal(video.audioTracks.length, 1);
+ assert_equals(video.audioTracks.length, stream.getAudioTracks().length);
+
+ for (var i = 0; i < video.audioTracks.length; i++) {
+ verifyOneMediaElementTrack(audio.audioTracks[i],
+ stream.getAudioTracks()[i]);
+ }
+
+ setsUpMediaTracksRightTest.done();
+ });
+ video.srcObject = stream;
});
- invokeGetUserMedia(createObjectURLTest, okCallback);
+ invokeGetUserMedia(setsUpMediaTracksRightTest, okCallback);
});
-// 9. MediaStreams as Media Elements.
-var mediaElementsTest = async_test('9. MediaStreams as Media Elements');
+var mediaElementsTest =
+ async_test('6.3 Media Element Attributes when Playing a MediaStream');
function verifyVideoTagWithStream(videoTag) {
test(function () {
+ assert_equals(videoTag.currentSrc, '');
+ }, '[Video tag] currentSrc attribute');
+
+ test(function () {
+ assert_equals(videoTag.preload, 'none');
+ }, '[Video tag] preload attribute');
+
+ test(function () {
assert_equals(videoTag.buffered.length, 0);
}, '[Video tag] buffered attribute');
test(function () {
- // Attempts to alter currentTime shall be ignored.
+ // Where 1 is NETWORK_IDLE.
+ assert_equals(videoTag.networkState, 1);
+ }, '[Video tag] networkState attribute');
+
+ test(function () {
+ // 0 is HAVE_NOTHING, 4 is HAVE_ENOUGH_DATA.
+ assert_true(videoTag.readyState == 0 || videoTag.readyState == 4);
+ }, '[Video tag] readyState attribute');
+
+ test(function () {
assert_true(videoTag.currentTime >= 0);
- assert_throws('InvalidStateError',
- function () { videoTag.currentTime = 1234; },
- 'Attempts to modify currentTime shall throw ' +
- 'InvalidStateError');
+ assert_throws(
+ 'InvalidStateError', function () { videoTag.currentTime = 1234; },
+ 'Attempts to modify currentTime shall throw InvalidStateError');
}, '[Video tag] currentTime attribute');
test(function () {
@@ -315,16 +395,16 @@ function verifyVideoTagWithStream(videoTag) {
test(function () {
assert_equals(videoTag.defaultPlaybackRate, 1.0);
- assert_throws('DOMException',
- function () { videoTag.defaultPlaybackRate = 2.0; },
- 'Attempts to alter videoTag.defaultPlaybackRate MUST fail');
+ assert_throws(
+ 'DOMException', function () { videoTag.defaultPlaybackRate = 2.0; },
+ 'Attempts to alter videoTag.defaultPlaybackRate MUST fail');
}, '[Video tag] defaultPlaybackRate attribute');
test(function () {
assert_equals(videoTag.playbackRate, 1.0);
- assert_throws('DOMException',
- function () { videoTag.playbackRate = 2.0; },
- 'Attempts to alter videoTag.playbackRate MUST fail');
+ assert_throws(
+ 'DOMException', function () { videoTag.playbackRate = 2.0; },
+ 'Attempts to alter videoTag.playbackRate MUST fail');
}, '[Video tag] playbackRate attribute');
test(function () {
@@ -335,56 +415,96 @@ function verifyVideoTagWithStream(videoTag) {
test(function () {
assert_equals(videoTag.seekable.length, 0);
- assert_equals(videoTag.seekable.start(), videoTag.currentTime);
- assert_equals(videoTag.seekable.end(), videoTag.currentTime);
- assert_equals(videoTag.startDate, NaN, 'videoTag.startDate');
+ // This is wrong in the standard: start() and end() must have arguments, but
+ // since the time range is empty as we assert in the line above, there is no
+ // valid argument with which we can call the methods.
+ // assert_equals(videoTag.seekable.start(), videoTag.currentTime);
+ // assert_equals(videoTag.seekable.end(), videoTag.currentTime);
}, '[Video tag] seekable attribute');
test(function () {
+ assert_equals(videoTag.startDate, NaN, 'videoTag.startDate');
+ }, '[Video tag] startDate attribute');
+
+ test(function () {
assert_false(videoTag.loop);
}, '[Video tag] loop attribute');
+
};
mediaElementsTest.step(function() {
var okCallback = mediaElementsTest.step_func(function (stream) {
- var videoTag = document.getElementById('local-view');
- videoTag.srcObject = stream;
- verifyVideoTagWithStream(videoTag);
+ var video = createInvisibleVideoTag();
+ video.srcObject = stream;
+ verifyVideoTagWithStream(video);
mediaElementsTest.done();
});
invokeGetUserMedia(mediaElementsTest, okCallback);
});
-// 11. Obtaining local multimedia content.
+// 9. Enumerating local media devices.
+// TODO(phoglund): add tests.
-// 11.1 NavigatorUserMedia.
-var getUserMediaTest = async_test('11.1 NavigatorUserMedia');
-getUserMediaTest.step(function() {
- var okCallback = getUserMediaTest.step_func(function (stream) {
+// 10. Obtaining local multimedia content.
+
+function testGetUserMedia(test, constraints) {
+ var okCallback = test.step_func(function (stream) {
assert_true(stream !== null);
- getUserMediaTest.done();
+ test.done();
});
+ navigator.getUserMedia(constraints, okCallback, failedCallback(test));
+}
- // All three arguments are mandatory, so pass all of them.
- navigator.getUserMedia({ video: true, audio: true }, okCallback,
- failedCallback(getUserMediaTest));
- navigator.getUserMedia({ video: true, audio: false }, okCallback,
- failedCallback(getUserMediaTest));
- navigator.getUserMedia({ video: false, audio: true }, okCallback,
- failedCallback(getUserMediaTest));
+var getUserMediaTestAudioVideo = async_test('10.1.1 NavigatorUserMedia A/V');
+getUserMediaTestAudioVideo.step(function() {
+ testGetUserMedia(getUserMediaTestAudioVideo, { video: true, audio: true });
+});
+
+var getUserMediaTestVideo = async_test('10.1.1 NavigatorUserMedia V');
+getUserMediaTestVideo.step(function() {
+ testGetUserMedia(getUserMediaTestVideo, { video: true, audio: false });
+});
+
+var getUserMediaTestAudio = async_test('10.1.1 NavigatorUserMedia A');
+getUserMediaTestAudio.step(function() {
+ testGetUserMedia(getUserMediaTestAudio, { video: false, audio: true });
+});
+
+var getUserMediaTestNull = async_test('10.1.1 NavigatorUserMedia Null');
+getUserMediaTestNull.step(function() {
+ testGetUserMedia(getUserMediaTestNull, null);
+});
+
+var getUserMediaTestPeerIdentity =
+ async_test('10.2 NavigatorUserMedia with peerIdentity');
+getUserMediaTestPeerIdentity.step(function() {
+ var peerIdentity = 'my_identity';
+ var okCallback = getUserMediaTestPeerIdentity.step_func(function (stream) {
+ assert_true(stream !== null);
+ stream.getVideoTracks().forEach(function(track) {
+ assert_equals(track.peerIdentity, peerIdentity);
+ });
+ stream.getAudioTracks().forEach(function(track) {
+ assert_equals(track.peerIdentity, peerIdentity);
+ });
+ getUserMediaTestPeerIdentity.done();
+ });
+ navigator.getUserMedia(
+ {video: true, audio: true, peerIdentity: 'my_identity' },
+ okCallback, failedCallback(getUserMediaTestPeerIdentity));
});
-// 11.2 MediaStreamConstraints.
-var constraintsTest = async_test('11.2 MediaStreamConstraints');
+// 10.2 MediaStreamConstraints.
+var constraintsTest = async_test('10.2 MediaStreamConstraints');
constraintsTest.step(function() {
var okCallback = constraintsTest.step_func(function (stream) {
assert_true(stream !== null);
constraintsTest.done();
});
- // Constraints on video.
- // See http://webrtc.googlecode.com/svn/trunk/samples/js/demos/html/constraints-and-stats.html
+ // See https://googlechrome.github.io/webrtc/samples/web/content/constraints/
// for more examples of constraints.
+ // TODO(phoglund): test more constraints; the possibilities here are endless.
var constraints = {};
constraints.audio = true;
constraints.video = { mandatory: {}, optional: [] };
@@ -396,9 +516,9 @@ constraintsTest.step(function() {
failedCallback(constraintsTest));
});
-// 11.3 NavigatorUserMediaSuccessCallback.
+// 10.4 NavigatorUserMediaSuccessCallback.
var successCallbackTest =
- async_test('11.3 NavigatorUserMediaSuccessCallback');
+ async_test('10.4 NavigatorUserMediaSuccessCallback');
successCallbackTest.step(function() {
var okCallback = successCallbackTest.step_func(function (stream) {
assert_true(stream !== null);
@@ -407,3 +527,5 @@ successCallbackTest.step(function() {
invokeGetUserMedia(successCallbackTest, okCallback);
});
+// 11. Constrainable Pattern.
+// TODO(phoglund): add tests.
diff --git a/video_engine/overuse_frame_detector.cc b/video_engine/overuse_frame_detector.cc
index ac9519f3..764c2584 100644
--- a/video_engine/overuse_frame_detector.cc
+++ b/video_engine/overuse_frame_detector.cc
@@ -42,8 +42,8 @@ const int kMaxRampUpDelayMs = 240 * 1000;
// Expontential back-off factor, to prevent annoying up-down behaviour.
const double kRampUpBackoffFactor = 2.0;
-// The initial average encode time (set to a fairly small value).
-const float kInitialAvgEncodeTimeMs = 5.0f;
+// Max number of overuses detected before always applying the rampup delay.
+const int kMaxOverusesBeforeApplyRampupDelay = 7;
// The maximum exponent to use in VCMExpFilter.
const float kSampleDiffMs = 33.0f;
@@ -115,6 +115,7 @@ class OveruseFrameDetector::EncodeTimeAvg {
public:
EncodeTimeAvg()
: kWeightFactor(0.5f),
+ kInitialAvgEncodeTimeMs(5.0f),
filtered_encode_time_ms_(new VCMExpFilter(kWeightFactor)) {
filtered_encode_time_ms_->Apply(1.0f, kInitialAvgEncodeTimeMs);
}
@@ -132,6 +133,7 @@ class OveruseFrameDetector::EncodeTimeAvg {
private:
const float kWeightFactor;
+ const float kInitialAvgEncodeTimeMs;
scoped_ptr<VCMExpFilter> filtered_encode_time_ms_;
};
@@ -378,6 +380,7 @@ OveruseFrameDetector::OveruseFrameDetector(Clock* clock)
last_capture_time_(0),
last_overuse_time_(0),
checks_above_threshold_(0),
+ num_overuse_detections_(0),
last_rampup_time_(0),
in_quick_rampup_(false),
current_rampup_delay_ms_(kStandardRampUpDelayMs),
@@ -514,7 +517,8 @@ int32_t OveruseFrameDetector::Process() {
// back and forth between this load, the system doesn't seem to handle it.
bool check_for_backoff = last_rampup_time_ > last_overuse_time_;
if (check_for_backoff) {
- if (now - last_rampup_time_ < kStandardRampUpDelayMs) {
+ if (now - last_rampup_time_ < kStandardRampUpDelayMs ||
+ num_overuse_detections_ > kMaxOverusesBeforeApplyRampupDelay) {
// Going up was not ok for very long, back off.
current_rampup_delay_ms_ *= kRampUpBackoffFactor;
if (current_rampup_delay_ms_ > kMaxRampUpDelayMs)
@@ -528,6 +532,7 @@ int32_t OveruseFrameDetector::Process() {
last_overuse_time_ = now;
in_quick_rampup_ = false;
checks_above_threshold_ = 0;
+ ++num_overuse_detections_;
if (observer_ != NULL)
observer_->OveruseDetected();
@@ -541,11 +546,12 @@ int32_t OveruseFrameDetector::Process() {
int rampup_delay =
in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_;
- LOG(LS_INFO) << " Frame stats: capture avg: " << capture_deltas_.Mean()
- << " capture stddev " << capture_deltas_.StdDev()
- << " encode usage " << encode_usage_->Value()
- << " encode rsd " << encode_rsd_->Value()
- << " rampup delay " << rampup_delay;
+ LOG(LS_VERBOSE) << " Frame stats: capture avg: " << capture_deltas_.Mean()
+ << " capture stddev " << capture_deltas_.StdDev()
+ << " encode usage " << encode_usage_->Value()
+ << " encode rsd " << encode_rsd_->Value()
+ << " overuse detections " << num_overuse_detections_
+ << " rampup delay " << rampup_delay;
return 0;
}
diff --git a/video_engine/overuse_frame_detector.h b/video_engine/overuse_frame_detector.h
index ef6d6aba..efd23dc4 100644
--- a/video_engine/overuse_frame_detector.h
+++ b/video_engine/overuse_frame_detector.h
@@ -124,6 +124,7 @@ class OveruseFrameDetector : public Module {
int64_t last_overuse_time_;
int checks_above_threshold_;
+ int num_overuse_detections_;
int64_t last_rampup_time_;
bool in_quick_rampup_;