Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit 72df795

Browse files
committed
Add clock sync module for per-frame delay calculation.
1 parent deef390 commit 72df795

File tree

8 files changed

+137
-20
lines changed

8 files changed

+137
-20
lines changed

api/video/encoded_image.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,14 @@ class RTC_EXPORT EncodedImage {
184184
int64_t receive_finish_ms = 0;
185185
} timing_;
186186

187+
#if defined(WEBRTC_WIN)
188+
struct BWEStats {
189+
double start_duration_ = 0;
190+
double last_duration_ = 0;
191+
int32_t packets_lost_ = 0;
192+
}bwe_stats_;
193+
#endif
194+
187195
private:
188196
size_t capacity() const {
189197
return buffer_ ? capacity_ : (encoded_data_ ? encoded_data_->size() : 0);

modules/video_coding/frame_object.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,15 @@ class RtpFrameObject : public EncodedFrame {
4949
const RTPVideoHeader& GetRtpVideoHeader() const;
5050

5151
uint8_t* mutable_data() { return image_buffer_->data(); }
52-
52+
#if defined(WEBRTC_WIN)
53+
void SetBWETiming(double start_duration,
54+
double last_duration,
55+
int32_t packets_lost) {
56+
bwe_stats_.start_duration_ = start_duration;
57+
bwe_stats_.last_duration_ = last_duration;
58+
bwe_stats_.packets_lost_ = packets_lost;
59+
}
60+
#endif
5361
private:
5462
// Reference for mutable access.
5563
rtc::scoped_refptr<EncodedImageBuffer> image_buffer_;

modules/video_coding/packet_buffer.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ PacketBuffer::InsertResult PacketBuffer::InsertPacket(
9999

100100
first_seq_num_ = seq_num;
101101
}
102-
102+
#if defined(WEBRTC_WIN)
103+
QueryPerformanceCounter((LARGE_INTEGER*)&packet->time_ticks);
104+
#endif
103105
if (buffer_[index] != nullptr) {
104106
// Duplicate packet, just delete the payload.
105107
if (buffer_[index]->seq_num == packet->seq_num) {

modules/video_coding/packet_buffer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ class PacketBuffer {
7070
RTPVideoHeader video_header;
7171

7272
RtpPacketInfo packet_info;
73+
#if defined(WEBRTC_WIN)
74+
int64_t time_ticks;
75+
#endif
7376
};
7477
struct InsertResult {
7578
std::vector<std::unique_ptr<Packet>> packets;

rtc_base/time/BUILD.gn

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,8 @@ rtc_library("timestamp_extrapolator") {
1717
"timestamp_extrapolator.cc",
1818
"timestamp_extrapolator.h",
1919
]
20+
21+
if(is_win) {
22+
sources += [ "ptp_clock_sync.h" ]
23+
}
2024
}

rtc_base/time/ptp_clock_sync.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (C) <2021> Intel Corporation
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#ifndef RTC_BASE_TIME_PTP_CLOCK_SYNC_H_
6+
#define RTC_BASE_TIME_PTP_CLOCK_SYNC_H_
7+
8+
#include <windows.h>
9+
#include <cstdint>
10+
11+
#define MICROSECONDS_FACTOR 1000000.0
12+
#define OFFSET_FACTOR 200000
13+
#define SERVER_FREQUENCY 0.09 // RTP/NTP timestamp runs at 90KHz clock
14+
15+
// A Windows implementation for PTP using timestamp from RTP and local
16+
// timestamp. We may need to implement something like QueryPerformanceFrequency
17+
// for this to work on Linux platforms.
18+
namespace webrtc {
19+
class PTPClockSync {
20+
public:
21+
PTPClockSync()
22+
: m_server_point(0), m_server_freq(0), m_client_point(0), m_last_ts(0) {
23+
uint64_t freq; // Performance counter frequency in a second.
24+
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
25+
m_client_freq = (double)freq / MICROSECONDS_FACTOR;
26+
m_server_freq = SERVER_FREQUENCY;
27+
}
28+
~PTPClockSync() {}
29+
30+
void Sync(uint32_t ts, uint64_t tc) {
31+
if (GetDuration(ts, tc) < 0 ||
32+
(ts - m_last_ts) > OFFSET_FACTOR * m_server_freq) {
33+
UpdateSync(ts, tc);
34+
}
35+
m_last_ts = ts;
36+
}
37+
38+
double GetDuration(uint32_t ts, uint64_t tc) {
39+
int ds = (int)(ts - m_server_point);
40+
int dc = (int)(tc - m_client_point);
41+
return (double)dc / m_client_freq - (double)ds / m_server_freq;
42+
}
43+
44+
protected:
45+
uint32_t m_server_point;
46+
double m_server_freq; // count per us
47+
uint64_t m_client_point;
48+
double m_client_freq; // count per us
49+
uint32_t m_last_ts;
50+
51+
void UpdateSync(uint32_t ts, uint64_t tc) {
52+
m_client_point = tc;
53+
m_server_point = ts;
54+
}
55+
};
56+
} // namespace webrtc
57+
#endif

video/rtp_video_stream_receiver2.cc

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,11 @@ void RtpVideoStreamReceiver2::OnInsertedPacket(
729729
std::vector<rtc::ArrayView<const uint8_t>> payloads;
730730
RtpPacketInfos::vector_type packet_infos;
731731

732+
// Add timing information required by sender-side BWE.
733+
#if defined(WEBRTC_WIN)
734+
int64_t max_tc = 0, min_tc = 0;
735+
double start_duration = 0, last_duration = 0;
736+
#endif
732737
bool frame_boundary = true;
733738
for (auto& packet : result.packets) {
734739
// PacketBuffer promisses frame boundaries are correctly set on each
@@ -741,18 +746,30 @@ void RtpVideoStreamReceiver2::OnInsertedPacket(
741746
max_recv_time = packet->packet_info.receive_time_ms();
742747
payloads.clear();
743748
packet_infos.clear();
749+
#if defined(WEBRTC_WIN)
750+
max_tc = min_tc = packet->time_ticks;
751+
#endif
744752
} else {
745753
max_nack_count = std::max(max_nack_count, packet->times_nacked);
746754
min_recv_time =
747755
std::min(min_recv_time, packet->packet_info.receive_time_ms());
748756
max_recv_time =
749757
std::max(max_recv_time, packet->packet_info.receive_time_ms());
758+
#if defined(WEBRTC_WIN)
759+
max_tc = std::max(max_tc, packet->time_ticks);
760+
min_tc = std::min(min_tc, packet->time_ticks);
761+
#endif
750762
}
751763
payloads.emplace_back(packet->video_payload);
752764
packet_infos.push_back(packet->packet_info);
753765

754766
frame_boundary = packet->is_last_packet_in_frame();
755767
if (packet->is_last_packet_in_frame()) {
768+
#if defined(WEBRTC_WIN)
769+
clock_sync_.Sync(packet->timestamp, min_tc);
770+
start_duration = clock_sync_.GetDuration(packet->timestamp, min_tc);
771+
last_duration = clock_sync_.GetDuration(packet->timestamp, max_tc);
772+
#endif
756773
auto depacketizer_it = payload_type_map_.find(first_packet->payload_type);
757774
RTC_CHECK(depacketizer_it != payload_type_map_.end());
758775

@@ -764,25 +781,37 @@ void RtpVideoStreamReceiver2::OnInsertedPacket(
764781
}
765782

766783
const video_coding::PacketBuffer::Packet& last_packet = *packet;
767-
OnAssembledFrame(std::make_unique<video_coding::RtpFrameObject>(
768-
first_packet->seq_num, //
769-
last_packet.seq_num, //
770-
last_packet.marker_bit, //
771-
max_nack_count, //
772-
min_recv_time, //
773-
max_recv_time, //
774-
first_packet->timestamp, //
775-
first_packet->ntp_time_ms, //
776-
last_packet.video_header.video_timing, //
777-
first_packet->payload_type, //
778-
first_packet->codec(), //
779-
last_packet.video_header.rotation, //
780-
last_packet.video_header.content_type, //
781-
first_packet->video_header, //
782-
last_packet.video_header.color_space, //
783-
RtpPacketInfos(std::move(packet_infos)), //
784-
std::move(bitstream)));
784+
std::unique_ptr<video_coding::RtpFrameObject> frame =
785+
std::make_unique<video_coding::RtpFrameObject>(
786+
first_packet->seq_num, //
787+
last_packet.seq_num, //
788+
last_packet.marker_bit, //
789+
max_nack_count, //
790+
min_recv_time, //
791+
max_recv_time, //
792+
first_packet->timestamp, //
793+
first_packet->ntp_time_ms, //
794+
last_packet.video_header.video_timing, //
795+
first_packet->payload_type, //
796+
first_packet->codec(), //
797+
last_packet.video_header.rotation, //
798+
last_packet.video_header.content_type, //
799+
first_packet->video_header, //
800+
last_packet.video_header.color_space, //
801+
RtpPacketInfos(std::move(packet_infos)), //
802+
std::move(bitstream));
803+
#if defined(WEBRTC_WIN)
804+
StreamStatistician* ss =
805+
rtp_receive_statistics_->GetStatistician(config_.rtp.remote_ssrc);
806+
int32_t packets_lost = 0;
807+
if (ss != nullptr) {
808+
packets_lost = ss->GetStats().packets_lost;
809+
frame->SetBWETiming(start_duration, last_duration, packets_lost);
810+
}
811+
#endif
812+
OnAssembledFrame(std::move(frame));
785813
}
814+
786815
}
787816
RTC_DCHECK(frame_boundary);
788817
if (result.buffer_cleared) {

video/rtp_video_stream_receiver2.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
#include "rtc_base/constructor_magic.h"
4343
#include "rtc_base/experiments/field_trial_parser.h"
4444
#include "rtc_base/numerics/sequence_number_util.h"
45+
#if defined(WEBRTC_WIN)
46+
#include "rtc_base/time/ptp_clock_sync.h"
47+
#endif
4548
#include "rtc_base/synchronization/sequence_checker.h"
4649
#include "rtc_base/thread_annotations.h"
4750
#include "video/buffered_frame_decryptor.h"
@@ -271,6 +274,9 @@ class RtpVideoStreamReceiver2 : public LossNotificationSender,
271274
void OnAssembledFrame(std::unique_ptr<video_coding::RtpFrameObject> frame);
272275

273276
Clock* const clock_;
277+
#if defined(WEBRTC_WIN)
278+
PTPClockSync clock_sync_;
279+
#endif
274280
// Ownership of this object lies with VideoReceiveStream, which owns |this|.
275281
const VideoReceiveStream::Config& config_;
276282
PacketRouter* const packet_router_;

0 commit comments

Comments
 (0)