summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/common
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/media/webrtc/common
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--dom/media/webrtc/common/CandidateInfo.h27
-rw-r--r--dom/media/webrtc/common/CommonTypes.h52
-rw-r--r--dom/media/webrtc/common/EncodingConstraints.h58
-rw-r--r--dom/media/webrtc/common/MediaEngineWrapper.h32
-rw-r--r--dom/media/webrtc/common/NullDeleter.h14
-rw-r--r--dom/media/webrtc/common/NullTransport.h56
-rw-r--r--dom/media/webrtc/common/Wrapper.h157
-rw-r--r--dom/media/webrtc/common/YuvStamper.cpp394
-rw-r--r--dom/media/webrtc/common/YuvStamper.h77
-rw-r--r--dom/media/webrtc/common/browser_logging/CSFLog.cpp85
-rw-r--r--dom/media/webrtc/common/browser_logging/CSFLog.h58
-rw-r--r--dom/media/webrtc/common/browser_logging/WebRtcLog.cpp162
-rw-r--r--dom/media/webrtc/common/browser_logging/WebRtcLog.h17
-rw-r--r--dom/media/webrtc/common/csf_common.h90
-rw-r--r--dom/media/webrtc/common/moz.build23
-rw-r--r--dom/media/webrtc/common/time_profiling/timecard.c112
-rw-r--r--dom/media/webrtc/common/time_profiling/timecard.h74
17 files changed, 1488 insertions, 0 deletions
diff --git a/dom/media/webrtc/common/CandidateInfo.h b/dom/media/webrtc/common/CandidateInfo.h
new file mode 100644
index 0000000000..eb5b2ea299
--- /dev/null
+++ b/dom/media/webrtc/common/CandidateInfo.h
@@ -0,0 +1,27 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _CANDIDATE_INFO_H__
+#define _CANDIDATE_INFO_H__
+
+#include <string>
+#include <cstdint>
+
+namespace mozilla {
+
+// This is used both by IPDL code, and by signaling code.
+struct CandidateInfo {
+ std::string mCandidate;
+ std::string mMDNSAddress;
+ std::string mActualAddress;
+ std::string mUfrag;
+ std::string mDefaultHostRtp;
+ uint16_t mDefaultPortRtp = 0;
+ std::string mDefaultHostRtcp;
+ uint16_t mDefaultPortRtcp = 0;
+};
+
+} // namespace mozilla
+
+#endif //_CANDIDATE_INFO_H__
diff --git a/dom/media/webrtc/common/CommonTypes.h b/dom/media/webrtc/common/CommonTypes.h
new file mode 100644
index 0000000000..e9c9ffdefc
--- /dev/null
+++ b/dom/media/webrtc/common/CommonTypes.h
@@ -0,0 +1,52 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#pragma once
+
+#include <string>
+
+namespace csf {
+
+namespace ProviderStateEnum {
+enum ProviderState {
+ Ready,
+ Registering,
+ AwaitingIpAddress,
+ FetchingDeviceConfig,
+ Idle,
+ RecoveryPending,
+ Connected
+};
+const std::string toString(ProviderState);
+} // namespace ProviderStateEnum
+namespace LoginErrorStatusEnum {
+enum LoginErrorStatus {
+ Ok, // No Error
+ Unknown, // Unknown Error
+ NoCallManagerConfigured, // No Primary or Backup Call Manager
+ NoDevicesFound, // No devices
+ NoCsfDevicesFound, // Devices but none of type CSF
+ PhoneConfigGenError, // Could not generate phone config
+ SipProfileGenError, // Could not build SIP profile
+ ConfigNotSet, // Config not set before calling login()
+ CreateConfigProviderFailed, // Could not create ConfigProvider
+ CreateSoftPhoneProviderFailed, // Could not create SoftPhoneProvider
+ MissingUsername, // Username argument missing,
+ ManualLogout, // logout() has been called
+ LoggedInElseWhere, // Another process has the mutex indicating it is logged
+ // in
+ AuthenticationFailure, // Authentication failure (probably bad password, but
+ // best not to say for sure)
+ CtiCouldNotConnect, // Could not connect to CTI service
+ InvalidServerSearchList
+};
+const std::string toString(LoginErrorStatus);
+} // namespace LoginErrorStatusEnum
+
+namespace ErrorCodeEnum {
+enum ErrorCode { Ok, Unknown, InvalidState, InvalidArgument };
+const std::string toString(ErrorCode);
+} // namespace ErrorCodeEnum
+
+} // namespace csf
diff --git a/dom/media/webrtc/common/EncodingConstraints.h b/dom/media/webrtc/common/EncodingConstraints.h
new file mode 100644
index 0000000000..0bfa7f9f75
--- /dev/null
+++ b/dom/media/webrtc/common/EncodingConstraints.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _ENCODING_CONSTRAINTS_H_
+#define _ENCODING_CONSTRAINTS_H_
+
+#include <algorithm>
+#include "mozilla/Maybe.h"
+
+namespace mozilla {
+class EncodingConstraints {
+ public:
+ EncodingConstraints()
+ : maxWidth(0),
+ maxHeight(0),
+ maxFs(0),
+ maxBr(0),
+ maxPps(0),
+ maxMbps(0),
+ maxCpb(0),
+ maxDpb(0),
+ scaleDownBy(1.0) {}
+
+ bool operator==(const EncodingConstraints& constraints) const {
+ return maxWidth == constraints.maxWidth &&
+ maxHeight == constraints.maxHeight && maxFps == constraints.maxFps &&
+ maxFs == constraints.maxFs && maxBr == constraints.maxBr &&
+ maxPps == constraints.maxPps && maxMbps == constraints.maxMbps &&
+ maxCpb == constraints.maxCpb && maxDpb == constraints.maxDpb &&
+ scaleDownBy == constraints.scaleDownBy;
+ }
+
+ /**
+ * This returns true if the constraints affecting resolution are equal.
+ */
+ bool ResolutionEquals(const EncodingConstraints& constraints) const {
+ return maxWidth == constraints.maxWidth &&
+ maxHeight == constraints.maxHeight && maxFs == constraints.maxFs &&
+ scaleDownBy == constraints.scaleDownBy;
+ }
+
+ uint32_t maxWidth;
+ uint32_t maxHeight;
+ Maybe<double> maxFps;
+ uint32_t maxFs;
+ uint32_t maxBr;
+ uint32_t maxPps;
+ uint32_t maxMbps; // macroblocks per second
+ uint32_t maxCpb; // coded picture buffer size
+ uint32_t maxDpb; // decoded picture buffer size
+ double scaleDownBy; // To preserve resolution
+};
+} // namespace mozilla
+
+#endif // _ENCODING_CONSTRAINTS_H_
diff --git a/dom/media/webrtc/common/MediaEngineWrapper.h b/dom/media/webrtc/common/MediaEngineWrapper.h
new file mode 100644
index 0000000000..ba48ad57d8
--- /dev/null
+++ b/dom/media/webrtc/common/MediaEngineWrapper.h
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MEDIA_ENGINE_WRAPPER_H_
+#define MEDIA_ENGINE_WRAPPER_H_
+
+#include <mozilla/Scoped.h>
+
+namespace mozilla {
+/**
+ * A Custom scoped template to release a resoure of Type T
+ * with a function of Type F
+ * ScopedCustomReleasePtr<webrtc::VoENetwork> ptr =
+ * webrtc::VoENetwork->GetInterface(voiceEngine);
+ *
+ */
+template <typename T>
+struct ScopedCustomReleaseTraits0 {
+ typedef T* type;
+ static T* empty() { return nullptr; }
+ static void release(T* ptr) {
+ if (ptr) {
+ (ptr)->Release();
+ }
+ }
+};
+
+SCOPED_TEMPLATE(ScopedCustomReleasePtr, ScopedCustomReleaseTraits0)
+} // namespace mozilla
+
+#endif
diff --git a/dom/media/webrtc/common/NullDeleter.h b/dom/media/webrtc/common/NullDeleter.h
new file mode 100644
index 0000000000..76326c197e
--- /dev/null
+++ b/dom/media/webrtc/common/NullDeleter.h
@@ -0,0 +1,14 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#pragma once
+
+/*
+ * Helper class to allow smart pointers to stack objects to be constructed for
+ * ease of unit testing. Recycled here to help expose a shared_ptr interface to
+ * objects which are really raw pointers.
+ */
+struct null_deleter {
+ void operator()(void const*) const {}
+};
diff --git a/dom/media/webrtc/common/NullTransport.h b/dom/media/webrtc/common/NullTransport.h
new file mode 100644
index 0000000000..a9b270c6d6
--- /dev/null
+++ b/dom/media/webrtc/common/NullTransport.h
@@ -0,0 +1,56 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef NULL_TRANSPORT_H_
+#define NULL_TRANSPORT_H_
+
+#include "mozilla/Attributes.h"
+
+#include "api/call/transport.h"
+
+namespace mozilla {
+
+/**
+ * NullTransport is registered as ExternalTransport to throw away data
+ */
+class NullTransport : public webrtc::Transport {
+ public:
+ virtual bool SendRtp(const uint8_t* packet, size_t length,
+ const webrtc::PacketOptions& options) override {
+ (void)packet;
+ (void)length;
+ (void)options;
+ return true;
+ }
+
+ virtual bool SendRtcp(const uint8_t* packet, size_t length) override {
+ (void)packet;
+ (void)length;
+ return true;
+ }
+#if 0
+ virtual int SendPacket(int channel, const void *data, size_t len)
+ {
+ (void) channel; (void) data;
+ return len;
+ }
+
+ virtual int SendRTCPPacket(int channel, const void *data, size_t len)
+ {
+ (void) channel; (void) data;
+ return len;
+ }
+#endif
+ NullTransport() {}
+
+ virtual ~NullTransport() {}
+
+ private:
+ NullTransport(const NullTransport& other) = delete;
+ void operator=(const NullTransport& other) = delete;
+};
+
+} // namespace mozilla
+
+#endif
diff --git a/dom/media/webrtc/common/Wrapper.h b/dom/media/webrtc/common/Wrapper.h
new file mode 100644
index 0000000000..69c7406b07
--- /dev/null
+++ b/dom/media/webrtc/common/Wrapper.h
@@ -0,0 +1,157 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#pragma once
+
+/*
+ * Wrapper - Helper class for wrapper objects.
+ *
+ * This helps to construct a shared_ptr object which wraps access to an
+ * underlying handle. (The handle could be a pointer to some low-level type, a
+ * conventional C handle, an int ID, a GUID, etc.)
+ *
+ * Usage:
+ * To obtain a FooPtr from a foo_handle_t, call
+ * FooPtr Foo::wrap(foo_handle_t);
+ *
+ * To implement Foo using Wrapper, Foo needs to include this macro in its class
+ * definition:
+ * CSF_DECLARE_WRAP(Foo, foo_handle_t);
+ * It also needs to include this in the cpp file, to provide the wrap()
+ * implementation and define the static Wrapper.
+ * CSF_IMPLEMENT_WRAP(Foo, foo_handle_t);
+ * These are all declared in common/Wrapper.h - Foo.h needs to include this
+ * too.
+ * The client needs to declare Foo(foo_handle_t) as private, and provide a
+ * suitable implementation, as well as implementing wrappers for any other
+ * functions to be exposed.
+ * The client needs to implement ~Foo() to perform any cleanup as usual.
+ *
+ * wrap() will always return the same FooPtr for a given foo_handle_t, it will
+ * not construct additional objects if a suitable one already exists.
+ * changeHandle() is used in rare cases where the underlying handle is changed,
+ * but the wrapper object is intended to remain. This is the
+ * case for the "fake" CC_DPCall generated on
+ * CC_DPLine::CreateCall(), where the correct IDPCall* is
+ * provided later.
+ * reset() is a cleanup step to wipe the handle map and allow memory to be
+ * reclaimed.
+ *
+ * Future enhancements:
+ * - For now, objects remain in the map forever. Better would be to add a
+ * releaseHandle() function which would allow the map to be emptied as
+ * underlying handles expired. While we can't force the client to give up
+ * its shared_ptr<Foo> objects, we can remove our own copy, for instance on a
+ * call ended event.
+ */
+
+#include <map>
+#include "prlock.h"
+#include "mozilla/Assertions.h"
+
+/*
+ * Wrapper has its own autolock class because the instances are declared
+ * statically and mozilla::Mutex will not work properly when instantiated
+ * in a static constructor.
+ */
+
+class LockNSPR {
+ public:
+ LockNSPR() : lock_(nullptr) {
+ lock_ = PR_NewLock();
+ MOZ_ASSERT(lock_);
+ }
+ ~LockNSPR() { PR_DestroyLock(lock_); }
+
+ void Acquire() { PR_Lock(lock_); }
+
+ void Release() { PR_Unlock(lock_); }
+
+ private:
+ PRLock* lock_;
+};
+
+class AutoLockNSPR {
+ public:
+ explicit AutoLockNSPR(LockNSPR& lock) : lock_(lock) { lock_.Acquire(); }
+ ~AutoLockNSPR() { lock_.Release(); }
+
+ private:
+ LockNSPR& lock_;
+};
+
+template <class T>
+class Wrapper {
+ private:
+ typedef std::map<typename T::Handle, typename T::Ptr> HandleMapType;
+ HandleMapType handleMap;
+ LockNSPR handleMapMutex;
+
+ public:
+ Wrapper() {}
+
+ typename T::Ptr wrap(typename T::Handle handle) {
+ AutoLockNSPR lock(handleMapMutex);
+ typename HandleMapType::iterator it = handleMap.find(handle);
+ if (it != handleMap.end()) {
+ return it->second;
+ } else {
+ typename T::Ptr p(new T(handle));
+ handleMap[handle] = p;
+ return p;
+ }
+ }
+
+ bool changeHandle(typename T::Handle oldHandle,
+ typename T::Handle newHandle) {
+ AutoLockNSPR lock(handleMapMutex);
+ typename HandleMapType::iterator it = handleMap.find(oldHandle);
+ if (it != handleMap.end()) {
+ typename T::Ptr p = it->second;
+ handleMap.erase(it);
+ handleMap[newHandle] = p;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ bool release(typename T::Handle handle) {
+ AutoLockNSPR lock(handleMapMutex);
+ typename HandleMapType::iterator it = handleMap.find(handle);
+ if (it != handleMap.end()) {
+ handleMap.erase(it);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ void reset() {
+ AutoLockNSPR lock(handleMapMutex);
+ handleMap.clear();
+ }
+};
+
+#define CSF_DECLARE_WRAP(classname, handletype) \
+ public: \
+ static classname##Ptr wrap(handletype handle); \
+ static void reset(); \
+ static void release(handletype handle); \
+ \
+ private: \
+ friend class Wrapper<classname>; \
+ typedef classname##Ptr Ptr; \
+ typedef handletype Handle; \
+ static Wrapper<classname>& getWrapper() { \
+ static Wrapper<classname> wrapper; \
+ return wrapper; \
+ }
+
+#define CSF_IMPLEMENT_WRAP(classname, handletype) \
+ classname##Ptr classname::wrap(handletype handle) { \
+ return getWrapper().wrap(handle); \
+ } \
+ void classname::reset() { getWrapper().reset(); } \
+ void classname::release(handletype handle) { getWrapper().release(handle); }
diff --git a/dom/media/webrtc/common/YuvStamper.cpp b/dom/media/webrtc/common/YuvStamper.cpp
new file mode 100644
index 0000000000..b0c8426983
--- /dev/null
+++ b/dom/media/webrtc/common/YuvStamper.cpp
@@ -0,0 +1,394 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#elif defined XP_WIN
+# include <winsock2.h>
+#endif
+#include <string.h>
+
+#include "nspr.h"
+#include "YuvStamper.h"
+#include "mozilla/Sprintf.h"
+
+typedef uint32_t UINT4; // Needed for r_crc32() call
+extern "C" {
+#include "r_crc32.h"
+}
+
+namespace mozilla {
+
+#define ON_5 0x20
+#define ON_4 0x10
+#define ON_3 0x08
+#define ON_2 0x04
+#define ON_1 0x02
+#define ON_0 0x01
+
+/*
+ 0, 0, 1, 1, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0
+*/
+static unsigned char DIGIT_0[] = {ON_3 | ON_2, ON_4 | ON_1, ON_5 | ON_0,
+ ON_5 | ON_0, ON_5 | ON_0, ON_4 | ON_1,
+ ON_3 | ON_2};
+
+/*
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+*/
+static unsigned char DIGIT_1[] = {ON_2, ON_2, ON_2, ON_2, ON_2, ON_2, ON_2};
+
+/*
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1,
+*/
+static unsigned char DIGIT_2[] = {
+ ON_5 | ON_4 | ON_3 | ON_2 | ON_1, ON_0, ON_0,
+ ON_4 | ON_3 | ON_2 | ON_1, ON_5, ON_5,
+ ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
+};
+
+/*
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 0,
+*/
+static unsigned char DIGIT_3[] = {
+ ON_5 | ON_4 | ON_3 | ON_2 | ON_1, ON_0, ON_0,
+ ON_4 | ON_3 | ON_2 | ON_1 | ON_0, ON_0, ON_0,
+ ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
+};
+
+/*
+ 0, 1, 0, 0, 0, 1,
+ 0, 1, 0, 0, 0, 1,
+ 0, 1, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 1
+*/
+static unsigned char DIGIT_4[] = {
+ ON_4 | ON_0, ON_4 | ON_0, ON_4 | ON_0, ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
+ ON_0, ON_0, ON_0,
+};
+
+/*
+ 0, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 0,
+*/
+static unsigned char DIGIT_5[] = {
+ ON_4 | ON_3 | ON_2 | ON_1 | ON_0, ON_5, ON_5,
+ ON_4 | ON_3 | ON_2 | ON_1, ON_0, ON_0,
+ ON_5 | ON_4 | ON_3 | ON_2 | ON_1,
+};
+
+/*
+ 0, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 0,
+*/
+static unsigned char DIGIT_6[] = {
+ ON_4 | ON_3 | ON_2 | ON_1 | ON_0, ON_5, ON_5,
+ ON_4 | ON_3 | ON_2 | ON_1, ON_5 | ON_0, ON_5 | ON_0,
+ ON_4 | ON_3 | ON_2 | ON_1,
+};
+
+/*
+ 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0
+*/
+static unsigned char DIGIT_7[] = {ON_5 | ON_4 | ON_3 | ON_2 | ON_1 | ON_0,
+ ON_0,
+ ON_1,
+ ON_2,
+ ON_3,
+ ON_4,
+ ON_5};
+
+/*
+ 0, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 0
+*/
+static unsigned char DIGIT_8[] = {
+ ON_4 | ON_3 | ON_2 | ON_1, ON_5 | ON_0, ON_5 | ON_0,
+ ON_4 | ON_3 | ON_2 | ON_1, ON_5 | ON_0, ON_5 | ON_0,
+ ON_4 | ON_3 | ON_2 | ON_1,
+};
+
+/*
+ 0, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 0
+*/
+static unsigned char DIGIT_9[] = {
+ ON_4 | ON_3 | ON_2 | ON_1 | ON_0, ON_5 | ON_0, ON_5 | ON_0,
+ ON_4 | ON_3 | ON_2 | ON_1 | ON_0, ON_0, ON_0,
+ ON_4 | ON_3 | ON_2 | ON_1,
+};
+
+static unsigned char* DIGITS[] = {DIGIT_0, DIGIT_1, DIGIT_2, DIGIT_3, DIGIT_4,
+ DIGIT_5, DIGIT_6, DIGIT_7, DIGIT_8, DIGIT_9};
+
+YuvStamper::YuvStamper(unsigned char* pYData, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t x, uint32_t y,
+ unsigned char symbol_width, unsigned char symbol_height)
+ : pYData(pYData),
+ mStride(stride),
+ mWidth(width),
+ mHeight(height),
+ mSymbolWidth(symbol_width),
+ mSymbolHeight(symbol_height),
+ mCursor(x, y) {}
+
+bool YuvStamper::Encode(uint32_t width, uint32_t height, uint32_t stride,
+ unsigned char* pYData, unsigned char* pMsg,
+ size_t msg_len, uint32_t x, uint32_t y) {
+ YuvStamper stamper(pYData, width, height, stride, x, y, sBitSize, sBitSize);
+
+ // Reserve space for a checksum.
+ if (stamper.Capacity() < 8 * (msg_len + sizeof(uint32_t))) {
+ return false;
+ }
+
+ bool ok = false;
+ uint32_t crc;
+ unsigned char* pCrc = reinterpret_cast<unsigned char*>(&crc);
+ r_crc32(reinterpret_cast<char*>(pMsg), (int)msg_len, &crc);
+ crc = htonl(crc);
+
+ while (msg_len-- > 0) {
+ if (!stamper.Write8(*pMsg++)) {
+ return false;
+ }
+ }
+
+ // Add checksum after the message.
+ ok = stamper.Write8(*pCrc++) && stamper.Write8(*pCrc++) &&
+ stamper.Write8(*pCrc++) && stamper.Write8(*pCrc++);
+
+ return ok;
+}
+
+bool YuvStamper::Decode(uint32_t width, uint32_t height, uint32_t stride,
+ unsigned char* pYData, unsigned char* pMsg,
+ size_t msg_len, uint32_t x, uint32_t y) {
+ YuvStamper stamper(pYData, width, height, stride, x, y, sBitSize, sBitSize);
+
+ unsigned char* ptr = pMsg;
+ size_t len = msg_len;
+ uint32_t crc, msg_crc;
+ unsigned char* pCrc = reinterpret_cast<unsigned char*>(&crc);
+
+ // Account for space reserved for the checksum
+ if (stamper.Capacity() < 8 * (len + sizeof(uint32_t))) {
+ return false;
+ }
+
+ while (len-- > 0) {
+ if (!stamper.Read8(*ptr++)) {
+ return false;
+ }
+ }
+
+ if (!(stamper.Read8(*pCrc++) && stamper.Read8(*pCrc++) &&
+ stamper.Read8(*pCrc++) && stamper.Read8(*pCrc++))) {
+ return false;
+ }
+
+ r_crc32(reinterpret_cast<char*>(pMsg), (int)msg_len, &msg_crc);
+ return crc == htonl(msg_crc);
+}
+
+inline uint32_t YuvStamper::Capacity() {
+ // Enforce at least a symbol width and height offset from outer edges.
+ if (mCursor.y + mSymbolHeight > mHeight) {
+ return 0;
+ }
+
+ if (mCursor.x + mSymbolWidth > mWidth && !AdvanceCursor()) {
+ return 0;
+ }
+
+ // Normalize frame integral to mSymbolWidth x mSymbolHeight
+ uint32_t width = mWidth / mSymbolWidth;
+ uint32_t height = mHeight / mSymbolHeight;
+ uint32_t x = mCursor.x / mSymbolWidth;
+ uint32_t y = mCursor.y / mSymbolHeight;
+
+ return (width * height - width * y) - x;
+}
+
+bool YuvStamper::Write8(unsigned char value) {
+ // Encode MSB to LSB.
+ unsigned char mask = 0x80;
+ while (mask) {
+ if (!WriteBit(!!(value & mask))) {
+ return false;
+ }
+ mask >>= 1;
+ }
+ return true;
+}
+
+bool YuvStamper::WriteBit(bool one) {
+ // A bit is mapped to a mSymbolWidth x mSymbolHeight square of luma data
+ // points. Don't use ternary op.:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1001708
+ unsigned char value;
+ if (one)
+ value = sYOn;
+ else
+ value = sYOff;
+
+ for (uint32_t y = 0; y < mSymbolHeight; y++) {
+ for (uint32_t x = 0; x < mSymbolWidth; x++) {
+ *(pYData + (mCursor.x + x) + ((mCursor.y + y) * mStride)) = value;
+ }
+ }
+
+ return AdvanceCursor();
+}
+
+bool YuvStamper::AdvanceCursor() {
+ mCursor.x += mSymbolWidth;
+ if (mCursor.x + mSymbolWidth > mWidth) {
+ // move to the start of the next row if possible.
+ mCursor.y += mSymbolHeight;
+ if (mCursor.y + mSymbolHeight > mHeight) {
+ // end of frame, do not advance
+ mCursor.y -= mSymbolHeight;
+ mCursor.x -= mSymbolWidth;
+ return false;
+ } else {
+ mCursor.x = 0;
+ }
+ }
+
+ return true;
+}
+
+bool YuvStamper::Read8(unsigned char& value) {
+ unsigned char octet = 0;
+ unsigned char bit = 0;
+
+ for (int i = 8; i > 0; --i) {
+ if (!ReadBit(bit)) {
+ return false;
+ }
+ octet <<= 1;
+ octet |= bit;
+ }
+
+ value = octet;
+ return true;
+}
+
+bool YuvStamper::ReadBit(unsigned char& bit) {
+ uint32_t sum = 0;
+ for (uint32_t y = 0; y < mSymbolHeight; y++) {
+ for (uint32_t x = 0; x < mSymbolWidth; x++) {
+ sum += *(pYData + mStride * (mCursor.y + y) + mCursor.x + x);
+ }
+ }
+
+ // apply threshold to collected bit square
+ bit = (sum > (sBitThreshold * mSymbolWidth * mSymbolHeight)) ? 1 : 0;
+ return AdvanceCursor();
+}
+
+bool YuvStamper::WriteDigits(uint32_t value) {
+ char buf[20];
+ SprintfLiteral(buf, "%.5u", value);
+ size_t size = strlen(buf);
+
+ if (Capacity() < size) {
+ return false;
+ }
+
+ for (size_t i = 0; i < size; ++i) {
+ if (!WriteDigit(buf[i] - '0')) return false;
+ if (!AdvanceCursor()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool YuvStamper::WriteDigit(unsigned char digit) {
+ if (digit > sizeof(DIGITS) / sizeof(DIGITS[0])) return false;
+
+ unsigned char* dig = DIGITS[digit];
+ for (uint32_t row = 0; row < sDigitHeight; ++row) {
+ unsigned char mask = 0x01 << (sDigitWidth - 1);
+ for (uint32_t col = 0; col < sDigitWidth; ++col, mask >>= 1) {
+ if (dig[row] & mask) {
+ for (uint32_t xx = 0; xx < sPixelSize; ++xx) {
+ for (uint32_t yy = 0; yy < sPixelSize; ++yy) {
+ WritePixel(pYData, mCursor.x + (col * sPixelSize) + xx,
+ mCursor.y + (row * sPixelSize) + yy);
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+void YuvStamper::WritePixel(unsigned char* data, uint32_t x, uint32_t y) {
+ unsigned char* ptr = &data[y * mStride + x];
+ // Don't use ternary op.: https://bugzilla.mozilla.org/show_bug.cgi?id=1001708
+ if (*ptr > sLumaThreshold)
+ *ptr = sLumaMin;
+ else
+ *ptr = sLumaMax;
+}
+
+} // namespace mozilla.
diff --git a/dom/media/webrtc/common/YuvStamper.h b/dom/media/webrtc/common/YuvStamper.h
new file mode 100644
index 0000000000..f355055cd9
--- /dev/null
+++ b/dom/media/webrtc/common/YuvStamper.h
@@ -0,0 +1,77 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef YUV_STAMPER_H_
+#define YUV_STAMPER_H_
+
+#include <cstdint>
+
+namespace mozilla {
+
+class YuvStamper {
+ public:
+ bool WriteDigits(uint32_t value);
+
+ template <typename T>
+ static bool Write(uint32_t width, uint32_t height, uint32_t stride,
+ unsigned char* pYData, const T& value, uint32_t x = 0,
+ uint32_t y = 0) {
+ YuvStamper stamper(pYData, width, height, stride, x, y,
+ (sDigitWidth + sInterDigit) * sPixelSize,
+ (sDigitHeight + sInterLine) * sPixelSize);
+ return stamper.WriteDigits(value);
+ }
+
+ static bool Encode(uint32_t width, uint32_t height, uint32_t stride,
+ unsigned char* pYData, unsigned char* pMsg, size_t msg_len,
+ uint32_t x = 0, uint32_t y = 0);
+
+ static bool Decode(uint32_t width, uint32_t height, uint32_t stride,
+ unsigned char* pYData, unsigned char* pMsg, size_t msg_len,
+ uint32_t x = 0, uint32_t y = 0);
+
+ private:
+ YuvStamper(unsigned char* pYData, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t x, uint32_t y,
+ unsigned char symbol_width, unsigned char symbol_height);
+
+ bool WriteDigit(unsigned char digit);
+ void WritePixel(unsigned char* data, uint32_t x, uint32_t y);
+ uint32_t Capacity();
+ bool AdvanceCursor();
+ bool WriteBit(bool one);
+ bool Write8(unsigned char value);
+ bool ReadBit(unsigned char& value);
+ bool Read8(unsigned char& bit);
+
+ const static unsigned char sPixelSize = 3;
+ const static unsigned char sDigitWidth = 6;
+ const static unsigned char sDigitHeight = 7;
+ const static unsigned char sInterDigit = 1;
+ const static unsigned char sInterLine = 1;
+ const static uint32_t sBitSize = 4;
+ const static uint32_t sBitThreshold = 60;
+ const static unsigned char sYOn = 0x80;
+ const static unsigned char sYOff = 0;
+ const static unsigned char sLumaThreshold = 96;
+ const static unsigned char sLumaMin = 16;
+ const static unsigned char sLumaMax = 235;
+
+ unsigned char* pYData;
+ uint32_t mStride;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ unsigned char mSymbolWidth;
+ unsigned char mSymbolHeight;
+
+ struct Cursor {
+ Cursor(uint32_t x, uint32_t y) : x(x), y(y) {}
+ uint32_t x;
+ uint32_t y;
+ } mCursor;
+};
+
+} // namespace mozilla
+
+#endif
diff --git a/dom/media/webrtc/common/browser_logging/CSFLog.cpp b/dom/media/webrtc/common/browser_logging/CSFLog.cpp
new file mode 100644
index 0000000000..d58f5726a5
--- /dev/null
+++ b/dom/media/webrtc/common/browser_logging/CSFLog.cpp
@@ -0,0 +1,85 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "CSFLog.h"
+
+#include <map>
+#include "prrwlock.h"
+#include "prthread.h"
+#include "nsThreadUtils.h"
+
+#include "mozilla/Logging.h"
+#include "mozilla/Sprintf.h"
+
+mozilla::LazyLogModule gSignalingLog("signaling");
+
+void CSFLogV(CSFLogLevel priority, const char* sourceFile, int sourceLine,
+ const char* tag, const char* format, va_list args) {
+#ifdef STDOUT_LOGGING
+ printf("%s\n:", tag);
+ vprintf(format, args);
+#else
+
+ mozilla::LogLevel level =
+ static_cast<mozilla::LogLevel>(static_cast<unsigned int>(priority));
+
+ // Skip doing any of this work if we're not logging the indicated level...
+ if (!MOZ_LOG_TEST(gSignalingLog, level)) {
+ return;
+ }
+
+ // Trim the path component from the filename
+ const char* lastSlash = sourceFile;
+ while (*sourceFile) {
+ if (*sourceFile == '/' || *sourceFile == '\\') {
+ lastSlash = sourceFile;
+ }
+ sourceFile++;
+ }
+ sourceFile = lastSlash;
+ if (*sourceFile == '/' || *sourceFile == '\\') {
+ sourceFile++;
+ }
+
+# define MAX_MESSAGE_LENGTH 1024
+ char message[MAX_MESSAGE_LENGTH];
+
+ const char* threadName = NULL;
+
+ // Check if we're the main thread...
+ if (NS_IsMainThread()) {
+ threadName = "main";
+ } else {
+ threadName = PR_GetThreadName(PR_GetCurrentThread());
+ }
+
+ // If we can't find it anywhere, use a blank string
+ if (!threadName) {
+ threadName = "";
+ }
+
+ VsprintfLiteral(message, format, args);
+ MOZ_LOG(
+ gSignalingLog, level,
+ ("[%s|%s] %s:%d: %s", threadName, tag, sourceFile, sourceLine, message));
+#endif
+}
+
+void CSFLog(CSFLogLevel priority, const char* sourceFile, int sourceLine,
+ const char* tag, const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+
+ CSFLogV(priority, sourceFile, sourceLine, tag, format, ap);
+ va_end(ap);
+}
+
+int CSFLogTestLevel(CSFLogLevel priority) {
+ return MOZ_LOG_TEST(gSignalingLog, static_cast<mozilla::LogLevel>(
+ static_cast<unsigned int>(priority)));
+}
diff --git a/dom/media/webrtc/common/browser_logging/CSFLog.h b/dom/media/webrtc/common/browser_logging/CSFLog.h
new file mode 100644
index 0000000000..eb46b37cc3
--- /dev/null
+++ b/dom/media/webrtc/common/browser_logging/CSFLog.h
@@ -0,0 +1,58 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef CSFLOG_H
+#define CSFLOG_H
+
+#include <stdarg.h>
+
+typedef enum {
+ CSF_LOG_ERROR = 1,
+ CSF_LOG_WARNING,
+ CSF_LOG_INFO,
+ CSF_LOG_DEBUG,
+ CSF_LOG_VERBOSE,
+} CSFLogLevel;
+
+#define CSFLogError(tag, format, ...) \
+ CSFLog(CSF_LOG_ERROR, __FILE__, __LINE__, tag, format, ##__VA_ARGS__)
+#define CSFLogErrorV(tag, format, va_list_arg) \
+ CSFLogV(CSF_LOG_ERROR, __FILE__, __LINE__, tag, format, va_list_arg)
+#define CSFLogWarn(tag, format, ...) \
+ CSFLog(CSF_LOG_WARNING, __FILE__, __LINE__, tag, format, ##__VA_ARGS__)
+#define CSFLogWarnV(tag, format, va_list_arg) \
+ CSFLogV(CSF_LOG_WARNING, __FILE__, __LINE__, tag, format, va_list_arg)
+#define CSFLogInfo(tag, format, ...) \
+ CSFLog(CSF_LOG_INFO, __FILE__, __LINE__, tag, format, ##__VA_ARGS__)
+#define CSFLogInfoV(tag, format, va_list_arg) \
+ CSFLogV(CSF_LOG_INFO, __FILE__, __LINE__, tag, format, va_list_arg)
+#define CSFLogDebug(tag, format, ...) \
+ CSFLog(CSF_LOG_DEBUG, __FILE__, __LINE__, tag, format, ##__VA_ARGS__)
+#define CSFLogDebugV(tag, format, va_list_arg) \
+ CSFLogV(CSF_LOG_DEBUG, __FILE__, __LINE__, tag, format, va_list_arg)
+#define CSFLogVerbose(tag, format, ...) \
+ CSFLog(CSF_LOG_VERBOSE, __FILE__, __LINE__, tag, format, ##__VA_ARGS__)
+#define CSFLogVerboseV(tag, format, va_list_arg) \
+ CSFLogV(CSF_LOG_VERBOSE, __FILE__, __LINE__, tag, format, va_list_arg)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void CSFLog(CSFLogLevel priority, const char* sourceFile, int sourceLine,
+ const char* tag, const char* format, ...)
+#ifdef __GNUC__
+ __attribute__((format(printf, 5, 6)))
+#endif
+ ;
+
+void CSFLogV(CSFLogLevel priority, const char* sourceFile, int sourceLine,
+ const char* tag, const char* format, va_list args);
+
+int CSFLogTestLevel(CSFLogLevel priority);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dom/media/webrtc/common/browser_logging/WebRtcLog.cpp b/dom/media/webrtc/common/browser_logging/WebRtcLog.cpp
new file mode 100644
index 0000000000..0f3769604e
--- /dev/null
+++ b/dom/media/webrtc/common/browser_logging/WebRtcLog.cpp
@@ -0,0 +1,162 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WebRtcLog.h"
+
+#include "mozilla/Logging.h"
+#include "mozilla/StaticPtr.h"
+#include "prenv.h"
+#include "rtc_base/logging.h"
+
+#include "nscore.h"
+#include "nsString.h"
+#include "nsXULAppAPI.h"
+#include "mozilla/Preferences.h"
+
+#include "nsIFile.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsNativeCharsetUtils.h"
+
+using mozilla::LogLevel;
+
+static mozilla::LazyLogModule sWebRtcLog("webrtc_trace");
+static mozilla::LazyLogModule sLogAEC("AEC");
+
+class LogSinkImpl : public rtc::LogSink {
+ public:
+ LogSinkImpl() {}
+
+ private:
+ void OnLogMessage(const std::string& message) override {
+ MOZ_LOG(sWebRtcLog, LogLevel::Debug, ("%s", message.data()));
+ }
+};
+
+// For RTC_LOG()
+static mozilla::StaticAutoPtr<LogSinkImpl> sSink;
+
+void GetWebRtcLogPrefs() {
+ rtc::LogMessage::set_aec_debug_size(
+ mozilla::Preferences::GetUint("media.webrtc.debug.aec_dump_max_size"));
+}
+
+mozilla::LogLevel CheckOverrides() {
+ mozilla::LogModule* log_info = sWebRtcLog;
+ mozilla::LogLevel log_level = log_info->Level();
+
+ log_info = sLogAEC;
+ if (sLogAEC && (log_info->Level() != mozilla::LogLevel::Disabled)) {
+ rtc::LogMessage::set_aec_debug(true);
+ }
+
+ return log_level;
+}
+
+void ConfigWebRtcLog(mozilla::LogLevel level) {
+ rtc::LoggingSeverity log_level;
+ switch (level) {
+ case mozilla::LogLevel::Verbose:
+ log_level = rtc::LoggingSeverity::LS_VERBOSE;
+ break;
+ case mozilla::LogLevel::Debug:
+ case mozilla::LogLevel::Info:
+ log_level = rtc::LoggingSeverity::LS_INFO;
+ break;
+ case mozilla::LogLevel::Warning:
+ log_level = rtc::LoggingSeverity::LS_WARNING;
+ break;
+ case mozilla::LogLevel::Error:
+ log_level = rtc::LoggingSeverity::LS_ERROR;
+ break;
+ case mozilla::LogLevel::Disabled:
+ log_level = rtc::LoggingSeverity::LS_NONE;
+ break;
+ default:
+ MOZ_ASSERT(false);
+ break;
+ }
+ rtc::LogMessage::LogToDebug(log_level);
+ if (level != mozilla::LogLevel::Disabled) {
+ // always capture LOG(...) << ... logging in webrtc.org code to nspr logs
+ if (!sSink) {
+ sSink = new LogSinkImpl();
+ rtc::LogMessage::AddLogToStream(sSink, log_level);
+ // it's ok if this leaks to program end
+ }
+ } else if (sSink) {
+ rtc::LogMessage::RemoveLogToStream(sSink);
+ sSink = nullptr;
+ }
+}
+
+void StartWebRtcLog(mozilla::LogLevel log_level) {
+ if (log_level == mozilla::LogLevel::Disabled) {
+ return;
+ }
+
+ GetWebRtcLogPrefs();
+ mozilla::LogLevel level = CheckOverrides();
+
+ ConfigWebRtcLog(level);
+}
+
+void EnableWebRtcLog() {
+ GetWebRtcLogPrefs();
+ mozilla::LogLevel level = CheckOverrides();
+ ConfigWebRtcLog(level);
+}
+
+// Called when we destroy the singletons from PeerConnectionCtx or if the
+// user changes logging in about:webrtc
+void StopWebRtcLog() {
+ if (sSink) {
+ rtc::LogMessage::RemoveLogToStream(sSink);
+ sSink = nullptr;
+ }
+}
+
+nsCString ConfigAecLog() {
+ nsCString aecLogDir;
+ if (rtc::LogMessage::aec_debug()) {
+ return ""_ns;
+ }
+#if defined(ANDROID)
+ const char* default_tmp_dir = "/dev/null";
+ aecLogDir.Assign(default_tmp_dir);
+#else
+ nsCOMPtr<nsIFile> tempDir;
+ nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tempDir));
+ if (NS_SUCCEEDED(rv)) {
+# ifdef XP_WIN
+ // WebRTC wants a path encoded in the native charset, not UTF-8.
+ nsAutoString temp;
+ tempDir->GetPath(temp);
+ NS_CopyUnicodeToNative(temp, aecLogDir);
+# else
+ tempDir->GetNativePath(aecLogDir);
+# endif
+ }
+#endif
+ rtc::LogMessage::set_aec_debug_filename(aecLogDir.get());
+
+ return aecLogDir;
+}
+
+nsCString StartAecLog() {
+ nsCString aecLogDir;
+ if (rtc::LogMessage::aec_debug()) {
+ return ""_ns;
+ }
+
+ GetWebRtcLogPrefs();
+ CheckOverrides();
+ aecLogDir = ConfigAecLog();
+
+ rtc::LogMessage::set_aec_debug(true);
+
+ return aecLogDir;
+}
+
+void StopAecLog() { rtc::LogMessage::set_aec_debug(false); }
diff --git a/dom/media/webrtc/common/browser_logging/WebRtcLog.h b/dom/media/webrtc/common/browser_logging/WebRtcLog.h
new file mode 100644
index 0000000000..b933ff43a5
--- /dev/null
+++ b/dom/media/webrtc/common/browser_logging/WebRtcLog.h
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBRTCLOG_H_
+#define WEBRTCLOG_H_
+
+#include "mozilla/Logging.h"
+#include "nsStringFwd.h"
+
+nsCString StartAecLog();
+void StopAecLog();
+void EnableWebRtcLog();
+void StartWebRtcLog(mozilla::LogLevel level);
+void StopWebRtcLog();
+
+#endif
diff --git a/dom/media/webrtc/common/csf_common.h b/dom/media/webrtc/common/csf_common.h
new file mode 100644
index 0000000000..8b01047553
--- /dev/null
+++ b/dom/media/webrtc/common/csf_common.h
@@ -0,0 +1,90 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _CSF_COMMON_E58E5677_950A_424c_B6C2_CA180092E6A2_H
+#define _CSF_COMMON_E58E5677_950A_424c_B6C2_CA180092E6A2_H
+
+#include <assert.h>
+#include <memory>
+#include <vector>
+#include <stdlib.h>
+
+/*
+
+This header file defines:
+
+csf_countof
+csf_sprintf
+csf_vsprintf
+
+*/
+
+/*
+ General security tip: Ensure that "format" is never a user-defined string.
+ Format should ALWAYS be something that's built into your code, not user
+ supplied. For example: never write:
+
+ csf_sprintf(buffer, csf_countof(buffer), pUserSuppliedString);
+
+ Instead write:
+
+ csf_sprintf(buffer, csf_countof(buffer), "%s", pUserSuppliedString);
+
+*/
+
+#ifdef WIN32
+# if !defined(_countof)
+# if !defined(__cplusplus)
+# define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+# else
+extern "C++" {
+template <typename _CountofType, size_t _SizeOfArray>
+char (*_csf_countof_helper(_CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];
+# define _countof(_Array) sizeof(*_csf_countof_helper(_Array))
+}
+# endif
+# endif
+#else
+# define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+#endif
+// csf_countof
+
+#define csf_countof(anArray) _countof(anArray)
+
+// csf_sprintf
+
+#ifdef _WIN32
+// Unlike snprintf, sprintf_s guarantees that the buffer will be null-terminated
+// (unless the buffer size is zero).
+# define csf_sprintf(/* char* */ buffer, \
+ /* size_t */ sizeOfBufferInCharsInclNullTerm, \
+ /* const char * */ format, ...) \
+ _snprintf_s(buffer, sizeOfBufferInCharsInclNullTerm, _TRUNCATE, format, \
+ __VA_ARGS__)
+#else
+# define csf_sprintf(/* char */ buffer, \
+ /* size_t */ sizeOfBufferInCharsInclNullTerm, \
+ /* const char * */ format, ...) \
+ snprintf(buffer, sizeOfBufferInCharsInclNullTerm, format, __VA_ARGS__); \
+ buffer[sizeOfBufferInCharsInclNullTerm - 1] = '\0'
+#endif
+
+// csf_vsprintf
+
+#ifdef _WIN32
+# define csf_vsprintf(/* char* */ buffer, \
+ /* size_t */ sizeOfBufferInCharsInclNullTerm, \
+ /* const char * */ format, /* va_list */ vaList) \
+ vsnprintf_s(buffer, sizeOfBufferInCharsInclNullTerm, _TRUNCATE, format, \
+ vaList); \
+ buffer[sizeOfBufferInCharsInclNullTerm - 1] = '\0'
+#else
+# define csf_vsprintf(/* char */ buffer, \
+ /* size_t */ sizeOfBufferInCharsInclNullTerm, \
+ /* const char * */ format, /* va_list */ vaList) \
+ vsprintf(buffer, format, vaList); \
+ buffer[sizeOfBufferInCharsInclNullTerm - 1] = '\0'
+#endif
+
+#endif
diff --git a/dom/media/webrtc/common/moz.build b/dom/media/webrtc/common/moz.build
new file mode 100644
index 0000000000..7605d27835
--- /dev/null
+++ b/dom/media/webrtc/common/moz.build
@@ -0,0 +1,23 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+include("/dom/media/webrtc/third_party_build/webrtc.mozbuild")
+
+EXPORTS.mozilla.dom += ["CandidateInfo.h"]
+
+LOCAL_INCLUDES += [
+ "/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr",
+ "/third_party/libwebrtc",
+ "/third_party/libwebrtc/third_party/abseil-cpp",
+]
+
+UNIFIED_SOURCES += [
+ "browser_logging/CSFLog.cpp",
+ "browser_logging/WebRtcLog.cpp",
+ "time_profiling/timecard.c",
+ "YuvStamper.cpp",
+]
+
+FINAL_LIBRARY = "xul"
diff --git a/dom/media/webrtc/common/time_profiling/timecard.c b/dom/media/webrtc/common/time_profiling/timecard.c
new file mode 100644
index 0000000000..c0218cb92d
--- /dev/null
+++ b/dom/media/webrtc/common/time_profiling/timecard.c
@@ -0,0 +1,112 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdio.h>
+#include <string.h>
+#include "timecard.h"
+#include "mozilla/mozalloc.h"
+
+Timecard* create_timecard() {
+ Timecard* tc = moz_xcalloc(1, sizeof(Timecard));
+ tc->entries_allocated = TIMECARD_INITIAL_TABLE_SIZE;
+ tc->entries = moz_xcalloc(tc->entries_allocated, sizeof(TimecardEntry));
+ tc->start_time = PR_Now();
+ return tc;
+}
+
+void destroy_timecard(Timecard* tc) {
+ free(tc->entries);
+ free(tc);
+}
+
+void stamp_timecard(Timecard* tc, const char* event, const char* file,
+ unsigned int line, const char* function) {
+ TimecardEntry* entry = NULL;
+
+ /* Trim the path component from the filename */
+ const char* last_slash = file;
+ while (*file) {
+ if (*file == '/' || *file == '\\') {
+ last_slash = file;
+ }
+ file++;
+ }
+ file = last_slash;
+ if (*file == '/' || *file == '\\') {
+ file++;
+ }
+
+ /* Ensure there is enough space left in the entries list */
+ if (tc->curr_entry == tc->entries_allocated) {
+ tc->entries_allocated *= 2;
+ tc->entries = moz_xrealloc(tc->entries,
+ tc->entries_allocated * sizeof(TimecardEntry));
+ }
+
+ /* Record the data into the timecard entry */
+ entry = &tc->entries[tc->curr_entry];
+ entry->timestamp = PR_Now();
+ entry->event = event;
+ entry->file = file;
+ entry->line = line;
+ entry->function = function;
+ tc->curr_entry++;
+}
+
+void print_timecard(Timecard* tc) {
+ size_t i;
+ TimecardEntry* entry;
+ size_t event_width = 5;
+ size_t file_width = 4;
+ size_t function_width = 8;
+ size_t line_width;
+ PRTime offset, delta;
+
+ for (i = 0; i < tc->curr_entry; i++) {
+ entry = &tc->entries[i];
+ if (strlen(entry->event) > event_width) {
+ event_width = strlen(entry->event);
+ }
+ if (strlen(entry->file) > file_width) {
+ file_width = strlen(entry->file);
+ }
+ if (strlen(entry->function) > function_width) {
+ function_width = strlen(entry->function);
+ }
+ }
+
+ printf("\nTimecard created %4ld.%6.6ld\n\n",
+ (long)(tc->start_time / PR_USEC_PER_SEC),
+ (long)(tc->start_time % PR_USEC_PER_SEC));
+
+ line_width =
+ 1 + 11 + 11 + event_width + file_width + 6 + function_width + (4 * 3);
+
+ printf(" %-11s | %-11s | %-*s | %-*s | %-*s\n", "Timestamp", "Delta",
+ (int)event_width, "Event", (int)file_width + 6, "File",
+ (int)function_width, "Function");
+
+ for (i = 0; i <= line_width; i++) {
+ printf("=");
+ }
+ printf("\n");
+
+ for (i = 0; i < tc->curr_entry; i++) {
+ entry = &tc->entries[i];
+ offset = entry->timestamp - tc->start_time;
+ if (i > 0) {
+ delta = entry->timestamp - tc->entries[i - 1].timestamp;
+ } else {
+ delta = entry->timestamp - tc->start_time;
+ }
+ printf(" %4ld.%6.6ld | %4ld.%6.6ld | %-*s | %*s:%-5d | %-*s\n",
+ (long)(offset / PR_USEC_PER_SEC), (long)(offset % PR_USEC_PER_SEC),
+ (long)(delta / PR_USEC_PER_SEC), (long)(delta % PR_USEC_PER_SEC),
+ (int)event_width, entry->event, (int)file_width, entry->file,
+ entry->line, (int)function_width, entry->function);
+ }
+ printf("\n");
+}
diff --git a/dom/media/webrtc/common/time_profiling/timecard.h b/dom/media/webrtc/common/time_profiling/timecard.h
new file mode 100644
index 0000000000..38d4a8d1ec
--- /dev/null
+++ b/dom/media/webrtc/common/time_profiling/timecard.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef timecard_h__
+#define timecard_h__
+
+#include <stdlib.h>
+#include "prtime.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define STAMP_TIMECARD(card, event) \
+ do { \
+ if (card) { \
+ stamp_timecard((card), (event), __FILE__, __LINE__, __FUNCTION__); \
+ } \
+ } while (0)
+
+#define TIMECARD_INITIAL_TABLE_SIZE 16
+
+/*
+ * The "const char *" members of this structure point to static strings.
+ * We do not own them, and should not attempt to deallocate them.
+ */
+
+typedef struct {
+ PRTime timestamp;
+ const char* event;
+ const char* file;
+ unsigned int line;
+ const char* function;
+} TimecardEntry;
+
+typedef struct Timecard {
+ size_t curr_entry;
+ size_t entries_allocated;
+ TimecardEntry* entries;
+ PRTime start_time;
+} Timecard;
+
+/**
+ * Creates a new Timecard structure for tracking events.
+ */
+Timecard* create_timecard();
+
+/**
+ * Frees the memory associated with a timecard. After returning, the
+ * timecard pointed to by tc is no longer valid.
+ */
+void destroy_timecard(Timecard* tc);
+
+/**
+ * Records a new event in the indicated timecard. This should not be
+ * called directly; code should instead use the STAMP_TIMECARD macro,
+ * above.
+ */
+void stamp_timecard(Timecard* tc, const char* event, const char* file,
+ unsigned int line, const char* function);
+
+/**
+ * Formats and outputs the contents of a timecard onto stdout.
+ */
+void print_timecard(Timecard* tc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif