mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 12:15:34 +08:00
[feat] move rtp packet sender out of channel module
This commit is contained in:
@@ -44,9 +44,9 @@ void AudioChannelSend::Destroy() {
|
|||||||
|
|
||||||
int AudioChannelSend::SendAudio(char *data, size_t size) {
|
int AudioChannelSend::SendAudio(char *data, size_t size) {
|
||||||
if (rtp_audio_sender_ && rtp_packetizer_) {
|
if (rtp_audio_sender_ && rtp_packetizer_) {
|
||||||
std::vector<std::shared_ptr<RtpPacket>> rtp_packets =
|
std::vector<std::unique_ptr<RtpPacket>> rtp_packets =
|
||||||
rtp_packetizer_->Build((uint8_t *)data, (uint32_t)size, 0, true);
|
rtp_packetizer_->Build((uint8_t *)data, (uint32_t)size, 0, true);
|
||||||
rtp_audio_sender_->Enqueue(rtp_packets);
|
rtp_audio_sender_->Enqueue(std::move(rtp_packets));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ void DataChannelSend::Destroy() {
|
|||||||
|
|
||||||
int DataChannelSend::SendData(const char *data, size_t size) {
|
int DataChannelSend::SendData(const char *data, size_t size) {
|
||||||
if (rtp_data_sender_ && rtp_packetizer_) {
|
if (rtp_data_sender_ && rtp_packetizer_) {
|
||||||
std::vector<std::shared_ptr<RtpPacket>> rtp_packets =
|
std::vector<std::unique_ptr<RtpPacket>> rtp_packets =
|
||||||
rtp_packetizer_->Build((uint8_t *)data, (uint32_t)size, 0, true);
|
rtp_packetizer_->Build((uint8_t *)data, (uint32_t)size, 0, true);
|
||||||
rtp_data_sender_->Enqueue(rtp_packets);
|
rtp_data_sender_->Enqueue(std::move(rtp_packets));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -48,6 +48,21 @@ void VideoChannelSend::Initialize(rtp::PAYLOAD_TYPE payload_type) {
|
|||||||
rtp_video_sender_->Start();
|
rtp_video_sender_->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoChannelSend::SetEnqueuePacketsFunc(
|
||||||
|
std::function<void(std::vector<std::unique_ptr<webrtc::RtpPacketToSend>>&)>
|
||||||
|
enqueue_packets_func) {
|
||||||
|
rtp_video_sender_->SetEnqueuePacketsFunc(enqueue_packets_func);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<RtpPacket>> VideoChannelSend::GeneratePadding(
|
||||||
|
uint32_t payload_size, int64_t capture_timestamp_ms) {
|
||||||
|
if (rtp_packetizer_) {
|
||||||
|
return rtp_packetizer_->BuildPadding(payload_size, capture_timestamp_ms,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
return std::vector<std::unique_ptr<RtpPacket>>{};
|
||||||
|
}
|
||||||
|
|
||||||
void VideoChannelSend::Destroy() {
|
void VideoChannelSend::Destroy() {
|
||||||
if (rtp_video_sender_) {
|
if (rtp_video_sender_) {
|
||||||
rtp_video_sender_->Stop();
|
rtp_video_sender_->Stop();
|
||||||
@@ -57,11 +72,12 @@ void VideoChannelSend::Destroy() {
|
|||||||
int VideoChannelSend::SendVideo(
|
int VideoChannelSend::SendVideo(
|
||||||
std::shared_ptr<VideoFrameWrapper> encoded_frame) {
|
std::shared_ptr<VideoFrameWrapper> encoded_frame) {
|
||||||
if (rtp_video_sender_ && rtp_packetizer_) {
|
if (rtp_video_sender_ && rtp_packetizer_) {
|
||||||
std::vector<std::shared_ptr<RtpPacket>> rtp_packets =
|
std::vector<std::unique_ptr<RtpPacket>> rtp_packets =
|
||||||
rtp_packetizer_->Build((uint8_t*)encoded_frame->Buffer(),
|
rtp_packetizer_->Build((uint8_t*)encoded_frame->Buffer(),
|
||||||
(uint32_t)encoded_frame->Size(),
|
(uint32_t)encoded_frame->Size(),
|
||||||
encoded_frame->CaptureTimestamp(), true);
|
encoded_frame->CaptureTimestamp(), true);
|
||||||
rtp_video_sender_->Enqueue(rtp_packets, encoded_frame->CaptureTimestamp());
|
rtp_video_sender_->Enqueue(std::move(rtp_packets),
|
||||||
|
encoded_frame->CaptureTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -28,6 +28,14 @@ class VideoChannelSend {
|
|||||||
on_sent_packet_func_);
|
on_sent_packet_func_);
|
||||||
~VideoChannelSend();
|
~VideoChannelSend();
|
||||||
|
|
||||||
|
void SetEnqueuePacketsFunc(
|
||||||
|
std::function<
|
||||||
|
void(std::vector<std::unique_ptr<webrtc::RtpPacketToSend>>&)>
|
||||||
|
enqueue_packets_func);
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<RtpPacket>> GeneratePadding(
|
||||||
|
uint32_t payload_size, int64_t capture_timestamp_ms);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Initialize(rtp::PAYLOAD_TYPE payload_type);
|
void Initialize(rtp::PAYLOAD_TYPE payload_type);
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ RtpAudioSender::~RtpAudioSender() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RtpAudioSender::Enqueue(
|
void RtpAudioSender::Enqueue(
|
||||||
std::vector<std::shared_ptr<RtpPacket>> rtp_packets) {
|
std::vector<std::unique_ptr<RtpPacket>> rtp_packets) {
|
||||||
if (!rtp_statistics_) {
|
if (!rtp_statistics_) {
|
||||||
rtp_statistics_ = std::make_unique<RtpStatistics>();
|
rtp_statistics_ = std::make_unique<RtpStatistics>();
|
||||||
rtp_statistics_->Start();
|
rtp_statistics_->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& rtp_packet : rtp_packets) {
|
for (auto& rtp_packet : rtp_packets) {
|
||||||
rtp_packet_queue_.push(rtp_packet);
|
rtp_packet_queue_.push(std::move(rtp_packet));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ void RtpAudioSender::SetSendDataFunc(
|
|||||||
data_send_func_ = data_send_func;
|
data_send_func_ = data_send_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RtpAudioSender::SendRtpPacket(std::shared_ptr<RtpPacket> rtp_packet) {
|
int RtpAudioSender::SendRtpPacket(std::unique_ptr<RtpPacket> rtp_packet) {
|
||||||
if (!data_send_func_) {
|
if (!data_send_func_) {
|
||||||
LOG_ERROR("data_send_func_ is nullptr");
|
LOG_ERROR("data_send_func_ is nullptr");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -141,9 +141,11 @@ bool RtpAudioSender::Process() {
|
|||||||
|
|
||||||
for (size_t i = 0; i < 10; i++)
|
for (size_t i = 0; i < 10; i++)
|
||||||
if (!rtp_packet_queue_.isEmpty()) {
|
if (!rtp_packet_queue_.isEmpty()) {
|
||||||
std::shared_ptr<RtpPacket> rtp_packet;
|
std::optional<std::unique_ptr<RtpPacket>> rtp_packet =
|
||||||
rtp_packet_queue_.pop(rtp_packet);
|
rtp_packet_queue_.pop();
|
||||||
SendRtpPacket(rtp_packet);
|
if (rtp_packet) {
|
||||||
|
SendRtpPacket(std::move(*rtp_packet));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtp_statistics_) {
|
if (rtp_statistics_) {
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ class RtpAudioSender : public ThreadBase {
|
|||||||
virtual ~RtpAudioSender();
|
virtual ~RtpAudioSender();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Enqueue(std::vector<std::shared_ptr<RtpPacket>> rtp_packets);
|
void Enqueue(std::vector<std::unique_ptr<RtpPacket>> rtp_packets);
|
||||||
void SetSendDataFunc(std::function<int(const char *, size_t)> data_send_func);
|
void SetSendDataFunc(std::function<int(const char *, size_t)> data_send_func);
|
||||||
uint32_t GetSsrc() { return ssrc_; }
|
uint32_t GetSsrc() { return ssrc_; }
|
||||||
void OnReceiverReport(const ReceiverReport &receiver_report) {}
|
void OnReceiverReport(const ReceiverReport &receiver_report) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int SendRtpPacket(std::shared_ptr<RtpPacket> rtp_packet);
|
int SendRtpPacket(std::unique_ptr<RtpPacket> rtp_packet);
|
||||||
int SendRtcpSR(SenderReport &rtcp_sr);
|
int SendRtcpSR(SenderReport &rtcp_sr);
|
||||||
|
|
||||||
bool CheckIsTimeSendSR();
|
bool CheckIsTimeSendSR();
|
||||||
@@ -40,7 +40,7 @@ class RtpAudioSender : public ThreadBase {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::function<int(const char *, size_t)> data_send_func_ = nullptr;
|
std::function<int(const char *, size_t)> data_send_func_ = nullptr;
|
||||||
RingBuffer<std::shared_ptr<RtpPacket>> rtp_packet_queue_;
|
RingBuffer<std::unique_ptr<RtpPacket>> rtp_packet_queue_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t ssrc_ = 0;
|
uint32_t ssrc_ = 0;
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ RtpDataSender::~RtpDataSender() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RtpDataSender::Enqueue(
|
void RtpDataSender::Enqueue(
|
||||||
std::vector<std::shared_ptr<RtpPacket>> rtp_packets) {
|
std::vector<std::unique_ptr<RtpPacket>> rtp_packets) {
|
||||||
if (!rtp_statistics_) {
|
if (!rtp_statistics_) {
|
||||||
rtp_statistics_ = std::make_unique<RtpStatistics>();
|
rtp_statistics_ = std::make_unique<RtpStatistics>();
|
||||||
rtp_statistics_->Start();
|
rtp_statistics_->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& rtp_packet : rtp_packets) {
|
for (auto& rtp_packet : rtp_packets) {
|
||||||
rtp_packet_queue_.push(rtp_packet);
|
rtp_packet_queue_.push(std::move(rtp_packet));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ void RtpDataSender::SetSendDataFunc(
|
|||||||
data_send_func_ = data_send_func;
|
data_send_func_ = data_send_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RtpDataSender::SendRtpPacket(std::shared_ptr<RtpPacket> rtp_packet) {
|
int RtpDataSender::SendRtpPacket(std::unique_ptr<RtpPacket> rtp_packet) {
|
||||||
if (!data_send_func_) {
|
if (!data_send_func_) {
|
||||||
LOG_ERROR("data_send_func_ is nullptr");
|
LOG_ERROR("data_send_func_ is nullptr");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -141,9 +141,11 @@ bool RtpDataSender::Process() {
|
|||||||
|
|
||||||
for (size_t i = 0; i < 10; i++)
|
for (size_t i = 0; i < 10; i++)
|
||||||
if (!rtp_packet_queue_.isEmpty()) {
|
if (!rtp_packet_queue_.isEmpty()) {
|
||||||
std::shared_ptr<RtpPacket> rtp_packet;
|
std::optional<std::unique_ptr<RtpPacket>> rtp_packet =
|
||||||
rtp_packet_queue_.pop(rtp_packet);
|
rtp_packet_queue_.pop();
|
||||||
SendRtpPacket(rtp_packet);
|
if (rtp_packet) {
|
||||||
|
SendRtpPacket(std::move(*rtp_packet));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtp_statistics_) {
|
if (rtp_statistics_) {
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ class RtpDataSender : public ThreadBase {
|
|||||||
virtual ~RtpDataSender();
|
virtual ~RtpDataSender();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Enqueue(std::vector<std::shared_ptr<RtpPacket>> rtp_packets);
|
void Enqueue(std::vector<std::unique_ptr<RtpPacket>> rtp_packets);
|
||||||
void SetSendDataFunc(std::function<int(const char *, size_t)> data_send_func);
|
void SetSendDataFunc(std::function<int(const char *, size_t)> data_send_func);
|
||||||
uint32_t GetSsrc() { return ssrc_; }
|
uint32_t GetSsrc() { return ssrc_; }
|
||||||
void OnReceiverReport(const ReceiverReport &receiver_report) {}
|
void OnReceiverReport(const ReceiverReport &receiver_report) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
private:
|
private:
|
||||||
int SendRtpPacket(std::shared_ptr<RtpPacket> rtp_packet);
|
int SendRtpPacket(std::unique_ptr<RtpPacket> rtp_packet);
|
||||||
int SendRtcpSR(SenderReport &rtcp_sr);
|
int SendRtcpSR(SenderReport &rtcp_sr);
|
||||||
|
|
||||||
bool CheckIsTimeSendSR();
|
bool CheckIsTimeSendSR();
|
||||||
@@ -41,7 +41,7 @@ class RtpDataSender : public ThreadBase {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::function<int(const char *, size_t)> data_send_func_ = nullptr;
|
std::function<int(const char *, size_t)> data_send_func_ = nullptr;
|
||||||
RingBuffer<std::shared_ptr<RtpPacket>> rtp_packet_queue_;
|
RingBuffer<std::unique_ptr<RtpPacket>> rtp_packet_queue_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t ssrc_ = 0;
|
uint32_t ssrc_ = 0;
|
||||||
|
|||||||
@@ -532,9 +532,8 @@ bool RtpVideoReceiver::CheckIsTimeSendRR() {
|
|||||||
|
|
||||||
bool RtpVideoReceiver::Process() {
|
bool RtpVideoReceiver::Process() {
|
||||||
if (!compelete_video_frame_queue_.isEmpty()) {
|
if (!compelete_video_frame_queue_.isEmpty()) {
|
||||||
VideoFrame video_frame;
|
std::optional<VideoFrame> video_frame = compelete_video_frame_queue_.pop();
|
||||||
compelete_video_frame_queue_.pop(video_frame);
|
if (on_receive_complete_frame_ && video_frame) {
|
||||||
if (on_receive_complete_frame_) {
|
|
||||||
// auto now_complete_frame_ts =
|
// auto now_complete_frame_ts =
|
||||||
// std::chrono::duration_cast<std::chrono::milliseconds>(
|
// std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
// std::chrono::system_clock::now().time_since_epoch())
|
// std::chrono::system_clock::now().time_since_epoch())
|
||||||
@@ -543,7 +542,7 @@ bool RtpVideoReceiver::Process() {
|
|||||||
// LOG_ERROR("Duration {}", duration);
|
// LOG_ERROR("Duration {}", duration);
|
||||||
// last_complete_frame_ts_ = now_complete_frame_ts;
|
// last_complete_frame_ts_ = now_complete_frame_ts;
|
||||||
|
|
||||||
on_receive_complete_frame_(video_frame);
|
on_receive_complete_frame_(*video_frame);
|
||||||
// #ifdef SAVE_RTP_RECV_STREAM
|
// #ifdef SAVE_RTP_RECV_STREAM
|
||||||
// fwrite((unsigned char*)video_frame.Buffer(), 1,
|
// fwrite((unsigned char*)video_frame.Buffer(), 1,
|
||||||
// video_frame.Size(),
|
// video_frame.Size(),
|
||||||
|
|||||||
@@ -44,22 +44,26 @@ RtpVideoSender::~RtpVideoSender() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RtpVideoSender::Enqueue(
|
void RtpVideoSender::Enqueue(
|
||||||
std::vector<std::shared_ptr<RtpPacket>>& rtp_packets,
|
std::vector<std::unique_ptr<RtpPacket>>& rtp_packets,
|
||||||
int64_t capture_timestamp_ms) {
|
int64_t capture_timestamp_ms) {
|
||||||
if (!rtp_statistics_) {
|
if (!rtp_statistics_) {
|
||||||
rtp_statistics_ = std::make_unique<RtpStatistics>();
|
rtp_statistics_ = std::make_unique<RtpStatistics>();
|
||||||
rtp_statistics_->Start();
|
rtp_statistics_->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> to_send_rtp_packets;
|
||||||
for (auto& rtp_packet : rtp_packets) {
|
for (auto& rtp_packet : rtp_packets) {
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send =
|
std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send(
|
||||||
std::dynamic_pointer_cast<webrtc::RtpPacketToSend>(rtp_packet);
|
static_cast<webrtc::RtpPacketToSend*>(rtp_packet.release()));
|
||||||
rtp_packet_to_send->set_capture_time(
|
rtp_packet_to_send->set_capture_time(
|
||||||
webrtc::Timestamp::Millis(capture_timestamp_ms));
|
webrtc::Timestamp::Millis(capture_timestamp_ms));
|
||||||
rtp_packet_to_send->set_transport_sequence_number(transport_seq_++);
|
rtp_packet_to_send->set_transport_sequence_number(transport_seq_++);
|
||||||
rtp_packet_to_send->set_packet_type(webrtc::RtpPacketMediaType::kVideo);
|
rtp_packet_to_send->set_packet_type(webrtc::RtpPacketMediaType::kVideo);
|
||||||
rtp_packet_queue_.push(std::move(rtp_packet_to_send));
|
// rtp_packet_queue_.push(std::move(rtp_packet_to_send));
|
||||||
|
|
||||||
|
to_send_rtp_packets.push_back(std::move(rtp_packet_to_send));
|
||||||
}
|
}
|
||||||
|
enqueue_packets_func_(std::move(to_send_rtp_packets));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpVideoSender::SetSendDataFunc(
|
void RtpVideoSender::SetSendDataFunc(
|
||||||
@@ -72,18 +76,19 @@ void RtpVideoSender::SetOnSentPacketFunc(
|
|||||||
on_sent_packet_func_ = on_sent_packet_func;
|
on_sent_packet_func_ = on_sent_packet_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RtpVideoSender::SetEnqueuePacketsFunc(
|
||||||
|
std::function<void(std::vector<std::unique_ptr<webrtc::RtpPacketToSend>>&)>
|
||||||
|
enqueue_packets_func) {
|
||||||
|
enqueue_packets_func_ = enqueue_packets_func;
|
||||||
|
}
|
||||||
|
|
||||||
int RtpVideoSender::SendRtpPacket(
|
int RtpVideoSender::SendRtpPacket(
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send) {
|
std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send) {
|
||||||
if (!data_send_func_) {
|
if (!data_send_func_) {
|
||||||
LOG_ERROR("data_send_func_ is nullptr");
|
LOG_ERROR("data_send_func_ is nullptr");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (on_sent_packet_func_) {
|
|
||||||
on_sent_packet_func_(*rtp_packet_to_send);
|
|
||||||
rtp_packet_history_->AddPacket(rtp_packet_to_send, clock_->CurrentTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
last_rtp_timestamp_ = rtp_packet_to_send->capture_time().ms();
|
last_rtp_timestamp_ = rtp_packet_to_send->capture_time().ms();
|
||||||
|
|
||||||
int ret = data_send_func_((const char*)rtp_packet_to_send->Buffer().data(),
|
int ret = data_send_func_((const char*)rtp_packet_to_send->Buffer().data(),
|
||||||
@@ -124,6 +129,12 @@ int RtpVideoSender::SendRtpPacket(
|
|||||||
SendRtcpSR(rtcp_sr);
|
SendRtcpSR(rtcp_sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (on_sent_packet_func_) {
|
||||||
|
on_sent_packet_func_(*rtp_packet_to_send);
|
||||||
|
rtp_packet_history_->AddPacket(std::move(rtp_packet_to_send),
|
||||||
|
clock_->CurrentTime());
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,10 +175,10 @@ bool RtpVideoSender::Process() {
|
|||||||
|
|
||||||
for (size_t i = 0; i < 10; i++)
|
for (size_t i = 0; i < 10; i++)
|
||||||
if (!rtp_packet_queue_.isEmpty()) {
|
if (!rtp_packet_queue_.isEmpty()) {
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send;
|
std::optional<std::unique_ptr<webrtc::RtpPacketToSend>>
|
||||||
pop_success = rtp_packet_queue_.pop(rtp_packet_to_send);
|
rtp_packet_to_send = rtp_packet_queue_.pop();
|
||||||
if (pop_success) {
|
if (rtp_packet_to_send) {
|
||||||
SendRtpPacket(rtp_packet_to_send);
|
SendRtpPacket(std::move(*rtp_packet_to_send));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,17 +23,21 @@ class RtpVideoSender : public ThreadBase {
|
|||||||
virtual ~RtpVideoSender();
|
virtual ~RtpVideoSender();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Enqueue(std::vector<std::shared_ptr<RtpPacket>> &rtp_packets,
|
void Enqueue(std::vector<std::unique_ptr<RtpPacket>> &rtp_packets,
|
||||||
int64_t capture_timestamp_ms);
|
int64_t capture_timestamp_ms);
|
||||||
void SetSendDataFunc(std::function<int(const char *, size_t)> data_send_func);
|
void SetSendDataFunc(std::function<int(const char *, size_t)> data_send_func);
|
||||||
void SetOnSentPacketFunc(
|
void SetOnSentPacketFunc(
|
||||||
std::function<void(const webrtc::RtpPacketToSend &)> on_sent_packet_func);
|
std::function<void(const webrtc::RtpPacketToSend &)> on_sent_packet_func);
|
||||||
|
void SetEnqueuePacketsFunc(
|
||||||
|
std::function<
|
||||||
|
void(std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> &)>
|
||||||
|
enqueue_packets_func);
|
||||||
uint32_t GetSsrc() { return ssrc_; }
|
uint32_t GetSsrc() { return ssrc_; }
|
||||||
void OnReceiverReport(const ReceiverReport &receiver_report);
|
void OnReceiverReport(const ReceiverReport &receiver_report);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int SendRtpPacket(
|
int SendRtpPacket(
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send);
|
std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send);
|
||||||
int SendRtcpSR(SenderReport &rtcp_sr);
|
int SendRtcpSR(SenderReport &rtcp_sr);
|
||||||
|
|
||||||
bool CheckIsTimeSendSR();
|
bool CheckIsTimeSendSR();
|
||||||
@@ -45,7 +49,9 @@ class RtpVideoSender : public ThreadBase {
|
|||||||
std::function<int(const char *, size_t)> data_send_func_ = nullptr;
|
std::function<int(const char *, size_t)> data_send_func_ = nullptr;
|
||||||
std::function<void(const webrtc::RtpPacketToSend &)> on_sent_packet_func_ =
|
std::function<void(const webrtc::RtpPacketToSend &)> on_sent_packet_func_ =
|
||||||
nullptr;
|
nullptr;
|
||||||
RingBuffer<std::shared_ptr<webrtc::RtpPacketToSend>> rtp_packet_queue_;
|
std::function<void(std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> &)>
|
||||||
|
enqueue_packets_func_ = nullptr;
|
||||||
|
RingBuffer<std::unique_ptr<webrtc::RtpPacketToSend>> rtp_packet_queue_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t ssrc_ = 0;
|
uint32_t ssrc_ = 0;
|
||||||
|
|||||||
@@ -26,23 +26,30 @@ BandwidthLimitedCause GetBandwidthLimitedCause(LossBasedState loss_based_state,
|
|||||||
BandwidthUsage bandwidth_usage) {
|
BandwidthUsage bandwidth_usage) {
|
||||||
if (bandwidth_usage == BandwidthUsage::kBwOverusing ||
|
if (bandwidth_usage == BandwidthUsage::kBwOverusing ||
|
||||||
bandwidth_usage == BandwidthUsage::kBwUnderusing) {
|
bandwidth_usage == BandwidthUsage::kBwUnderusing) {
|
||||||
|
LOG_ERROR("kDelayBasedLimitedDelayIncreased");
|
||||||
return BandwidthLimitedCause::kDelayBasedLimitedDelayIncreased;
|
return BandwidthLimitedCause::kDelayBasedLimitedDelayIncreased;
|
||||||
} else if (is_rtt_above_limit) {
|
} else if (is_rtt_above_limit) {
|
||||||
|
LOG_ERROR("kDelayBasedLimitedDelayIncreased");
|
||||||
return BandwidthLimitedCause::kRttBasedBackOffHighRtt;
|
return BandwidthLimitedCause::kRttBasedBackOffHighRtt;
|
||||||
}
|
}
|
||||||
switch (loss_based_state) {
|
switch (loss_based_state) {
|
||||||
case LossBasedState::kDecreasing:
|
case LossBasedState::kDecreasing:
|
||||||
// Probes may not be sent in this state.
|
// Probes may not be sent in this state.
|
||||||
|
LOG_ERROR("kLossLimitedBwe");
|
||||||
return BandwidthLimitedCause::kLossLimitedBwe;
|
return BandwidthLimitedCause::kLossLimitedBwe;
|
||||||
case webrtc::LossBasedState::kIncreaseUsingPadding:
|
case webrtc::LossBasedState::kIncreaseUsingPadding:
|
||||||
// Probes may not be sent in this state.
|
// Probes may not be sent in this state.
|
||||||
|
LOG_ERROR("kLossLimitedBwe");
|
||||||
return BandwidthLimitedCause::kLossLimitedBwe;
|
return BandwidthLimitedCause::kLossLimitedBwe;
|
||||||
case LossBasedState::kIncreasing:
|
case LossBasedState::kIncreasing:
|
||||||
|
LOG_ERROR("kLossLimitedBweIncreasing");
|
||||||
// Probes may be sent in this state.
|
// Probes may be sent in this state.
|
||||||
return BandwidthLimitedCause::kLossLimitedBweIncreasing;
|
return BandwidthLimitedCause::kLossLimitedBweIncreasing;
|
||||||
case LossBasedState::kDelayBasedEstimate:
|
case LossBasedState::kDelayBasedEstimate:
|
||||||
|
// LOG_ERROR("kDelayBasedLimited");
|
||||||
return BandwidthLimitedCause::kDelayBasedLimited;
|
return BandwidthLimitedCause::kDelayBasedLimited;
|
||||||
default:
|
default:
|
||||||
|
LOG_ERROR("kLossLimitedBwe");
|
||||||
return BandwidthLimitedCause::kLossLimitedBwe;
|
return BandwidthLimitedCause::kLossLimitedBwe;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,6 +94,13 @@ CongestionControl::CongestionControl()
|
|||||||
|
|
||||||
CongestionControl::~CongestionControl() {}
|
CongestionControl::~CongestionControl() {}
|
||||||
|
|
||||||
|
NetworkControlUpdate CongestionControl::OnNetworkAvailability(
|
||||||
|
NetworkAvailability msg) {
|
||||||
|
NetworkControlUpdate update;
|
||||||
|
update.probe_cluster_configs = probe_controller_->OnNetworkAvailability(msg);
|
||||||
|
return update;
|
||||||
|
}
|
||||||
|
|
||||||
NetworkControlUpdate CongestionControl::OnProcessInterval(ProcessInterval msg) {
|
NetworkControlUpdate CongestionControl::OnProcessInterval(ProcessInterval msg) {
|
||||||
NetworkControlUpdate update;
|
NetworkControlUpdate update;
|
||||||
if (initial_config_) {
|
if (initial_config_) {
|
||||||
@@ -122,7 +136,6 @@ NetworkControlUpdate CongestionControl::OnProcessInterval(ProcessInterval msg) {
|
|||||||
auto probes = probe_controller_->Process(msg.at_time);
|
auto probes = probe_controller_->Process(msg.at_time);
|
||||||
update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
|
update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
|
||||||
probes.begin(), probes.end());
|
probes.begin(), probes.end());
|
||||||
|
|
||||||
update.congestion_window = current_data_window_;
|
update.congestion_window = current_data_window_;
|
||||||
|
|
||||||
MaybeTriggerOnNetworkChanged(&update, msg.at_time);
|
MaybeTriggerOnNetworkChanged(&update, msg.at_time);
|
||||||
@@ -407,8 +420,10 @@ void CongestionControl::MaybeTriggerOnNetworkChanged(
|
|||||||
update->probe_cluster_configs.insert(update->probe_cluster_configs.end(),
|
update->probe_cluster_configs.insert(update->probe_cluster_configs.end(),
|
||||||
probes.begin(), probes.end());
|
probes.begin(), probes.end());
|
||||||
update->pacer_config = GetPacingRates(at_time);
|
update->pacer_config = GetPacingRates(at_time);
|
||||||
// LOG_INFO("bwe {} pushback_target_bps={} estimate_bps={}", at_time.ms(),
|
// LOG_INFO("bwe {} pushback_target_bps={} estimate_bps={}",
|
||||||
// last_pushback_target_rate_.bps(), loss_based_target_rate.bps());
|
// at_time.ms(),
|
||||||
|
// last_pushback_target_rate_.bps(),
|
||||||
|
// loss_based_target_rate.bps());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ class CongestionControl {
|
|||||||
~CongestionControl();
|
~CongestionControl();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
NetworkControlUpdate OnNetworkAvailability(NetworkAvailability msg);
|
||||||
|
|
||||||
NetworkControlUpdate OnProcessInterval(ProcessInterval msg);
|
NetworkControlUpdate OnProcessInterval(ProcessInterval msg);
|
||||||
|
|
||||||
NetworkControlUpdate OnTransportLossReport(TransportLossReport msg);
|
NetworkControlUpdate OnTransportLossReport(TransportLossReport msg);
|
||||||
|
|||||||
@@ -397,6 +397,8 @@ void PacingController::ProcessPackets() {
|
|||||||
if (now + early_execute_margin < target_send_time) {
|
if (now + early_execute_margin < target_send_time) {
|
||||||
// We are too early, but if queue is empty still allow draining some debt.
|
// We are too early, but if queue is empty still allow draining some debt.
|
||||||
// Probing is allowed to be sent up to kMinSleepTime early.
|
// Probing is allowed to be sent up to kMinSleepTime early.
|
||||||
|
LOG_ERROR("!!!!!!! too early, target_send_time {}, now {}, {}",
|
||||||
|
target_send_time.ms(), now.ms(), early_execute_margin.ms());
|
||||||
UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(now));
|
UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(now));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -664,8 +666,8 @@ void PacingController::MaybeUpdateMediaRateDueToLongQueue(Timestamp now) {
|
|||||||
DataRate min_rate_needed = queue_size_data / avg_time_left;
|
DataRate min_rate_needed = queue_size_data / avg_time_left;
|
||||||
if (min_rate_needed > pacing_rate_) {
|
if (min_rate_needed > pacing_rate_) {
|
||||||
adjusted_media_rate_ = min_rate_needed;
|
adjusted_media_rate_ = min_rate_needed;
|
||||||
LOG_INFO("bwe:large_pacing_queue pacing_rate_kbps={}",
|
// LOG_INFO("bwe:large_pacing_queue pacing_rate_kbps={}",
|
||||||
pacing_rate_.kbps());
|
// pacing_rate_.kbps());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ std::vector<ProbeClusterConfig> ProbeController::SetBitrates(
|
|||||||
if (start_bitrate > DataRate::Zero()) {
|
if (start_bitrate > DataRate::Zero()) {
|
||||||
start_bitrate_ = start_bitrate;
|
start_bitrate_ = start_bitrate;
|
||||||
estimated_bitrate_ = start_bitrate;
|
estimated_bitrate_ = start_bitrate;
|
||||||
|
LOG_WARN("1 setting estimated_bitrate_ = {}", estimated_bitrate_.bps());
|
||||||
} else if (start_bitrate_.IsZero()) {
|
} else if (start_bitrate_.IsZero()) {
|
||||||
start_bitrate_ = min_bitrate;
|
start_bitrate_ = min_bitrate;
|
||||||
}
|
}
|
||||||
@@ -117,10 +118,11 @@ std::vector<ProbeClusterConfig> ProbeController::SetBitrates(
|
|||||||
DataRate old_max_bitrate = max_bitrate_;
|
DataRate old_max_bitrate = max_bitrate_;
|
||||||
max_bitrate_ =
|
max_bitrate_ =
|
||||||
max_bitrate.IsFinite() ? max_bitrate : kDefaultMaxProbingBitrate;
|
max_bitrate.IsFinite() ? max_bitrate : kDefaultMaxProbingBitrate;
|
||||||
|
|
||||||
switch (state_) {
|
switch (state_) {
|
||||||
case State::kInit:
|
case State::kInit:
|
||||||
if (network_available_) return InitiateExponentialProbing(at_time);
|
if (network_available_) {
|
||||||
|
return InitiateExponentialProbing(at_time);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::kWaitingForProbingResult:
|
case State::kWaitingForProbingResult:
|
||||||
@@ -131,6 +133,7 @@ std::vector<ProbeClusterConfig> ProbeController::SetBitrates(
|
|||||||
// estimate then initiate probing.
|
// estimate then initiate probing.
|
||||||
if (!estimated_bitrate_.IsZero() && old_max_bitrate < max_bitrate_ &&
|
if (!estimated_bitrate_.IsZero() && old_max_bitrate < max_bitrate_ &&
|
||||||
estimated_bitrate_ < max_bitrate_) {
|
estimated_bitrate_ < max_bitrate_) {
|
||||||
|
LOG_WARN("probing complete");
|
||||||
return InitiateProbing(at_time, {max_bitrate_}, false);
|
return InitiateProbing(at_time, {max_bitrate_}, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -150,8 +153,9 @@ std::vector<ProbeClusterConfig> ProbeController::OnMaxTotalAllocatedBitrate(
|
|||||||
allow_allocation_probe) {
|
allow_allocation_probe) {
|
||||||
max_total_allocated_bitrate_ = max_total_allocated_bitrate;
|
max_total_allocated_bitrate_ = max_total_allocated_bitrate;
|
||||||
|
|
||||||
if (!config_.first_allocation_probe_scale)
|
if (!config_.first_allocation_probe_scale) {
|
||||||
return std::vector<ProbeClusterConfig>();
|
return std::vector<ProbeClusterConfig>();
|
||||||
|
}
|
||||||
|
|
||||||
DataRate first_probe_rate =
|
DataRate first_probe_rate =
|
||||||
max_total_allocated_bitrate * config_.first_allocation_probe_scale;
|
max_total_allocated_bitrate * config_.first_allocation_probe_scale;
|
||||||
@@ -174,7 +178,7 @@ std::vector<ProbeClusterConfig> ProbeController::OnMaxTotalAllocatedBitrate(
|
|||||||
probes.push_back(second_probe_rate);
|
probes.push_back(second_probe_rate);
|
||||||
}
|
}
|
||||||
bool allow_further_probing = limited_by_current_bwe;
|
bool allow_further_probing = limited_by_current_bwe;
|
||||||
|
LOG_WARN("allow_further_probing {}", allow_further_probing);
|
||||||
return InitiateProbing(at_time, probes, allow_further_probing);
|
return InitiateProbing(at_time, probes, allow_further_probing);
|
||||||
}
|
}
|
||||||
if (!max_total_allocated_bitrate.IsZero()) {
|
if (!max_total_allocated_bitrate.IsZero()) {
|
||||||
@@ -228,12 +232,10 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateExponentialProbing(
|
|||||||
max_total_allocated_bitrate_.IsZero()) {
|
max_total_allocated_bitrate_.IsZero()) {
|
||||||
last_allowed_repeated_initial_probe_ =
|
last_allowed_repeated_initial_probe_ =
|
||||||
at_time + config_.repeated_initial_probing_time_period;
|
at_time + config_.repeated_initial_probing_time_period;
|
||||||
// LOG_INFO("Repeated initial probing enabled, last allowed probe: {} now:
|
LOG_INFO("Repeated initial probing enabled, last allowed probe: {} now: {}",
|
||||||
// {}",
|
last_allowed_repeated_initial_probe_.ms(), at_time.ms());
|
||||||
// ToString(last_allowed_repeated_initial_probe_),
|
|
||||||
// ToString(at_time));
|
|
||||||
}
|
}
|
||||||
|
LOG_WARN("InitiateExponentialProbing");
|
||||||
return InitiateProbing(at_time, probes, true);
|
return InitiateProbing(at_time, probes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +248,6 @@ std::vector<ProbeClusterConfig> ProbeController::SetEstimatedBitrate(
|
|||||||
bitrate_before_last_large_drop_ = estimated_bitrate_;
|
bitrate_before_last_large_drop_ = estimated_bitrate_;
|
||||||
}
|
}
|
||||||
estimated_bitrate_ = bitrate;
|
estimated_bitrate_ = bitrate;
|
||||||
|
|
||||||
if (state_ == State::kWaitingForProbingResult) {
|
if (state_ == State::kWaitingForProbingResult) {
|
||||||
// Continue probing if probing results indicate channel has greater
|
// Continue probing if probing results indicate channel has greater
|
||||||
// capacity unless we already reached the needed bitrate.
|
// capacity unless we already reached the needed bitrate.
|
||||||
@@ -264,13 +265,14 @@ std::vector<ProbeClusterConfig> ProbeController::SetEstimatedBitrate(
|
|||||||
? network_estimate_->link_capacity_upper *
|
? network_estimate_->link_capacity_upper *
|
||||||
config_.further_probe_threshold
|
config_.further_probe_threshold
|
||||||
: DataRate::PlusInfinity();
|
: DataRate::PlusInfinity();
|
||||||
// LOG_INFO(
|
LOG_INFO(
|
||||||
// "Measured bitrate: {} Minimum to probe further: {} upper limit: {}",
|
"Measured bitrate: {} Minimum to probe further: {} upper limit: {}",
|
||||||
// bitrate, ToString(min_bitrate_to_probe_further_),
|
bitrate.bps(), min_bitrate_to_probe_further_.bps(),
|
||||||
// ToString(network_state_estimate_probe_further_limit));
|
network_state_estimate_probe_further_limit.bps());
|
||||||
|
|
||||||
if (bitrate > min_bitrate_to_probe_further_ &&
|
if (bitrate > min_bitrate_to_probe_further_ &&
|
||||||
bitrate <= network_state_estimate_probe_further_limit) {
|
bitrate <= network_state_estimate_probe_further_limit) {
|
||||||
|
LOG_WARN("InitiateProbing SetEstimatedBitrate");
|
||||||
return InitiateProbing(
|
return InitiateProbing(
|
||||||
at_time, {config_.further_exponential_probe_scale * bitrate}, true);
|
at_time, {config_.further_exponential_probe_scale * bitrate}, true);
|
||||||
}
|
}
|
||||||
@@ -323,6 +325,7 @@ std::vector<ProbeClusterConfig> ProbeController::RequestProbe(
|
|||||||
time_since_probe > kMinTimeBetweenAlrProbes) {
|
time_since_probe > kMinTimeBetweenAlrProbes) {
|
||||||
LOG_INFO("Detected big bandwidth drop, start probing");
|
LOG_INFO("Detected big bandwidth drop, start probing");
|
||||||
last_bwe_drop_probing_time_ = at_time;
|
last_bwe_drop_probing_time_ = at_time;
|
||||||
|
LOG_WARN("InitiateProbing RequestProbe");
|
||||||
return InitiateProbing(at_time, {suggested_probe}, false);
|
return InitiateProbing(at_time, {suggested_probe}, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,6 +344,7 @@ void ProbeController::Reset(Timestamp at_time) {
|
|||||||
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
|
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
|
||||||
time_last_probing_initiated_ = Timestamp::Zero();
|
time_last_probing_initiated_ = Timestamp::Zero();
|
||||||
estimated_bitrate_ = DataRate::Zero();
|
estimated_bitrate_ = DataRate::Zero();
|
||||||
|
LOG_WARN("3 setting estimated_bitrate_ = {}", estimated_bitrate_.bps());
|
||||||
network_estimate_ = std::nullopt;
|
network_estimate_ = std::nullopt;
|
||||||
start_bitrate_ = DataRate::Zero();
|
start_bitrate_ = DataRate::Zero();
|
||||||
max_bitrate_ = kDefaultMaxProbingBitrate;
|
max_bitrate_ = kDefaultMaxProbingBitrate;
|
||||||
@@ -413,15 +417,21 @@ std::vector<ProbeClusterConfig> ProbeController::Process(Timestamp at_time) {
|
|||||||
UpdateState(State::kProbingComplete);
|
UpdateState(State::kProbingComplete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (estimated_bitrate_.IsZero() || state_ != State::kProbingComplete) {
|
if (estimated_bitrate_.IsZero() || state_ != State::kProbingComplete) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (TimeForNextRepeatedInitialProbe(at_time)) {
|
if (TimeForNextRepeatedInitialProbe(at_time)) {
|
||||||
|
LOG_WARN(
|
||||||
|
"InitiateProbing TimeForNextRepeatedInitialProbe, estimated_bitrate_ = "
|
||||||
|
"{}",
|
||||||
|
estimated_bitrate_.bps());
|
||||||
return InitiateProbing(
|
return InitiateProbing(
|
||||||
at_time, {estimated_bitrate_ * config_.first_exponential_probe_scale},
|
at_time, {estimated_bitrate_ * config_.first_exponential_probe_scale},
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
if (TimeForAlrProbe(at_time) || TimeForNetworkStateProbe(at_time)) {
|
if (TimeForAlrProbe(at_time) || TimeForNetworkStateProbe(at_time)) {
|
||||||
|
LOG_WARN("InitiateProbing TimeForNetworkStateProbe");
|
||||||
return InitiateProbing(
|
return InitiateProbing(
|
||||||
at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true);
|
at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true);
|
||||||
}
|
}
|
||||||
@@ -505,7 +515,6 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
|
|||||||
if (config_.network_state_estimate_probing_interval.IsFinite() &&
|
if (config_.network_state_estimate_probing_interval.IsFinite() &&
|
||||||
network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) {
|
network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) {
|
||||||
if (network_estimate_->link_capacity_upper.IsZero()) {
|
if (network_estimate_->link_capacity_upper.IsZero()) {
|
||||||
LOG_INFO("Not sending probe, Network state estimate is zero");
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
max_probe_bitrate = std::min(
|
max_probe_bitrate = std::min(
|
||||||
@@ -522,6 +531,7 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
|
|||||||
}
|
}
|
||||||
pending_probes.push_back(CreateProbeClusterConfig(now, bitrate));
|
pending_probes.push_back(CreateProbeClusterConfig(now, bitrate));
|
||||||
}
|
}
|
||||||
|
LOG_ERROR("2 pending probes size {}", pending_probes.size());
|
||||||
time_last_probing_initiated_ = now;
|
time_last_probing_initiated_ = now;
|
||||||
if (probe_further) {
|
if (probe_further) {
|
||||||
UpdateState(State::kWaitingForProbingResult);
|
UpdateState(State::kWaitingForProbingResult);
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation()
|
|||||||
low_loss_threshold_(kDefaultLowLossThreshold),
|
low_loss_threshold_(kDefaultLowLossThreshold),
|
||||||
high_loss_threshold_(kDefaultHighLossThreshold),
|
high_loss_threshold_(kDefaultHighLossThreshold),
|
||||||
bitrate_threshold_(kDefaultBitrateThreshold),
|
bitrate_threshold_(kDefaultBitrateThreshold),
|
||||||
|
loss_based_state_(LossBasedState::kDelayBasedEstimate),
|
||||||
disable_receiver_limit_caps_only_(false) {
|
disable_receiver_limit_caps_only_(false) {
|
||||||
// rtt_backoff_ =
|
// rtt_backoff_ =
|
||||||
}
|
}
|
||||||
@@ -407,7 +408,7 @@ void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) {
|
|||||||
// it would take over one second since the lower packet loss to achieve
|
// it would take over one second since the lower packet loss to achieve
|
||||||
// 108kbps.
|
// 108kbps.
|
||||||
DataRate new_bitrate = DataRate::BitsPerSec(
|
DataRate new_bitrate = DataRate::BitsPerSec(
|
||||||
min_bitrate_history_.front().second.bps() * 1.5 + 0.5);
|
min_bitrate_history_.front().second.bps() * 1.08 + 0.5);
|
||||||
|
|
||||||
// Add 1 kbps extra, just to make sure that we do not get stuck
|
// Add 1 kbps extra, just to make sure that we do not get stuck
|
||||||
// (gives a little extra increase at low rates, negligible at higher
|
// (gives a little extra increase at low rates, negligible at higher
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
int RingBufferDummy();
|
int RingBufferDummy();
|
||||||
|
|
||||||
@@ -62,37 +63,25 @@ class RingBuffer {
|
|||||||
|
|
||||||
bool isFull() const { return m_front == (m_rear + 1) % m_size; }
|
bool isFull() const { return m_front == (m_rear + 1) % m_size; }
|
||||||
|
|
||||||
bool push(const T& value) {
|
bool push(T value) {
|
||||||
if (isFull()) {
|
if (isFull()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!m_data) {
|
if (!m_data) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_data[m_rear] = value;
|
m_data[m_rear] = std::move(value);
|
||||||
m_rear = (m_rear + 1) % m_size;
|
m_rear = (m_rear + 1) % m_size;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool push(const T* value) {
|
std::optional<T> pop() {
|
||||||
if (isFull()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!m_data) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_data[m_rear] = *value;
|
|
||||||
m_rear = (m_rear + 1) % m_size;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pop(T& value) {
|
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
return false;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
value = m_data[m_front];
|
std::optional<T> value = std::move(m_data[m_front]);
|
||||||
m_front = (m_front + 1) % m_size;
|
m_front = (m_front + 1) % m_size;
|
||||||
return true;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int front() const { return m_front; }
|
unsigned int front() const { return m_front; }
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ void RtpPacketHistory::SetRtt(webrtc::TimeDelta rtt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RtpPacketHistory::AddPacket(
|
void RtpPacketHistory::AddPacket(
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet,
|
std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet,
|
||||||
webrtc::Timestamp send_time) {
|
webrtc::Timestamp send_time) {
|
||||||
RemoveDeadPackets();
|
RemoveDeadPackets();
|
||||||
const uint16_t rtp_seq_no = rtp_packet->SequenceNumber();
|
const uint16_t rtp_seq_no = rtp_packet->SequenceNumber();
|
||||||
@@ -40,7 +40,7 @@ void RtpPacketHistory::AddPacket(
|
|||||||
rtp_packet_history_.emplace_back();
|
rtp_packet_history_.emplace_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
rtp_packet_history_[packet_index] = {rtp_packet, send_time,
|
rtp_packet_history_[packet_index] = {std::move(rtp_packet), send_time,
|
||||||
packets_inserted_++};
|
packets_inserted_++};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,10 +79,10 @@ void RtpPacketHistory::RemoveDeadPackets() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> RtpPacketHistory::RemovePacket(
|
std::unique_ptr<webrtc::RtpPacketToSend> RtpPacketHistory::RemovePacket(
|
||||||
int packet_index) {
|
int packet_index) {
|
||||||
// Move the packet out from the StoredPacket container.
|
// Move the packet out from the StoredPacket container.
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet =
|
std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet =
|
||||||
std::move(rtp_packet_history_[packet_index].rtp_packet);
|
std::move(rtp_packet_history_[packet_index].rtp_packet);
|
||||||
if (packet_index == 0) {
|
if (packet_index == 0) {
|
||||||
while (!rtp_packet_history_.empty() &&
|
while (!rtp_packet_history_.empty() &&
|
||||||
|
|||||||
@@ -31,25 +31,27 @@ class RtpPacketHistory {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
void SetRtt(webrtc::TimeDelta rtt);
|
void SetRtt(webrtc::TimeDelta rtt);
|
||||||
void AddPacket(std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet,
|
void AddPacket(std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet,
|
||||||
webrtc::Timestamp send_time);
|
webrtc::Timestamp send_time);
|
||||||
void RemoveDeadPackets();
|
void RemoveDeadPackets();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> RemovePacket(int packet_index);
|
std::unique_ptr<webrtc::RtpPacketToSend> RemovePacket(int packet_index);
|
||||||
int GetPacketIndex(uint16_t sequence_number) const;
|
int GetPacketIndex(uint16_t sequence_number) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct RtpPacketToSendInfo {
|
struct RtpPacketToSendInfo {
|
||||||
RtpPacketToSendInfo() = default;
|
RtpPacketToSendInfo() = default;
|
||||||
RtpPacketToSendInfo(std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet,
|
RtpPacketToSendInfo(std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet,
|
||||||
webrtc::Timestamp send_time, uint64_t index)
|
webrtc::Timestamp send_time, uint64_t index)
|
||||||
: rtp_packet(rtp_packet), send_time(send_time), index(index) {}
|
: rtp_packet(std::move(rtp_packet)),
|
||||||
|
send_time(send_time),
|
||||||
|
index(index) {}
|
||||||
RtpPacketToSendInfo(RtpPacketToSendInfo&&) = default;
|
RtpPacketToSendInfo(RtpPacketToSendInfo&&) = default;
|
||||||
RtpPacketToSendInfo& operator=(RtpPacketToSendInfo&&) = default;
|
RtpPacketToSendInfo& operator=(RtpPacketToSendInfo&&) = default;
|
||||||
~RtpPacketToSendInfo() = default;
|
~RtpPacketToSendInfo() = default;
|
||||||
|
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet;
|
std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet;
|
||||||
webrtc::Timestamp send_time = webrtc::Timestamp::Zero();
|
webrtc::Timestamp send_time = webrtc::Timestamp::Zero();
|
||||||
uint64_t index;
|
uint64_t index;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,9 +21,13 @@ class RtpPacketizer {
|
|||||||
|
|
||||||
virtual ~RtpPacketizer() = default;
|
virtual ~RtpPacketizer() = default;
|
||||||
|
|
||||||
virtual std::vector<std::shared_ptr<RtpPacket>> Build(
|
virtual std::vector<std::unique_ptr<RtpPacket>> Build(
|
||||||
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
bool use_rtp_packet_to_send) = 0;
|
bool use_rtp_packet_to_send) = 0;
|
||||||
|
|
||||||
|
virtual std::vector<std::unique_ptr<RtpPacket>> BuildPadding(
|
||||||
|
uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
|
bool use_rtp_packet_to_send) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -4,10 +4,10 @@ RtpPacketizerAv1::RtpPacketizerAv1(uint32_t ssrc) {}
|
|||||||
|
|
||||||
RtpPacketizerAv1::~RtpPacketizerAv1() {}
|
RtpPacketizerAv1::~RtpPacketizerAv1() {}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerAv1::Build(
|
std::vector<std::unique_ptr<RtpPacket>> RtpPacketizerAv1::Build(
|
||||||
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
bool use_rtp_packet_to_send) {
|
bool use_rtp_packet_to_send) {
|
||||||
std::vector<std::shared_ptr<RtpPacket>> rtp_packets;
|
std::vector<std::unique_ptr<RtpPacket>> rtp_packets;
|
||||||
|
|
||||||
return rtp_packets;
|
return rtp_packets;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,16 @@ class RtpPacketizerAv1 : public RtpPacketizer {
|
|||||||
|
|
||||||
virtual ~RtpPacketizerAv1();
|
virtual ~RtpPacketizerAv1();
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RtpPacket>> Build(
|
std::vector<std::unique_ptr<RtpPacket>> Build(
|
||||||
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
bool use_rtp_packet_to_send) override;
|
bool use_rtp_packet_to_send) override;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<RtpPacket>> BuildPadding(
|
||||||
|
uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
|
bool use_rtp_packet_to_send) override {
|
||||||
|
return std::vector<std::unique_ptr<RtpPacket>>{};
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t version_;
|
uint8_t version_;
|
||||||
bool has_padding_;
|
bool has_padding_;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ void RtpPacketizerGeneric::AddAbsSendTimeExtension(
|
|||||||
rtp_packet_frame.push_back(abs_send_time & 0xFF);
|
rtp_packet_frame.push_back(abs_send_time & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerGeneric::Build(
|
std::vector<std::unique_ptr<RtpPacket>> RtpPacketizerGeneric::Build(
|
||||||
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
bool use_rtp_packet_to_send) {
|
bool use_rtp_packet_to_send) {
|
||||||
uint32_t last_packet_size = payload_size % MAX_NALU_LEN;
|
uint32_t last_packet_size = payload_size % MAX_NALU_LEN;
|
||||||
@@ -58,7 +58,7 @@ std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerGeneric::Build(
|
|||||||
std::chrono::system_clock::now().time_since_epoch())
|
std::chrono::system_clock::now().time_since_epoch())
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RtpPacket>> rtp_packets;
|
std::vector<std::unique_ptr<RtpPacket>> rtp_packets;
|
||||||
|
|
||||||
for (uint32_t index = 0; index < packet_num; index++) {
|
for (uint32_t index = 0; index < packet_num; index++) {
|
||||||
version_ = kRtpVersion;
|
version_ = kRtpVersion;
|
||||||
@@ -109,12 +109,12 @@ std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerGeneric::Build(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (use_rtp_packet_to_send) {
|
if (use_rtp_packet_to_send) {
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet =
|
std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet =
|
||||||
std::make_unique<webrtc::RtpPacketToSend>();
|
std::make_unique<webrtc::RtpPacketToSend>();
|
||||||
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
||||||
rtp_packets.emplace_back(std::move(rtp_packet));
|
rtp_packets.emplace_back(std::move(rtp_packet));
|
||||||
} else {
|
} else {
|
||||||
std::shared_ptr<RtpPacket> rtp_packet = std::make_unique<RtpPacket>();
|
std::unique_ptr<RtpPacket> rtp_packet = std::make_unique<RtpPacket>();
|
||||||
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
||||||
rtp_packets.emplace_back(std::move(rtp_packet));
|
rtp_packets.emplace_back(std::move(rtp_packet));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,16 @@ class RtpPacketizerGeneric : public RtpPacketizer {
|
|||||||
|
|
||||||
virtual ~RtpPacketizerGeneric();
|
virtual ~RtpPacketizerGeneric();
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RtpPacket>> Build(
|
std::vector<std::unique_ptr<RtpPacket>> Build(
|
||||||
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
bool use_rtp_packet_to_send) override;
|
bool use_rtp_packet_to_send) override;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<RtpPacket>> BuildPadding(
|
||||||
|
uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
|
bool use_rtp_packet_to_send) override {
|
||||||
|
return std::vector<std::unique_ptr<RtpPacket>>{};
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddAbsSendTimeExtension(std::vector<uint8_t>& rtp_packet_frame);
|
void AddAbsSendTimeExtension(std::vector<uint8_t>& rtp_packet_frame);
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ void RtpPacketizerH264::AddAbsSendTimeExtension(
|
|||||||
rtp_packet_frame.push_back(abs_send_time & 0xFF);
|
rtp_packet_frame.push_back(abs_send_time & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerH264::Build(
|
std::vector<std::unique_ptr<RtpPacket>> RtpPacketizerH264::Build(
|
||||||
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
bool use_rtp_packet_to_send) {
|
bool use_rtp_packet_to_send) {
|
||||||
if (payload_size <= MAX_NALU_LEN) {
|
if (payload_size <= MAX_NALU_LEN) {
|
||||||
@@ -72,10 +72,10 @@ std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerH264::Build(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerH264::BuildNalu(
|
std::vector<std::unique_ptr<RtpPacket>> RtpPacketizerH264::BuildNalu(
|
||||||
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
bool use_rtp_packet_to_send) {
|
bool use_rtp_packet_to_send) {
|
||||||
std::vector<std::shared_ptr<RtpPacket>> rtp_packets;
|
std::vector<std::unique_ptr<RtpPacket>> rtp_packets;
|
||||||
|
|
||||||
version_ = kRtpVersion;
|
version_ = kRtpVersion;
|
||||||
has_padding_ = false;
|
has_padding_ = false;
|
||||||
@@ -128,12 +128,12 @@ std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerH264::BuildNalu(
|
|||||||
payload + payload_size);
|
payload + payload_size);
|
||||||
|
|
||||||
if (use_rtp_packet_to_send) {
|
if (use_rtp_packet_to_send) {
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet =
|
std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet =
|
||||||
std::make_shared<webrtc::RtpPacketToSend>();
|
std::make_unique<webrtc::RtpPacketToSend>();
|
||||||
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
||||||
rtp_packets.emplace_back(std::move(rtp_packet));
|
rtp_packets.emplace_back(std::move(rtp_packet));
|
||||||
} else {
|
} else {
|
||||||
std::shared_ptr<RtpPacket> rtp_packet = std::make_shared<RtpPacket>();
|
std::unique_ptr<RtpPacket> rtp_packet = std::make_unique<RtpPacket>();
|
||||||
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
||||||
rtp_packets.emplace_back(std::move(rtp_packet));
|
rtp_packets.emplace_back(std::move(rtp_packet));
|
||||||
}
|
}
|
||||||
@@ -141,10 +141,10 @@ std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerH264::BuildNalu(
|
|||||||
return rtp_packets;
|
return rtp_packets;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerH264::BuildFua(
|
std::vector<std::unique_ptr<RtpPacket>> RtpPacketizerH264::BuildFua(
|
||||||
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
bool use_rtp_packet_to_send) {
|
bool use_rtp_packet_to_send) {
|
||||||
std::vector<std::shared_ptr<RtpPacket>> rtp_packets;
|
std::vector<std::unique_ptr<RtpPacket>> rtp_packets;
|
||||||
|
|
||||||
uint32_t last_packet_size = payload_size % MAX_NALU_LEN;
|
uint32_t last_packet_size = payload_size % MAX_NALU_LEN;
|
||||||
uint32_t packet_num =
|
uint32_t packet_num =
|
||||||
@@ -227,12 +227,12 @@ std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerH264::BuildFua(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (use_rtp_packet_to_send) {
|
if (use_rtp_packet_to_send) {
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet =
|
std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet =
|
||||||
std::make_shared<webrtc::RtpPacketToSend>();
|
std::make_unique<webrtc::RtpPacketToSend>();
|
||||||
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
||||||
rtp_packets.emplace_back(std::move(rtp_packet));
|
rtp_packets.emplace_back(std::move(rtp_packet));
|
||||||
} else {
|
} else {
|
||||||
std::shared_ptr<RtpPacket> rtp_packet = std::make_shared<RtpPacket>();
|
std::unique_ptr<RtpPacket> rtp_packet = std::make_unique<RtpPacket>();
|
||||||
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
||||||
rtp_packets.emplace_back(std::move(rtp_packet));
|
rtp_packets.emplace_back(std::move(rtp_packet));
|
||||||
}
|
}
|
||||||
@@ -241,6 +241,65 @@ std::vector<std::shared_ptr<RtpPacket>> RtpPacketizerH264::BuildFua(
|
|||||||
return rtp_packets;
|
return rtp_packets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<RtpPacket>> RtpPacketizerH264::BuildPadding(
|
||||||
|
uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
|
bool use_rtp_packet_to_send) {
|
||||||
|
std::vector<std::unique_ptr<RtpPacket>> rtp_packets;
|
||||||
|
|
||||||
|
version_ = kRtpVersion;
|
||||||
|
has_padding_ = true;
|
||||||
|
has_extension_ = true;
|
||||||
|
csrc_count_ = 0;
|
||||||
|
marker_ = 0;
|
||||||
|
uint8_t payload_type = rtp::PAYLOAD_TYPE(payload_type_ - 1);
|
||||||
|
sequence_number_++;
|
||||||
|
timestamp_ = kMsToRtpTimestamp * static_cast<uint32_t>(capture_timestamp_ms);
|
||||||
|
|
||||||
|
rtp_packet_frame_.clear();
|
||||||
|
rtp_packet_frame_.push_back((version_ << 6) | (has_padding_ << 5) |
|
||||||
|
(has_extension_ << 4) | csrc_count_);
|
||||||
|
rtp_packet_frame_.push_back((marker_ << 7) | payload_type);
|
||||||
|
rtp_packet_frame_.push_back((sequence_number_ >> 8) & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back(sequence_number_ & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back((timestamp_ >> 24) & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back((timestamp_ >> 16) & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back((timestamp_ >> 8) & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back(timestamp_ & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back((ssrc_ >> 24) & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back((ssrc_ >> 16) & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back((ssrc_ >> 8) & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back(ssrc_ & 0xFF);
|
||||||
|
|
||||||
|
for (uint32_t index = 0; index < csrc_count_ && !csrcs_.empty(); index++) {
|
||||||
|
rtp_packet_frame_.push_back((csrcs_[index] >> 24) & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back((csrcs_[index] >> 16) & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back((csrcs_[index] >> 8) & 0xFF);
|
||||||
|
rtp_packet_frame_.push_back(csrcs_[index] & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_extension_) {
|
||||||
|
AddAbsSendTimeExtension(rtp_packet_frame_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add padding bytes
|
||||||
|
uint32_t padding_size = payload_size;
|
||||||
|
rtp_packet_frame_.insert(rtp_packet_frame_.end(), padding_size - 1, 0);
|
||||||
|
rtp_packet_frame_.push_back(padding_size);
|
||||||
|
|
||||||
|
if (use_rtp_packet_to_send) {
|
||||||
|
std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet =
|
||||||
|
std::make_unique<webrtc::RtpPacketToSend>();
|
||||||
|
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
||||||
|
rtp_packets.emplace_back(std::move(rtp_packet));
|
||||||
|
} else {
|
||||||
|
std::unique_ptr<RtpPacket> rtp_packet = std::make_unique<RtpPacket>();
|
||||||
|
rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size());
|
||||||
|
rtp_packets.emplace_back(std::move(rtp_packet));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rtp_packets;
|
||||||
|
}
|
||||||
|
|
||||||
// bool BuildFec(uint8_t* payload, uint32_t payload_size) {
|
// bool BuildFec(uint8_t* payload, uint32_t payload_size) {
|
||||||
// uint8_t** fec_packets =
|
// uint8_t** fec_packets =
|
||||||
// fec_encoder_.Encode((const char*)payload, payload_size);
|
// fec_encoder_.Encode((const char*)payload, payload_size);
|
||||||
|
|||||||
@@ -15,19 +15,23 @@ class RtpPacketizerH264 : public RtpPacketizer {
|
|||||||
|
|
||||||
virtual ~RtpPacketizerH264();
|
virtual ~RtpPacketizerH264();
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RtpPacket>> Build(
|
std::vector<std::unique_ptr<RtpPacket>> Build(
|
||||||
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
bool use_rtp_packet_to_send) override;
|
bool use_rtp_packet_to_send) override;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RtpPacket>> BuildNalu(
|
std::vector<std::unique_ptr<RtpPacket>> BuildNalu(
|
||||||
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
uint8_t* payload, uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
bool use_rtp_packet_to_send);
|
bool use_rtp_packet_to_send);
|
||||||
|
|
||||||
std::vector<std::shared_ptr<RtpPacket>> BuildFua(uint8_t* payload,
|
std::vector<std::unique_ptr<RtpPacket>> BuildFua(uint8_t* payload,
|
||||||
uint32_t payload_size,
|
uint32_t payload_size,
|
||||||
int64_t capture_timestamp_ms,
|
int64_t capture_timestamp_ms,
|
||||||
bool use_rtp_packet_to_send);
|
bool use_rtp_packet_to_send);
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<RtpPacket>> BuildPadding(
|
||||||
|
uint32_t payload_size, int64_t capture_timestamp_ms,
|
||||||
|
bool use_rtp_packet_to_send) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool EncodeH264Fua(RtpPacket& rtp_packet, uint8_t* payload,
|
bool EncodeH264Fua(RtpPacket& rtp_packet, uint8_t* payload,
|
||||||
size_t payload_size);
|
size_t payload_size);
|
||||||
|
|||||||
@@ -110,6 +110,9 @@ void IceTransport::OnIceStateChange(NiceAgent *agent, guint stream_id,
|
|||||||
if (state == NICE_COMPONENT_STATE_READY ||
|
if (state == NICE_COMPONENT_STATE_READY ||
|
||||||
state == NICE_COMPONENT_STATE_CONNECTED) {
|
state == NICE_COMPONENT_STATE_CONNECTED) {
|
||||||
ice_io_statistics_->Start();
|
ice_io_statistics_->Start();
|
||||||
|
if (ice_transport_controller_) {
|
||||||
|
ice_transport_controller_->UpdateNetworkAvaliablity(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
on_ice_status_change_(nice_component_state_to_string(state),
|
on_ice_status_change_(nice_component_state_to_string(state),
|
||||||
@@ -202,6 +205,8 @@ void IceTransport::OnReceiveBuffer(NiceAgent *agent, guint stream_id,
|
|||||||
// LOG_ERROR("Rtcp packet [{}]", (uint8_t)(buffer[1]));
|
// LOG_ERROR("Rtcp packet [{}]", (uint8_t)(buffer[1]));
|
||||||
RtcpPacketInfo rtcp_packet_info;
|
RtcpPacketInfo rtcp_packet_info;
|
||||||
ParseRtcpPacket((const uint8_t *)buffer, size, &rtcp_packet_info);
|
ParseRtcpPacket((const uint8_t *)buffer, size, &rtcp_packet_info);
|
||||||
|
} else if (CheckIsRtpPaddingPacket(buffer, size)) {
|
||||||
|
// LOG_WARN("Rtp padding packet");
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR("Unknown packet");
|
LOG_ERROR("Unknown packet");
|
||||||
}
|
}
|
||||||
@@ -920,7 +925,22 @@ uint8_t IceTransport::CheckIsRtpPacket(const char *buffer, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t payload_type = buffer[1] & 0x7F;
|
uint8_t payload_type = buffer[1] & 0x7F;
|
||||||
if (payload_type >= 96 && payload_type <= 127) {
|
if (payload_type == 96 || payload_type == 99 || payload_type == 111 ||
|
||||||
|
payload_type == 127) {
|
||||||
|
return payload_type;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t IceTransport::CheckIsRtpPaddingPacket(const char *buffer, size_t size) {
|
||||||
|
if (size < 2) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t payload_type = buffer[1] & 0x7F;
|
||||||
|
if (payload_type == 95 || payload_type == 98 || payload_type == 110 ||
|
||||||
|
payload_type == 126) {
|
||||||
return payload_type;
|
return payload_type;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ class IceTransport {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t CheckIsRtpPacket(const char *buffer, size_t size);
|
uint8_t CheckIsRtpPacket(const char *buffer, size_t size);
|
||||||
|
uint8_t CheckIsRtpPaddingPacket(const char *buffer, size_t size);
|
||||||
uint8_t CheckIsRtcpPacket(const char *buffer, size_t size);
|
uint8_t CheckIsRtcpPacket(const char *buffer, size_t size);
|
||||||
uint8_t CheckIsVideoPacket(const char *buffer, size_t size);
|
uint8_t CheckIsVideoPacket(const char *buffer, size_t size);
|
||||||
uint8_t CheckIsAudioPacket(const char *buffer, size_t size);
|
uint8_t CheckIsAudioPacket(const char *buffer, size_t size);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ void IceTransportController::Create(
|
|||||||
std::shared_ptr<IOStatistics> ice_io_statistics,
|
std::shared_ptr<IOStatistics> ice_io_statistics,
|
||||||
OnReceiveVideo on_receive_video, OnReceiveAudio on_receive_audio,
|
OnReceiveVideo on_receive_video, OnReceiveAudio on_receive_audio,
|
||||||
OnReceiveData on_receive_data, void* user_data) {
|
OnReceiveData on_receive_data, void* user_data) {
|
||||||
|
ice_agent_ = ice_agent;
|
||||||
remote_user_id_ = remote_user_id;
|
remote_user_id_ = remote_user_id;
|
||||||
on_receive_video_ = on_receive_video;
|
on_receive_video_ = on_receive_video;
|
||||||
on_receive_audio_ = on_receive_audio;
|
on_receive_audio_ = on_receive_audio;
|
||||||
@@ -53,6 +54,16 @@ void IceTransportController::Create(
|
|||||||
|
|
||||||
controller_ = std::make_unique<CongestionControl>();
|
controller_ = std::make_unique<CongestionControl>();
|
||||||
packet_sender_ = std::make_unique<PacketSender>(ice_agent, webrtc_clock_);
|
packet_sender_ = std::make_unique<PacketSender>(ice_agent, webrtc_clock_);
|
||||||
|
packet_sender_->SetPacingRates(DataRate::BitsPerSec(300000),
|
||||||
|
DataRate::Zero());
|
||||||
|
packet_sender_->SetOnSentPacketFunc(
|
||||||
|
[this](const webrtc::RtpPacketToSend& packet) {
|
||||||
|
if (ice_agent_) {
|
||||||
|
ice_agent_->Send((const char*)packet.Buffer().data(), packet.Size());
|
||||||
|
OnSentRtpPacket(packet);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
resolution_adapter_ = std::make_unique<ResolutionAdapter>();
|
resolution_adapter_ = std::make_unique<ResolutionAdapter>();
|
||||||
|
|
||||||
video_channel_send_ = std::make_unique<VideoChannelSend>(
|
video_channel_send_ = std::make_unique<VideoChannelSend>(
|
||||||
@@ -60,6 +71,13 @@ void IceTransportController::Create(
|
|||||||
[this](const webrtc::RtpPacketToSend& packet) {
|
[this](const webrtc::RtpPacketToSend& packet) {
|
||||||
OnSentRtpPacket(packet);
|
OnSentRtpPacket(packet);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
packet_sender_->SetGeneratePaddingFunc(
|
||||||
|
[this](uint32_t size, int64_t capture_timestamp_ms)
|
||||||
|
-> std::vector<std::unique_ptr<RtpPacket>> {
|
||||||
|
return video_channel_send_->GeneratePadding(size, capture_timestamp_ms);
|
||||||
|
});
|
||||||
|
|
||||||
audio_channel_send_ =
|
audio_channel_send_ =
|
||||||
std::make_unique<AudioChannelSend>(ice_agent, ice_io_statistics);
|
std::make_unique<AudioChannelSend>(ice_agent, ice_io_statistics);
|
||||||
data_channel_send_ =
|
data_channel_send_ =
|
||||||
@@ -69,6 +87,10 @@ void IceTransportController::Create(
|
|||||||
audio_channel_send_->Initialize(rtp::PAYLOAD_TYPE::OPUS);
|
audio_channel_send_->Initialize(rtp::PAYLOAD_TYPE::OPUS);
|
||||||
data_channel_send_->Initialize(rtp::PAYLOAD_TYPE::DATA);
|
data_channel_send_->Initialize(rtp::PAYLOAD_TYPE::DATA);
|
||||||
|
|
||||||
|
video_channel_send_->SetEnqueuePacketsFunc(
|
||||||
|
[this](std::vector<std::unique_ptr<webrtc::RtpPacketToSend>>& packets)
|
||||||
|
-> void { packet_sender_->EnqueuePackets(std::move(packets)); });
|
||||||
|
|
||||||
std::weak_ptr<IceTransportController> weak_self = shared_from_this();
|
std::weak_ptr<IceTransportController> weak_self = shared_from_this();
|
||||||
video_channel_receive_ = std::make_unique<VideoChannelReceive>(
|
video_channel_receive_ = std::make_unique<VideoChannelReceive>(
|
||||||
clock_, ice_agent, ice_io_statistics,
|
clock_, ice_agent, ice_io_statistics,
|
||||||
@@ -161,6 +183,7 @@ int IceTransportController::SendVideo(const XVideoFrame* video_frame) {
|
|||||||
[this](std::shared_ptr<VideoFrameWrapper> encoded_frame) -> int {
|
[this](std::shared_ptr<VideoFrameWrapper> encoded_frame) -> int {
|
||||||
if (video_channel_send_) {
|
if (video_channel_send_) {
|
||||||
video_channel_send_->SendVideo(encoded_frame);
|
video_channel_send_->SendVideo(encoded_frame);
|
||||||
|
LOG_WARN("SendVideo rtp packets");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -205,6 +228,17 @@ int IceTransportController::SendData(const char* data, size_t size) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IceTransportController::UpdateNetworkAvaliablity(bool network_available) {
|
||||||
|
if (controller_) {
|
||||||
|
webrtc::NetworkAvailability msg;
|
||||||
|
msg.at_time =
|
||||||
|
webrtc::Timestamp::Millis(webrtc_clock_->TimeInMilliseconds());
|
||||||
|
msg.network_available = network_available;
|
||||||
|
controller_->OnNetworkAvailability(msg);
|
||||||
|
packet_sender_->EnsureStarted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int IceTransportController::OnReceiveVideoRtpPacket(const char* data,
|
int IceTransportController::OnReceiveVideoRtpPacket(const char* data,
|
||||||
size_t size) {
|
size_t size) {
|
||||||
if (video_channel_receive_) {
|
if (video_channel_receive_) {
|
||||||
@@ -486,7 +520,7 @@ void IceTransportController::PostUpdates(webrtc::NetworkControlUpdate update) {
|
|||||||
target_height_.reset();
|
target_height_.reset();
|
||||||
}
|
}
|
||||||
video_encoder_->SetTargetBitrate(target_bitrate_);
|
video_encoder_->SetTargetBitrate(target_bitrate_);
|
||||||
LOG_WARN("Set target bitrate [{}]bps", target_bitrate_);
|
// LOG_WARN("Set target bitrate [{}]bps", target_bitrate_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ class IceTransportController
|
|||||||
|
|
||||||
void FullIntraRequest() { b_force_i_frame_ = true; }
|
void FullIntraRequest() { b_force_i_frame_ = true; }
|
||||||
|
|
||||||
|
void UpdateNetworkAvaliablity(bool network_available);
|
||||||
|
|
||||||
int OnReceiveVideoRtpPacket(const char *data, size_t size);
|
int OnReceiveVideoRtpPacket(const char *data, size_t size);
|
||||||
int OnReceiveAudioRtpPacket(const char *data, size_t size);
|
int OnReceiveAudioRtpPacket(const char *data, size_t size);
|
||||||
int OnReceiveDataRtpPacket(const char *data, size_t size);
|
int OnReceiveDataRtpPacket(const char *data, size_t size);
|
||||||
|
|||||||
@@ -3,116 +3,244 @@
|
|||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
const int PacketSender::kNoPacketHoldback = -1;
|
||||||
|
|
||||||
PacketSender::PacketSender(std::shared_ptr<IceAgent> ice_agent,
|
PacketSender::PacketSender(std::shared_ptr<IceAgent> ice_agent,
|
||||||
std::shared_ptr<webrtc::Clock> clock)
|
std::shared_ptr<webrtc::Clock> clock)
|
||||||
: ice_agent_(ice_agent),
|
: ice_agent_(ice_agent),
|
||||||
clock_(clock),
|
clock_(clock),
|
||||||
pacing_controller_(clock.get(), this) {}
|
pacing_controller_(clock.get(), this),
|
||||||
|
max_hold_back_window_(webrtc::TimeDelta::Millis(5)),
|
||||||
|
max_hold_back_window_in_packets_(3),
|
||||||
|
next_process_time_(webrtc::Timestamp::MinusInfinity()),
|
||||||
|
is_started_(false),
|
||||||
|
is_shutdown_(false),
|
||||||
|
packet_size_(/*alpha=*/0.95),
|
||||||
|
include_overhead_(false) {}
|
||||||
|
|
||||||
PacketSender::~PacketSender() {}
|
PacketSender::~PacketSender() {}
|
||||||
|
|
||||||
// int PacketSender::SendPacket(const char *data, size_t size) {
|
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>>
|
||||||
// LOG_INFO("Send packet, size: %d", size);
|
PacketSender::GeneratePadding(webrtc::DataSize size) {
|
||||||
// return ice_agent_->Send(data, size);
|
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> to_send_rtp_packets;
|
||||||
// }
|
std::vector<std::unique_ptr<RtpPacket>> rtp_packets =
|
||||||
|
generat_padding_func_(size.bytes(), clock_->CurrentTime().ms());
|
||||||
|
// for (auto &packet : rtp_packets) {
|
||||||
|
// std::unique_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send(
|
||||||
|
// static_cast<webrtc::RtpPacketToSend *>(packet.release()));
|
||||||
|
// to_send_rtp_packets.push_back(std::move(rtp_packet_to_send));
|
||||||
|
// }
|
||||||
|
|
||||||
// void PacketSender::CreateProbeClusters(
|
return to_send_rtp_packets;
|
||||||
// std::vector<webrtc::ProbeClusterConfig> probe_cluster_configs) {
|
}
|
||||||
// pacing_controller_.CreateProbeClusters(probe_cluster_configs);
|
|
||||||
// MaybeScheduleProcessPackets();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void PacketSender::MaybeScheduleProcessPackets() {
|
void PacketSender::SetSendBurstInterval(webrtc::TimeDelta burst_interval) {
|
||||||
// if (!processing_packets_)
|
pacing_controller_.SetSendBurstInterval(burst_interval);
|
||||||
// MaybeProcessPackets(webrtc::Timestamp::MinusInfinity());
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// void PacketSender::MaybeProcessPackets(
|
void PacketSender::SetAllowProbeWithoutMediaPacket(bool allow) {
|
||||||
// webrtc::Timestamp scheduled_process_time) {
|
pacing_controller_.SetAllowProbeWithoutMediaPacket(allow);
|
||||||
// if (is_shutdown_ || !is_started_) {
|
}
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Protects against re-entry from transport feedback calling into the task
|
void PacketSender::EnsureStarted() {
|
||||||
// // queue pacer.
|
is_started_ = true;
|
||||||
// processing_packets_ = true;
|
MaybeProcessPackets(webrtc::Timestamp::MinusInfinity());
|
||||||
// auto cleanup = std::unique_ptr<void, std::function<void(void *)>>(
|
}
|
||||||
// nullptr, [this](void *) { processing_packets_ = false; });
|
|
||||||
|
|
||||||
// webrtc::Timestamp next_send_time = pacing_controller_.NextSendTime();
|
void PacketSender::Pause() { pacing_controller_.Pause(); }
|
||||||
// const webrtc::Timestamp now = clock_->CurrentTime();
|
|
||||||
// webrtc::TimeDelta early_execute_margin =
|
|
||||||
// pacing_controller_.IsProbing()
|
|
||||||
// ? webrtc::PacingController::kMaxEarlyProbeProcessing
|
|
||||||
// : webrtc::TimeDelta::Zero();
|
|
||||||
|
|
||||||
// // Process packets and update stats.
|
void PacketSender::Resume() {
|
||||||
// while (next_send_time <= now + early_execute_margin) {
|
pacing_controller_.Resume();
|
||||||
// pacing_controller_.ProcessPackets();
|
MaybeProcessPackets(webrtc::Timestamp::MinusInfinity());
|
||||||
// next_send_time = pacing_controller_.NextSendTime();
|
}
|
||||||
|
|
||||||
// // Probing state could change. Get margin after process packets.
|
void PacketSender::SetCongested(bool congested) {
|
||||||
// early_execute_margin =
|
pacing_controller_.SetCongested(congested);
|
||||||
// pacing_controller_.IsProbing()
|
MaybeScheduleProcessPackets();
|
||||||
// ? webrtc::PacingController::kMaxEarlyProbeProcessing
|
}
|
||||||
// : webrtc::TimeDelta::Zero();
|
|
||||||
// }
|
|
||||||
// UpdateStats();
|
|
||||||
|
|
||||||
// // Ignore retired scheduled task, otherwise reset `next_process_time_`.
|
void PacketSender::SetPacingRates(webrtc::DataRate pacing_rate,
|
||||||
// if (scheduled_process_time.IsFinite()) {
|
webrtc::DataRate padding_rate) {
|
||||||
// if (scheduled_process_time != next_process_time_) {
|
pacing_controller_.SetPacingRates(pacing_rate, padding_rate);
|
||||||
// return;
|
MaybeScheduleProcessPackets();
|
||||||
// }
|
}
|
||||||
// next_process_time_ = webrtc::Timestamp::MinusInfinity();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Do not hold back in probing.
|
void PacketSender::EnqueuePackets(
|
||||||
// webrtc::TimeDelta hold_back_window = webrtc::TimeDelta::Zero();
|
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> packets) {
|
||||||
// if (!pacing_controller_.IsProbing()) {
|
// task_queue_->PostTask()
|
||||||
// hold_back_window = max_hold_back_window_;
|
for (auto &packet : packets) {
|
||||||
// webrtc::DataRate pacing_rate = pacing_controller_.pacing_rate();
|
size_t packet_size = packet->payload_size() + packet->padding_size();
|
||||||
// if (max_hold_back_window_in_packets_ != kNoPacketHoldback &&
|
if (include_overhead_) {
|
||||||
// !pacing_rate.IsZero() &&
|
packet_size += packet->headers_size();
|
||||||
// packet_size_.filtered() != rtc::ExpFilter::kValueUndefined) {
|
}
|
||||||
// webrtc::TimeDelta avg_packet_send_time =
|
packet_size_.Apply(1, packet_size);
|
||||||
// webrtc::DataSize::Bytes(packet_size_.filtered()) / pacing_rate;
|
pacing_controller_.EnqueuePacket(std::move(packet));
|
||||||
// hold_back_window =
|
}
|
||||||
// std::min(hold_back_window,
|
MaybeProcessPackets(webrtc::Timestamp::MinusInfinity());
|
||||||
// avg_packet_send_time * max_hold_back_window_in_packets_);
|
}
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Calculate next process time.
|
void PacketSender::RemovePacketsForSsrc(uint32_t ssrc) {
|
||||||
// webrtc::TimeDelta time_to_next_process =
|
// task_queue_->PostTask(SafeTask(safety_.flag(), [this, ssrc] {
|
||||||
// std::max(hold_back_window, next_send_time - now -
|
pacing_controller_.RemovePacketsForSsrc(ssrc);
|
||||||
// early_execute_margin);
|
MaybeProcessPackets(webrtc::Timestamp::MinusInfinity());
|
||||||
// next_send_time = now + time_to_next_process;
|
// }));
|
||||||
|
}
|
||||||
|
|
||||||
// // If no in flight task or in flight task is later than `next_send_time`,
|
void PacketSender::SetAccountForAudioPackets(bool account_for_audio) {
|
||||||
// // schedule a new one. Previous in flight task will be retired.
|
pacing_controller_.SetAccountForAudioPackets(account_for_audio);
|
||||||
// if (next_process_time_.IsMinusInfinity() ||
|
MaybeProcessPackets(webrtc::Timestamp::MinusInfinity());
|
||||||
// next_process_time_ > next_send_time) {
|
}
|
||||||
// // Prefer low precision if allowed and not probing.
|
|
||||||
// task_queue_->PostDelayedHighPrecisionTask(
|
|
||||||
// SafeTask(
|
|
||||||
// safety_.flag(),
|
|
||||||
// [this, next_send_time]() { MaybeProcessPackets(next_send_time);
|
|
||||||
// }),
|
|
||||||
// time_to_next_process.RoundUpTo(webrtc::TimeDelta::Millis(1)));
|
|
||||||
// next_process_time_ = next_send_time;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void PacketSender::UpdateStats() {
|
void PacketSender::SetIncludeOverhead() {
|
||||||
// Stats new_stats;
|
include_overhead_ = true;
|
||||||
// new_stats.expected_queue_time = pacing_controller_.ExpectedQueueTime();
|
pacing_controller_.SetIncludeOverhead();
|
||||||
// new_stats.first_sent_packet_time =
|
MaybeProcessPackets(webrtc::Timestamp::MinusInfinity());
|
||||||
// pacing_controller_.FirstSentPacketTime();
|
}
|
||||||
// new_stats.oldest_packet_enqueue_time =
|
|
||||||
// pacing_controller_.OldestPacketEnqueueTime();
|
|
||||||
// new_stats.queue_size = pacing_controller_.QueueSizeData();
|
|
||||||
// OnStatsUpdated(new_stats);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// PacketSender::Stats PacketSender::GetStats() const { return current_stats_; }
|
void PacketSender::SetTransportOverhead(webrtc::DataSize overhead_per_packet) {
|
||||||
|
pacing_controller_.SetTransportOverhead(overhead_per_packet);
|
||||||
|
MaybeProcessPackets(webrtc::Timestamp::MinusInfinity());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketSender::SetQueueTimeLimit(webrtc::TimeDelta limit) {
|
||||||
|
pacing_controller_.SetQueueTimeLimit(limit);
|
||||||
|
MaybeProcessPackets(webrtc::Timestamp::MinusInfinity());
|
||||||
|
}
|
||||||
|
|
||||||
|
webrtc::TimeDelta PacketSender::ExpectedQueueTime() const {
|
||||||
|
return GetStats().expected_queue_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
webrtc::DataSize PacketSender::QueueSizeData() const {
|
||||||
|
return GetStats().queue_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<webrtc::Timestamp> PacketSender::FirstSentPacketTime() const {
|
||||||
|
return GetStats().first_sent_packet_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
webrtc::TimeDelta PacketSender::OldestPacketWaitTime() const {
|
||||||
|
webrtc::Timestamp oldest_packet = GetStats().oldest_packet_enqueue_time;
|
||||||
|
if (oldest_packet.IsInfinite()) {
|
||||||
|
return webrtc::TimeDelta::Zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
// (webrtc:9716): The clock is not always monotonic.
|
||||||
|
webrtc::Timestamp current = clock_->CurrentTime();
|
||||||
|
if (current < oldest_packet) {
|
||||||
|
return webrtc::TimeDelta::Zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
return current - oldest_packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketSender::CreateProbeClusters(
|
||||||
|
std::vector<webrtc::ProbeClusterConfig> probe_cluster_configs) {
|
||||||
|
pacing_controller_.CreateProbeClusters(probe_cluster_configs);
|
||||||
|
MaybeScheduleProcessPackets();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketSender::OnStatsUpdated(const Stats &stats) {
|
||||||
|
current_stats_ = stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketSender::MaybeScheduleProcessPackets() {
|
||||||
|
LOG_ERROR("x1");
|
||||||
|
if (!processing_packets_) {
|
||||||
|
LOG_ERROR("x2");
|
||||||
|
MaybeProcessPackets(webrtc::Timestamp::MinusInfinity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketSender::MaybeProcessPackets(
|
||||||
|
webrtc::Timestamp scheduled_process_time) {
|
||||||
|
if (is_shutdown_ || !is_started_) {
|
||||||
|
LOG_ERROR("shutdown {}, started {}", is_shutdown_, is_started_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protects against re-entry from transport feedback calling into the task
|
||||||
|
// queue pacer.
|
||||||
|
processing_packets_ = true;
|
||||||
|
// auto cleanup = std::unique_ptr<void, std::function<void(void *)>>(
|
||||||
|
// nullptr, [this](void *) { processing_packets_ = false; });
|
||||||
|
|
||||||
|
webrtc::Timestamp next_send_time = pacing_controller_.NextSendTime();
|
||||||
|
const webrtc::Timestamp now = clock_->CurrentTime();
|
||||||
|
webrtc::TimeDelta early_execute_margin =
|
||||||
|
pacing_controller_.IsProbing()
|
||||||
|
? webrtc::PacingController::kMaxEarlyProbeProcessing
|
||||||
|
: webrtc::TimeDelta::Zero();
|
||||||
|
|
||||||
|
// Process packets and update stats.
|
||||||
|
while (next_send_time <= now + early_execute_margin) {
|
||||||
|
pacing_controller_.ProcessPackets();
|
||||||
|
next_send_time = pacing_controller_.NextSendTime();
|
||||||
|
|
||||||
|
// Probing state could change. Get margin after process packets.
|
||||||
|
early_execute_margin =
|
||||||
|
pacing_controller_.IsProbing()
|
||||||
|
? webrtc::PacingController::kMaxEarlyProbeProcessing
|
||||||
|
: webrtc::TimeDelta::Zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateStats();
|
||||||
|
|
||||||
|
// Ignore retired scheduled task, otherwise reset `next_process_time_`.
|
||||||
|
if (scheduled_process_time.IsFinite()) {
|
||||||
|
if (scheduled_process_time != next_process_time_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
next_process_time_ = webrtc::Timestamp::MinusInfinity();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not hold back in probing.
|
||||||
|
webrtc::TimeDelta hold_back_window = webrtc::TimeDelta::Zero();
|
||||||
|
if (!pacing_controller_.IsProbing()) {
|
||||||
|
hold_back_window = max_hold_back_window_;
|
||||||
|
webrtc::DataRate pacing_rate = pacing_controller_.pacing_rate();
|
||||||
|
if (max_hold_back_window_in_packets_ != kNoPacketHoldback &&
|
||||||
|
!pacing_rate.IsZero() &&
|
||||||
|
packet_size_.filtered() != rtc::ExpFilter::kValueUndefined) {
|
||||||
|
webrtc::TimeDelta avg_packet_send_time =
|
||||||
|
webrtc::DataSize::Bytes(packet_size_.filtered()) / pacing_rate;
|
||||||
|
hold_back_window =
|
||||||
|
std::min(hold_back_window,
|
||||||
|
avg_packet_send_time * max_hold_back_window_in_packets_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate next process time.
|
||||||
|
webrtc::TimeDelta time_to_next_process =
|
||||||
|
std::max(hold_back_window, next_send_time - now - early_execute_margin);
|
||||||
|
next_send_time = now + time_to_next_process;
|
||||||
|
|
||||||
|
// If no in flight task or in flight task is later than `next_send_time`,
|
||||||
|
// schedule a new one. Previous in flight task will be retired.
|
||||||
|
if (next_process_time_.IsMinusInfinity() ||
|
||||||
|
next_process_time_ > next_send_time) {
|
||||||
|
// Prefer low precision if allowed and not probing.
|
||||||
|
// task_queue_->PostDelayedHighPrecisionTask(
|
||||||
|
// SafeTask(
|
||||||
|
// safety_.flag(),
|
||||||
|
// [this, next_send_time]() { MaybeProcessPackets(next_send_time);
|
||||||
|
// }),
|
||||||
|
MaybeProcessPackets(next_send_time);
|
||||||
|
time_to_next_process.RoundUpTo(webrtc::TimeDelta::Millis(1));
|
||||||
|
next_process_time_ = next_send_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
processing_packets_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketSender::UpdateStats() {
|
||||||
|
Stats new_stats;
|
||||||
|
new_stats.expected_queue_time = pacing_controller_.ExpectedQueueTime();
|
||||||
|
new_stats.first_sent_packet_time = pacing_controller_.FirstSentPacketTime();
|
||||||
|
new_stats.oldest_packet_enqueue_time =
|
||||||
|
pacing_controller_.OldestPacketEnqueueTime();
|
||||||
|
new_stats.queue_size = pacing_controller_.QueueSizeData();
|
||||||
|
OnStatsUpdated(new_stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketSender::Stats PacketSender::GetStats() const { return current_stats_; }
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "api/units/time_delta.h"
|
#include "api/units/time_delta.h"
|
||||||
#include "api/units/timestamp.h"
|
#include "api/units/timestamp.h"
|
||||||
#include "ice_agent.h"
|
#include "ice_agent.h"
|
||||||
|
#include "log.h"
|
||||||
#include "pacing_controller.h"
|
#include "pacing_controller.h"
|
||||||
#include "rtc_base/numerics/exp_filter.h"
|
#include "rtc_base/numerics/exp_filter.h"
|
||||||
#include "rtp_packet_pacer.h"
|
#include "rtp_packet_pacer.h"
|
||||||
@@ -24,74 +25,38 @@
|
|||||||
class PacketSender : public webrtc::RtpPacketPacer,
|
class PacketSender : public webrtc::RtpPacketPacer,
|
||||||
public webrtc::PacingController::PacketSender {
|
public webrtc::PacingController::PacketSender {
|
||||||
public:
|
public:
|
||||||
|
static const int kNoPacketHoldback;
|
||||||
|
|
||||||
PacketSender(std::shared_ptr<IceAgent> ice_agent,
|
PacketSender(std::shared_ptr<IceAgent> ice_agent,
|
||||||
std::shared_ptr<webrtc::Clock> clock);
|
std::shared_ptr<webrtc::Clock> clock);
|
||||||
~PacketSender();
|
~PacketSender();
|
||||||
|
|
||||||
int SendPacket(const char* data, size_t size);
|
void SetOnSentPacketFunc(
|
||||||
|
std::function<void(const webrtc::RtpPacketToSend&)> on_sent_packet_func) {
|
||||||
public:
|
on_sent_packet_func_ = on_sent_packet_func;
|
||||||
void CreateProbeClusters(
|
|
||||||
std::vector<webrtc::ProbeClusterConfig> probe_cluster_configs) override{};
|
|
||||||
|
|
||||||
// Temporarily pause all sending.
|
|
||||||
void Pause() override{};
|
|
||||||
|
|
||||||
// Resume sending packets.
|
|
||||||
void Resume() override{};
|
|
||||||
|
|
||||||
void SetCongested(bool congested) override{};
|
|
||||||
|
|
||||||
// Sets the pacing rates. Must be called once before packets can be sent.
|
|
||||||
void SetPacingRates(webrtc::DataRate pacing_rate,
|
|
||||||
webrtc::DataRate padding_rate) override{};
|
|
||||||
|
|
||||||
// Time since the oldest packet currently in the queue was added.
|
|
||||||
webrtc::TimeDelta OldestPacketWaitTime() const override {
|
|
||||||
return webrtc::TimeDelta::Zero();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Sum of payload + padding bytes of all packets currently in the pacer queue.
|
|
||||||
webrtc::DataSize QueueSizeData() const override {
|
|
||||||
return webrtc::DataSize::Zero();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns the time when the first packet was sent.
|
|
||||||
std::optional<webrtc::Timestamp> FirstSentPacketTime() const override {
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the expected number of milliseconds it will take to send the
|
void SetGeneratePaddingFunc(
|
||||||
// current packets in the queue, given the current size and bitrate, ignoring
|
std::function<std::vector<std::unique_ptr<RtpPacket>>(uint32_t, int64_t)>
|
||||||
// priority.
|
generat_padding_func) {
|
||||||
webrtc::TimeDelta ExpectedQueueTime() const override {
|
generat_padding_func_ = generat_padding_func;
|
||||||
return webrtc::TimeDelta::Zero();
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// Set the average upper bound on pacer queuing delay. The pacer may send at
|
|
||||||
// a higher rate than what was configured via SetPacingRates() in order to
|
|
||||||
// keep ExpectedQueueTimeMs() below `limit_ms` on average.
|
|
||||||
void SetQueueTimeLimit(webrtc::TimeDelta limit) override{};
|
|
||||||
|
|
||||||
// Currently audio traffic is not accounted by pacer and passed through.
|
|
||||||
// With the introduction of audio BWE audio traffic will be accounted for
|
|
||||||
// the pacer budget calculation. The audio traffic still will be injected
|
|
||||||
// at high priority.
|
|
||||||
void SetAccountForAudioPackets(bool account_for_audio) override{};
|
|
||||||
void SetIncludeOverhead() override{};
|
|
||||||
void SetTransportOverhead(webrtc::DataSize overhead_per_packet) override{};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void SendPacket(std::unique_ptr<webrtc::RtpPacketToSend> packet,
|
void SendPacket(std::unique_ptr<webrtc::RtpPacketToSend> packet,
|
||||||
const webrtc::PacedPacketInfo& cluster_info) override {}
|
const webrtc::PacedPacketInfo& cluster_info) override {
|
||||||
|
if (on_sent_packet_func_) {
|
||||||
|
on_sent_packet_func_(*packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Should be called after each call to SendPacket().
|
// Should be called after each call to SendPacket().
|
||||||
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> FetchFec() override {
|
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> FetchFec() override {
|
||||||
return {};
|
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> fec_packets;
|
||||||
|
return fec_packets;
|
||||||
}
|
}
|
||||||
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> GeneratePadding(
|
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> GeneratePadding(
|
||||||
webrtc::DataSize size) override {
|
webrtc::DataSize size) override;
|
||||||
return {};
|
|
||||||
}
|
|
||||||
// TODO(bugs.webrtc.org/1439830): Make pure once subclasses adapt.
|
// TODO(bugs.webrtc.org/1439830): Make pure once subclasses adapt.
|
||||||
void OnBatchComplete() override {}
|
void OnBatchComplete() override {}
|
||||||
|
|
||||||
@@ -105,12 +70,133 @@ class PacketSender : public webrtc::RtpPacketPacer,
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void SetSendBurstInterval(webrtc::TimeDelta burst_interval);
|
||||||
|
|
||||||
|
// A probe may be sent without first waing for a media packet.
|
||||||
|
void SetAllowProbeWithoutMediaPacket(bool allow);
|
||||||
|
|
||||||
|
// Ensure that necessary delayed tasks are scheduled.
|
||||||
|
void EnsureStarted();
|
||||||
|
|
||||||
|
// Methods implementing RtpPacketSender.
|
||||||
|
|
||||||
|
// Adds the packet to the queue and calls
|
||||||
|
// PacingController::PacketSender::SendPacket() when it's time to send.
|
||||||
|
void EnqueuePackets(
|
||||||
|
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> packets);
|
||||||
|
// Remove any pending packets matching this SSRC from the packet queue.
|
||||||
|
void RemovePacketsForSsrc(uint32_t ssrc);
|
||||||
|
|
||||||
|
void CreateProbeClusters(
|
||||||
|
std::vector<webrtc::ProbeClusterConfig> probe_cluster_configs) override;
|
||||||
|
|
||||||
|
// Temporarily pause all sending.
|
||||||
|
void Pause() override;
|
||||||
|
|
||||||
|
// Resume sending packets.
|
||||||
|
void Resume() override;
|
||||||
|
|
||||||
|
void SetCongested(bool congested) override;
|
||||||
|
|
||||||
|
// Sets the pacing rates. Must be called once before packets can be sent.
|
||||||
|
void SetPacingRates(webrtc::DataRate pacing_rate,
|
||||||
|
webrtc::DataRate padding_rate) override;
|
||||||
|
|
||||||
|
// Currently audio traffic is not accounted for by pacer and passed through.
|
||||||
|
// With the introduction of audio BWE, audio traffic will be accounted for
|
||||||
|
// in the pacer budget calculation. The audio traffic will still be injected
|
||||||
|
// at high priority.
|
||||||
|
void SetAccountForAudioPackets(bool account_for_audio) override;
|
||||||
|
|
||||||
|
void SetIncludeOverhead() override;
|
||||||
|
void SetTransportOverhead(webrtc::DataSize overhead_per_packet) override;
|
||||||
|
|
||||||
|
// Time since the oldest packet currently in the queue was added.
|
||||||
|
webrtc::TimeDelta OldestPacketWaitTime() const override;
|
||||||
|
|
||||||
|
// Sum of payload + padding bytes of all packets currently in the pacer queue.
|
||||||
|
webrtc::DataSize QueueSizeData() const override;
|
||||||
|
|
||||||
|
// Returns the time when the first packet was sent.
|
||||||
|
std::optional<webrtc::Timestamp> FirstSentPacketTime() const override;
|
||||||
|
|
||||||
|
// Returns the expected number of milliseconds it will take to send the
|
||||||
|
// current packets in the queue, given the current size and bitrate, ignoring
|
||||||
|
// priority.
|
||||||
|
webrtc::TimeDelta ExpectedQueueTime() const override;
|
||||||
|
|
||||||
|
// Set the average upper bound on pacer queuing delay. The pacer may send at
|
||||||
|
// a higher rate than what was configured via SetPacingRates() in order to
|
||||||
|
// keep ExpectedQueueTimeMs() below `limit_ms` on average.
|
||||||
|
void SetQueueTimeLimit(webrtc::TimeDelta limit) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Exposed as protected for test.
|
||||||
|
struct Stats {
|
||||||
|
Stats()
|
||||||
|
: oldest_packet_enqueue_time(webrtc::Timestamp::MinusInfinity()),
|
||||||
|
queue_size(webrtc::DataSize::Zero()),
|
||||||
|
expected_queue_time(webrtc::TimeDelta::Zero()) {}
|
||||||
|
webrtc::Timestamp oldest_packet_enqueue_time;
|
||||||
|
webrtc::DataSize queue_size;
|
||||||
|
webrtc::TimeDelta expected_queue_time;
|
||||||
|
std::optional<webrtc::Timestamp> first_sent_packet_time;
|
||||||
|
};
|
||||||
|
void OnStatsUpdated(const Stats& stats);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Call in response to state updates that could warrant sending out packets.
|
||||||
|
// Protected against re-entry from packet sent receipts.
|
||||||
|
void MaybeScheduleProcessPackets();
|
||||||
|
// Check if it is time to send packets, or schedule a delayed task if not.
|
||||||
|
// Use Timestamp::MinusInfinity() to indicate that this call has _not_
|
||||||
|
// been scheduled by the pacing controller. If this is the case, check if we
|
||||||
|
// can execute immediately otherwise schedule a delay task that calls this
|
||||||
|
// method again with desired (finite) scheduled process time.
|
||||||
|
void MaybeProcessPackets(webrtc::Timestamp scheduled_process_time);
|
||||||
|
|
||||||
|
void UpdateStats();
|
||||||
|
Stats GetStats() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<IceAgent> ice_agent_ = nullptr;
|
std::shared_ptr<IceAgent> ice_agent_ = nullptr;
|
||||||
webrtc::PacingController pacing_controller_;
|
webrtc::PacingController pacing_controller_;
|
||||||
|
std::function<void(const webrtc::RtpPacketToSend&)> on_sent_packet_func_ =
|
||||||
|
nullptr;
|
||||||
|
|
||||||
|
std::function<std::vector<std::unique_ptr<RtpPacket>>(uint32_t, int64_t)>
|
||||||
|
generat_padding_func_ = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<webrtc::Clock> clock_ = nullptr;
|
std::shared_ptr<webrtc::Clock> clock_ = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const webrtc::TimeDelta max_hold_back_window_;
|
||||||
|
const int max_hold_back_window_in_packets_;
|
||||||
|
// We want only one (valid) delayed process task in flight at a time.
|
||||||
|
// If the value of `next_process_time_` is finite, it is an id for a
|
||||||
|
// delayed task that will call MaybeProcessPackets() with that time
|
||||||
|
// as parameter.
|
||||||
|
// Timestamp::MinusInfinity() indicates no valid pending task.
|
||||||
|
webrtc::Timestamp next_process_time_;
|
||||||
|
|
||||||
|
// Indicates if this task queue is started. If not, don't allow
|
||||||
|
// posting delayed tasks yet.
|
||||||
|
bool is_started_;
|
||||||
|
|
||||||
|
// Indicates if this task queue is shutting down. If so, don't allow
|
||||||
|
// posting any more delayed tasks as that can cause the task queue to
|
||||||
|
// never drain.
|
||||||
|
bool is_shutdown_;
|
||||||
|
|
||||||
|
// Filtered size of enqueued packets, in bytes.
|
||||||
|
rtc::ExpFilter packet_size_;
|
||||||
|
bool include_overhead_;
|
||||||
|
|
||||||
|
Stats current_stats_;
|
||||||
|
// Protects against ProcessPackets reentry from packet sent receipts.
|
||||||
|
bool processing_packets_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user