diff options
Diffstat (limited to 'dom/media/webrtc/common')
-rw-r--r-- | dom/media/webrtc/common/CandidateInfo.h | 27 | ||||
-rw-r--r-- | dom/media/webrtc/common/CommonTypes.h | 52 | ||||
-rw-r--r-- | dom/media/webrtc/common/EncodingConstraints.h | 58 | ||||
-rw-r--r-- | dom/media/webrtc/common/MediaEngineWrapper.h | 32 | ||||
-rw-r--r-- | dom/media/webrtc/common/NullDeleter.h | 14 | ||||
-rw-r--r-- | dom/media/webrtc/common/NullTransport.h | 56 | ||||
-rw-r--r-- | dom/media/webrtc/common/Wrapper.h | 157 | ||||
-rw-r--r-- | dom/media/webrtc/common/YuvStamper.cpp | 394 | ||||
-rw-r--r-- | dom/media/webrtc/common/YuvStamper.h | 77 | ||||
-rw-r--r-- | dom/media/webrtc/common/browser_logging/CSFLog.cpp | 85 | ||||
-rw-r--r-- | dom/media/webrtc/common/browser_logging/CSFLog.h | 58 | ||||
-rw-r--r-- | dom/media/webrtc/common/browser_logging/WebRtcLog.cpp | 162 | ||||
-rw-r--r-- | dom/media/webrtc/common/browser_logging/WebRtcLog.h | 17 | ||||
-rw-r--r-- | dom/media/webrtc/common/csf_common.h | 90 | ||||
-rw-r--r-- | dom/media/webrtc/common/moz.build | 23 | ||||
-rw-r--r-- | dom/media/webrtc/common/time_profiling/timecard.c | 112 | ||||
-rw-r--r-- | dom/media/webrtc/common/time_profiling/timecard.h | 74 |
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 |