Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
2
TMessagesProj/jni/voip/webrtc/system_wrappers/OWNERS
Normal file
2
TMessagesProj/jni/voip/webrtc/system_wrappers/OWNERS
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
henrika@webrtc.org
|
||||
mflodman@webrtc.org
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_WRAPPERS_INCLUDE_CLOCK_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_CLOCK_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
#include "api/units/timestamp.h"
|
||||
#include "rtc_base/system/rtc_export.h"
|
||||
#include "system_wrappers/include/ntp_time.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// January 1970, in NTP seconds.
|
||||
const uint32_t kNtpJan1970 = 2208988800UL;
|
||||
|
||||
// Magic NTP fractional unit.
|
||||
const double kMagicNtpFractionalUnit = 4.294967296E+9;
|
||||
|
||||
// A clock interface that allows reading of absolute and relative timestamps.
|
||||
class RTC_EXPORT Clock {
|
||||
public:
|
||||
virtual ~Clock() {}
|
||||
|
||||
// Return a timestamp relative to an unspecified epoch.
|
||||
virtual Timestamp CurrentTime() = 0;
|
||||
int64_t TimeInMilliseconds() { return CurrentTime().ms(); }
|
||||
int64_t TimeInMicroseconds() { return CurrentTime().us(); }
|
||||
|
||||
// Retrieve an NTP absolute timestamp (with an epoch of Jan 1, 1900).
|
||||
NtpTime CurrentNtpTime() { return ConvertTimestampToNtpTime(CurrentTime()); }
|
||||
int64_t CurrentNtpInMilliseconds() { return CurrentNtpTime().ToMs(); }
|
||||
|
||||
// Converts between a relative timestamp returned by this clock, to NTP time.
|
||||
virtual NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) = 0;
|
||||
int64_t ConvertTimestampToNtpTimeInMilliseconds(int64_t timestamp_ms) {
|
||||
return ConvertTimestampToNtpTime(Timestamp::Millis(timestamp_ms)).ToMs();
|
||||
}
|
||||
|
||||
// Returns an instance of the real-time system clock implementation.
|
||||
static Clock* GetRealTimeClock();
|
||||
};
|
||||
|
||||
class SimulatedClock : public Clock {
|
||||
public:
|
||||
// The constructors assume an epoch of Jan 1, 1970.
|
||||
explicit SimulatedClock(int64_t initial_time_us);
|
||||
explicit SimulatedClock(Timestamp initial_time);
|
||||
~SimulatedClock() override;
|
||||
|
||||
// Return a timestamp with an epoch of Jan 1, 1970.
|
||||
Timestamp CurrentTime() override;
|
||||
|
||||
NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) override;
|
||||
|
||||
// Advance the simulated clock with a given number of milliseconds or
|
||||
// microseconds.
|
||||
void AdvanceTimeMilliseconds(int64_t milliseconds);
|
||||
void AdvanceTimeMicroseconds(int64_t microseconds);
|
||||
void AdvanceTime(TimeDelta delta);
|
||||
|
||||
private:
|
||||
// The time is read and incremented with relaxed order. Each thread will see
|
||||
// monotonically increasing time, and when threads post tasks or messages to
|
||||
// one another, the synchronization done as part of the message passing should
|
||||
// ensure that any causual chain of events on multiple threads also
|
||||
// corresponds to monotonically increasing time.
|
||||
std::atomic<int64_t> time_us_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_CLOCK_H_
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// List of features in x86.
|
||||
typedef enum { kSSE2, kSSE3, kAVX2, kFMA3 } CPUFeature;
|
||||
|
||||
// List of features in ARM.
|
||||
enum {
|
||||
kCPUFeatureARMv7 = (1 << 0),
|
||||
kCPUFeatureVFPv3 = (1 << 1),
|
||||
kCPUFeatureNEON = (1 << 2),
|
||||
kCPUFeatureLDREXSTREX = (1 << 3)
|
||||
};
|
||||
|
||||
// Returns true if the CPU supports the feature.
|
||||
int GetCPUInfo(CPUFeature feature);
|
||||
|
||||
// No CPU feature is available => straight C path.
|
||||
int GetCPUInfoNoASM(CPUFeature feature);
|
||||
|
||||
// Return the features in an ARM device.
|
||||
// It detects the features in the hardware platform, and returns supported
|
||||
// values in the above enum definition as a bitmask.
|
||||
uint64_t GetCPUFeaturesARM(void);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_WRAPPERS_INCLUDE_CPU_INFO_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_CPU_INFO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CpuInfo {
|
||||
public:
|
||||
static uint32_t DetectNumberOfCores();
|
||||
|
||||
private:
|
||||
CpuInfo() {}
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_CPU_INFO_H_
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 SYSTEM_WRAPPERS_INCLUDE_DENORMAL_DISABLER_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_DENORMAL_DISABLER_H_
|
||||
|
||||
#include "rtc_base/system/arch.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Activates the hardware (HW) way to flush denormals (see [1]) to zero as they
|
||||
// can very seriously impact performance. At destruction time restores the
|
||||
// denormals handling state read by the ctor; hence, supports nested calls.
|
||||
// Equals a no-op if the architecture is not x86 or ARM or if the compiler is
|
||||
// not CLANG.
|
||||
// [1] https://en.wikipedia.org/wiki/Denormal_number
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// void Foo() {
|
||||
// DenormalDisabler d;
|
||||
// ...
|
||||
// }
|
||||
class DenormalDisabler {
|
||||
public:
|
||||
// Ctor. If architecture and compiler are supported, stores the HW settings
|
||||
// for denormals, disables denormals and sets `disabling_activated_` to true.
|
||||
// Otherwise, only sets `disabling_activated_` to false.
|
||||
DenormalDisabler();
|
||||
// Ctor. Same as above, but also requires `enabled` to be true to disable
|
||||
// denormals.
|
||||
explicit DenormalDisabler(bool enabled);
|
||||
DenormalDisabler(const DenormalDisabler&) = delete;
|
||||
DenormalDisabler& operator=(const DenormalDisabler&) = delete;
|
||||
// Dtor. If `disabling_activated_` is true, restores the denormals HW settings
|
||||
// read by the ctor before denormals were disabled. Otherwise it's a no-op.
|
||||
~DenormalDisabler();
|
||||
|
||||
// Returns true if architecture and compiler are supported.
|
||||
static bool IsSupported();
|
||||
|
||||
private:
|
||||
const int status_word_;
|
||||
const bool disabling_activated_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_DENORMAL_DISABLER_H_
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
//
|
||||
// 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 SYSTEM_WRAPPERS_INCLUDE_FIELD_TRIAL_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_FIELD_TRIAL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "rtc_base/containers/flat_set.h"
|
||||
|
||||
// Field trials allow webrtc clients (such as Chrome) to turn on feature code
|
||||
// in binaries out in the field and gather information with that.
|
||||
//
|
||||
// By default WebRTC provides an implementation of field trials that can be
|
||||
// found in system_wrappers/source/field_trial.cc. If clients want to provide
|
||||
// a custom version, they will have to:
|
||||
//
|
||||
// 1. Compile WebRTC defining the preprocessor macro
|
||||
// WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT (if GN is used this can be achieved
|
||||
// by setting the GN arg rtc_exclude_field_trial_default to true).
|
||||
// 2. Provide an implementation of:
|
||||
// std::string webrtc::field_trial::FindFullName(absl::string_view trial).
|
||||
//
|
||||
// They are designed to wire up directly to chrome field trials and to speed up
|
||||
// developers by reducing the need to wire APIs to control whether a feature is
|
||||
// on/off. E.g. to experiment with a new method that could lead to a different
|
||||
// trade-off between CPU/bandwidth:
|
||||
//
|
||||
// 1 - Develop the feature with default behaviour off:
|
||||
//
|
||||
// if (FieldTrial::FindFullName("WebRTCExperimentMethod2") == "Enabled")
|
||||
// method2();
|
||||
// else
|
||||
// method1();
|
||||
//
|
||||
// 2 - Once the changes are rolled to chrome, the new code path can be
|
||||
// controlled as normal chrome field trials.
|
||||
//
|
||||
// 3 - Evaluate the new feature and clean the code paths.
|
||||
//
|
||||
// Notes:
|
||||
// - NOT every feature is a candidate to be controlled by this mechanism as
|
||||
// it may require negotiation between involved parties (e.g. SDP).
|
||||
//
|
||||
// TODO(andresp): since chrome --force-fieldtrials does not marks the trial
|
||||
// as active it does not get propagated to the renderer process. For now one
|
||||
// needs to push a config with start_active:true or run a local finch
|
||||
// server.
|
||||
//
|
||||
// TODO(andresp): find out how to get bots to run tests with trials enabled.
|
||||
|
||||
namespace webrtc {
|
||||
namespace field_trial {
|
||||
|
||||
// Returns the group name chosen for the named trial, or the empty string
|
||||
// if the trial does not exists.
|
||||
//
|
||||
// Note: To keep things tidy append all the trial names with WebRTC.
|
||||
std::string FindFullName(absl::string_view name);
|
||||
|
||||
// Convenience method, returns true iff FindFullName(name) return a string that
|
||||
// starts with "Enabled".
|
||||
// TODO(tommi): Make sure all implementations support this.
|
||||
inline bool IsEnabled(absl::string_view name) {
|
||||
return FindFullName(name).find("Enabled") == 0;
|
||||
}
|
||||
|
||||
// Convenience method, returns true iff FindFullName(name) return a string that
|
||||
// starts with "Disabled".
|
||||
inline bool IsDisabled(absl::string_view name) {
|
||||
return FindFullName(name).find("Disabled") == 0;
|
||||
}
|
||||
|
||||
// Optionally initialize field trial from a string.
|
||||
// This method can be called at most once before any other call into webrtc.
|
||||
// E.g. before the peer connection factory is constructed.
|
||||
// Note: trials_string must never be destroyed.
|
||||
void InitFieldTrialsFromString(const char* trials_string);
|
||||
|
||||
const char* GetFieldTrialString();
|
||||
|
||||
// Validates the given field trial string.
|
||||
bool FieldTrialsStringIsValid(absl::string_view trials_string);
|
||||
|
||||
// Merges two field trial strings.
|
||||
//
|
||||
// If a key (trial) exists twice with conflicting values (groups), the value
|
||||
// in 'second' takes precedence.
|
||||
// Shall only be called with valid FieldTrial strings.
|
||||
std::string MergeFieldTrialsStrings(absl::string_view first,
|
||||
absl::string_view second);
|
||||
|
||||
// This helper allows to temporary "register" a field trial within the current
|
||||
// scope. This is only useful for tests that use the global field trial string,
|
||||
// otherwise you can use `webrtc::FieldTrialsRegistry`.
|
||||
//
|
||||
// If you want to isolate changes to the global field trial string itself within
|
||||
// the current scope you should use `webrtc::test::ScopedFieldTrials`.
|
||||
class FieldTrialsAllowedInScopeForTesting {
|
||||
public:
|
||||
explicit FieldTrialsAllowedInScopeForTesting(flat_set<std::string> keys);
|
||||
~FieldTrialsAllowedInScopeForTesting();
|
||||
};
|
||||
|
||||
} // namespace field_trial
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_FIELD_TRIAL_H_
|
||||
460
TMessagesProj/jni/voip/webrtc/system_wrappers/include/metrics.h
Normal file
460
TMessagesProj/jni/voip/webrtc/system_wrappers/include/metrics.h
Normal file
|
|
@ -0,0 +1,460 @@
|
|||
//
|
||||
// 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 SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/string_utils.h"
|
||||
|
||||
#if defined(RTC_DISABLE_METRICS)
|
||||
#define RTC_METRICS_ENABLED 0
|
||||
#else
|
||||
#define RTC_METRICS_ENABLED 1
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
namespace metrics_impl {
|
||||
template <typename... Ts>
|
||||
void NoOp(const Ts&...) {}
|
||||
} // namespace metrics_impl
|
||||
} // namespace webrtc
|
||||
|
||||
#if RTC_METRICS_ENABLED
|
||||
#define EXPECT_METRIC_EQ(val1, val2) EXPECT_EQ(val1, val2)
|
||||
#define EXPECT_METRIC_EQ_WAIT(val1, val2, timeout) \
|
||||
EXPECT_EQ_WAIT(val1, val2, timeout)
|
||||
#define EXPECT_METRIC_GT(val1, val2) EXPECT_GT(val1, val2)
|
||||
#define EXPECT_METRIC_LE(val1, val2) EXPECT_LE(val1, val2)
|
||||
#define EXPECT_METRIC_TRUE(conditon) EXPECT_TRUE(conditon)
|
||||
#define EXPECT_METRIC_FALSE(conditon) EXPECT_FALSE(conditon)
|
||||
#define EXPECT_METRIC_THAT(value, matcher) EXPECT_THAT(value, matcher)
|
||||
#else
|
||||
#define EXPECT_METRIC_EQ(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
|
||||
#define EXPECT_METRIC_EQ_WAIT(val1, val2, timeout) \
|
||||
webrtc::metrics_impl::NoOp(val1, val2, timeout)
|
||||
#define EXPECT_METRIC_GT(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
|
||||
#define EXPECT_METRIC_LE(val1, val2) webrtc::metrics_impl::NoOp(val1, val2)
|
||||
#define EXPECT_METRIC_TRUE(condition) \
|
||||
webrtc::metrics_impl::NoOp(condition || true)
|
||||
#define EXPECT_METRIC_FALSE(condition) \
|
||||
webrtc::metrics_impl::NoOp(condition && false)
|
||||
#define EXPECT_METRIC_THAT(value, matcher) \
|
||||
webrtc::metrics_impl::NoOp(value, testing::_)
|
||||
#endif
|
||||
|
||||
#if RTC_METRICS_ENABLED
|
||||
// Macros for allowing WebRTC clients (e.g. Chrome) to gather and aggregate
|
||||
// statistics.
|
||||
//
|
||||
// Histogram for counters.
|
||||
// RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count);
|
||||
//
|
||||
// Histogram for enumerators.
|
||||
// The boundary should be above the max enumerator sample.
|
||||
// RTC_HISTOGRAM_ENUMERATION(name, sample, boundary);
|
||||
//
|
||||
//
|
||||
// The macros use the methods HistogramFactoryGetCounts,
|
||||
// HistogramFactoryGetEnumeration and HistogramAdd.
|
||||
//
|
||||
// By default WebRTC provides implementations of the aforementioned methods
|
||||
// that can be found in system_wrappers/source/metrics.cc. If clients want to
|
||||
// provide a custom version, they will have to:
|
||||
//
|
||||
// 1. Compile WebRTC defining the preprocessor macro
|
||||
// WEBRTC_EXCLUDE_METRICS_DEFAULT (if GN is used this can be achieved
|
||||
// by setting the GN arg rtc_exclude_metrics_default to true).
|
||||
// 2. Provide implementations of:
|
||||
// Histogram* webrtc::metrics::HistogramFactoryGetCounts(
|
||||
// absl::string_view name, int sample, int min, int max,
|
||||
// int bucket_count);
|
||||
// Histogram* webrtc::metrics::HistogramFactoryGetEnumeration(
|
||||
// absl::string_view name, int sample, int boundary);
|
||||
// void webrtc::metrics::HistogramAdd(
|
||||
// Histogram* histogram_pointer, absl::string_view name, int sample);
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// RTC_HISTOGRAM_COUNTS("WebRTC.Video.NacksSent", nacks_sent, 1, 100000, 100);
|
||||
//
|
||||
// enum Types {
|
||||
// kTypeX,
|
||||
// kTypeY,
|
||||
// kBoundary,
|
||||
// };
|
||||
//
|
||||
// RTC_HISTOGRAM_ENUMERATION("WebRTC.Types", kTypeX, kBoundary);
|
||||
//
|
||||
// NOTE: It is recommended to do the Chromium review for modifications to
|
||||
// histograms.xml before new metrics are committed to WebRTC.
|
||||
|
||||
// Macros for adding samples to a named histogram.
|
||||
|
||||
// Histogram for counters (exponentially spaced buckets).
|
||||
#define RTC_HISTOGRAM_COUNTS_100(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 100, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_200(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 200, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_500(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 500, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_1000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_10000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 10000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_100000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetCounts( \
|
||||
name, min, max, bucket_count))
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_LINEAR(name, sample, min, max, bucket_count) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetCountsLinear( \
|
||||
name, min, max, bucket_count))
|
||||
|
||||
// Slow metrics: pointer to metric is acquired at each call and is not cached.
|
||||
//
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 100, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_200(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 200, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_500(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 500, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_1000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 1000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_10000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 10000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100000(name, sample) \
|
||||
RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, 1, 100000, 50)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, min, max, bucket_count) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetCounts( \
|
||||
name, min, max, bucket_count))
|
||||
|
||||
// Histogram for percentage (evenly spaced buckets).
|
||||
#define RTC_HISTOGRAM_PERCENTAGE_SPARSE(name, sample) \
|
||||
RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, 101)
|
||||
|
||||
// Histogram for booleans.
|
||||
#define RTC_HISTOGRAM_BOOLEAN_SPARSE(name, sample) \
|
||||
RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, 2)
|
||||
|
||||
// Histogram for enumerators (evenly spaced buckets).
|
||||
// `boundary` should be above the max enumerator sample.
|
||||
//
|
||||
// TODO(qingsi): Refactor the default implementation given by RtcHistogram,
|
||||
// which is already sparse, and remove the boundary argument from the macro.
|
||||
#define RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, boundary) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK_SLOW( \
|
||||
name, sample, \
|
||||
webrtc::metrics::SparseHistogramFactoryGetEnumeration(name, boundary))
|
||||
|
||||
// Histogram for percentage (evenly spaced buckets).
|
||||
#define RTC_HISTOGRAM_PERCENTAGE(name, sample) \
|
||||
RTC_HISTOGRAM_ENUMERATION(name, sample, 101)
|
||||
|
||||
// Histogram for booleans.
|
||||
#define RTC_HISTOGRAM_BOOLEAN(name, sample) \
|
||||
RTC_HISTOGRAM_ENUMERATION(name, sample, 2)
|
||||
|
||||
// Histogram for enumerators (evenly spaced buckets).
|
||||
// `boundary` should be above the max enumerator sample.
|
||||
#define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \
|
||||
RTC_HISTOGRAM_COMMON_BLOCK_SLOW( \
|
||||
name, sample, \
|
||||
webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary))
|
||||
|
||||
// The name of the histogram should not vary.
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \
|
||||
factory_get_invocation) \
|
||||
do { \
|
||||
static std::atomic<webrtc::metrics::Histogram*> atomic_histogram_pointer( \
|
||||
nullptr); \
|
||||
webrtc::metrics::Histogram* histogram_pointer = \
|
||||
atomic_histogram_pointer.load(std::memory_order_acquire); \
|
||||
if (!histogram_pointer) { \
|
||||
histogram_pointer = factory_get_invocation; \
|
||||
webrtc::metrics::Histogram* null_histogram = nullptr; \
|
||||
atomic_histogram_pointer.compare_exchange_strong(null_histogram, \
|
||||
histogram_pointer); \
|
||||
} \
|
||||
if (histogram_pointer) { \
|
||||
webrtc::metrics::HistogramAdd(histogram_pointer, sample); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// The histogram is constructed/found for each call.
|
||||
// May be used for histograms with infrequent updates.`
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \
|
||||
do { \
|
||||
webrtc::metrics::Histogram* histogram_pointer = factory_get_invocation; \
|
||||
if (histogram_pointer) { \
|
||||
webrtc::metrics::HistogramAdd(histogram_pointer, sample); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Helper macros.
|
||||
// Macros for calling a histogram with varying name (e.g. when using a metric
|
||||
// in different modes such as real-time vs screenshare). Fast, because pointer
|
||||
// is cached. `index` should be different for different names. Allowed `index`
|
||||
// values are 0, 1, and 2.
|
||||
#define RTC_HISTOGRAMS_COUNTS_100(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 100, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_200(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 200, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_500(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 500, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_1000(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_10000(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 10000, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_100000(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50))
|
||||
|
||||
#define RTC_HISTOGRAMS_ENUMERATION(index, name, sample, boundary) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_ENUMERATION(name, sample, boundary))
|
||||
|
||||
#define RTC_HISTOGRAMS_PERCENTAGE(index, name, sample) \
|
||||
RTC_HISTOGRAMS_COMMON(index, name, sample, \
|
||||
RTC_HISTOGRAM_PERCENTAGE(name, sample))
|
||||
|
||||
#define RTC_HISTOGRAMS_COMMON(index, name, sample, macro_invocation) \
|
||||
do { \
|
||||
switch (index) { \
|
||||
case 0: \
|
||||
macro_invocation; \
|
||||
break; \
|
||||
case 1: \
|
||||
macro_invocation; \
|
||||
break; \
|
||||
case 2: \
|
||||
macro_invocation; \
|
||||
break; \
|
||||
default: \
|
||||
RTC_DCHECK_NOTREACHED(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This section defines no-op alternatives to the metrics macros when
|
||||
// RTC_METRICS_ENABLED is defined.
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_100(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_200(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_500(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_1000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_10000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_100000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_LINEAR(name, sample, min, max, bucket_count) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_200(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_500(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_1000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_10000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE_100000(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_COUNTS_SPARSE(name, sample, min, max, bucket_count) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, min, max, bucket_count)
|
||||
|
||||
#define RTC_HISTOGRAM_PERCENTAGE_SPARSE(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_BOOLEAN_SPARSE(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_ENUMERATION_SPARSE(name, sample, boundary) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, boundary)
|
||||
|
||||
#define RTC_HISTOGRAM_PERCENTAGE(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_BOOLEAN(name, sample) \
|
||||
webrtc::metrics_impl::NoOp(name, sample)
|
||||
|
||||
#define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, boundary)
|
||||
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \
|
||||
factory_get_invocation) \
|
||||
webrtc::metrics_impl::NoOp(constant_name, sample, factory_get_invocation)
|
||||
|
||||
#define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \
|
||||
webrtc::metrics_impl::NoOp(name, sample, factory_get_invocation)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_100(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_200(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_500(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_1000(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_10000(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COUNTS_100000(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_ENUMERATION(index, name, sample, boundary) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample, boundary)
|
||||
|
||||
#define RTC_HISTOGRAMS_PERCENTAGE(index, name, sample) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample)
|
||||
|
||||
#define RTC_HISTOGRAMS_COMMON(index, name, sample, macro_invocation) \
|
||||
webrtc::metrics_impl::NoOp(index, name, sample, macro_invocation)
|
||||
|
||||
#endif // RTC_METRICS_ENABLED
|
||||
|
||||
namespace webrtc {
|
||||
namespace metrics {
|
||||
|
||||
// Time that should have elapsed for stats that are gathered once per call.
|
||||
constexpr int kMinRunTimeInSeconds = 10;
|
||||
|
||||
class Histogram;
|
||||
|
||||
// Functions for getting pointer to histogram (constructs or finds the named
|
||||
// histogram).
|
||||
|
||||
// Get histogram for counters.
|
||||
Histogram* HistogramFactoryGetCounts(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count);
|
||||
|
||||
// Get histogram for counters with linear bucket spacing.
|
||||
Histogram* HistogramFactoryGetCountsLinear(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count);
|
||||
|
||||
// Get histogram for enumerators.
|
||||
// `boundary` should be above the max enumerator sample.
|
||||
Histogram* HistogramFactoryGetEnumeration(absl::string_view name, int boundary);
|
||||
|
||||
// Get sparse histogram for enumerators.
|
||||
// `boundary` should be above the max enumerator sample.
|
||||
Histogram* SparseHistogramFactoryGetEnumeration(absl::string_view name,
|
||||
int boundary);
|
||||
|
||||
// Function for adding a `sample` to a histogram.
|
||||
void HistogramAdd(Histogram* histogram_pointer, int sample);
|
||||
|
||||
struct SampleInfo {
|
||||
SampleInfo(absl::string_view name, int min, int max, size_t bucket_count);
|
||||
~SampleInfo();
|
||||
|
||||
const std::string name;
|
||||
const int min;
|
||||
const int max;
|
||||
const size_t bucket_count;
|
||||
std::map<int, int> samples; // <value, # of events>
|
||||
};
|
||||
|
||||
// Enables collection of samples.
|
||||
// This method should be called before any other call into webrtc.
|
||||
void Enable();
|
||||
|
||||
// Gets histograms and clears all samples.
|
||||
void GetAndReset(
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>, rtc::AbslStringViewCmp>*
|
||||
histograms);
|
||||
|
||||
// Functions below are mainly for testing.
|
||||
|
||||
// Clears all samples.
|
||||
void Reset();
|
||||
|
||||
// Returns the number of times the `sample` has been added to the histogram.
|
||||
int NumEvents(absl::string_view name, int sample);
|
||||
|
||||
// Returns the total number of added samples to the histogram.
|
||||
int NumSamples(absl::string_view name);
|
||||
|
||||
// Returns the minimum sample value (or -1 if the histogram has no samples).
|
||||
int MinSample(absl::string_view name);
|
||||
|
||||
// Returns a map with keys the samples with at least one event and values the
|
||||
// number of events for that sample.
|
||||
std::map<int, int> Samples(absl::string_view name);
|
||||
|
||||
} // namespace metrics
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_METRICS_H_
|
||||
124
TMessagesProj/jni/voip/webrtc/system_wrappers/include/ntp_time.h
Normal file
124
TMessagesProj/jni/voip/webrtc/system_wrappers/include/ntp_time.h
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef SYSTEM_WRAPPERS_INCLUDE_NTP_TIME_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_NTP_TIME_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class NtpTime {
|
||||
public:
|
||||
static constexpr uint64_t kFractionsPerSecond = 0x100000000;
|
||||
NtpTime() : value_(0) {}
|
||||
explicit NtpTime(uint64_t value) : value_(value) {}
|
||||
NtpTime(uint32_t seconds, uint32_t fractions)
|
||||
: value_(seconds * kFractionsPerSecond + fractions) {}
|
||||
|
||||
NtpTime(const NtpTime&) = default;
|
||||
NtpTime& operator=(const NtpTime&) = default;
|
||||
explicit operator uint64_t() const { return value_; }
|
||||
|
||||
void Set(uint32_t seconds, uint32_t fractions) {
|
||||
value_ = seconds * kFractionsPerSecond + fractions;
|
||||
}
|
||||
void Reset() { value_ = 0; }
|
||||
|
||||
int64_t ToMs() const {
|
||||
static constexpr double kNtpFracPerMs = 4.294967296E6; // 2^32 / 1000.
|
||||
const double frac_ms = static_cast<double>(fractions()) / kNtpFracPerMs;
|
||||
return 1000 * static_cast<int64_t>(seconds()) +
|
||||
static_cast<int64_t>(frac_ms + 0.5);
|
||||
}
|
||||
// NTP standard (RFC1305, section 3.1) explicitly state value 0 is invalid.
|
||||
bool Valid() const { return value_ != 0; }
|
||||
|
||||
uint32_t seconds() const {
|
||||
return rtc::dchecked_cast<uint32_t>(value_ / kFractionsPerSecond);
|
||||
}
|
||||
uint32_t fractions() const {
|
||||
return rtc::dchecked_cast<uint32_t>(value_ % kFractionsPerSecond);
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t value_;
|
||||
};
|
||||
|
||||
inline bool operator==(const NtpTime& n1, const NtpTime& n2) {
|
||||
return static_cast<uint64_t>(n1) == static_cast<uint64_t>(n2);
|
||||
}
|
||||
inline bool operator!=(const NtpTime& n1, const NtpTime& n2) {
|
||||
return !(n1 == n2);
|
||||
}
|
||||
|
||||
// Converts `int64_t` milliseconds to Q32.32-formatted fixed-point seconds.
|
||||
// Performs clamping if the result overflows or underflows.
|
||||
inline int64_t Int64MsToQ32x32(int64_t milliseconds) {
|
||||
// TODO(bugs.webrtc.org/10893): Change to use `rtc::saturated_cast` once the
|
||||
// bug has been fixed.
|
||||
double result =
|
||||
std::round(milliseconds * (NtpTime::kFractionsPerSecond / 1000.0));
|
||||
|
||||
// Explicitly cast values to double to avoid implicit conversion warnings
|
||||
// The conversion of the std::numeric_limits<int64_t>::max() triggers
|
||||
// -Wimplicit-int-float-conversion warning in clang 10.0.0 without explicit
|
||||
// cast
|
||||
if (result <= static_cast<double>(std::numeric_limits<int64_t>::min())) {
|
||||
return std::numeric_limits<int64_t>::min();
|
||||
}
|
||||
|
||||
if (result >= static_cast<double>(std::numeric_limits<int64_t>::max())) {
|
||||
return std::numeric_limits<int64_t>::max();
|
||||
}
|
||||
|
||||
return rtc::dchecked_cast<int64_t>(result);
|
||||
}
|
||||
|
||||
// Converts `int64_t` milliseconds to UQ32.32-formatted fixed-point seconds.
|
||||
// Performs clamping if the result overflows or underflows.
|
||||
inline uint64_t Int64MsToUQ32x32(int64_t milliseconds) {
|
||||
// TODO(bugs.webrtc.org/10893): Change to use `rtc::saturated_cast` once the
|
||||
// bug has been fixed.
|
||||
double result =
|
||||
std::round(milliseconds * (NtpTime::kFractionsPerSecond / 1000.0));
|
||||
|
||||
// Explicitly cast values to double to avoid implicit conversion warnings
|
||||
// The conversion of the std::numeric_limits<int64_t>::max() triggers
|
||||
// -Wimplicit-int-float-conversion warning in clang 10.0.0 without explicit
|
||||
// cast
|
||||
if (result <= static_cast<double>(std::numeric_limits<uint64_t>::min())) {
|
||||
return std::numeric_limits<uint64_t>::min();
|
||||
}
|
||||
|
||||
if (result >= static_cast<double>(std::numeric_limits<uint64_t>::max())) {
|
||||
return std::numeric_limits<uint64_t>::max();
|
||||
}
|
||||
|
||||
return rtc::dchecked_cast<uint64_t>(result);
|
||||
}
|
||||
|
||||
// Converts Q32.32-formatted fixed-point seconds to `int64_t` milliseconds.
|
||||
inline int64_t Q32x32ToInt64Ms(int64_t q32x32) {
|
||||
return rtc::dchecked_cast<int64_t>(
|
||||
std::round(q32x32 * (1000.0 / NtpTime::kFractionsPerSecond)));
|
||||
}
|
||||
|
||||
// Converts UQ32.32-formatted fixed-point seconds to `int64_t` milliseconds.
|
||||
inline int64_t UQ32x32ToInt64Ms(uint64_t q32x32) {
|
||||
return rtc::dchecked_cast<int64_t>(
|
||||
std::round(q32x32 * (1000.0 / NtpTime::kFractionsPerSecond)));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_NTP_TIME_H_
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_ESTIMATOR_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_ESTIMATOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/numerics/sequence_number_unwrapper.h"
|
||||
#include "system_wrappers/include/ntp_time.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Converts an RTP timestamp to the NTP domain.
|
||||
// The class needs to be trained with (at least 2) RTP/NTP timestamp pairs from
|
||||
// RTCP sender reports before the convertion can be done.
|
||||
class RtpToNtpEstimator {
|
||||
public:
|
||||
static constexpr int kMaxInvalidSamples = 3;
|
||||
|
||||
RtpToNtpEstimator() = default;
|
||||
RtpToNtpEstimator(const RtpToNtpEstimator&) = delete;
|
||||
RtpToNtpEstimator& operator=(const RtpToNtpEstimator&) = delete;
|
||||
~RtpToNtpEstimator() = default;
|
||||
|
||||
enum UpdateResult { kInvalidMeasurement, kSameMeasurement, kNewMeasurement };
|
||||
// Updates measurements with RTP/NTP timestamp pair from a RTCP sender report.
|
||||
UpdateResult UpdateMeasurements(NtpTime ntp, uint32_t rtp_timestamp);
|
||||
|
||||
// Converts an RTP timestamp to the NTP domain.
|
||||
// Returns invalid NtpTime (i.e. NtpTime(0)) on failure.
|
||||
NtpTime Estimate(uint32_t rtp_timestamp) const;
|
||||
|
||||
// Returns estimated rtp_timestamp frequency, or 0 on failure.
|
||||
double EstimatedFrequencyKhz() const;
|
||||
|
||||
private:
|
||||
// Estimated parameters from RTP and NTP timestamp pairs in `measurements_`.
|
||||
// Defines linear estimation: NtpTime (in units of 1s/2^32) =
|
||||
// `Parameters::slope` * rtp_timestamp + `Parameters::offset`.
|
||||
struct Parameters {
|
||||
double slope;
|
||||
double offset;
|
||||
};
|
||||
|
||||
// RTP and NTP timestamp pair from a RTCP SR report.
|
||||
struct RtcpMeasurement {
|
||||
NtpTime ntp_time;
|
||||
int64_t unwrapped_rtp_timestamp;
|
||||
};
|
||||
|
||||
void UpdateParameters();
|
||||
|
||||
int consecutive_invalid_samples_ = 0;
|
||||
std::list<RtcpMeasurement> measurements_;
|
||||
absl::optional<Parameters> params_;
|
||||
mutable RtpTimestampUnwrapper unwrapper_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_ESTIMATOR_H_
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
// An OS-independent sleep function.
|
||||
|
||||
#ifndef SYSTEM_WRAPPERS_INCLUDE_SLEEP_H_
|
||||
#define SYSTEM_WRAPPERS_INCLUDE_SLEEP_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// This function sleeps for the specified number of milliseconds.
|
||||
// It may return early if the thread is woken by some other event,
|
||||
// such as the delivery of a signal on Unix.
|
||||
void SleepMs(int msecs);
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SYSTEM_WRAPPERS_INCLUDE_SLEEP_H_
|
||||
102
TMessagesProj/jni/voip/webrtc/system_wrappers/source/clock.cc
Normal file
102
TMessagesProj/jni/voip/webrtc/system_wrappers/source/clock.cc
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "system_wrappers/include/clock.h"
|
||||
|
||||
#include "rtc_base/time_utils.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
int64_t NtpOffsetUsCalledOnce() {
|
||||
constexpr int64_t kNtpJan1970Sec = 2208988800;
|
||||
int64_t clock_time = rtc::TimeMicros();
|
||||
int64_t utc_time = rtc::TimeUTCMicros();
|
||||
return utc_time - clock_time + kNtpJan1970Sec * rtc::kNumMicrosecsPerSec;
|
||||
}
|
||||
|
||||
NtpTime TimeMicrosToNtp(int64_t time_us) {
|
||||
static int64_t ntp_offset_us = NtpOffsetUsCalledOnce();
|
||||
|
||||
int64_t time_ntp_us = time_us + ntp_offset_us;
|
||||
RTC_DCHECK_GE(time_ntp_us, 0); // Time before year 1900 is unsupported.
|
||||
|
||||
// Convert seconds to uint32 through uint64 for a well-defined cast.
|
||||
// A wrap around, which will happen in 2036, is expected for NTP time.
|
||||
uint32_t ntp_seconds =
|
||||
static_cast<uint64_t>(time_ntp_us / rtc::kNumMicrosecsPerSec);
|
||||
|
||||
// Scale fractions of the second to NTP resolution.
|
||||
constexpr int64_t kNtpFractionsInSecond = 1LL << 32;
|
||||
int64_t us_fractions = time_ntp_us % rtc::kNumMicrosecsPerSec;
|
||||
uint32_t ntp_fractions =
|
||||
us_fractions * kNtpFractionsInSecond / rtc::kNumMicrosecsPerSec;
|
||||
|
||||
return NtpTime(ntp_seconds, ntp_fractions);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class RealTimeClock : public Clock {
|
||||
public:
|
||||
RealTimeClock() = default;
|
||||
|
||||
Timestamp CurrentTime() override {
|
||||
return Timestamp::Micros(rtc::TimeMicros());
|
||||
}
|
||||
|
||||
NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) override {
|
||||
return TimeMicrosToNtp(timestamp.us());
|
||||
}
|
||||
};
|
||||
|
||||
Clock* Clock::GetRealTimeClock() {
|
||||
static Clock* const clock = new RealTimeClock();
|
||||
return clock;
|
||||
}
|
||||
|
||||
SimulatedClock::SimulatedClock(int64_t initial_time_us)
|
||||
: time_us_(initial_time_us) {}
|
||||
|
||||
SimulatedClock::SimulatedClock(Timestamp initial_time)
|
||||
: SimulatedClock(initial_time.us()) {}
|
||||
|
||||
SimulatedClock::~SimulatedClock() {}
|
||||
|
||||
Timestamp SimulatedClock::CurrentTime() {
|
||||
return Timestamp::Micros(time_us_.load(std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
NtpTime SimulatedClock::ConvertTimestampToNtpTime(Timestamp timestamp) {
|
||||
int64_t now_us = timestamp.us();
|
||||
uint32_t seconds = (now_us / 1'000'000) + kNtpJan1970;
|
||||
uint32_t fractions = static_cast<uint32_t>(
|
||||
(now_us % 1'000'000) * kMagicNtpFractionalUnit / 1'000'000);
|
||||
return NtpTime(seconds, fractions);
|
||||
}
|
||||
|
||||
void SimulatedClock::AdvanceTimeMilliseconds(int64_t milliseconds) {
|
||||
AdvanceTime(TimeDelta::Millis(milliseconds));
|
||||
}
|
||||
|
||||
void SimulatedClock::AdvanceTimeMicroseconds(int64_t microseconds) {
|
||||
AdvanceTime(TimeDelta::Micros(microseconds));
|
||||
}
|
||||
|
||||
// TODO(bugs.webrtc.org(12102): It's desirable to let a single thread own
|
||||
// advancement of the clock. We could then replace this read-modify-write
|
||||
// operation with just a thread checker. But currently, that breaks a couple of
|
||||
// tests, in particular, RepeatingTaskTest.ClockIntegration and
|
||||
// CallStatsTest.LastProcessedRtt.
|
||||
void SimulatedClock::AdvanceTime(TimeDelta delta) {
|
||||
time_us_.fetch_add(delta.us(), std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Parts of this file derived from Chromium's base/cpu.cc.
|
||||
|
||||
#include "rtc_base/system/arch.h"
|
||||
#include "system_wrappers/include/cpu_features_wrapper.h"
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY) && defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// No CPU feature is available => straight C path.
|
||||
int GetCPUInfoNoASM(CPUFeature feature) {
|
||||
(void)feature;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
|
||||
#if defined(WEBRTC_ENABLE_AVX2)
|
||||
// xgetbv returns the value of an Intel Extended Control Register (XCR).
|
||||
// Currently only XCR0 is defined by Intel so `xcr` should always be zero.
|
||||
static uint64_t xgetbv(uint32_t xcr) {
|
||||
#if defined(_MSC_VER)
|
||||
return _xgetbv(xcr);
|
||||
#else
|
||||
uint32_t eax, edx;
|
||||
|
||||
__asm__ volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr));
|
||||
return (static_cast<uint64_t>(edx) << 32) | eax;
|
||||
#endif // _MSC_VER
|
||||
}
|
||||
#endif // WEBRTC_ENABLE_AVX2
|
||||
|
||||
#ifndef _MSC_VER
|
||||
// Intrinsic for "cpuid".
|
||||
#if defined(__pic__) && defined(__i386__)
|
||||
static inline void __cpuid(int cpu_info[4], int info_type) {
|
||||
__asm__ volatile(
|
||||
"mov %%ebx, %%edi\n"
|
||||
"cpuid\n"
|
||||
"xchg %%edi, %%ebx\n"
|
||||
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]),
|
||||
"=d"(cpu_info[3])
|
||||
: "a"(info_type));
|
||||
}
|
||||
#else
|
||||
static inline void __cpuid(int cpu_info[4], int info_type) {
|
||||
__asm__ volatile("cpuid\n"
|
||||
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
|
||||
"=d"(cpu_info[3])
|
||||
: "a"(info_type), "c"(0));
|
||||
}
|
||||
#endif
|
||||
#endif // _MSC_VER
|
||||
#endif // WEBRTC_ARCH_X86_FAMILY
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
// Actual feature detection for x86.
|
||||
int GetCPUInfo(CPUFeature feature) {
|
||||
int cpu_info[4];
|
||||
__cpuid(cpu_info, 1);
|
||||
if (feature == kSSE2) {
|
||||
return 0 != (cpu_info[3] & 0x04000000);
|
||||
}
|
||||
if (feature == kSSE3) {
|
||||
return 0 != (cpu_info[2] & 0x00000001);
|
||||
}
|
||||
#if defined(WEBRTC_ENABLE_AVX2)
|
||||
if (feature == kAVX2 &&
|
||||
!webrtc::field_trial::IsEnabled("WebRTC-Avx2SupportKillSwitch")) {
|
||||
int cpu_info7[4];
|
||||
__cpuid(cpu_info7, 0);
|
||||
int num_ids = cpu_info7[0];
|
||||
if (num_ids < 7) {
|
||||
return 0;
|
||||
}
|
||||
// Interpret CPU feature information.
|
||||
__cpuid(cpu_info7, 7);
|
||||
|
||||
// AVX instructions can be used when
|
||||
// a) AVX are supported by the CPU,
|
||||
// b) XSAVE is supported by the CPU,
|
||||
// c) XSAVE is enabled by the kernel.
|
||||
// Compiling with MSVC and /arch:AVX2 surprisingly generates BMI2
|
||||
// instructions (see crbug.com/1315519).
|
||||
return (cpu_info[2] & 0x10000000) != 0 /* AVX */ &&
|
||||
(cpu_info[2] & 0x04000000) != 0 /* XSAVE */ &&
|
||||
(cpu_info[2] & 0x08000000) != 0 /* OSXSAVE */ &&
|
||||
(xgetbv(0) & 0x00000006) == 6 /* XSAVE enabled by kernel */ &&
|
||||
(cpu_info7[1] & 0x00000020) != 0 /* AVX2 */ &&
|
||||
(cpu_info7[1] & 0x00000100) != 0 /* BMI2 */;
|
||||
}
|
||||
#endif // WEBRTC_ENABLE_AVX2
|
||||
if (feature == kFMA3) {
|
||||
return 0 != (cpu_info[2] & 0x00001000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
// Default to straight C for other platforms.
|
||||
int GetCPUInfo(CPUFeature feature) {
|
||||
(void)feature;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <cpu-features.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
uint64_t GetCPUFeaturesARM(void) {
|
||||
return android_getCpuFeatures();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <features.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __GLIBC_PREREQ
|
||||
#define WEBRTC_GLIBC_PREREQ(a, b) __GLIBC_PREREQ(a, b)
|
||||
#else
|
||||
#define WEBRTC_GLIBC_PREREQ(a, b) 0
|
||||
#endif
|
||||
|
||||
#if WEBRTC_GLIBC_PREREQ(2, 16)
|
||||
#include <sys/auxv.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <link.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "rtc_base/system/arch.h"
|
||||
#include "system_wrappers/include/cpu_features_wrapper.h"
|
||||
|
||||
#if defined(WEBRTC_ARCH_ARM_FAMILY)
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
uint64_t GetCPUFeaturesARM(void) {
|
||||
uint64_t result = 0;
|
||||
int architecture = 0;
|
||||
uint64_t hwcap = 0;
|
||||
const char* platform = NULL;
|
||||
#if WEBRTC_GLIBC_PREREQ(2, 16)
|
||||
hwcap = getauxval(AT_HWCAP);
|
||||
platform = (const char*)getauxval(AT_PLATFORM);
|
||||
#else
|
||||
ElfW(auxv_t) auxv;
|
||||
int fd = open("/proc/self/auxv", O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
while (hwcap == 0 || platform == NULL) {
|
||||
if (read(fd, &auxv, sizeof(auxv)) < (ssize_t)sizeof(auxv)) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
switch (auxv.a_type) {
|
||||
case AT_HWCAP:
|
||||
hwcap = auxv.a_un.a_val;
|
||||
break;
|
||||
case AT_PLATFORM:
|
||||
platform = (const char*)auxv.a_un.a_val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
#endif // WEBRTC_GLIBC_PREREQ(2, 16)
|
||||
#if defined(__aarch64__)
|
||||
(void)platform;
|
||||
architecture = 8;
|
||||
if ((hwcap & HWCAP_FP) != 0)
|
||||
result |= kCPUFeatureVFPv3;
|
||||
if ((hwcap & HWCAP_ASIMD) != 0)
|
||||
result |= kCPUFeatureNEON;
|
||||
#else
|
||||
if (platform != NULL) {
|
||||
/* expect a string in the form "v6l" or "v7l", etc.
|
||||
*/
|
||||
if (platform[0] == 'v' && '0' <= platform[1] && platform[1] <= '9' &&
|
||||
(platform[2] == 'l' || platform[2] == 'b')) {
|
||||
architecture = platform[1] - '0';
|
||||
}
|
||||
}
|
||||
if ((hwcap & HWCAP_VFPv3) != 0)
|
||||
result |= kCPUFeatureVFPv3;
|
||||
if ((hwcap & HWCAP_NEON) != 0)
|
||||
result |= kCPUFeatureNEON;
|
||||
#endif
|
||||
if (architecture >= 7)
|
||||
result |= kCPUFeatureARMv7;
|
||||
if (architecture >= 6)
|
||||
result |= kCPUFeatureLDREXSTREX;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_ARCH_ARM_FAMILY
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "system_wrappers/include/cpu_info.h"
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
#include <windows.h>
|
||||
#elif defined(WEBRTC_LINUX)
|
||||
#include <unistd.h>
|
||||
#elif defined(WEBRTC_MAC)
|
||||
#include <sys/sysctl.h>
|
||||
#elif defined(WEBRTC_FUCHSIA)
|
||||
#include <zircon/syscalls.h>
|
||||
#endif
|
||||
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace internal {
|
||||
static int DetectNumberOfCores() {
|
||||
int number_of_cores;
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
SYSTEM_INFO si;
|
||||
GetNativeSystemInfo(&si);
|
||||
number_of_cores = static_cast<int>(si.dwNumberOfProcessors);
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
|
||||
number_of_cores = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
|
||||
if (number_of_cores <= 0) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to get number of cores";
|
||||
number_of_cores = 1;
|
||||
}
|
||||
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
|
||||
int name[] = {CTL_HW, HW_AVAILCPU};
|
||||
size_t size = sizeof(number_of_cores);
|
||||
if (0 != sysctl(name, 2, &number_of_cores, &size, NULL, 0)) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to get number of cores";
|
||||
number_of_cores = 1;
|
||||
}
|
||||
#elif defined(WEBRTC_FUCHSIA)
|
||||
number_of_cores = zx_system_get_num_cpus();
|
||||
#else
|
||||
RTC_LOG(LS_ERROR) << "No function to get number of cores";
|
||||
number_of_cores = 1;
|
||||
#endif
|
||||
|
||||
RTC_LOG(LS_INFO) << "Available number of cores: " << number_of_cores;
|
||||
|
||||
RTC_CHECK_GT(number_of_cores, 0);
|
||||
return number_of_cores;
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
uint32_t CpuInfo::DetectNumberOfCores() {
|
||||
// Statically cache the number of system cores available since if the process
|
||||
// is running in a sandbox, we may only be able to read the value once (before
|
||||
// the sandbox is initialized) and not thereafter.
|
||||
// For more information see crbug.com/176522.
|
||||
static const uint32_t logical_cpus =
|
||||
static_cast<uint32_t>(internal::DetectNumberOfCores());
|
||||
return logical_cpus;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "system_wrappers/include/denormal_disabler.h"
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY) && defined(__clang__)
|
||||
#define WEBRTC_DENORMAL_DISABLER_X86_SUPPORTED
|
||||
#endif
|
||||
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_X86_SUPPORTED) || \
|
||||
defined(WEBRTC_ARCH_ARM_FAMILY)
|
||||
#define WEBRTC_DENORMAL_DISABLER_SUPPORTED
|
||||
#endif
|
||||
|
||||
constexpr int kUnspecifiedStatusWord = -1;
|
||||
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_SUPPORTED)
|
||||
|
||||
// Control register bit mask to disable denormals on the hardware.
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_X86_SUPPORTED)
|
||||
// On x86 two bits are used: flush-to-zero (FTZ) and denormals-are-zero (DAZ).
|
||||
constexpr int kDenormalBitMask = 0x8040;
|
||||
#elif defined(WEBRTC_ARCH_ARM_FAMILY)
|
||||
// On ARM one bit is used: flush-to-zero (FTZ).
|
||||
constexpr int kDenormalBitMask = 1 << 24;
|
||||
#endif
|
||||
|
||||
// Reads the relevant CPU control register and returns its value for supported
|
||||
// architectures and compilers. Otherwise returns `kUnspecifiedStatusWord`.
|
||||
int ReadStatusWord() {
|
||||
int result = kUnspecifiedStatusWord;
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_X86_SUPPORTED)
|
||||
asm volatile("stmxcsr %0" : "=m"(result));
|
||||
#elif defined(WEBRTC_ARCH_ARM_FAMILY) && defined(WEBRTC_ARCH_32_BITS)
|
||||
asm volatile("vmrs %[result], FPSCR" : [result] "=r"(result));
|
||||
#elif defined(WEBRTC_ARCH_ARM_FAMILY) && defined(WEBRTC_ARCH_64_BITS)
|
||||
asm volatile("mrs %x[result], FPCR" : [result] "=r"(result));
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
// Writes `status_word` in the relevant CPU control register if the architecture
|
||||
// and the compiler are supported.
|
||||
void SetStatusWord(int status_word) {
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_X86_SUPPORTED)
|
||||
asm volatile("ldmxcsr %0" : : "m"(status_word));
|
||||
#elif defined(WEBRTC_ARCH_ARM_FAMILY) && defined(WEBRTC_ARCH_32_BITS)
|
||||
asm volatile("vmsr FPSCR, %[src]" : : [src] "r"(status_word));
|
||||
#elif defined(WEBRTC_ARCH_ARM_FAMILY) && defined(WEBRTC_ARCH_64_BITS)
|
||||
asm volatile("msr FPCR, %x[src]" : : [src] "r"(status_word));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns true if the status word indicates that denormals are enabled.
|
||||
constexpr bool DenormalsEnabled(int status_word) {
|
||||
return (status_word & kDenormalBitMask) != kDenormalBitMask;
|
||||
}
|
||||
|
||||
#endif // defined(WEBRTC_DENORMAL_DISABLER_SUPPORTED)
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(WEBRTC_DENORMAL_DISABLER_SUPPORTED)
|
||||
DenormalDisabler::DenormalDisabler() : DenormalDisabler(/*enabled=*/true) {}
|
||||
|
||||
DenormalDisabler::DenormalDisabler(bool enabled)
|
||||
: status_word_(enabled ? ReadStatusWord() : kUnspecifiedStatusWord),
|
||||
disabling_activated_(enabled && DenormalsEnabled(status_word_)) {
|
||||
if (disabling_activated_) {
|
||||
RTC_DCHECK_NE(status_word_, kUnspecifiedStatusWord);
|
||||
SetStatusWord(status_word_ | kDenormalBitMask);
|
||||
RTC_DCHECK(!DenormalsEnabled(ReadStatusWord()));
|
||||
}
|
||||
}
|
||||
|
||||
bool DenormalDisabler::IsSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
DenormalDisabler::~DenormalDisabler() {
|
||||
if (disabling_activated_) {
|
||||
RTC_DCHECK_NE(status_word_, kUnspecifiedStatusWord);
|
||||
SetStatusWord(status_word_);
|
||||
}
|
||||
}
|
||||
#else
|
||||
DenormalDisabler::DenormalDisabler() : DenormalDisabler(/*enabled=*/false) {}
|
||||
|
||||
DenormalDisabler::DenormalDisabler(bool enabled)
|
||||
: status_word_(kUnspecifiedStatusWord), disabling_activated_(false) {}
|
||||
|
||||
bool DenormalDisabler::IsSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
DenormalDisabler::~DenormalDisabler() = default;
|
||||
#endif
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
//
|
||||
|
||||
#include "system_wrappers/include/field_trial.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "experiments/registered_field_trials.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/containers/flat_set.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/string_encode.h"
|
||||
|
||||
// Simple field trial implementation, which allows client to
|
||||
// specify desired flags in InitFieldTrialsFromString.
|
||||
namespace webrtc {
|
||||
namespace field_trial {
|
||||
|
||||
static const char* trials_init_string = NULL;
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kPersistentStringSeparator = '/';
|
||||
|
||||
flat_set<std::string>& TestKeys() {
|
||||
static auto* test_keys = new flat_set<std::string>();
|
||||
return *test_keys;
|
||||
}
|
||||
|
||||
// Validates the given field trial string.
|
||||
// E.g.:
|
||||
// "WebRTC-experimentFoo/Enabled/WebRTC-experimentBar/Enabled100kbps/"
|
||||
// Assigns the process to group "Enabled" on WebRTCExperimentFoo trial
|
||||
// and to group "Enabled100kbps" on WebRTCExperimentBar.
|
||||
//
|
||||
// E.g. invalid config:
|
||||
// "WebRTC-experiment1/Enabled" (note missing / separator at the end).
|
||||
bool FieldTrialsStringIsValidInternal(const absl::string_view trials) {
|
||||
if (trials.empty())
|
||||
return true;
|
||||
|
||||
size_t next_item = 0;
|
||||
std::map<absl::string_view, absl::string_view> field_trials;
|
||||
while (next_item < trials.length()) {
|
||||
size_t name_end = trials.find(kPersistentStringSeparator, next_item);
|
||||
if (name_end == trials.npos || next_item == name_end)
|
||||
return false;
|
||||
size_t group_name_end =
|
||||
trials.find(kPersistentStringSeparator, name_end + 1);
|
||||
if (group_name_end == trials.npos || name_end + 1 == group_name_end)
|
||||
return false;
|
||||
absl::string_view name = trials.substr(next_item, name_end - next_item);
|
||||
absl::string_view group_name =
|
||||
trials.substr(name_end + 1, group_name_end - name_end - 1);
|
||||
|
||||
next_item = group_name_end + 1;
|
||||
|
||||
// Fail if duplicate with different group name.
|
||||
if (field_trials.find(name) != field_trials.end() &&
|
||||
field_trials.find(name)->second != group_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
field_trials[name] = group_name;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool FieldTrialsStringIsValid(absl::string_view trials_string) {
|
||||
return FieldTrialsStringIsValidInternal(trials_string);
|
||||
}
|
||||
|
||||
void InsertOrReplaceFieldTrialStringsInMap(
|
||||
std::map<std::string, std::string>* fieldtrial_map,
|
||||
const absl::string_view trials_string) {
|
||||
if (FieldTrialsStringIsValidInternal(trials_string)) {
|
||||
std::vector<absl::string_view> tokens = rtc::split(trials_string, '/');
|
||||
// Skip last token which is empty due to trailing '/'.
|
||||
for (size_t idx = 0; idx < tokens.size() - 1; idx += 2) {
|
||||
(*fieldtrial_map)[std::string(tokens[idx])] =
|
||||
std::string(tokens[idx + 1]);
|
||||
}
|
||||
} else {
|
||||
RTC_DCHECK_NOTREACHED() << "Invalid field trials string:" << trials_string;
|
||||
}
|
||||
}
|
||||
|
||||
std::string MergeFieldTrialsStrings(absl::string_view first,
|
||||
absl::string_view second) {
|
||||
std::map<std::string, std::string> fieldtrial_map;
|
||||
InsertOrReplaceFieldTrialStringsInMap(&fieldtrial_map, first);
|
||||
InsertOrReplaceFieldTrialStringsInMap(&fieldtrial_map, second);
|
||||
|
||||
// Merge into fieldtrial string.
|
||||
std::string merged = "";
|
||||
for (auto const& fieldtrial : fieldtrial_map) {
|
||||
merged += fieldtrial.first + '/' + fieldtrial.second + '/';
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
#ifndef WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
std::string FindFullName(absl::string_view name) {
|
||||
#if WEBRTC_STRICT_FIELD_TRIALS == 1
|
||||
RTC_DCHECK(absl::c_linear_search(kRegisteredFieldTrials, name) ||
|
||||
TestKeys().contains(name))
|
||||
<< name << " is not registered, see g3doc/field-trials.md.";
|
||||
#elif WEBRTC_STRICT_FIELD_TRIALS == 2
|
||||
RTC_LOG_IF(LS_WARNING,
|
||||
!(absl::c_linear_search(kRegisteredFieldTrials, name) ||
|
||||
TestKeys().contains(name)))
|
||||
<< name << " is not registered, see g3doc/field-trials.md.";
|
||||
#endif
|
||||
|
||||
if (trials_init_string == NULL)
|
||||
return std::string();
|
||||
|
||||
absl::string_view trials_string(trials_init_string);
|
||||
if (trials_string.empty())
|
||||
return std::string();
|
||||
|
||||
size_t next_item = 0;
|
||||
while (next_item < trials_string.length()) {
|
||||
// Find next name/value pair in field trial configuration string.
|
||||
size_t field_name_end =
|
||||
trials_string.find(kPersistentStringSeparator, next_item);
|
||||
if (field_name_end == trials_string.npos || field_name_end == next_item)
|
||||
break;
|
||||
size_t field_value_end =
|
||||
trials_string.find(kPersistentStringSeparator, field_name_end + 1);
|
||||
if (field_value_end == trials_string.npos ||
|
||||
field_value_end == field_name_end + 1)
|
||||
break;
|
||||
absl::string_view field_name =
|
||||
trials_string.substr(next_item, field_name_end - next_item);
|
||||
absl::string_view field_value = trials_string.substr(
|
||||
field_name_end + 1, field_value_end - field_name_end - 1);
|
||||
next_item = field_value_end + 1;
|
||||
|
||||
if (name == field_name)
|
||||
return std::string(field_value);
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
#endif // WEBRTC_EXCLUDE_FIELD_TRIAL_DEFAULT
|
||||
|
||||
// Optionally initialize field trial from a string.
|
||||
void InitFieldTrialsFromString(const char* trials_string) {
|
||||
RTC_LOG(LS_INFO) << "Setting field trial string:" << trials_string;
|
||||
if (trials_string) {
|
||||
RTC_DCHECK(FieldTrialsStringIsValidInternal(trials_string))
|
||||
<< "Invalid field trials string:" << trials_string;
|
||||
};
|
||||
trials_init_string = trials_string;
|
||||
}
|
||||
|
||||
const char* GetFieldTrialString() {
|
||||
return trials_init_string;
|
||||
}
|
||||
|
||||
FieldTrialsAllowedInScopeForTesting::FieldTrialsAllowedInScopeForTesting(
|
||||
flat_set<std::string> keys) {
|
||||
TestKeys() = std::move(keys);
|
||||
}
|
||||
|
||||
FieldTrialsAllowedInScopeForTesting::~FieldTrialsAllowedInScopeForTesting() {
|
||||
TestKeys().clear();
|
||||
}
|
||||
|
||||
} // namespace field_trial
|
||||
} // namespace webrtc
|
||||
331
TMessagesProj/jni/voip/webrtc/system_wrappers/source/metrics.cc
Normal file
331
TMessagesProj/jni/voip/webrtc/system_wrappers/source/metrics.cc
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
//
|
||||
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "rtc_base/string_utils.h"
|
||||
#include "rtc_base/synchronization/mutex.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
|
||||
// Default implementation of histogram methods for WebRTC clients that do not
|
||||
// want to provide their own implementation.
|
||||
|
||||
namespace webrtc {
|
||||
namespace metrics {
|
||||
class Histogram;
|
||||
|
||||
namespace {
|
||||
// Limit for the maximum number of sample values that can be stored.
|
||||
// TODO(asapersson): Consider using bucket count (and set up
|
||||
// linearly/exponentially spaced buckets) if samples are logged more frequently.
|
||||
const int kMaxSampleMapSize = 300;
|
||||
|
||||
class RtcHistogram {
|
||||
public:
|
||||
RtcHistogram(absl::string_view name, int min, int max, int bucket_count)
|
||||
: min_(min), max_(max), info_(name, min, max, bucket_count) {
|
||||
RTC_DCHECK_GT(bucket_count, 0);
|
||||
}
|
||||
|
||||
RtcHistogram(const RtcHistogram&) = delete;
|
||||
RtcHistogram& operator=(const RtcHistogram&) = delete;
|
||||
|
||||
void Add(int sample) {
|
||||
sample = std::min(sample, max_);
|
||||
sample = std::max(sample, min_ - 1); // Underflow bucket.
|
||||
|
||||
MutexLock lock(&mutex_);
|
||||
if (info_.samples.size() == kMaxSampleMapSize &&
|
||||
info_.samples.find(sample) == info_.samples.end()) {
|
||||
return;
|
||||
}
|
||||
++info_.samples[sample];
|
||||
}
|
||||
|
||||
// Returns a copy (or nullptr if there are no samples) and clears samples.
|
||||
std::unique_ptr<SampleInfo> GetAndReset() {
|
||||
MutexLock lock(&mutex_);
|
||||
if (info_.samples.empty())
|
||||
return nullptr;
|
||||
|
||||
SampleInfo* copy =
|
||||
new SampleInfo(info_.name, info_.min, info_.max, info_.bucket_count);
|
||||
|
||||
std::swap(info_.samples, copy->samples);
|
||||
|
||||
return std::unique_ptr<SampleInfo>(copy);
|
||||
}
|
||||
|
||||
const std::string& name() const { return info_.name; }
|
||||
|
||||
// Functions only for testing.
|
||||
void Reset() {
|
||||
MutexLock lock(&mutex_);
|
||||
info_.samples.clear();
|
||||
}
|
||||
|
||||
int NumEvents(int sample) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto it = info_.samples.find(sample);
|
||||
return (it == info_.samples.end()) ? 0 : it->second;
|
||||
}
|
||||
|
||||
int NumSamples() const {
|
||||
int num_samples = 0;
|
||||
MutexLock lock(&mutex_);
|
||||
for (const auto& sample : info_.samples) {
|
||||
num_samples += sample.second;
|
||||
}
|
||||
return num_samples;
|
||||
}
|
||||
|
||||
int MinSample() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return (info_.samples.empty()) ? -1 : info_.samples.begin()->first;
|
||||
}
|
||||
|
||||
std::map<int, int> Samples() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return info_.samples;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable Mutex mutex_;
|
||||
const int min_;
|
||||
const int max_;
|
||||
SampleInfo info_ RTC_GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
class RtcHistogramMap {
|
||||
public:
|
||||
RtcHistogramMap() {}
|
||||
~RtcHistogramMap() {}
|
||||
|
||||
RtcHistogramMap(const RtcHistogramMap&) = delete;
|
||||
RtcHistogramMap& operator=(const RtcHistogramMap&) = delete;
|
||||
|
||||
Histogram* GetCountsHistogram(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
if (it != map_.end())
|
||||
return reinterpret_cast<Histogram*>(it->second.get());
|
||||
|
||||
RtcHistogram* hist = new RtcHistogram(name, min, max, bucket_count);
|
||||
map_.emplace(name, hist);
|
||||
return reinterpret_cast<Histogram*>(hist);
|
||||
}
|
||||
|
||||
Histogram* GetEnumerationHistogram(absl::string_view name, int boundary) {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
if (it != map_.end())
|
||||
return reinterpret_cast<Histogram*>(it->second.get());
|
||||
|
||||
RtcHistogram* hist = new RtcHistogram(name, 1, boundary, boundary + 1);
|
||||
map_.emplace(name, hist);
|
||||
return reinterpret_cast<Histogram*>(hist);
|
||||
}
|
||||
|
||||
void GetAndReset(std::map<std::string,
|
||||
std::unique_ptr<SampleInfo>,
|
||||
rtc::AbslStringViewCmp>* histograms) {
|
||||
MutexLock lock(&mutex_);
|
||||
for (const auto& kv : map_) {
|
||||
std::unique_ptr<SampleInfo> info = kv.second->GetAndReset();
|
||||
if (info)
|
||||
histograms->insert(std::make_pair(kv.first, std::move(info)));
|
||||
}
|
||||
}
|
||||
|
||||
// Functions only for testing.
|
||||
void Reset() {
|
||||
MutexLock lock(&mutex_);
|
||||
for (const auto& kv : map_)
|
||||
kv.second->Reset();
|
||||
}
|
||||
|
||||
int NumEvents(absl::string_view name, int sample) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? 0 : it->second->NumEvents(sample);
|
||||
}
|
||||
|
||||
int NumSamples(absl::string_view name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? 0 : it->second->NumSamples();
|
||||
}
|
||||
|
||||
int MinSample(absl::string_view name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? -1 : it->second->MinSample();
|
||||
}
|
||||
|
||||
std::map<int, int> Samples(absl::string_view name) const {
|
||||
MutexLock lock(&mutex_);
|
||||
const auto& it = map_.find(name);
|
||||
return (it == map_.end()) ? std::map<int, int>() : it->second->Samples();
|
||||
}
|
||||
|
||||
private:
|
||||
mutable Mutex mutex_;
|
||||
std::map<std::string, std::unique_ptr<RtcHistogram>, rtc::AbslStringViewCmp>
|
||||
map_ RTC_GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
// RtcHistogramMap is allocated upon call to Enable().
|
||||
// The histogram getter functions, which return pointer values to the histograms
|
||||
// in the map, are cached in WebRTC. Therefore, this memory is not freed by the
|
||||
// application (the memory will be reclaimed by the OS).
|
||||
static std::atomic<RtcHistogramMap*> g_rtc_histogram_map(nullptr);
|
||||
|
||||
void CreateMap() {
|
||||
RtcHistogramMap* map = g_rtc_histogram_map.load(std::memory_order_acquire);
|
||||
if (map == nullptr) {
|
||||
RtcHistogramMap* new_map = new RtcHistogramMap();
|
||||
if (!g_rtc_histogram_map.compare_exchange_strong(map, new_map))
|
||||
delete new_map;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the first time we start using histograms. Used to make sure Enable() is
|
||||
// not called thereafter.
|
||||
#if RTC_DCHECK_IS_ON
|
||||
static std::atomic<int> g_rtc_histogram_called(0);
|
||||
#endif
|
||||
|
||||
// Gets the map (or nullptr).
|
||||
RtcHistogramMap* GetMap() {
|
||||
#if RTC_DCHECK_IS_ON
|
||||
g_rtc_histogram_called.store(1, std::memory_order_release);
|
||||
#endif
|
||||
return g_rtc_histogram_map.load();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
#ifndef WEBRTC_EXCLUDE_METRICS_DEFAULT
|
||||
// Implementation of histogram methods in
|
||||
// webrtc/system_wrappers/interface/metrics.h.
|
||||
|
||||
// Histogram with exponentially spaced buckets.
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetCounts(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
// TODO(asapersson): Alternative implementation will be needed if this
|
||||
// histogram type should be truly exponential.
|
||||
return HistogramFactoryGetCountsLinear(name, min, max, bucket_count);
|
||||
}
|
||||
|
||||
// Histogram with linearly spaced buckets.
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetCountsLinear(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
int bucket_count) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (!map)
|
||||
return nullptr;
|
||||
|
||||
return map->GetCountsHistogram(name, min, max, bucket_count);
|
||||
}
|
||||
|
||||
// Histogram with linearly spaced buckets.
|
||||
// Creates (or finds) histogram.
|
||||
// The returned histogram pointer is cached (and used for adding samples in
|
||||
// subsequent calls).
|
||||
Histogram* HistogramFactoryGetEnumeration(absl::string_view name,
|
||||
int boundary) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (!map)
|
||||
return nullptr;
|
||||
|
||||
return map->GetEnumerationHistogram(name, boundary);
|
||||
}
|
||||
|
||||
// Our default implementation reuses the non-sparse histogram.
|
||||
Histogram* SparseHistogramFactoryGetEnumeration(absl::string_view name,
|
||||
int boundary) {
|
||||
return HistogramFactoryGetEnumeration(name, boundary);
|
||||
}
|
||||
|
||||
// Fast path. Adds `sample` to cached `histogram_pointer`.
|
||||
void HistogramAdd(Histogram* histogram_pointer, int sample) {
|
||||
RtcHistogram* ptr = reinterpret_cast<RtcHistogram*>(histogram_pointer);
|
||||
ptr->Add(sample);
|
||||
}
|
||||
|
||||
#endif // WEBRTC_EXCLUDE_METRICS_DEFAULT
|
||||
|
||||
SampleInfo::SampleInfo(absl::string_view name,
|
||||
int min,
|
||||
int max,
|
||||
size_t bucket_count)
|
||||
: name(name), min(min), max(max), bucket_count(bucket_count) {}
|
||||
|
||||
SampleInfo::~SampleInfo() {}
|
||||
|
||||
// Implementation of global functions in metrics.h.
|
||||
void Enable() {
|
||||
RTC_DCHECK(g_rtc_histogram_map.load() == nullptr);
|
||||
#if RTC_DCHECK_IS_ON
|
||||
RTC_DCHECK_EQ(0, g_rtc_histogram_called.load(std::memory_order_acquire));
|
||||
#endif
|
||||
CreateMap();
|
||||
}
|
||||
|
||||
void GetAndReset(
|
||||
std::map<std::string, std::unique_ptr<SampleInfo>, rtc::AbslStringViewCmp>*
|
||||
histograms) {
|
||||
histograms->clear();
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (map)
|
||||
map->GetAndReset(histograms);
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
if (map)
|
||||
map->Reset();
|
||||
}
|
||||
|
||||
int NumEvents(absl::string_view name, int sample) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->NumEvents(name, sample) : 0;
|
||||
}
|
||||
|
||||
int NumSamples(absl::string_view name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->NumSamples(name) : 0;
|
||||
}
|
||||
|
||||
int MinSample(absl::string_view name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->MinSample(name) : -1;
|
||||
}
|
||||
|
||||
std::map<int, int> Samples(absl::string_view name) {
|
||||
RtcHistogramMap* map = GetMap();
|
||||
return map ? map->Samples(name) : std::map<int, int>();
|
||||
}
|
||||
|
||||
} // namespace metrics
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "system_wrappers/include/rtp_to_ntp_estimator.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
// Maximum number of RTCP SR reports to use to map between RTP and NTP.
|
||||
constexpr size_t kNumRtcpReportsToUse = 20;
|
||||
// Don't allow NTP timestamps to jump more than 1 hour. Chosen arbitrary as big
|
||||
// enough to not affect normal use-cases. Yet it is smaller than RTP wrap-around
|
||||
// half-period (90khz RTP clock wrap-arounds every 13.25 hours). After half of
|
||||
// wrap-around period it is impossible to unwrap RTP timestamps correctly.
|
||||
constexpr uint64_t kMaxAllowedRtcpNtpInterval = uint64_t{60 * 60} << 32;
|
||||
} // namespace
|
||||
|
||||
void RtpToNtpEstimator::UpdateParameters() {
|
||||
size_t n = measurements_.size();
|
||||
if (n < 2)
|
||||
return;
|
||||
|
||||
// Run linear regression:
|
||||
// Given x[] and y[] writes out such k and b that line y=k*x+b approximates
|
||||
// given points in the best way (Least Squares Method).
|
||||
auto x = [](const RtcpMeasurement& m) {
|
||||
return static_cast<double>(m.unwrapped_rtp_timestamp);
|
||||
};
|
||||
auto y = [](const RtcpMeasurement& m) {
|
||||
return static_cast<double>(static_cast<uint64_t>(m.ntp_time));
|
||||
};
|
||||
|
||||
double avg_x = 0;
|
||||
double avg_y = 0;
|
||||
for (const RtcpMeasurement& m : measurements_) {
|
||||
avg_x += x(m);
|
||||
avg_y += y(m);
|
||||
}
|
||||
avg_x /= n;
|
||||
avg_y /= n;
|
||||
|
||||
double variance_x = 0;
|
||||
double covariance_xy = 0;
|
||||
for (const RtcpMeasurement& m : measurements_) {
|
||||
double normalized_x = x(m) - avg_x;
|
||||
double normalized_y = y(m) - avg_y;
|
||||
variance_x += normalized_x * normalized_x;
|
||||
covariance_xy += normalized_x * normalized_y;
|
||||
}
|
||||
|
||||
if (std::fabs(variance_x) < 1e-8)
|
||||
return;
|
||||
|
||||
double k = covariance_xy / variance_x;
|
||||
double b = avg_y - k * avg_x;
|
||||
params_ = {{.slope = k, .offset = b}};
|
||||
}
|
||||
|
||||
RtpToNtpEstimator::UpdateResult RtpToNtpEstimator::UpdateMeasurements(
|
||||
NtpTime ntp,
|
||||
uint32_t rtp_timestamp) {
|
||||
int64_t unwrapped_rtp_timestamp = unwrapper_.Unwrap(rtp_timestamp);
|
||||
|
||||
RtcpMeasurement new_measurement = {
|
||||
.ntp_time = ntp, .unwrapped_rtp_timestamp = unwrapped_rtp_timestamp};
|
||||
|
||||
for (const RtcpMeasurement& measurement : measurements_) {
|
||||
// Use || since two equal timestamps will result in zero frequency.
|
||||
if (measurement.ntp_time == ntp ||
|
||||
measurement.unwrapped_rtp_timestamp == unwrapped_rtp_timestamp) {
|
||||
return kSameMeasurement;
|
||||
}
|
||||
}
|
||||
|
||||
if (!new_measurement.ntp_time.Valid())
|
||||
return kInvalidMeasurement;
|
||||
|
||||
uint64_t ntp_new = static_cast<uint64_t>(new_measurement.ntp_time);
|
||||
bool invalid_sample = false;
|
||||
if (!measurements_.empty()) {
|
||||
int64_t old_rtp_timestamp = measurements_.front().unwrapped_rtp_timestamp;
|
||||
uint64_t old_ntp = static_cast<uint64_t>(measurements_.front().ntp_time);
|
||||
if (ntp_new <= old_ntp || ntp_new > old_ntp + kMaxAllowedRtcpNtpInterval) {
|
||||
invalid_sample = true;
|
||||
} else if (unwrapped_rtp_timestamp <= old_rtp_timestamp) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "Newer RTCP SR report with older RTP timestamp, dropping";
|
||||
invalid_sample = true;
|
||||
} else if (unwrapped_rtp_timestamp - old_rtp_timestamp > (1 << 25)) {
|
||||
// Sanity check. No jumps too far into the future in rtp.
|
||||
invalid_sample = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalid_sample) {
|
||||
++consecutive_invalid_samples_;
|
||||
if (consecutive_invalid_samples_ < kMaxInvalidSamples) {
|
||||
return kInvalidMeasurement;
|
||||
}
|
||||
RTC_LOG(LS_WARNING) << "Multiple consecutively invalid RTCP SR reports, "
|
||||
"clearing measurements.";
|
||||
measurements_.clear();
|
||||
params_ = absl::nullopt;
|
||||
}
|
||||
consecutive_invalid_samples_ = 0;
|
||||
|
||||
// Insert new RTCP SR report.
|
||||
if (measurements_.size() == kNumRtcpReportsToUse)
|
||||
measurements_.pop_back();
|
||||
|
||||
measurements_.push_front(new_measurement);
|
||||
|
||||
// List updated, calculate new parameters.
|
||||
UpdateParameters();
|
||||
return kNewMeasurement;
|
||||
}
|
||||
|
||||
NtpTime RtpToNtpEstimator::Estimate(uint32_t rtp_timestamp) const {
|
||||
if (!params_)
|
||||
return NtpTime();
|
||||
|
||||
double estimated =
|
||||
static_cast<double>(unwrapper_.Unwrap(rtp_timestamp)) * params_->slope +
|
||||
params_->offset + 0.5f;
|
||||
|
||||
return NtpTime(rtc::saturated_cast<uint64_t>(estimated));
|
||||
}
|
||||
|
||||
double RtpToNtpEstimator::EstimatedFrequencyKhz() const {
|
||||
if (!params_.has_value()) {
|
||||
return 0.0;
|
||||
}
|
||||
static constexpr double kNtpUnitPerMs = 4.294967296E6; // 2^32 / 1000.
|
||||
return kNtpUnitPerMs / params_->slope;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
// An OS-independent sleep function.
|
||||
|
||||
#include "system_wrappers/include/sleep.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
// For Sleep()
|
||||
#include <windows.h>
|
||||
#else
|
||||
// For nanosleep()
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
void SleepMs(int msecs) {
|
||||
#ifdef _WIN32
|
||||
Sleep(msecs);
|
||||
#else
|
||||
struct timespec short_wait;
|
||||
struct timespec remainder;
|
||||
short_wait.tv_sec = msecs / 1000;
|
||||
short_wait.tv_nsec = (msecs % 1000) * 1000 * 1000;
|
||||
nanosleep(&short_wait, &remainder);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
Loading…
Add table
Add a link
Reference in a new issue