mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 20:25:34 +08:00
[feat] add timestamp to sender report
This commit is contained in:
@@ -30,7 +30,7 @@ void RtpAudioSender::Enqueue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto& rtp_packet : rtp_packets) {
|
for (auto& rtp_packet : rtp_packets) {
|
||||||
rtp_packe_queue_.push(rtp_packet);
|
rtp_packet_queue_.push(rtp_packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,9 +139,9 @@ bool RtpAudioSender::Process() {
|
|||||||
last_send_bytes_ = 0;
|
last_send_bytes_ = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < 10; i++)
|
for (size_t i = 0; i < 10; i++)
|
||||||
if (!rtp_packe_queue_.isEmpty()) {
|
if (!rtp_packet_queue_.isEmpty()) {
|
||||||
std::shared_ptr<RtpPacket> rtp_packet;
|
std::shared_ptr<RtpPacket> rtp_packet;
|
||||||
rtp_packe_queue_.pop(rtp_packet);
|
rtp_packet_queue_.pop(rtp_packet);
|
||||||
SendRtpPacket(rtp_packet);
|
SendRtpPacket(rtp_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,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_packe_queue_;
|
RingBuffer<std::shared_ptr<RtpPacket>> rtp_packet_queue_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t ssrc_ = 0;
|
uint32_t ssrc_ = 0;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ void RtpDataSender::Enqueue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto& rtp_packet : rtp_packets) {
|
for (auto& rtp_packet : rtp_packets) {
|
||||||
rtp_packe_queue_.push(rtp_packet);
|
rtp_packet_queue_.push(rtp_packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,9 +139,9 @@ bool RtpDataSender::Process() {
|
|||||||
last_send_bytes_ = 0;
|
last_send_bytes_ = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < 10; i++)
|
for (size_t i = 0; i < 10; i++)
|
||||||
if (!rtp_packe_queue_.isEmpty()) {
|
if (!rtp_packet_queue_.isEmpty()) {
|
||||||
std::shared_ptr<RtpPacket> rtp_packet;
|
std::shared_ptr<RtpPacket> rtp_packet;
|
||||||
rtp_packe_queue_.pop(rtp_packet);
|
rtp_packet_queue_.pop(rtp_packet);
|
||||||
SendRtpPacket(rtp_packet);
|
SendRtpPacket(rtp_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,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_packe_queue_;
|
RingBuffer<std::shared_ptr<RtpPacket>> rtp_packet_queue_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t ssrc_ = 0;
|
uint32_t ssrc_ = 0;
|
||||||
|
|||||||
@@ -44,14 +44,21 @@ RtpVideoSender::~RtpVideoSender() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RtpVideoSender::Enqueue(
|
void RtpVideoSender::Enqueue(
|
||||||
std::vector<std::shared_ptr<RtpPacket>>& rtp_packets) {
|
std::vector<std::shared_ptr<RtpPacket>>& rtp_packets,
|
||||||
|
int64_t capture_timestamp) {
|
||||||
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_packe_queue_.push(std::move(rtp_packet));
|
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send =
|
||||||
|
std::dynamic_pointer_cast<webrtc::RtpPacketToSend>(rtp_packet);
|
||||||
|
rtp_packet_to_send->set_capture_time(
|
||||||
|
webrtc::Timestamp::Millis(capture_timestamp));
|
||||||
|
rtp_packet_to_send->set_transport_sequence_number(transport_seq_++);
|
||||||
|
rtp_packet_to_send->set_packet_type(webrtc::RtpPacketMediaType::kVideo);
|
||||||
|
rtp_packet_queue_.push(std::move(rtp_packet_to_send));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,34 +72,32 @@ void RtpVideoSender::SetOnSentPacketFunc(
|
|||||||
on_sent_packet_func_ = on_sent_packet_func;
|
on_sent_packet_func_ = on_sent_packet_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RtpVideoSender::SendRtpPacket(std::shared_ptr<RtpPacket> rtp_packet) {
|
int RtpVideoSender::SendRtpPacket(
|
||||||
|
std::shared_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_) {
|
if (on_sent_packet_func_) {
|
||||||
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send =
|
|
||||||
std::dynamic_pointer_cast<webrtc::RtpPacketToSend>(rtp_packet);
|
|
||||||
rtp_packet_to_send->set_transport_sequence_number(transport_seq_++);
|
|
||||||
rtp_packet_to_send->set_packet_type(webrtc::RtpPacketMediaType::kVideo);
|
|
||||||
on_sent_packet_func_(*rtp_packet_to_send);
|
on_sent_packet_func_(*rtp_packet_to_send);
|
||||||
rtp_packet_history_->AddPacket(rtp_packet_to_send, clock_->CurrentTime());
|
rtp_packet_history_->AddPacket(rtp_packet_to_send, clock_->CurrentTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != data_send_func_((const char*)rtp_packet->Buffer().data(),
|
last_rtp_timestamp_ = rtp_packet_to_send->capture_time().ms();
|
||||||
rtp_packet->Size())) {
|
if (0 != data_send_func_((const char*)rtp_packet_to_send->Buffer().data(),
|
||||||
|
rtp_packet_to_send->Size())) {
|
||||||
// LOG_ERROR("Send rtp packet failed");
|
// LOG_ERROR("Send rtp packet failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SAVE_RTP_SENT_STREAM
|
#ifdef SAVE_RTP_SENT_STREAM
|
||||||
fwrite((unsigned char*)rtp_packet->Payload(), 1, rtp_packet->PayloadSize(),
|
fwrite((unsigned char*)rtp_packet_to_send->Payload(), 1,
|
||||||
file_rtp_sent_);
|
rtp_packet_to_send->PayloadSize(), file_rtp_sent_);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
last_send_bytes_ += (uint32_t)rtp_packet->Size();
|
last_send_bytes_ += (uint32_t)rtp_packet_to_send->Size();
|
||||||
total_rtp_payload_sent_ += (uint32_t)rtp_packet->PayloadSize();
|
total_rtp_payload_sent_ += (uint32_t)rtp_packet_to_send->PayloadSize();
|
||||||
total_rtp_packets_sent_++;
|
total_rtp_packets_sent_++;
|
||||||
|
|
||||||
if (io_statistics_) {
|
if (io_statistics_) {
|
||||||
@@ -103,13 +108,17 @@ int RtpVideoSender::SendRtpPacket(std::shared_ptr<RtpPacket> rtp_packet) {
|
|||||||
if (CheckIsTimeSendSR()) {
|
if (CheckIsTimeSendSR()) {
|
||||||
SenderReport rtcp_sr;
|
SenderReport rtcp_sr;
|
||||||
rtcp_sr.SetSenderSsrc(ssrc_);
|
rtcp_sr.SetSenderSsrc(ssrc_);
|
||||||
rtcp_sr.SetTimestamp(0);
|
|
||||||
rtcp_sr.SetNtpTimestamp(0);
|
uint32_t rtp_timestamp =
|
||||||
|
last_rtp_timestamp_ +
|
||||||
|
((clock_->CurrentTime().us() + 500) / 1000 - last_frame_capture_time_) *
|
||||||
|
rtp::kVideoPayloadTypeFrequency;
|
||||||
|
rtcp_sr.SetTimestamp(rtp_timestamp);
|
||||||
|
rtcp_sr.SetNtpTimestamp((uint64_t)clock_->CurrentNtpTime());
|
||||||
rtcp_sr.SetSenderPacketCount(total_rtp_packets_sent_);
|
rtcp_sr.SetSenderPacketCount(total_rtp_packets_sent_);
|
||||||
rtcp_sr.SetSenderOctetCount(total_rtp_payload_sent_);
|
rtcp_sr.SetSenderOctetCount(total_rtp_payload_sent_);
|
||||||
|
|
||||||
RtcpReportBlock report;
|
RtcpReportBlock report;
|
||||||
|
|
||||||
report.SetMediaSsrc(ssrc_);
|
report.SetMediaSsrc(ssrc_);
|
||||||
report.SetFractionLost(0);
|
report.SetFractionLost(0);
|
||||||
report.SetCumulativeLost(0);
|
report.SetCumulativeLost(0);
|
||||||
@@ -162,11 +171,11 @@ bool RtpVideoSender::Process() {
|
|||||||
last_send_bytes_ = 0;
|
last_send_bytes_ = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < 10; i++)
|
for (size_t i = 0; i < 10; i++)
|
||||||
if (!rtp_packe_queue_.isEmpty()) {
|
if (!rtp_packet_queue_.isEmpty()) {
|
||||||
std::shared_ptr<RtpPacket> rtp_packet;
|
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send;
|
||||||
pop_success = rtp_packe_queue_.pop(rtp_packet);
|
pop_success = rtp_packet_queue_.pop(rtp_packet_to_send);
|
||||||
if (pop_success) {
|
if (pop_success) {
|
||||||
SendRtpPacket(rtp_packet);
|
SendRtpPacket(rtp_packet_to_send);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,14 +22,16 @@ 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::shared_ptr<RtpPacket>> &rtp_packets,
|
||||||
|
int64_t capture_timestamp);
|
||||||
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);
|
||||||
uint32_t GetSsrc() { return ssrc_; }
|
uint32_t GetSsrc() { return ssrc_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int SendRtpPacket(std::shared_ptr<RtpPacket> rtp_packet);
|
int SendRtpPacket(
|
||||||
|
std::shared_ptr<webrtc::RtpPacketToSend> rtp_packet_to_send);
|
||||||
int SendRtcpSR(SenderReport &rtcp_sr);
|
int SendRtcpSR(SenderReport &rtcp_sr);
|
||||||
|
|
||||||
bool CheckIsTimeSendSR();
|
bool CheckIsTimeSendSR();
|
||||||
@@ -41,7 +43,7 @@ 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<RtpPacket>> rtp_packe_queue_;
|
RingBuffer<std::shared_ptr<webrtc::RtpPacketToSend>> rtp_packet_queue_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t ssrc_ = 0;
|
uint32_t ssrc_ = 0;
|
||||||
@@ -54,6 +56,9 @@ class RtpVideoSender : public ThreadBase {
|
|||||||
uint32_t total_rtp_payload_sent_ = 0;
|
uint32_t total_rtp_payload_sent_ = 0;
|
||||||
uint32_t total_rtp_packets_sent_ = 0;
|
uint32_t total_rtp_packets_sent_ = 0;
|
||||||
|
|
||||||
|
uint32_t last_rtp_timestamp_ = 0;
|
||||||
|
int64_t last_frame_capture_time_ = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t transport_seq_ = 0;
|
int64_t transport_seq_ = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ int VideoChannelSend::SendVideo(
|
|||||||
std::vector<std::shared_ptr<RtpPacket>> rtp_packets =
|
std::vector<std::shared_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(), true);
|
(uint32_t)encoded_frame->Size(), true);
|
||||||
rtp_video_sender_->Enqueue(rtp_packets);
|
rtp_video_sender_->Enqueue(rtp_packets, encoded_frame->CaptureTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -39,5 +39,7 @@ typedef struct {
|
|||||||
} FU_HEADER;
|
} FU_HEADER;
|
||||||
|
|
||||||
typedef enum { UNKNOWN = 0, NALU = 1, FU_A = 28, FU_B = 29 } NAL_UNIT_TYPE;
|
typedef enum { UNKNOWN = 0, NALU = 1, FU_A = 28, FU_B = 29 } NAL_UNIT_TYPE;
|
||||||
|
|
||||||
|
const int kVideoPayloadTypeFrequency = 90000;
|
||||||
} // namespace rtp
|
} // namespace rtp
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user