/* * Copyright (c) 2017 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 "api/video/video_timing.h" #include #include #include #include "api/array_view.h" #include "api/units/time_delta.h" #include "rtc_base/logging.h" #include "rtc_base/numerics/safe_conversions.h" #include "rtc_base/strings/string_builder.h" namespace webrtc { uint16_t VideoSendTiming::GetDeltaCappedMs(int64_t base_ms, int64_t time_ms) { if (time_ms < base_ms) { RTC_DLOG(LS_ERROR) << "Delta " << (time_ms - base_ms) << "ms expected to be positive"; } return rtc::saturated_cast(time_ms - base_ms); } uint16_t VideoSendTiming::GetDeltaCappedMs(TimeDelta delta) { if (delta < TimeDelta::Zero()) { RTC_DLOG(LS_ERROR) << "Delta " << delta.ms() << "ms expected to be positive"; } return rtc::saturated_cast(delta.ms()); } TimingFrameInfo::TimingFrameInfo() : rtp_timestamp(0), capture_time_ms(-1), encode_start_ms(-1), encode_finish_ms(-1), packetization_finish_ms(-1), pacer_exit_ms(-1), network_timestamp_ms(-1), network2_timestamp_ms(-1), receive_start_ms(-1), receive_finish_ms(-1), decode_start_ms(-1), decode_finish_ms(-1), render_time_ms(-1), flags(VideoSendTiming::kNotTriggered) {} int64_t TimingFrameInfo::EndToEndDelay() const { return capture_time_ms >= 0 ? decode_finish_ms - capture_time_ms : -1; } bool TimingFrameInfo::IsLongerThan(const TimingFrameInfo& other) const { int64_t other_delay = other.EndToEndDelay(); return other_delay == -1 || EndToEndDelay() > other_delay; } bool TimingFrameInfo::operator<(const TimingFrameInfo& other) const { return other.IsLongerThan(*this); } bool TimingFrameInfo::operator<=(const TimingFrameInfo& other) const { return !IsLongerThan(other); } bool TimingFrameInfo::IsOutlier() const { return !IsInvalid() && (flags & VideoSendTiming::kTriggeredBySize); } bool TimingFrameInfo::IsTimerTriggered() const { return !IsInvalid() && (flags & VideoSendTiming::kTriggeredByTimer); } bool TimingFrameInfo::IsInvalid() const { return flags == VideoSendTiming::kInvalid; } std::string TimingFrameInfo::ToString() const { if (IsInvalid()) { return ""; } char buf[1024]; rtc::SimpleStringBuilder sb(buf); sb << rtp_timestamp << ',' << capture_time_ms << ',' << encode_start_ms << ',' << encode_finish_ms << ',' << packetization_finish_ms << ',' << pacer_exit_ms << ',' << network_timestamp_ms << ',' << network2_timestamp_ms << ',' << receive_start_ms << ',' << receive_finish_ms << ',' << decode_start_ms << ',' << decode_finish_ms << ',' << render_time_ms << ',' << IsOutlier() << ',' << IsTimerTriggered(); return sb.str(); } VideoPlayoutDelay::VideoPlayoutDelay(TimeDelta min, TimeDelta max) : min_(std::clamp(min, TimeDelta::Zero(), kMax)), max_(std::clamp(max, min_, kMax)) { if (!(TimeDelta::Zero() <= min && min <= max && max <= kMax)) { RTC_LOG(LS_ERROR) << "Invalid video playout delay: [" << min << "," << max << "]. Clamped to [" << this->min() << "," << this->max() << "]"; } } bool VideoPlayoutDelay::Set(TimeDelta min, TimeDelta max) { if (TimeDelta::Zero() <= min && min <= max && max <= kMax) { min_ = min; max_ = max; return true; } return false; } } // namespace webrtc