#include "api/rtc_event_log/rtc_event_log.h"
+#include <memory>
+
+#include "logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h"
+
namespace webrtc {
+void RtcEventLog::LogRtpPacket(const RtpPacketReceived& packet) {
+ Log(std::make_unique<RtcEventRtpPacketIncoming>(packet));
+}
+
bool RtcEventLogNull::StartLogging(
std::unique_ptr<RtcEventLogOutput> /*output*/,
int64_t /*output_period_ms*/) {
namespace webrtc {
+class RtpPacketReceived;
+
class RtcEventLog {
public:
enum : size_t { kUnlimitedOutput = 0 };
// Log an RTC event (the type of event is determined by the subclass).
virtual void Log(std::unique_ptr<RtcEvent> event) = 0;
+
+ virtual void LogRtpPacket(const RtpPacketReceived& packet);
};
// No-op implementation is used if flag is not set, or in tests.
int64_t output_period_ms) override;
void StopLogging() override {}
void Log(std::unique_ptr<RtcEvent> event) override {}
+ void LogRtpPacket(const RtpPacketReceived& packet) override {}
};
} // namespace webrtc
// TODO(bugs.webrtc.org/11993): Expect to be called exclusively on the
// network thread. Once that's done, the same applies to
// UpdatePlayoutTimestamp and
- int64_t now_ms = rtc::TimeMillis();
+ Timestamp now = (!packet.receive_time().IsMinusInfinity()
+ ? packet.receive_time()
+ : Timestamp::Micros(rtc::TimeMicros()));
+ int64_t now_ms = now.ms();
last_received_rtp_timestamp_ = packet.Timestamp();
last_received_rtp_system_time_ms_ = now_ms;
// Interpolates absolute capture timestamp RTP header extension.
header.extension.absolute_capture_time =
absolute_capture_time_interpolator_.OnReceivePacket(
+ now,
AbsoluteCaptureTimeInterpolator::GetSource(header.ssrc,
header.arrOfCSRCs),
header.timestamp,
~ReceiveStats();
void AddReceivedRtcpBytes(int bytes);
- void AddReceivedAudioBytes(int bytes, webrtc::Timestamp arrival_time);
- void AddReceivedVideoBytes(int bytes, webrtc::Timestamp arrival_time);
+ void AddReceivedAudioBytes(int bytes,
+ webrtc::Timestamp now,
+ webrtc::Timestamp arrival_time);
+ void AddReceivedVideoBytes(int bytes,
+ webrtc::Timestamp now,
+ webrtc::Timestamp arrival_time);
private:
RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_;
absl::string_view sync_group) RTC_RUN_ON(worker_thread_);
void ConfigureSync(absl::string_view sync_group) RTC_RUN_ON(worker_thread_);
- void NotifyBweOfReceivedPacket(const RtpPacketReceived& packet,
+ void NotifyBweOfReceivedPacket(Timestamp now,
+ const RtpPacketReceived& packet,
MediaType media_type)
RTC_RUN_ON(worker_thread_);
}
void Call::ReceiveStats::AddReceivedAudioBytes(int bytes,
+ webrtc::Timestamp now,
webrtc::Timestamp arrival_time) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
- received_bytes_per_second_counter_.Add(bytes);
- received_audio_bytes_per_second_counter_.Add(bytes);
+ received_bytes_per_second_counter_.Add(now, bytes);
+ received_audio_bytes_per_second_counter_.Add(now, bytes);
if (!first_received_rtp_audio_timestamp_)
first_received_rtp_audio_timestamp_ = arrival_time;
last_received_rtp_audio_timestamp_ = arrival_time;
}
void Call::ReceiveStats::AddReceivedVideoBytes(int bytes,
+ webrtc::Timestamp now,
webrtc::Timestamp arrival_time) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
- received_bytes_per_second_counter_.Add(bytes);
- received_video_bytes_per_second_counter_.Add(bytes);
+ received_bytes_per_second_counter_.Add(now, bytes);
+ received_video_bytes_per_second_counter_.Add(now, bytes);
if (!first_received_rtp_video_timestamp_)
first_received_rtp_video_timestamp_ = arrival_time;
last_received_rtp_video_timestamp_ = arrival_time;
RTC_DCHECK_RUN_ON(worker_thread_);
RTC_DCHECK(packet.arrival_time().IsFinite());
+ Timestamp now = clock_->CurrentTime();
if (receive_time_calculator_) {
int64_t packet_time_us = packet.arrival_time().us();
// Repair packet_time_us for clock resets by comparing a new read of
// the same clock (TimeUTCMicros) to a monotonic clock reading.
packet_time_us = receive_time_calculator_->ReconcileReceiveTimes(
- packet_time_us, rtc::TimeUTCMicros(), clock_->TimeInMicroseconds());
+ packet_time_us, rtc::TimeUTCMicros(), now.us());
packet.set_arrival_time(Timestamp::Micros(packet_time_us));
}
+ packet.set_receive_time(now);
- NotifyBweOfReceivedPacket(packet, media_type);
+ NotifyBweOfReceivedPacket(now, packet, media_type);
- event_log_->Log(std::make_unique<RtcEventRtpPacketIncoming>(packet));
+ event_log_->LogRtpPacket(packet);
if (media_type != MediaType::AUDIO && media_type != MediaType::VIDEO) {
return;
}
// instead of converting each time it is passed to RateCounter::Add below.
int length = static_cast<int>(packet.size());
if (media_type == MediaType::AUDIO) {
- receive_stats_.AddReceivedAudioBytes(length, packet.arrival_time());
+ receive_stats_.AddReceivedAudioBytes(length, now, packet.arrival_time());
}
if (media_type == MediaType::VIDEO) {
- receive_stats_.AddReceivedVideoBytes(length, packet.arrival_time());
+ receive_stats_.AddReceivedVideoBytes(length, now, packet.arrival_time());
}
}
-void Call::NotifyBweOfReceivedPacket(const RtpPacketReceived& packet,
+void Call::NotifyBweOfReceivedPacket(Timestamp now,
+ const RtpPacketReceived& packet,
MediaType media_type) {
RTC_DCHECK_RUN_ON(worker_thread_);
}
transport_send_->OnReceivedPacket(packet_msg);
- receive_side_cc_.OnReceivedPacket(packet, media_type);
+ receive_side_cc_.OnReceivedPacket(now, packet, media_type);
}
} // namespace internal
media_packet.SetPayloadType(it->second);
media_packet.set_recovered(true);
media_packet.set_arrival_time(rtx_packet.arrival_time());
+ media_packet.set_receive_time(rtx_packet.receive_time());
// Skip the RTX header.
rtc::ArrayView<const uint8_t> rtx_payload = payload.subview(kRtxHeaderSize);
~ReceiveSideCongestionController() override {}
- void OnReceivedPacket(const RtpPacketReceived& packet, MediaType media_type);
+ void OnReceivedPacket(Timestamp now,
+ const RtpPacketReceived& packet,
+ MediaType media_type);
// Implements CallStatsObserver.
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
packets_since_absolute_send_time_(0) {}
void ReceiveSideCongestionController::OnReceivedPacket(
+ Timestamp now,
const RtpPacketReceived& packet,
MediaType media_type) {
bool has_transport_sequence_number =
// Receive-side BWE.
MutexLock lock(&mutex_);
PickEstimator(packet.HasExtension<AbsoluteSendTime>());
- rbe_->IncomingPacket(packet);
+ rbe_->IncomingPacket(now, packet);
}
}
Timestamp now = clock_.CurrentTime();
packet.SetExtension<AbsoluteSendTime>(AbsoluteSendTime::To24Bits(now));
packet.set_arrival_time(now);
- controller.OnReceivedPacket(packet, MediaType::VIDEO);
+ controller.OnReceivedPacket(now, packet, MediaType::VIDEO);
}
}
#include <cstdint>
#include <vector>
+#include "absl/types/optional.h"
#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "modules/include/module_common_types.h"
// Called for each incoming packet. Updates the incoming payload bitrate
// estimate and the over-use detector. If an over-use is detected the
// remote bitrate estimate will be updated.
- virtual void IncomingPacket(const RtpPacketReceived& rtp_packet) = 0;
+ virtual void IncomingPacket(absl::optional<Timestamp> now,
+ const RtpPacketReceived& rtp_packet) = 0;
// Removes all data for `ssrc`.
virtual void RemoveStream(uint32_t ssrc) = 0;
}
void RemoteBitrateEstimatorAbsSendTime::IncomingPacket(
+ absl::optional<Timestamp> now_cached,
const RtpPacketReceived& rtp_packet) {
uint32_t send_time_24bits;
if (!rtp_packet.GetExtension<AbsoluteSendTime>(&send_time_24bits)) {
Timestamp send_time =
Timestamp::Millis(static_cast<int64_t>(timestamp) * kTimestampToMs);
- Timestamp now = clock_->CurrentTime();
+ Timestamp now = (now_cached ? *now_cached : clock_->CurrentTime());
// TODO(holmer): SSRCs are only needed for REMB, should be broken out from
// here.
~RemoteBitrateEstimatorAbsSendTime() override;
- void IncomingPacket(const RtpPacketReceived& rtp_packet) override;
+ void IncomingPacket(absl::optional<Timestamp> now,
+ const RtpPacketReceived& rtp_packet) override;
TimeDelta Process() override;
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
void RemoveStream(uint32_t ssrc) override;
default;
void RemoteBitrateEstimatorSingleStream::IncomingPacket(
+ absl::optional<Timestamp> now_cached,
const RtpPacketReceived& rtp_packet) {
absl::optional<int32_t> transmission_time_offset =
rtp_packet.GetExtension<TransmissionOffset>();
uint32_t ssrc = rtp_packet.Ssrc();
uint32_t rtp_timestamp =
rtp_packet.Timestamp() + transmission_time_offset.value_or(0);
- Timestamp now = clock_->CurrentTime();
+ Timestamp now = (now_cached ? *now_cached : clock_->CurrentTime());
Detector& estimator = overuse_detectors_[ssrc];
estimator.last_packet_time = now;
~RemoteBitrateEstimatorSingleStream() override;
- void IncomingPacket(const RtpPacketReceived& rtp_packet) override;
+ void IncomingPacket(absl::optional<Timestamp> now,
+ const RtpPacketReceived& rtp_packet) override;
TimeDelta Process() override;
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
void RemoveStream(uint32_t ssrc) override;
rtp_packet.set_arrival_time(
Timestamp::Millis(arrival_time + arrival_time_offset_ms_));
- bitrate_estimator_->IncomingPacket(rtp_packet);
+ bitrate_estimator_->IncomingPacket(absl::nullopt, rtp_packet);
}
// Generates a frame of packets belonging to a stream at a given bitrate and
uint32_t rtp_timestamp,
int rtp_clock_frequency_hz,
const absl::optional<AbsoluteCaptureTime>& received_extension) {
- const Timestamp receive_time = clock_->CurrentTime();
+ return OnReceivePacket(clock_->CurrentTime(), source, rtp_timestamp,
+ rtp_clock_frequency_hz, received_extension);
+}
+absl::optional<AbsoluteCaptureTime>
+AbsoluteCaptureTimeInterpolator::OnReceivePacket(
+ Timestamp receive_time,
+ uint32_t source,
+ uint32_t rtp_timestamp,
+ uint32_t rtp_clock_frequency_hz,
+ const absl::optional<AbsoluteCaptureTime>& received_extension) {
MutexLock lock(&mutex_);
if (received_extension == absl::nullopt) {
uint32_t rtp_timestamp,
int rtp_clock_frequency_hz,
const absl::optional<AbsoluteCaptureTime>& received_extension);
+ absl::optional<AbsoluteCaptureTime> OnReceivePacket(
+ Timestamp receive_time,
+ uint32_t source,
+ uint32_t rtp_timestamp,
+ uint32_t rtp_clock_frequency,
+ const absl::optional<AbsoluteCaptureTime>& received_extension);
private:
friend class AbsoluteCaptureTimeSender;
void StreamStatisticianImpl::UpdateCounters(const RtpPacketReceived& packet) {
RTC_DCHECK_EQ(ssrc_, packet.Ssrc());
- Timestamp now = clock_->CurrentTime();
+ Timestamp now =
+ (!packet.receive_time().IsMinusInfinity() ? packet.receive_time()
+ : clock_->CurrentTime());
incoming_bitrate_.Update(packet.size(), now);
receive_counters_.transmitted.AddPacket(packet);
RtpPacketReceived& RtpPacketReceived::operator=(RtpPacketReceived&& packet) =
default;
-RtpPacketReceived::~RtpPacketReceived() {}
+RtpPacketReceived::~RtpPacketReceived() = default;
void RtpPacketReceived::GetHeader(RTPHeader* header) const {
header->markerBit = Marker();
webrtc::Timestamp arrival_time() const { return arrival_time_; }
void set_arrival_time(webrtc::Timestamp time) { arrival_time_ = time; }
+ // arrival_time() can use non-monotonic clock, this one uses monotonic clock
+ webrtc::Timestamp receive_time() const { return receive_time_; }
+ void set_receive_time(webrtc::Timestamp time) { receive_time_ = time; }
+
// Flag if packet was recovered via RTX or FEC.
bool recovered() const { return recovered_; }
void set_recovered(bool value) { recovered_ = value; }
private:
webrtc::Timestamp arrival_time_ = Timestamp::MinusInfinity();
+ webrtc::Timestamp receive_time_ = Timestamp::MinusInfinity();
int payload_type_frequency_ = 0;
bool recovered_ = false;
rtc::scoped_refptr<rtc::RefCountedBase> additional_data_;
#include "rtc_base/string_utils.h"
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/third_party/base64/base64.h"
+#include "rtc_base/time_utils.h"
namespace cricket {
namespace {
if (!port_->GetStunMessage(data, size, addr, &msg, &remote_ufrag)) {
// The packet did not parse as a valid STUN message
// This is a data packet, pass it along.
- last_data_received_ = rtc::TimeMillis();
+ last_data_received_ =
+ (packet_time_us > 0 ? packet_time_us / rtc::kNumMicrosecsPerMillisec
+ : rtc::TimeMillis());
UpdateReceiving(last_data_received_);
- recv_rate_tracker_.AddSamples(size);
+ recv_rate_tracker_.AddSamplesAtTime(last_data_received_, size);
stats_.packets_received++;
if (received_packet_callback_) {
RTC_DCHECK(packet_time_us == -1 || packet_time_us >= 0);
namespace rtc {
+// For WEBRTC_TIZEN_TV implemented directly in
+// `third_party/webrtc/rtc_base/time_utils.cc`. See comments there why.
+#if !defined(WEBRTC_TIZEN_TV)
+
int64_t SystemTimeNanos() {
int64_t ticks;
#if defined(WEBRTC_MAC)
return ticks;
}
+#endif
+
} // namespace rtc
#endif // WEBRTC_EXCLUDE_SYSTEM_TIME
void Thread::Dispatch(absl::AnyInvocable<void() &&> task) {
TRACE_EVENT0("webrtc", "Thread::Dispatch");
RTC_DCHECK_RUN_ON(this);
+#if !defined(WEBRTC_TIZEN_TV)
int64_t start_time = TimeMillis();
+#endif
std::move(task)();
+#if !defined(WEBRTC_TIZEN_TV)
int64_t end_time = TimeMillis();
int64_t diff = TimeDiff(end_time, start_time);
if (diff >= dispatch_warning_ms_) {
// for delays that are larger than the one observed.
dispatch_warning_ms_ = diff + 1;
}
+#endif
}
bool Thread::IsCurrent() const {
#endif // defined(WINUWP)
+#if defined(WEBRTC_TIZEN_TV)
+// For WEBRTC_TIZEN_TV `SystemTimeNanos()` calls
+// `base::TimeTicks::Now()` from chromium, which uses calls
+// `clock_gettime(CLOCK_MONOTONIC, ...)` and converts result to microseconds
+// held in `int64_t` variable. This variable is then converted to
+// nanoseconds (== * 1000) and then this value is converted to desired
+// precision. So implementing this call directly for desired time unit
+// saves at least one multiplication and one integer division
+// (which on ARM EABI may be expensive).
+
+int64_t SystemTimeNanos() {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ int64_t nsec = ts.tv_sec;
+ nsec *= kNumNanosecsPerSec;
+ nsec += ts.tv_nsec;
+ return nsec;
+}
+
+int64_t SystemTimeMicros() {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ int64_t nsec = ts.tv_sec;
+ nsec *= kNumMicrosecsPerSec;
+ nsec += ts.tv_nsec / kNumNanosecsPerMicrosec;
+ return nsec;
+}
+
+int64_t SystemTimeMillis() {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ int64_t nsec = ts.tv_sec;
+ nsec *= kNumMillisecsPerSec;
+ nsec += ts.tv_nsec / kNumNanosecsPerMillisec;
+ return nsec;
+}
+
+int64_t TimeNanos() {
+#if WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS
+ if (g_clock) {
+ return g_clock->TimeNanos();
+ }
+#endif
+
+ return SystemTimeNanos();
+}
+
+uint32_t Time32() {
+#if WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS
+ if (g_clock) {
+ return static_cast<uint32_t>(g_clock->TimeNanos() /
+ kNumNanosecsPerMillisec);
+ }
+#endif
+
+ return static_cast<uint32_t>(SystemTimeMillis());
+}
+
+int64_t TimeMillis() {
+#if WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS
+ if (g_clock) {
+ return g_clock->TimeNanos() / kNumNanosecsPerMillisec;
+ }
+#endif
+
+ return SystemTimeMillis();
+}
+
+int64_t TimeMicros() {
+#if WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS
+ if (g_clock) {
+ return g_clock->TimeNanos() / kNumNanosecsPerMicrosec;
+ }
+#endif
+
+ return SystemTimeMicros();
+}
+
+#else
int64_t SystemTimeMillis() {
return static_cast<int64_t>(SystemTimeNanos() / kNumNanosecsPerMillisec);
}
int64_t TimeMicros() {
return TimeNanos() / kNumNanosecsPerMicrosec;
}
+#endif
int64_t TimeAfter(int64_t elapsed) {
RTC_DCHECK_GE(elapsed, 0);
namespace rtc {
-static const int64_t kNumMillisecsPerSec = INT64_C(1000);
-static const int64_t kNumMicrosecsPerSec = INT64_C(1000000);
-static const int64_t kNumNanosecsPerSec = INT64_C(1000000000);
+static constexpr int64_t kNumMillisecsPerSec = INT64_C(1000);
+static constexpr int64_t kNumMicrosecsPerSec = INT64_C(1000000);
+static constexpr int64_t kNumNanosecsPerSec = INT64_C(1000000000);
-static const int64_t kNumMicrosecsPerMillisec =
+static constexpr int64_t kNumMicrosecsPerMillisec =
kNumMicrosecsPerSec / kNumMillisecsPerSec;
-static const int64_t kNumNanosecsPerMillisec =
+static constexpr int64_t kNumNanosecsPerMillisec =
kNumNanosecsPerSec / kNumMillisecsPerSec;
-static const int64_t kNumNanosecsPerMicrosec =
+static constexpr int64_t kNumNanosecsPerMicrosec =
kNumNanosecsPerSec / kNumMicrosecsPerSec;
// Elapsed milliseconds between NTP base, 1900 January 1 00:00 GMT
auto packet =
std::make_unique<video_coding::PacketBuffer::Packet>(rtp_packet, video);
+ Timestamp receive_time =
+ (!rtp_packet.receive_time().IsMinusInfinity() ? rtp_packet.receive_time()
+ : clock_->CurrentTime());
packet->packet_info = RtpPacketInfo(
rtp_packet.Ssrc(), rtp_packet.Csrcs(), rtp_packet.Timestamp(),
- /*receive_time_ms=*/clock_->CurrentTime());
+ /*receive_time_ms=*/receive_time);
auto& packet_info = packet->packet_info;
// Try to extrapolate absolute capture time if it is missing.
packet_info.set_absolute_capture_time(
absolute_capture_time_interpolator_.OnReceivePacket(
+ receive_time,
AbsoluteCaptureTimeInterpolator::GetSource(packet_info.ssrc(),
packet_info.csrcs()),
packet_info.rtp_timestamp(),
void RtpVideoStreamReceiver2::UpdatePacketReceiveTimestamps(
const RtpPacketReceived& packet,
bool is_keyframe) {
- Timestamp now = clock_->CurrentTime();
+ Timestamp now =
+ (!packet.receive_time().IsMinusInfinity() ? packet.receive_time()
+ : clock_->CurrentTime());
if (is_keyframe ||
last_received_keyframe_rtp_timestamp_ == packet.Timestamp()) {
last_received_keyframe_rtp_timestamp_ = packet.Timestamp();
AggregatedStats StatsCounter::ProcessAndGetStats() {
if (HasSample())
- TryProcess();
+ TryProcess(clock_->CurrentTime());
return aggregated_counter_->ComputeStats();
}
void StatsCounter::ProcessAndPause() {
if (HasSample())
- TryProcess();
+ TryProcess(clock_->CurrentTime());
paused_ = true;
pause_time_ms_ = clock_->TimeInMilliseconds();
}
void StatsCounter::ProcessAndStopPause() {
if (HasSample())
- TryProcess();
+ TryProcess(clock_->CurrentTime());
Resume();
}
return last_process_time_ms_ != -1;
}
-bool StatsCounter::TimeToProcess(int* elapsed_intervals) {
- int64_t now = clock_->TimeInMilliseconds();
+bool StatsCounter::TimeToProcess(Timestamp now_ts, int* elapsed_intervals) {
+ int64_t now = now_ts.ms(); // clock_->TimeInMilliseconds();
if (last_process_time_ms_ == -1)
last_process_time_ms_ = now;
}
void StatsCounter::Add(int sample) {
- TryProcess();
+ Add(clock_->CurrentTime(), sample);
+}
+
+void StatsCounter::Add(Timestamp now, int sample) {
+ TryProcess(now);
samples_->Add(sample, kStreamId0);
- ResumeIfMinTimePassed();
+ ResumeIfMinTimePassed(now);
}
void StatsCounter::Set(int64_t sample, uint32_t stream_id) {
// Do not add same sample while paused (will reset pause).
return;
}
- TryProcess();
+ Timestamp now = clock_->CurrentTime();
+ TryProcess(now);
samples_->Set(sample, stream_id);
- ResumeIfMinTimePassed();
+ ResumeIfMinTimePassed(now);
}
void StatsCounter::SetLast(int64_t sample, uint32_t stream_id) {
}
}
-void StatsCounter::TryProcess() {
+void StatsCounter::TryProcess(Timestamp now) {
int elapsed_intervals;
- if (!TimeToProcess(&elapsed_intervals))
+ if (!TimeToProcess(now, &elapsed_intervals))
return;
// Get and report periodically computed metric.
bool StatsCounter::IncludeEmptyIntervals() const {
return include_empty_intervals_ && !paused_ && !aggregated_counter_->Empty();
}
-void StatsCounter::ResumeIfMinTimePassed() {
- if (paused_ &&
- (clock_->TimeInMilliseconds() - pause_time_ms_) >= min_pause_time_ms_) {
+void StatsCounter::ResumeIfMinTimePassed(Timestamp now) {
+ if (paused_ && (now.ms() - pause_time_ms_) >= min_pause_time_ms_) {
Resume();
}
}
StatsCounter::Add(sample);
}
+void RateCounter::Add(Timestamp now, int sample) {
+ StatsCounter::Add(now, sample);
+}
+
bool RateCounter::GetMetric(int* metric) const {
if (samples_->Empty())
return false;
#include <memory>
#include <string>
+#include "api/units/timestamp.h"
+
namespace webrtc {
class AggregatedCounter;
StatsCounterObserver* observer);
void Add(int sample);
+ void Add(Timestamp now, int sample);
void Set(int64_t sample, uint32_t stream_id);
void SetLast(int64_t sample, uint32_t stream_id);
const std::unique_ptr<Samples> samples_;
private:
- bool TimeToProcess(int* num_elapsed_intervals);
- void TryProcess();
+ bool TimeToProcess(Timestamp now, int* num_elapsed_intervals);
+ void TryProcess(Timestamp now);
void ReportMetricToAggregatedCounter(int value, int num_values_to_add) const;
bool IncludeEmptyIntervals() const;
void Resume();
- void ResumeIfMinTimePassed();
+ void ResumeIfMinTimePassed(Timestamp now);
Clock* const clock_;
const std::unique_ptr<StatsCounterObserver> observer_;
RateCounter& operator=(const RateCounter&) = delete;
void Add(int sample);
+ void Add(Timestamp now, int sample);
private:
bool GetMetric(int* metric) const override;
namespace rtc {
+// For Tizen TV profile this is implemented directly in
+// `third_party/webrtc/rtc_base/time_utils.cc`. See comments there why.
+#if !BUILDFLAG(IS_TIZEN_TV)
int64_t SystemTimeNanos() {
return (base::TimeTicks::Now() - base::TimeTicks()).InNanoseconds();
}
+#endif
} // namespace rtc