Added receive time calculator under field trial.
The receive time calculator combines the packet time stamps received from the socket interface with the system clock used in WebRTC. This means that the packet timestamps are set in the WebRTC clock timebase and that large jumps in the time stamps from the socket will not affect the reported receive time stamps. Bug: None Change-Id: I293925c41919829524a115bb9377027bf0a797fb Reviewed-on: https://webrtc-review.googlesource.com/61862 Reviewed-by: Niels Moller <nisse@webrtc.org> Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org> Commit-Queue: Sebastian Jansson <srte@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22540}
This commit is contained in:
parent
763e947cf3
commit
b34556e598
@ -147,6 +147,8 @@ rtc_static_library("call") {
|
|||||||
"degraded_call.h",
|
"degraded_call.h",
|
||||||
"flexfec_receive_stream_impl.cc",
|
"flexfec_receive_stream_impl.cc",
|
||||||
"flexfec_receive_stream_impl.h",
|
"flexfec_receive_stream_impl.h",
|
||||||
|
"receive_time_calculator.cc",
|
||||||
|
"receive_time_calculator.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
if (!build_with_chromium && is_clang) {
|
if (!build_with_chromium && is_clang) {
|
||||||
@ -249,6 +251,7 @@ if (rtc_include_tests) {
|
|||||||
"bitrate_estimator_tests.cc",
|
"bitrate_estimator_tests.cc",
|
||||||
"call_unittest.cc",
|
"call_unittest.cc",
|
||||||
"flexfec_receive_stream_unittest.cc",
|
"flexfec_receive_stream_unittest.cc",
|
||||||
|
"receive_time_calculator_unittest.cc",
|
||||||
"rtcp_demuxer_unittest.cc",
|
"rtcp_demuxer_unittest.cc",
|
||||||
"rtp_bitrate_configurator_unittest.cc",
|
"rtp_bitrate_configurator_unittest.cc",
|
||||||
"rtp_demuxer_unittest.cc",
|
"rtp_demuxer_unittest.cc",
|
||||||
|
|||||||
12
call/call.cc
12
call/call.cc
@ -24,6 +24,7 @@
|
|||||||
#include "call/bitrate_allocator.h"
|
#include "call/bitrate_allocator.h"
|
||||||
#include "call/call.h"
|
#include "call/call.h"
|
||||||
#include "call/flexfec_receive_stream_impl.h"
|
#include "call/flexfec_receive_stream_impl.h"
|
||||||
|
#include "call/receive_time_calculator.h"
|
||||||
#include "call/rtp_stream_receiver_controller.h"
|
#include "call/rtp_stream_receiver_controller.h"
|
||||||
#include "call/rtp_transport_controller_send.h"
|
#include "call/rtp_transport_controller_send.h"
|
||||||
#include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
|
#include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
|
||||||
@ -362,6 +363,9 @@ class Call : public webrtc::Call,
|
|||||||
RateLimiter retransmission_rate_limiter_;
|
RateLimiter retransmission_rate_limiter_;
|
||||||
std::unique_ptr<RtpTransportControllerSendInterface> transport_send_;
|
std::unique_ptr<RtpTransportControllerSendInterface> transport_send_;
|
||||||
ReceiveSideCongestionController receive_side_cc_;
|
ReceiveSideCongestionController receive_side_cc_;
|
||||||
|
|
||||||
|
const std::unique_ptr<ReceiveTimeCalculator> receive_time_calculator_;
|
||||||
|
|
||||||
const std::unique_ptr<SendDelayStats> video_send_delay_stats_;
|
const std::unique_ptr<SendDelayStats> video_send_delay_stats_;
|
||||||
const int64_t start_ms_;
|
const int64_t start_ms_;
|
||||||
// TODO(perkj): |worker_queue_| is supposed to replace
|
// TODO(perkj): |worker_queue_| is supposed to replace
|
||||||
@ -436,6 +440,7 @@ Call::Call(const Call::Config& config,
|
|||||||
pacer_bitrate_kbps_counter_(clock_, nullptr, true),
|
pacer_bitrate_kbps_counter_(clock_, nullptr, true),
|
||||||
retransmission_rate_limiter_(clock_, kRetransmitWindowSizeMs),
|
retransmission_rate_limiter_(clock_, kRetransmitWindowSizeMs),
|
||||||
receive_side_cc_(clock_, transport_send->packet_router()),
|
receive_side_cc_(clock_, transport_send->packet_router()),
|
||||||
|
receive_time_calculator_(ReceiveTimeCalculator::CreateFromFieldTrial()),
|
||||||
video_send_delay_stats_(new SendDelayStats(clock_)),
|
video_send_delay_stats_(new SendDelayStats(clock_)),
|
||||||
start_ms_(clock_->TimeInMilliseconds()),
|
start_ms_(clock_->TimeInMilliseconds()),
|
||||||
worker_queue_("call_worker_queue") {
|
worker_queue_("call_worker_queue") {
|
||||||
@ -1227,7 +1232,12 @@ PacketReceiver::DeliveryStatus Call::DeliverRtp(MediaType media_type,
|
|||||||
return DELIVERY_PACKET_ERROR;
|
return DELIVERY_PACKET_ERROR;
|
||||||
|
|
||||||
if (packet_time.timestamp != -1) {
|
if (packet_time.timestamp != -1) {
|
||||||
parsed_packet.set_arrival_time_ms((packet_time.timestamp + 500) / 1000);
|
int64_t timestamp_us = packet_time.timestamp;
|
||||||
|
if (receive_time_calculator_) {
|
||||||
|
timestamp_us = receive_time_calculator_->ReconcileReceiveTimes(
|
||||||
|
packet_time.timestamp, clock_->TimeInMicroseconds());
|
||||||
|
}
|
||||||
|
parsed_packet.set_arrival_time_ms((timestamp_us + 500) / 1000);
|
||||||
} else {
|
} else {
|
||||||
parsed_packet.set_arrival_time_ms(clock_->TimeInMilliseconds());
|
parsed_packet.set_arrival_time_ms(clock_->TimeInMilliseconds());
|
||||||
}
|
}
|
||||||
|
|||||||
67
call/receive_time_calculator.cc
Normal file
67
call/receive_time_calculator.cc
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 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 "call/receive_time_calculator.h"
|
||||||
|
#include "rtc_base/logging.h"
|
||||||
|
#include "rtc_base/ptr_util.h"
|
||||||
|
#include "system_wrappers/include/field_trial.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
using ::webrtc::field_trial::FindFullName;
|
||||||
|
using ::webrtc::field_trial::IsEnabled;
|
||||||
|
|
||||||
|
const char kBweReceiveTimeCorrection[] = "WebRTC-BweReceiveTimeCorrection";
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
ReceiveTimeCalculator::ReceiveTimeCalculator(int64_t min_delta_ms,
|
||||||
|
int64_t max_delta_diff_ms)
|
||||||
|
: min_delta_us_(min_delta_ms * 1000),
|
||||||
|
max_delta_diff_us_(max_delta_diff_ms * 1000) {}
|
||||||
|
|
||||||
|
std::unique_ptr<ReceiveTimeCalculator>
|
||||||
|
ReceiveTimeCalculator::CreateFromFieldTrial() {
|
||||||
|
if (!IsEnabled(kBweReceiveTimeCorrection))
|
||||||
|
return nullptr;
|
||||||
|
int min, max;
|
||||||
|
if (sscanf(FindFullName(kBweReceiveTimeCorrection).c_str(), "Enabled/%d,%d",
|
||||||
|
&min, &max) != 2) {
|
||||||
|
RTC_LOG(LS_WARNING) << "Invalid number of parameters provided.";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return rtc::MakeUnique<ReceiveTimeCalculator>(min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t ReceiveTimeCalculator::ReconcileReceiveTimes(int64_t packet_time_us_,
|
||||||
|
int64_t safe_time_us_) {
|
||||||
|
if (!receive_time_offset_us_) {
|
||||||
|
receive_time_offset_us_ = safe_time_us_ - packet_time_us_;
|
||||||
|
} else {
|
||||||
|
int64_t safe_delta_us = safe_time_us_ - last_safe_time_us_;
|
||||||
|
int64_t packet_delta_us_ = packet_time_us_ - last_packet_time_us_;
|
||||||
|
int64_t delta_diff = packet_delta_us_ - safe_delta_us;
|
||||||
|
// Packet time should not decrease significantly, a large decrease indicates
|
||||||
|
// a reset of the packet time clock and we should reset the offest
|
||||||
|
// parameter. The safe reference time can increase in large jumps if the
|
||||||
|
// thread measuring it is backgrounded for longer periods. But if the packet
|
||||||
|
// time increases significantly more than the safe time, it indicates a
|
||||||
|
// clock reset and we should reset the offset.
|
||||||
|
|
||||||
|
if (packet_delta_us_ < min_delta_us_ || delta_diff > max_delta_diff_us_) {
|
||||||
|
RTC_LOG(LS_WARNING) << "Received a clock jump of " << delta_diff
|
||||||
|
<< " resetting offset";
|
||||||
|
receive_time_offset_us_ = safe_time_us_ - packet_time_us_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_packet_time_us_ = packet_time_us_;
|
||||||
|
last_safe_time_us_ = safe_time_us_;
|
||||||
|
return packet_time_us_ + *receive_time_offset_us_;
|
||||||
|
}
|
||||||
|
} // namespace webrtc
|
||||||
47
call/receive_time_calculator.h
Normal file
47
call/receive_time_calculator.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 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 CALL_RECEIVE_TIME_CALCULATOR_H_
|
||||||
|
#define CALL_RECEIVE_TIME_CALCULATOR_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "api/optional.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// The receive time calculator serves the purpose of combining packet time
|
||||||
|
// stamps with a safely incremental clock. This assumes that the packet time
|
||||||
|
// stamps are based on lower layer timestamps that have more accurate time
|
||||||
|
// increments since they are based on the exact receive time. They might
|
||||||
|
// however, have large jumps due to clock resets in the system. To compensate
|
||||||
|
// this they are combined with a safe clock source that is guaranteed to be
|
||||||
|
// consistent, but it will not be able to measure the exact time when a packet
|
||||||
|
// is received.
|
||||||
|
class ReceiveTimeCalculator {
|
||||||
|
public:
|
||||||
|
static std::unique_ptr<ReceiveTimeCalculator> CreateFromFieldTrial();
|
||||||
|
// The min delta is used to correct for jumps backwards in time, to allow some
|
||||||
|
// packet reordering a small negative value is appropriate to use. The max
|
||||||
|
// delta difference is used as margin when detecting when packet time
|
||||||
|
// increases more than the safe clock. This should be larger than the largest
|
||||||
|
// expected sysmtem induced delay in the safe clock timestamp.
|
||||||
|
ReceiveTimeCalculator(int64_t min_delta_ms, int64_t max_delta_diff_ms);
|
||||||
|
int64_t ReconcileReceiveTimes(int64_t packet_time_us_, int64_t safe_time_us_);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int64_t min_delta_us_;
|
||||||
|
const int64_t max_delta_diff_us_;
|
||||||
|
rtc::Optional<int64_t> receive_time_offset_us_;
|
||||||
|
int64_t last_packet_time_us_ = 0;
|
||||||
|
int64_t last_safe_time_us_ = 0;
|
||||||
|
};
|
||||||
|
} // namespace webrtc
|
||||||
|
#endif // CALL_RECEIVE_TIME_CALCULATOR_H_
|
||||||
74
call/receive_time_calculator_unittest.cc
Normal file
74
call/receive_time_calculator_unittest.cc
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 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 "call/receive_time_calculator.h"
|
||||||
|
|
||||||
|
#include "test/gtest.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace test {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
int64_t ReconcileMs(ReceiveTimeCalculator* calc,
|
||||||
|
int64_t packet_time_ms,
|
||||||
|
int64_t safe_time_ms) {
|
||||||
|
return calc->ReconcileReceiveTimes(packet_time_ms * 1000,
|
||||||
|
safe_time_ms * 1000) /
|
||||||
|
1000;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST(ReceiveTimeCalculatorTest, UsesSmallerIncrements) {
|
||||||
|
int64_t kMinDeltaMs = -20;
|
||||||
|
int64_t kMaxDeltaDiffMs = 100;
|
||||||
|
ReceiveTimeCalculator calc(kMinDeltaMs, kMaxDeltaDiffMs);
|
||||||
|
// Initialize offset.
|
||||||
|
ReconcileMs(&calc, 10000, 20000);
|
||||||
|
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10010, 20100), 20010);
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10020, 20100), 20020);
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10030, 20100), 20030);
|
||||||
|
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10110, 20200), 20110);
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10120, 20200), 20120);
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10130, 20200), 20130);
|
||||||
|
|
||||||
|
// Small jumps backwards are let trough, they might be due to reordering.
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10120, 20200), 20120);
|
||||||
|
// The safe clock might be smaller than the packet clock.
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10210, 20200), 20210);
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10240, 20200), 20240);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ReceiveTimeCalculatorTest, CorrectsJumps) {
|
||||||
|
int64_t kMinDeltaMs = -20;
|
||||||
|
int64_t kMaxDeltaDiffMs = 100;
|
||||||
|
ReceiveTimeCalculator calc(kMinDeltaMs, kMaxDeltaDiffMs);
|
||||||
|
// Initialize offset.
|
||||||
|
ReconcileMs(&calc, 10000, 20000);
|
||||||
|
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10010, 20100), 20010);
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10020, 20100), 20020);
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10030, 20100), 20030);
|
||||||
|
|
||||||
|
// Jump forward in time.
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10240, 20200), 20200);
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10250, 20200), 20210);
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10260, 20200), 20220);
|
||||||
|
|
||||||
|
// Jump backward in time.
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10230, 20300), 20300);
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10240, 20300), 20310);
|
||||||
|
EXPECT_EQ(ReconcileMs(&calc, 10250, 20300), 20320);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace test
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
Loading…
x
Reference in New Issue
Block a user