diff --git a/src/channel/audio_channel_send.cpp b/src/channel/audio_channel_send.cpp index 4d4bdf3..ebde3ca 100644 --- a/src/channel/audio_channel_send.cpp +++ b/src/channel/audio_channel_send.cpp @@ -47,8 +47,8 @@ void AudioChannelSend::Destroy() { int AudioChannelSend::SendAudio(char *data, size_t size) { if (rtp_audio_sender_ && rtp_packetizer_) { - std::vector rtp_packets = - rtp_packetizer_->Build((uint8_t *)data, (uint32_t)size); + std::vector> rtp_packets = + rtp_packetizer_->Build((uint8_t *)data, (uint32_t)size, true); rtp_audio_sender_->Enqueue(rtp_packets); } diff --git a/src/channel/data_channel_send.cpp b/src/channel/data_channel_send.cpp index 172c918..65f0cfc 100644 --- a/src/channel/data_channel_send.cpp +++ b/src/channel/data_channel_send.cpp @@ -47,8 +47,8 @@ void DataChannelSend::Destroy() { int DataChannelSend::SendData(const char *data, size_t size) { if (rtp_data_sender_ && rtp_packetizer_) { - std::vector rtp_packets = - rtp_packetizer_->Build((uint8_t *)data, (uint32_t)size); + std::vector> rtp_packets = + rtp_packetizer_->Build((uint8_t *)data, (uint32_t)size, true); rtp_data_sender_->Enqueue(rtp_packets); } diff --git a/src/channel/rtp_channel/rtp_audio_sender.cpp b/src/channel/rtp_channel/rtp_audio_sender.cpp index 9a1af5f..d989c29 100644 --- a/src/channel/rtp_channel/rtp_audio_sender.cpp +++ b/src/channel/rtp_channel/rtp_audio_sender.cpp @@ -22,7 +22,8 @@ RtpAudioSender::~RtpAudioSender() { SSRCManager::Instance().DeleteSsrc(ssrc_); } -void RtpAudioSender::Enqueue(std::vector& rtp_packets) { +void RtpAudioSender::Enqueue( + std::vector> rtp_packets) { if (!rtp_statistics_) { rtp_statistics_ = std::make_unique(); rtp_statistics_->Start(); @@ -38,20 +39,20 @@ void RtpAudioSender::SetSendDataFunc( data_send_func_ = data_send_func; } -int RtpAudioSender::SendRtpPacket(RtpPacket& rtp_packet) { +int RtpAudioSender::SendRtpPacket(std::shared_ptr rtp_packet) { if (!data_send_func_) { LOG_ERROR("data_send_func_ is nullptr"); return -1; } - if (0 != data_send_func_((const char*)rtp_packet.Buffer().data(), - rtp_packet.Size())) { + if (0 != data_send_func_((const char*)rtp_packet->Buffer().data(), + rtp_packet->Size())) { LOG_ERROR("Send rtp packet failed"); return -1; } - last_send_bytes_ += (uint32_t)rtp_packet.Size(); - total_rtp_payload_sent_ += (uint32_t)rtp_packet.PayloadSize(); + last_send_bytes_ += (uint32_t)rtp_packet->Size(); + total_rtp_payload_sent_ += (uint32_t)rtp_packet->PayloadSize(); total_rtp_packets_sent_++; if (io_statistics_) { @@ -136,7 +137,7 @@ bool RtpAudioSender::Process() { for (size_t i = 0; i < 10; i++) if (!rtp_packe_queue_.isEmpty()) { - RtpPacket rtp_packet; + std::shared_ptr rtp_packet; rtp_packe_queue_.pop(rtp_packet); SendRtpPacket(rtp_packet); } diff --git a/src/channel/rtp_channel/rtp_audio_sender.h b/src/channel/rtp_channel/rtp_audio_sender.h index 9fbf1e5..fea889c 100644 --- a/src/channel/rtp_channel/rtp_audio_sender.h +++ b/src/channel/rtp_channel/rtp_audio_sender.h @@ -23,12 +23,12 @@ class RtpAudioSender : public ThreadBase { virtual ~RtpAudioSender(); public: - void Enqueue(std::vector &rtp_packets); + void Enqueue(std::vector> rtp_packets); void SetSendDataFunc(std::function data_send_func); uint32_t GetSsrc() { return ssrc_; } private: - int SendRtpPacket(RtpPacket &rtp_packet); + int SendRtpPacket(std::shared_ptr rtp_packet); int SendRtcpSR(RtcpSenderReport &rtcp_sr); bool CheckIsTimeSendSR(); @@ -38,7 +38,7 @@ class RtpAudioSender : public ThreadBase { private: std::function data_send_func_ = nullptr; - RingBuffer rtp_packe_queue_; + RingBuffer> rtp_packe_queue_; private: uint32_t ssrc_ = 0; diff --git a/src/channel/rtp_channel/rtp_data_sender.cpp b/src/channel/rtp_channel/rtp_data_sender.cpp index 5eac720..c49591e 100644 --- a/src/channel/rtp_channel/rtp_data_sender.cpp +++ b/src/channel/rtp_channel/rtp_data_sender.cpp @@ -22,7 +22,8 @@ RtpDataSender::~RtpDataSender() { SSRCManager::Instance().DeleteSsrc(ssrc_); } -void RtpDataSender::Enqueue(std::vector& rtp_packets) { +void RtpDataSender::Enqueue( + std::vector> rtp_packets) { if (!rtp_statistics_) { rtp_statistics_ = std::make_unique(); rtp_statistics_->Start(); @@ -38,20 +39,20 @@ void RtpDataSender::SetSendDataFunc( data_send_func_ = data_send_func; } -int RtpDataSender::SendRtpPacket(RtpPacket& rtp_packet) { +int RtpDataSender::SendRtpPacket(std::shared_ptr rtp_packet) { if (!data_send_func_) { LOG_ERROR("data_send_func_ is nullptr"); return -1; } - if (0 != data_send_func_((const char*)rtp_packet.Buffer().data(), - rtp_packet.Size())) { + if (0 != data_send_func_((const char*)rtp_packet->Buffer().data(), + rtp_packet->Size())) { LOG_ERROR("Send rtp packet failed"); return -1; } - last_send_bytes_ += (uint32_t)rtp_packet.Size(); - total_rtp_payload_sent_ += (uint32_t)rtp_packet.PayloadSize(); + last_send_bytes_ += (uint32_t)rtp_packet->Size(); + total_rtp_payload_sent_ += (uint32_t)rtp_packet->PayloadSize(); total_rtp_packets_sent_++; if (io_statistics_) { @@ -136,7 +137,7 @@ bool RtpDataSender::Process() { for (size_t i = 0; i < 10; i++) if (!rtp_packe_queue_.isEmpty()) { - RtpPacket rtp_packet; + std::shared_ptr rtp_packet; rtp_packe_queue_.pop(rtp_packet); SendRtpPacket(rtp_packet); } diff --git a/src/channel/rtp_channel/rtp_data_sender.h b/src/channel/rtp_channel/rtp_data_sender.h index 0f68849..bec0e99 100644 --- a/src/channel/rtp_channel/rtp_data_sender.h +++ b/src/channel/rtp_channel/rtp_data_sender.h @@ -23,13 +23,13 @@ class RtpDataSender : public ThreadBase { virtual ~RtpDataSender(); public: - void Enqueue(std::vector &rtp_packets); + void Enqueue(std::vector> rtp_packets); void SetSendDataFunc(std::function data_send_func); uint32_t GetSsrc() { return ssrc_; } private: private: - int SendRtpPacket(RtpPacket &rtp_packet); + int SendRtpPacket(std::shared_ptr rtp_packet); int SendRtcpSR(RtcpSenderReport &rtcp_sr); bool CheckIsTimeSendSR(); @@ -39,7 +39,7 @@ class RtpDataSender : public ThreadBase { private: std::function data_send_func_ = nullptr; - RingBuffer rtp_packe_queue_; + RingBuffer> rtp_packe_queue_; private: uint32_t ssrc_ = 0; diff --git a/src/channel/rtp_channel/rtp_video_sender.cpp b/src/channel/rtp_channel/rtp_video_sender.cpp index aaeb57f..6c4f1c8 100644 --- a/src/channel/rtp_channel/rtp_video_sender.cpp +++ b/src/channel/rtp_channel/rtp_video_sender.cpp @@ -38,14 +38,15 @@ RtpVideoSender::~RtpVideoSender() { #endif } -void RtpVideoSender::Enqueue(std::vector& rtp_packets) { +void RtpVideoSender::Enqueue( + std::vector>& rtp_packets) { if (!rtp_statistics_) { rtp_statistics_ = std::make_unique(); rtp_statistics_->Start(); } for (auto& rtp_packet : rtp_packets) { - rtp_packe_queue_.push(rtp_packet); + rtp_packe_queue_.push(std::move(rtp_packet)); } } @@ -59,35 +60,33 @@ void RtpVideoSender::SetOnSentPacketFunc( on_sent_packet_func_ = on_sent_packet_func; } -int RtpVideoSender::SendRtpPacket(RtpPacket& rtp_packet) { +int RtpVideoSender::SendRtpPacket(std::shared_ptr rtp_packet) { if (!data_send_func_) { LOG_ERROR("data_send_func_ is nullptr"); return -1; } if (on_sent_packet_func_) { - webrtc::RtpPacketToSend rtp_packet_to_send; - rtp_packet_to_send.SetSequenceNumber(rtp_packet.SequenceNumber()); - rtp_packet_to_send.SetSsrc(rtp_packet.Ssrc()); - rtp_packet_to_send.SetSize(rtp_packet.Size()); - 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); + webrtc::RtpPacketToSend* rtp_packet_to_send = + dynamic_cast(rtp_packet.get()); + 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); } - if (0 != data_send_func_((const char*)rtp_packet.Buffer().data(), - rtp_packet.Size())) { + if (0 != data_send_func_((const char*)rtp_packet->Buffer().data(), + rtp_packet->Size())) { // LOG_ERROR("Send rtp packet failed"); return -1; } #ifdef SAVE_RTP_SENT_STREAM - fwrite((unsigned char*)rtp_packet.Payload(), 1, rtp_packet.PayloadSize(), + fwrite((unsigned char*)rtp_packet->Payload(), 1, rtp_packet->PayloadSize(), file_rtp_sent_); #endif - last_send_bytes_ += (uint32_t)rtp_packet.Size(); - total_rtp_payload_sent_ += (uint32_t)rtp_packet.PayloadSize(); + last_send_bytes_ += (uint32_t)rtp_packet->Size(); + total_rtp_payload_sent_ += (uint32_t)rtp_packet->PayloadSize(); total_rtp_packets_sent_++; if (io_statistics_) { @@ -131,7 +130,7 @@ int RtpVideoSender::SendRtpPacket(RtpPacket& rtp_packet) { rtcp_sr.Encode(); - // SendRtcpSR(rtcp_sr); + SendRtcpSR(rtcp_sr); } return 0; @@ -168,13 +167,16 @@ bool RtpVideoSender::CheckIsTimeSendSR() { } bool RtpVideoSender::Process() { + bool pop_success = false; last_send_bytes_ = 0; for (size_t i = 0; i < 10; i++) if (!rtp_packe_queue_.isEmpty()) { - RtpPacket rtp_packet; - rtp_packe_queue_.pop(rtp_packet); - SendRtpPacket(rtp_packet); + std::shared_ptr rtp_packet; + pop_success = rtp_packe_queue_.pop(rtp_packet); + if (pop_success) { + SendRtpPacket(rtp_packet); + } } if (rtp_statistics_) { diff --git a/src/channel/rtp_channel/rtp_video_sender.h b/src/channel/rtp_channel/rtp_video_sender.h index a4070ba..ab16d89 100644 --- a/src/channel/rtp_channel/rtp_video_sender.h +++ b/src/channel/rtp_channel/rtp_video_sender.h @@ -18,14 +18,14 @@ class RtpVideoSender : public ThreadBase { virtual ~RtpVideoSender(); public: - void Enqueue(std::vector &rtp_packets); + void Enqueue(std::vector> &rtp_packets); void SetSendDataFunc(std::function data_send_func); void SetOnSentPacketFunc( std::function on_sent_packet_func); uint32_t GetSsrc() { return ssrc_; } private: - int SendRtpPacket(RtpPacket &rtp_packet); + int SendRtpPacket(std::shared_ptr rtp_packet); int SendRtcpSR(RtcpSenderReport &rtcp_sr); bool CheckIsTimeSendSR(); @@ -37,7 +37,7 @@ class RtpVideoSender : public ThreadBase { std::function data_send_func_ = nullptr; std::function on_sent_packet_func_ = nullptr; - RingBuffer rtp_packe_queue_; + RingBuffer> rtp_packe_queue_; private: uint32_t ssrc_ = 0; diff --git a/src/channel/video_channel_send.cpp b/src/channel/video_channel_send.cpp index 88e3db5..a442004 100644 --- a/src/channel/video_channel_send.cpp +++ b/src/channel/video_channel_send.cpp @@ -58,8 +58,8 @@ void VideoChannelSend::Destroy() { int VideoChannelSend::SendVideo(char* data, size_t size) { if (rtp_video_sender_ && rtp_packetizer_) { - std::vector rtp_packets = - rtp_packetizer_->Build((uint8_t*)data, (uint32_t)size); + std::vector> rtp_packets = + rtp_packetizer_->Build((uint8_t*)data, (uint32_t)size, true); rtp_video_sender_->Enqueue(rtp_packets); } diff --git a/src/channel/video_channel_send.h b/src/channel/video_channel_send.h index c9ab41f..93fe63a 100644 --- a/src/channel/video_channel_send.h +++ b/src/channel/video_channel_send.h @@ -15,7 +15,6 @@ #include "ice_agent.h" #include "rtp_packetizer.h" #include "rtp_video_sender.h" -#include "transport_feedback.h" #include "transport_feedback_adapter.h" class VideoChannelSend { @@ -38,9 +37,6 @@ class VideoChannelSend { Timestamp recv_ts, const webrtc::rtcp::CongestionControlFeedback& feedback); - void HandleTransportPacketsFeedback( - const webrtc::TransportPacketsFeedback& feedback); - private: void PostUpdates(webrtc::NetworkControlUpdate update); void UpdateControlState(); diff --git a/src/common/api/rtp_rtcp/rtp_rtcp_typedef.h b/src/common/api/rtp_rtcp/rtp_rtcp_typedef.h new file mode 100644 index 0000000..e31fd18 --- /dev/null +++ b/src/common/api/rtp_rtcp/rtp_rtcp_typedef.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef _RTP_RTCP_TYPEDEF_H_ +#define _RTP_RTCP_TYPEDEF_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "api/array_view.h" +#include "api/transport/network_types.h" +#include "api/units/data_rate.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" + +#define RTCP_CNAME_SIZE 256 // RFC 3550 page 44, including null termination +#define IP_PACKET_SIZE 1500 // we assume ethernet + +namespace webrtc { + +const int kVideoPayloadTypeFrequency = 90000; + +// TODO(bugs.webrtc.org/6458): Remove this when all the depending projects are +// updated to correctly set rtp rate for RtcpSender. +const int kBogusRtpRateForAudioRtcp = 8000; + +// Minimum RTP header size in bytes. +const uint8_t kRtpHeaderSize = 12; + +// This enum must not have any gaps, i.e., all integers between +// kRtpExtensionNone and kRtpExtensionNumberOfExtensions must be valid enum +// entries. +enum RTPExtensionType : int { + kRtpExtensionNone, + kRtpExtensionTransmissionTimeOffset, + kRtpExtensionAudioLevel, + kRtpExtensionCsrcAudioLevel, + kRtpExtensionInbandComfortNoise, + kRtpExtensionAbsoluteSendTime, + kRtpExtensionAbsoluteCaptureTime, + kRtpExtensionVideoRotation, + kRtpExtensionTransportSequenceNumber, + kRtpExtensionTransportSequenceNumber02, + kRtpExtensionPlayoutDelay, + kRtpExtensionVideoContentType, + kRtpExtensionVideoLayersAllocation, + kRtpExtensionVideoTiming, + kRtpExtensionRtpStreamId, + kRtpExtensionRepairedRtpStreamId, + kRtpExtensionMid, + kRtpExtensionGenericFrameDescriptor, + kRtpExtensionGenericFrameDescriptor00 [[deprecated]] = + kRtpExtensionGenericFrameDescriptor, + kRtpExtensionDependencyDescriptor, + kRtpExtensionGenericFrameDescriptor02 [[deprecated]] = + kRtpExtensionDependencyDescriptor, + kRtpExtensionColorSpace, + kRtpExtensionVideoFrameTrackingId, + kRtpExtensionCorruptionDetection, + kRtpExtensionNumberOfExtensions // Must be the last entity in the enum. +}; + +enum RTCPAppSubTypes { kAppSubtypeBwe = 0x00 }; + +// TODO(sprang): Make this an enum class once rtcp_receiver has been cleaned up. +enum RTCPPacketType : uint32_t { + kRtcpReport = 0x0001, + kRtcpSr = 0x0002, + kRtcpRr = 0x0004, + kRtcpSdes = 0x0008, + kRtcpBye = 0x0010, + kRtcpPli = 0x0020, + kRtcpNack = 0x0040, + kRtcpFir = 0x0080, + kRtcpTmmbr = 0x0100, + kRtcpTmmbn = 0x0200, + kRtcpSrReq = 0x0400, + kRtcpLossNotification = 0x2000, + kRtcpRemb = 0x10000, + kRtcpTransmissionTimeOffset = 0x20000, + kRtcpXrReceiverReferenceTime = 0x40000, + kRtcpXrDlrrReportBlock = 0x80000, + kRtcpTransportFeedback = 0x100000, + kRtcpXrTargetBitrate = 0x200000, +}; + +enum class KeyFrameReqMethod : uint8_t { + kNone, // Don't request keyframes. + kPliRtcp, // Request keyframes through Picture Loss Indication. + kFirRtcp // Request keyframes through Full Intra-frame Request. +}; + +enum RtxMode { + kRtxOff = 0x0, + kRtxRetransmitted = 0x1, // Only send retransmissions over RTX. + kRtxRedundantPayloads = 0x2 // Preventively send redundant payloads + // instead of padding. +}; + +const size_t kRtxHeaderSize = 2; + +// NOTE! `kNumMediaTypes` must be kept in sync with RtpPacketMediaType! +static constexpr size_t kNumMediaTypes = 5; +enum class RtpPacketMediaType : size_t { + kAudio, // Audio media packets. + kVideo, // Video media packets. + kRetransmission, // Retransmisions, sent as response to NACK. + kForwardErrorCorrection, // FEC packets. + kPadding = kNumMediaTypes - 1, // RTX or plain padding sent to maintain BWE. + // Again, don't forget to update `kNumMediaTypes` if you add another value! +}; + +} // namespace webrtc +#endif // _RTP_RTCP_TYPEDEF_H_ diff --git a/src/qos/rtp_rtcp_defines.h b/src/qos/rtp_rtcp_defines.h index 4bc7225..1f4db1b 100644 --- a/src/qos/rtp_rtcp_defines.h +++ b/src/qos/rtp_rtcp_defines.h @@ -23,6 +23,7 @@ #include #include "api/array_view.h" +#include "api/rtp_rtcp/rtp_rtcp_typedef.h" #include "api/transport/network_types.h" #include "api/units/data_rate.h" #include "api/units/time_delta.h" @@ -30,97 +31,10 @@ #include "congestion_control_feedback.h" #include "report_block_data.h" -#define RTCP_CNAME_SIZE 256 // RFC 3550 page 44, including null termination -#define IP_PACKET_SIZE 1500 // we assume ethernet - class RtpPacket; namespace webrtc { class RtpPacketToSend; -namespace rtcp { -class TransportFeedback; -} - -const int kVideoPayloadTypeFrequency = 90000; - -// TODO(bugs.webrtc.org/6458): Remove this when all the depending projects are -// updated to correctly set rtp rate for RtcpSender. -const int kBogusRtpRateForAudioRtcp = 8000; - -// Minimum RTP header size in bytes. -const uint8_t kRtpHeaderSize = 12; - -// This enum must not have any gaps, i.e., all integers between -// kRtpExtensionNone and kRtpExtensionNumberOfExtensions must be valid enum -// entries. -enum RTPExtensionType : int { - kRtpExtensionNone, - kRtpExtensionTransmissionTimeOffset, - kRtpExtensionAudioLevel, - kRtpExtensionCsrcAudioLevel, - kRtpExtensionInbandComfortNoise, - kRtpExtensionAbsoluteSendTime, - kRtpExtensionAbsoluteCaptureTime, - kRtpExtensionVideoRotation, - kRtpExtensionTransportSequenceNumber, - kRtpExtensionTransportSequenceNumber02, - kRtpExtensionPlayoutDelay, - kRtpExtensionVideoContentType, - kRtpExtensionVideoLayersAllocation, - kRtpExtensionVideoTiming, - kRtpExtensionRtpStreamId, - kRtpExtensionRepairedRtpStreamId, - kRtpExtensionMid, - kRtpExtensionGenericFrameDescriptor, - kRtpExtensionGenericFrameDescriptor00 [[deprecated]] = - kRtpExtensionGenericFrameDescriptor, - kRtpExtensionDependencyDescriptor, - kRtpExtensionGenericFrameDescriptor02 [[deprecated]] = - kRtpExtensionDependencyDescriptor, - kRtpExtensionColorSpace, - kRtpExtensionVideoFrameTrackingId, - kRtpExtensionCorruptionDetection, - kRtpExtensionNumberOfExtensions // Must be the last entity in the enum. -}; - -enum RTCPAppSubTypes { kAppSubtypeBwe = 0x00 }; - -// TODO(sprang): Make this an enum class once rtcp_receiver has been cleaned up. -enum RTCPPacketType : uint32_t { - kRtcpReport = 0x0001, - kRtcpSr = 0x0002, - kRtcpRr = 0x0004, - kRtcpSdes = 0x0008, - kRtcpBye = 0x0010, - kRtcpPli = 0x0020, - kRtcpNack = 0x0040, - kRtcpFir = 0x0080, - kRtcpTmmbr = 0x0100, - kRtcpTmmbn = 0x0200, - kRtcpSrReq = 0x0400, - kRtcpLossNotification = 0x2000, - kRtcpRemb = 0x10000, - kRtcpTransmissionTimeOffset = 0x20000, - kRtcpXrReceiverReferenceTime = 0x40000, - kRtcpXrDlrrReportBlock = 0x80000, - kRtcpTransportFeedback = 0x100000, - kRtcpXrTargetBitrate = 0x200000, -}; - -enum class KeyFrameReqMethod : uint8_t { - kNone, // Don't request keyframes. - kPliRtcp, // Request keyframes through Picture Loss Indication. - kFirRtcp // Request keyframes through Full Intra-frame Request. -}; - -enum RtxMode { - kRtxOff = 0x0, - kRtxRetransmitted = 0x1, // Only send retransmissions over RTX. - kRtxRedundantPayloads = 0x2 // Preventively send redundant payloads - // instead of padding. -}; - -const size_t kRtxHeaderSize = 2; struct RtpState { uint16_t sequence_number = 0; @@ -159,9 +73,6 @@ class NetworkLinkRtcpObserver { public: virtual ~NetworkLinkRtcpObserver() = default; - virtual void OnTransportFeedback( - Timestamp /* receive_time */, - const rtcp::TransportFeedback& /* feedback */) {} // RFC 8888 congestion control feedback. virtual void OnCongestionControlFeedback( Timestamp /* receive_time */, @@ -177,17 +88,6 @@ class NetworkLinkRtcpObserver { virtual void OnRttUpdate(Timestamp /* receive_time */, TimeDelta /* rtt */) {} }; -// NOTE! `kNumMediaTypes` must be kept in sync with RtpPacketMediaType! -static constexpr size_t kNumMediaTypes = 5; -enum class RtpPacketMediaType : size_t { - kAudio, // Audio media packets. - kVideo, // Video media packets. - kRetransmission, // Retransmisions, sent as response to NACK. - kForwardErrorCorrection, // FEC packets. - kPadding = kNumMediaTypes - 1, // RTX or plain padding sent to maintain BWE. - // Again, don't forget to update `kNumMediaTypes` if you add another value! -}; - struct RtpPacketSendInfo { static RtpPacketSendInfo From(const RtpPacketToSend& rtp_packet_to_send, const PacedPacketInfo& pacing_info); diff --git a/src/qos/transport_feedback.cc b/src/qos/transport_feedback.cc deleted file mode 100644 index 4ab634f..0000000 --- a/src/qos/transport_feedback.cc +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "transport_feedback.h" - -#include -#include -#include -#include - -#include "byte_io.h" -#include "common_header.h" -#include "log.h" -#include "module_common_types_public.h" - -namespace webrtc { -namespace rtcp { -namespace { -// Header size: -// * 4 bytes Common RTCP Packet Header -// * 8 bytes Common Packet Format for RTCP Feedback Messages -// * 8 bytes FeedbackPacket header -constexpr size_t kTransportFeedbackHeaderSizeBytes = 4 + 8 + 8; -constexpr size_t kChunkSizeBytes = 2; -// TODO(sprang): Add support for dynamic max size for easier fragmentation, -// eg. set it to what's left in the buffer or IP_PACKET_SIZE. -// Size constraint imposed by RTCP common header: 16bit size field interpreted -// as number of four byte words minus the first header word. -constexpr size_t kMaxSizeBytes = (1 << 16) * 4; -// Payload size: -// * 8 bytes Common Packet Format for RTCP Feedback Messages -// * 8 bytes FeedbackPacket header. -// * 2 bytes for one chunk. -constexpr size_t kMinPayloadSizeBytes = 8 + 8 + 2; -constexpr TimeDelta kBaseTimeTick = TransportFeedback::kDeltaTick * (1 << 8); -constexpr TimeDelta kTimeWrapPeriod = kBaseTimeTick * (1 << 24); - -// Message format -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |V=2|P| FMT=15 | PT=205 | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 0 | SSRC of packet sender | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 4 | SSRC of media source | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 8 | base sequence number | packet status count | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 12 | reference time | fb pkt. count | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 16 | packet chunk | packet chunk | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// . . -// . . -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | packet chunk | recv delta | recv delta | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// . . -// . . -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | recv delta | recv delta | zero padding | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -} // namespace - -TransportFeedback::LastChunk::LastChunk() { Clear(); } - -bool TransportFeedback::LastChunk::Empty() const { return size_ == 0; } - -void TransportFeedback::LastChunk::Clear() { - size_ = 0; - all_same_ = true; - has_large_delta_ = false; -} - -bool TransportFeedback::LastChunk::CanAdd(DeltaSize delta_size) const { - if (size_ < kMaxTwoBitCapacity) return true; - if (size_ < kMaxOneBitCapacity && !has_large_delta_ && delta_size != kLarge) - return true; - if (size_ < kMaxRunLengthCapacity && all_same_ && - delta_sizes_[0] == delta_size) - return true; - return false; -} - -void TransportFeedback::LastChunk::Add(DeltaSize delta_size) { - if (size_ < kMaxVectorCapacity) delta_sizes_[size_] = delta_size; - size_++; - all_same_ = all_same_ && delta_size == delta_sizes_[0]; - has_large_delta_ = has_large_delta_ || delta_size == kLarge; -} - -void TransportFeedback::LastChunk::AddMissingPackets(size_t num_missing) { - std::fill(delta_sizes_.begin(), delta_sizes_.end(), DeltaSize(0)); - size_ = num_missing; -} - -uint16_t TransportFeedback::LastChunk::Emit() { - if (all_same_) { - uint16_t chunk = EncodeRunLength(); - Clear(); - return chunk; - } - if (size_ == kMaxOneBitCapacity) { - uint16_t chunk = EncodeOneBit(); - Clear(); - return chunk; - } - uint16_t chunk = EncodeTwoBit(kMaxTwoBitCapacity); - // Remove `kMaxTwoBitCapacity` encoded delta sizes: - // Shift remaining delta sizes and recalculate all_same_ && has_large_delta_. - size_ -= kMaxTwoBitCapacity; - all_same_ = true; - has_large_delta_ = false; - for (size_t i = 0; i < size_; ++i) { - DeltaSize delta_size = delta_sizes_[kMaxTwoBitCapacity + i]; - delta_sizes_[i] = delta_size; - all_same_ = all_same_ && delta_size == delta_sizes_[0]; - has_large_delta_ = has_large_delta_ || delta_size == kLarge; - } - - return chunk; -} - -uint16_t TransportFeedback::LastChunk::EncodeLast() const { - if (all_same_) return EncodeRunLength(); - if (size_ <= kMaxTwoBitCapacity) return EncodeTwoBit(size_); - return EncodeOneBit(); -} - -// Appends content of the Lastchunk to `deltas`. -void TransportFeedback::LastChunk::AppendTo( - std::vector* deltas) const { - if (all_same_) { - deltas->insert(deltas->end(), size_, delta_sizes_[0]); - } else { - deltas->insert(deltas->end(), delta_sizes_.begin(), - delta_sizes_.begin() + size_); - } -} - -void TransportFeedback::LastChunk::Decode(uint16_t chunk, size_t max_size) { - if ((chunk & 0x8000) == 0) { - DecodeRunLength(chunk, max_size); - } else if ((chunk & 0x4000) == 0) { - DecodeOneBit(chunk, max_size); - } else { - DecodeTwoBit(chunk, max_size); - } -} - -// One Bit Status Vector Chunk -// -// 0 1 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |T|S| symbol list | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// T = 1 -// S = 0 -// Symbol list = 14 entries where 0 = not received, 1 = received 1-byte delta. -uint16_t TransportFeedback::LastChunk::EncodeOneBit() const { - uint16_t chunk = 0x8000; - for (size_t i = 0; i < size_; ++i) - chunk |= delta_sizes_[i] << (kMaxOneBitCapacity - 1 - i); - return chunk; -} - -void TransportFeedback::LastChunk::DecodeOneBit(uint16_t chunk, - size_t max_size) { - size_ = std::min(kMaxOneBitCapacity, max_size); - has_large_delta_ = false; - all_same_ = false; - for (size_t i = 0; i < size_; ++i) - delta_sizes_[i] = (chunk >> (kMaxOneBitCapacity - 1 - i)) & 0x01; -} - -// Two Bit Status Vector Chunk -// -// 0 1 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |T|S| symbol list | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// T = 1 -// S = 1 -// symbol list = 7 entries of two bits each. -uint16_t TransportFeedback::LastChunk::EncodeTwoBit(size_t size) const { - uint16_t chunk = 0xc000; - for (size_t i = 0; i < size; ++i) - chunk |= delta_sizes_[i] << 2 * (kMaxTwoBitCapacity - 1 - i); - return chunk; -} - -void TransportFeedback::LastChunk::DecodeTwoBit(uint16_t chunk, - size_t max_size) { - size_ = std::min(kMaxTwoBitCapacity, max_size); - has_large_delta_ = true; - all_same_ = false; - for (size_t i = 0; i < size_; ++i) - delta_sizes_[i] = (chunk >> 2 * (kMaxTwoBitCapacity - 1 - i)) & 0x03; -} - -// Run Length Status Vector Chunk -// -// 0 1 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |T| S | Run Length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// T = 0 -// S = symbol -// Run Length = Unsigned integer denoting the run length of the symbol -uint16_t TransportFeedback::LastChunk::EncodeRunLength() const { - return (delta_sizes_[0] << 13) | static_cast(size_); -} - -void TransportFeedback::LastChunk::DecodeRunLength(uint16_t chunk, - size_t max_count) { - size_ = std::min(chunk & 0x1fff, max_count); - DeltaSize delta_size = (chunk >> 13) & 0x03; - has_large_delta_ = delta_size >= kLarge; - all_same_ = true; - // To make it consistent with Add function, populate delta_sizes_ beyond 1st. - for (size_t i = 0; i < std::min(size_, kMaxVectorCapacity); ++i) - delta_sizes_[i] = delta_size; -} - -TransportFeedback::TransportFeedback() - : TransportFeedback(/*include_timestamps=*/true) {} - -TransportFeedback::TransportFeedback(bool include_timestamps) - : base_seq_no_(0), - num_seq_no_(0), - base_time_ticks_(0), - feedback_seq_(0), - include_timestamps_(include_timestamps), - last_timestamp_(Timestamp::Zero()), - size_bytes_(kTransportFeedbackHeaderSizeBytes) {} - -TransportFeedback::TransportFeedback(const TransportFeedback&) = default; - -TransportFeedback::TransportFeedback(TransportFeedback&& other) - : base_seq_no_(other.base_seq_no_), - num_seq_no_(other.num_seq_no_), - base_time_ticks_(other.base_time_ticks_), - feedback_seq_(other.feedback_seq_), - include_timestamps_(other.include_timestamps_), - last_timestamp_(other.last_timestamp_), - received_packets_(std::move(other.received_packets_)), - all_packets_(std::move(other.all_packets_)), - encoded_chunks_(std::move(other.encoded_chunks_)), - last_chunk_(other.last_chunk_), - size_bytes_(other.size_bytes_) { - other.Clear(); -} - -TransportFeedback::~TransportFeedback() {} - -void TransportFeedback::SetBase(uint16_t base_sequence, - Timestamp ref_timestamp) { - base_seq_no_ = base_sequence; - base_time_ticks_ = - (ref_timestamp.us() % kTimeWrapPeriod.us()) / kBaseTimeTick.us(); - last_timestamp_ = BaseTime(); -} - -void TransportFeedback::SetFeedbackSequenceNumber(uint8_t feedback_sequence) { - feedback_seq_ = feedback_sequence; -} - -bool TransportFeedback::AddReceivedPacket(uint16_t sequence_number, - Timestamp timestamp) { - // Set delta to zero if timestamps are not included, this will simplify the - // encoding process. - int16_t delta = 0; - if (include_timestamps_) { - // Convert to ticks and round. - if (last_timestamp_ > timestamp) { - timestamp += (last_timestamp_ - timestamp).RoundUpTo(kTimeWrapPeriod); - } - int64_t delta_full = - (timestamp - last_timestamp_).us() % kTimeWrapPeriod.us(); - if (delta_full > kTimeWrapPeriod.us() / 2) { - delta_full -= kTimeWrapPeriod.us(); - delta_full -= kDeltaTick.us() / 2; - } else { - delta_full += kDeltaTick.us() / 2; - } - delta_full /= kDeltaTick.us(); - - delta = static_cast(delta_full); - // If larger than 16bit signed, we can't represent it - need new fb packet. - if (delta != delta_full) { - LOG_WARN("Delta value too large ( >= 2^16 ticks )"); - return false; - } - } - - uint16_t next_seq_no = base_seq_no_ + num_seq_no_; - if (sequence_number != next_seq_no) { - uint16_t last_seq_no = next_seq_no - 1; - if (!IsNewerSequenceNumber(sequence_number, last_seq_no)) return false; - uint16_t num_missing_packets = sequence_number - next_seq_no; - if (!AddMissingPackets(num_missing_packets)) return false; - } - - DeltaSize delta_size = (delta >= 0 && delta <= 0xff) ? 1 : 2; - if (!AddDeltaSize(delta_size)) return false; - - received_packets_.emplace_back(sequence_number, delta); - last_timestamp_ += delta * kDeltaTick; - if (include_timestamps_) { - size_bytes_ += delta_size; - } - return true; -} - -const std::vector& -TransportFeedback::GetReceivedPackets() const { - return received_packets_; -} - -void TransportFeedback::ForAllPackets( - rtc::FunctionView handler) const { - TimeDelta delta_since_base = TimeDelta::Zero(); - auto received_it = received_packets_.begin(); - const uint16_t last_seq_num = base_seq_no_ + num_seq_no_; - for (uint16_t seq_num = base_seq_no_; seq_num != last_seq_num; ++seq_num) { - if (received_it != received_packets_.end() && - received_it->sequence_number() == seq_num) { - delta_since_base += received_it->delta(); - handler(seq_num, delta_since_base); - ++received_it; - } else { - handler(seq_num, TimeDelta::PlusInfinity()); - } - } -} - -uint16_t TransportFeedback::GetBaseSequence() const { return base_seq_no_; } - -Timestamp TransportFeedback::BaseTime() const { - // Add an extra kTimeWrapPeriod to allow add received packets arrived earlier - // than the first added packet (and thus allow to record negative deltas) - // even when base_time_ticks_ == 0. - return Timestamp::Zero() + kTimeWrapPeriod + - int64_t{base_time_ticks_} * kBaseTimeTick; -} - -TimeDelta TransportFeedback::GetBaseDelta(Timestamp prev_timestamp) const { - TimeDelta delta = BaseTime() - prev_timestamp; - // Compensate for wrap around. - if ((delta - kTimeWrapPeriod).Abs() < delta.Abs()) { - delta -= kTimeWrapPeriod; // Wrap backwards. - } else if ((delta + kTimeWrapPeriod).Abs() < delta.Abs()) { - delta += kTimeWrapPeriod; // Wrap forwards. - } - return delta; -} - -// De-serialize packet. -bool TransportFeedback::Parse(const CommonHeader& packet) { - if (packet.payload_size_bytes() < kMinPayloadSizeBytes) { - LOG_WARN( - "Buffer too small ({} bytes) to fit a FeedbackPacket. Minimum size = " - "{}", - packet.payload_size_bytes(), kMinPayloadSizeBytes); - return false; - } - - const uint8_t* const payload = packet.payload(); - ParseCommonFeedback(payload); - - base_seq_no_ = ByteReader::ReadBigEndian(&payload[8]); - uint16_t status_count = ByteReader::ReadBigEndian(&payload[10]); - base_time_ticks_ = ByteReader::ReadBigEndian(&payload[12]); - feedback_seq_ = payload[15]; - Clear(); - size_t index = 16; - const size_t end_index = packet.payload_size_bytes(); - - if (status_count == 0) { - LOG_WARN("Empty feedback messages not allowed."); - return false; - } - - std::vector delta_sizes; - delta_sizes.reserve(status_count); - while (delta_sizes.size() < status_count) { - if (index + kChunkSizeBytes > end_index) { - LOG_WARN("Buffer overflow while parsing packet."); - Clear(); - return false; - } - - uint16_t chunk = ByteReader::ReadBigEndian(&payload[index]); - index += kChunkSizeBytes; - encoded_chunks_.push_back(chunk); - last_chunk_.Decode(chunk, status_count - delta_sizes.size()); - last_chunk_.AppendTo(&delta_sizes); - } - // Last chunk is stored in the `last_chunk_`. - encoded_chunks_.pop_back(); - num_seq_no_ = status_count; - - uint16_t seq_no = base_seq_no_; - size_t recv_delta_size = - std::accumulate(delta_sizes.begin(), delta_sizes.end(), 0); - - // Determine if timestamps, that is, recv_delta are included in the packet. - if (end_index >= index + recv_delta_size) { - for (size_t delta_size : delta_sizes) { - switch (delta_size) { - case 0: - break; - case 1: { - int16_t delta = payload[index]; - received_packets_.emplace_back(seq_no, delta); - last_timestamp_ += delta * kDeltaTick; - index += delta_size; - break; - } - case 2: { - int16_t delta = ByteReader::ReadBigEndian(&payload[index]); - received_packets_.emplace_back(seq_no, delta); - last_timestamp_ += delta * kDeltaTick; - index += delta_size; - break; - } - case 3: - Clear(); - LOG_WARN("Invalid delta_size for seq_no {}", seq_no); - - return false; - default: - break; - } - ++seq_no; - } - } else { - // The packet does not contain receive deltas. - include_timestamps_ = false; - for (size_t delta_size : delta_sizes) { - // Use delta sizes to detect if packet was received. - if (delta_size > 0) { - received_packets_.emplace_back(seq_no, 0); - } - ++seq_no; - } - } - size_bytes_ = RtcpPacket::kHeaderLength + index; - return true; -} - -std::unique_ptr TransportFeedback::ParseFrom( - const uint8_t* buffer, size_t length) { - CommonHeader header; - if (!header.Parse(buffer, length)) return nullptr; - if (header.type() != kPacketType || header.fmt() != kFeedbackMessageType) - return nullptr; - std::unique_ptr parsed(new TransportFeedback); - if (!parsed->Parse(header)) return nullptr; - return parsed; -} - -bool TransportFeedback::IsConsistent() const { - size_t packet_size = kTransportFeedbackHeaderSizeBytes; - std::vector delta_sizes; - LastChunk chunk_decoder; - for (uint16_t chunk : encoded_chunks_) { - chunk_decoder.Decode(chunk, kMaxReportedPackets); - chunk_decoder.AppendTo(&delta_sizes); - packet_size += kChunkSizeBytes; - } - if (!last_chunk_.Empty()) { - last_chunk_.AppendTo(&delta_sizes); - packet_size += kChunkSizeBytes; - } - if (num_seq_no_ != delta_sizes.size()) { - LOG_ERROR("{} packets encoded. Expected {}", delta_sizes.size(), - num_seq_no_); - return false; - } - Timestamp timestamp = BaseTime(); - auto packet_it = received_packets_.begin(); - uint16_t seq_no = base_seq_no_; - for (DeltaSize delta_size : delta_sizes) { - if (delta_size > 0) { - if (packet_it == received_packets_.end()) { - LOG_ERROR("Failed to find delta for seq_no {}", seq_no); - return false; - } - if (packet_it->sequence_number() != seq_no) { - LOG_ERROR("Expected to find delta for seq_no {}. Next delta is for {}", - seq_no, packet_it->sequence_number()); - return false; - } - if (delta_size == 1 && - (packet_it->delta_ticks() < 0 || packet_it->delta_ticks() > 0xff)) { - LOG_ERROR("Delta {} for seq_no {} doesn't fit into one byte", - packet_it->delta_ticks(), seq_no); - return false; - } - timestamp += packet_it->delta(); - ++packet_it; - } - if (include_timestamps_) { - packet_size += delta_size; - } - ++seq_no; - } - if (packet_it != received_packets_.end()) { - LOG_ERROR("Unencoded delta for seq_no {}", packet_it->sequence_number()); - return false; - } - if (timestamp != last_timestamp_) { - LOG_ERROR("Last timestamp mismatch. Calculated: {}. Saved: {}", - ToString(timestamp), ToString(last_timestamp_)); - return false; - } - if (size_bytes_ != packet_size) { - LOG_ERROR("Rtcp packet size mismatch. Calculated: {}. Saved: {}", - packet_size, size_bytes_); - return false; - } - return true; -} - -size_t TransportFeedback::BlockLength() const { - // Round size_bytes_ up to multiple of 32bits. - return (size_bytes_ + 3) & (~static_cast(3)); -} - -size_t TransportFeedback::PaddingLength() const { - return BlockLength() - size_bytes_; -} - -// Serialize packet. -bool TransportFeedback::Create(uint8_t* packet, size_t* position, - size_t max_length, - PacketReadyCallback callback) const { - if (num_seq_no_ == 0) return false; - - while (*position + BlockLength() > max_length) { - if (!OnBufferFull(packet, position, callback)) return false; - } - const size_t position_end = *position + BlockLength(); - const size_t padding_length = PaddingLength(); - bool has_padding = padding_length > 0; - CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), has_padding, - packet, position); - CreateCommonFeedback(packet + *position); - *position += kCommonFeedbackLength; - - ByteWriter::WriteBigEndian(&packet[*position], base_seq_no_); - *position += 2; - - ByteWriter::WriteBigEndian(&packet[*position], num_seq_no_); - *position += 2; - - ByteWriter::WriteBigEndian(&packet[*position], base_time_ticks_); - *position += 3; - - packet[(*position)++] = feedback_seq_; - - for (uint16_t chunk : encoded_chunks_) { - ByteWriter::WriteBigEndian(&packet[*position], chunk); - *position += 2; - } - if (!last_chunk_.Empty()) { - uint16_t chunk = last_chunk_.EncodeLast(); - ByteWriter::WriteBigEndian(&packet[*position], chunk); - *position += 2; - } - - if (include_timestamps_) { - for (const auto& received_packet : received_packets_) { - int16_t delta = received_packet.delta_ticks(); - if (delta >= 0 && delta <= 0xFF) { - packet[(*position)++] = delta; - } else { - ByteWriter::WriteBigEndian(&packet[*position], delta); - *position += 2; - } - } - } - - if (padding_length > 0) { - for (size_t i = 0; i < padding_length - 1; ++i) { - packet[(*position)++] = 0; - } - packet[(*position)++] = padding_length; - } - return true; -} - -void TransportFeedback::Clear() { - num_seq_no_ = 0; - last_timestamp_ = BaseTime(); - received_packets_.clear(); - all_packets_.clear(); - encoded_chunks_.clear(); - last_chunk_.Clear(); - size_bytes_ = kTransportFeedbackHeaderSizeBytes; -} - -bool TransportFeedback::AddDeltaSize(DeltaSize delta_size) { - if (num_seq_no_ == kMaxReportedPackets) return false; - size_t add_chunk_size = last_chunk_.Empty() ? kChunkSizeBytes : 0; - if (size_bytes_ + delta_size + add_chunk_size > kMaxSizeBytes) return false; - - if (last_chunk_.CanAdd(delta_size)) { - size_bytes_ += add_chunk_size; - last_chunk_.Add(delta_size); - ++num_seq_no_; - return true; - } - if (size_bytes_ + delta_size + kChunkSizeBytes > kMaxSizeBytes) return false; - - encoded_chunks_.push_back(last_chunk_.Emit()); - size_bytes_ += kChunkSizeBytes; - last_chunk_.Add(delta_size); - ++num_seq_no_; - return true; -} - -bool TransportFeedback::AddMissingPackets(size_t num_missing_packets) { - size_t new_num_seq_no = num_seq_no_ + num_missing_packets; - if (new_num_seq_no > kMaxReportedPackets) { - return false; - } - - if (!last_chunk_.Empty()) { - while (num_missing_packets > 0 && last_chunk_.CanAdd(0)) { - last_chunk_.Add(0); - --num_missing_packets; - } - if (num_missing_packets == 0) { - num_seq_no_ = new_num_seq_no; - return true; - } - encoded_chunks_.push_back(last_chunk_.Emit()); - } - size_t full_chunks = num_missing_packets / LastChunk::kMaxRunLengthCapacity; - size_t partial_chunk = num_missing_packets % LastChunk::kMaxRunLengthCapacity; - size_t num_chunks = full_chunks + (partial_chunk > 0 ? 1 : 0); - if (size_bytes_ + kChunkSizeBytes * num_chunks > kMaxSizeBytes) { - num_seq_no_ = (new_num_seq_no - num_missing_packets); - return false; - } - size_bytes_ += kChunkSizeBytes * num_chunks; - // T = 0, S = 0, run length = kMaxRunLengthCapacity, see EncodeRunLength(). - encoded_chunks_.insert(encoded_chunks_.end(), full_chunks, - LastChunk::kMaxRunLengthCapacity); - last_chunk_.AddMissingPackets(partial_chunk); - num_seq_no_ = new_num_seq_no; - return true; -} -} // namespace rtcp -} // namespace webrtc diff --git a/src/qos/transport_feedback.h b/src/qos/transport_feedback.h deleted file mode 100644 index 1d1c095..0000000 --- a/src/qos/transport_feedback.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TRANSPORT_FEEDBACK_H_ -#define MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TRANSPORT_FEEDBACK_H_ - -#include -#include -#include - -#include "api/function_view.h" -#include "api/units/time_delta.h" -#include "api/units/timestamp.h" -#include "rtpfb.h" - -namespace webrtc { -namespace rtcp { -class CommonHeader; - -class TransportFeedback : public Rtpfb { - public: - class ReceivedPacket { - public: - ReceivedPacket(uint16_t sequence_number, int16_t delta_ticks) - : sequence_number_(sequence_number), delta_ticks_(delta_ticks) {} - ReceivedPacket(const ReceivedPacket&) = default; - ReceivedPacket& operator=(const ReceivedPacket&) = default; - - uint16_t sequence_number() const { return sequence_number_; } - int16_t delta_ticks() const { return delta_ticks_; } - TimeDelta delta() const { return delta_ticks_ * kDeltaTick; } - - private: - uint16_t sequence_number_; - int16_t delta_ticks_; - }; - // TODO(sprang): IANA reg? - static constexpr uint8_t kFeedbackMessageType = 15; - // Convert to multiples of 0.25ms. - static constexpr TimeDelta kDeltaTick = TimeDelta::Micros(250); - // Maximum number of packets (including missing) TransportFeedback can report. - static constexpr size_t kMaxReportedPackets = 0xffff; - - TransportFeedback(); - - // If `include_timestamps` is set to false, the created packet will not - // contain the receive delta block. - explicit TransportFeedback(bool include_timestamps); - TransportFeedback(const TransportFeedback&); - TransportFeedback(TransportFeedback&&); - - ~TransportFeedback() override; - - void SetBase(uint16_t base_sequence, // Seq# of first packet in this msg. - Timestamp ref_timestamp); // Reference timestamp for this msg. - - void SetFeedbackSequenceNumber(uint8_t feedback_sequence); - // NOTE: This method requires increasing sequence numbers (excepting wraps). - bool AddReceivedPacket(uint16_t sequence_number, Timestamp timestamp); - const std::vector& GetReceivedPackets() const; - - // Calls `handler` for all packets this feedback describes. - // For received packets pass receieve time as `delta_since_base` since the - // `BaseTime()`. For missed packets calls `handler` with `delta_since_base = - // PlusInfinity()`. - void ForAllPackets(rtc::FunctionView - handler) const; - - uint16_t GetBaseSequence() const; - - // Returns number of packets (including missing) this feedback describes. - size_t GetPacketStatusCount() const { return num_seq_no_; } - - // Get the reference time including any precision loss. - Timestamp BaseTime() const; - - // Get the unwrapped delta between current base time and `prev_timestamp`. - TimeDelta GetBaseDelta(Timestamp prev_timestamp) const; - - // Does the feedback packet contain timestamp information? - bool IncludeTimestamps() const { return include_timestamps_; } - - bool Parse(const CommonHeader& packet); - static std::unique_ptr ParseFrom(const uint8_t* buffer, - size_t length); - // Pre and postcondition for all public methods. Should always return true. - // This function is for tests. - bool IsConsistent() const; - - size_t BlockLength() const override; - size_t PaddingLength() const; - - bool Create(uint8_t* packet, size_t* position, size_t max_length, - PacketReadyCallback callback) const override; - - private: - // Size in bytes of a delta time in rtcp packet. - // Valid values are 0 (packet wasn't received), 1 or 2. - using DeltaSize = uint8_t; - // Keeps DeltaSizes that can be encoded into single chunk if it is last chunk. - class LastChunk { - public: - using DeltaSize = TransportFeedback::DeltaSize; - static constexpr size_t kMaxRunLengthCapacity = 0x1fff; - - LastChunk(); - - bool Empty() const; - void Clear(); - // Return if delta sizes still can be encoded into single chunk with added - // `delta_size`. - bool CanAdd(DeltaSize delta_size) const; - // Add `delta_size`, assumes `CanAdd(delta_size)`, - void Add(DeltaSize delta_size); - // Equivalent to calling Add(0) `num_missing` times. Assumes `Empty()`. - void AddMissingPackets(size_t num_missing); - - // Encode chunk as large as possible removing encoded delta sizes. - // Assume CanAdd() == false for some valid delta_size. - uint16_t Emit(); - // Encode all stored delta_sizes into single chunk, pad with 0s if needed. - uint16_t EncodeLast() const; - - // Decode up to `max_size` delta sizes from `chunk`. - void Decode(uint16_t chunk, size_t max_size); - // Appends content of the Lastchunk to `deltas`. - void AppendTo(std::vector* deltas) const; - - private: - static constexpr size_t kMaxOneBitCapacity = 14; - static constexpr size_t kMaxTwoBitCapacity = 7; - static constexpr size_t kMaxVectorCapacity = kMaxOneBitCapacity; - static constexpr DeltaSize kLarge = 2; - - uint16_t EncodeOneBit() const; - void DecodeOneBit(uint16_t chunk, size_t max_size); - - uint16_t EncodeTwoBit(size_t size) const; - void DecodeTwoBit(uint16_t chunk, size_t max_size); - - uint16_t EncodeRunLength() const; - void DecodeRunLength(uint16_t chunk, size_t max_size); - - std::array delta_sizes_; - size_t size_; - bool all_same_; - bool has_large_delta_; - }; - - // Reset packet to consistent empty state. - void Clear(); - - bool AddDeltaSize(DeltaSize delta_size); - // Adds `num_missing_packets` deltas of size 0. - bool AddMissingPackets(size_t num_missing_packets); - - uint16_t base_seq_no_; - uint16_t num_seq_no_; - uint32_t base_time_ticks_; - uint8_t feedback_seq_; - bool include_timestamps_; - - Timestamp last_timestamp_; - std::vector received_packets_; - std::vector all_packets_; - // All but last encoded packet chunks. - std::vector encoded_chunks_; - LastChunk last_chunk_; - size_t size_bytes_; -}; - -} // namespace rtcp -} // namespace webrtc -#endif // MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TRANSPORT_FEEDBACK_H_ diff --git a/src/qos/transport_feedback_adapter.cc b/src/qos/transport_feedback_adapter.cc index 243d509..8d2d12a 100644 --- a/src/qos/transport_feedback_adapter.cc +++ b/src/qos/transport_feedback_adapter.cc @@ -24,7 +24,6 @@ #include "log.h" #include "ntp_time_util.h" #include "rtp_packet_to_send.h" -#include "transport_feedback.h" namespace webrtc { @@ -163,77 +162,6 @@ std::optional TransportFeedbackAdapter::ProcessSentPacket( return std::nullopt; } -std::optional -TransportFeedbackAdapter::ProcessTransportFeedback( - const rtcp::TransportFeedback& feedback, Timestamp feedback_receive_time) { - if (feedback.GetPacketStatusCount() == 0) { - LOG_INFO("Empty transport feedback packet received."); - return std::nullopt; - } - - // Add timestamp deltas to a local time base selected on first packet arrival. - // This won't be the true time base, but makes it easier to manually inspect - // time stamps. - if (last_transport_feedback_base_time_.IsInfinite()) { - current_offset_ = feedback_receive_time; - } else { - // TODO(srte): We shouldn't need to do rounding here. - const TimeDelta delta = - feedback.GetBaseDelta(last_transport_feedback_base_time_) - .RoundDownTo(TimeDelta::Millis(1)); - // Protect against assigning current_offset_ negative value. - if (delta < Timestamp::Zero() - current_offset_) { - LOG_WARN("Unexpected feedback timestamp received."); - current_offset_ = feedback_receive_time; - } else { - current_offset_ += delta; - } - } - last_transport_feedback_base_time_ = feedback.BaseTime(); - - std::vector packet_result_vector; - packet_result_vector.reserve(feedback.GetPacketStatusCount()); - - size_t failed_lookups = 0; - size_t ignored = 0; - - feedback.ForAllPackets([&](uint16_t sequence_number, - TimeDelta delta_since_base) { - int64_t seq_num = seq_num_unwrapper_.Unwrap(sequence_number); - std::optional packet_feedback = RetrievePacketFeedback( - seq_num, /*received=*/delta_since_base.IsFinite()); - if (!packet_feedback) { - ++failed_lookups; - return; - } - if (delta_since_base.IsFinite()) { - packet_feedback->receive_time = - current_offset_ + delta_since_base.RoundDownTo(TimeDelta::Millis(1)); - } - if (packet_feedback->network_route == network_route_) { - PacketResult result; - result.sent_packet = packet_feedback->sent; - result.receive_time = packet_feedback->receive_time; - packet_result_vector.push_back(result); - } else { - ++ignored; - } - }); - - if (failed_lookups > 0) { - LOG_WARN( - "Failed to lookup send time for {} packet {}. Packets reordered or " - "send time history too small?", - failed_lookups, (failed_lookups > 1 ? "s" : "")); - } - if (ignored > 0) { - LOG_INFO("Ignoring packets because they were sent on a different route.", - ignored); - } - return ToTransportFeedback(std::move(packet_result_vector), - feedback_receive_time, /*suports_ecn=*/false); -} - std::optional TransportFeedbackAdapter::ProcessCongestionControlFeedback( const rtcp::CongestionControlFeedback& feedback, diff --git a/src/qos/transport_feedback_adapter.h b/src/qos/transport_feedback_adapter.h index 778409d..3417d70 100644 --- a/src/qos/transport_feedback_adapter.h +++ b/src/qos/transport_feedback_adapter.h @@ -76,9 +76,6 @@ class TransportFeedbackAdapter { std::optional ProcessSentPacket( const rtc::SentPacket& sent_packet); - std::optional ProcessTransportFeedback( - const rtcp::TransportFeedback& feedback, Timestamp feedback_receive_time); - std::optional ProcessCongestionControlFeedback( const rtcp::CongestionControlFeedback& feedback, Timestamp feedback_receive_time); diff --git a/src/rtp/rtp_packet/rtp_packet_history.cpp b/src/rtp/rtp_packet/rtp_packet_history.cpp new file mode 100644 index 0000000..179420d --- /dev/null +++ b/src/rtp/rtp_packet/rtp_packet_history.cpp @@ -0,0 +1,39 @@ +#include "rtp_packet_history.h" + +#include "sequence_number_compare.h" + +RtpPacketHistory::RtpPacketHistory() {} + +RtpPacketHistory::~RtpPacketHistory() {} + +void RtpPacketHistory::AddPacket(std::shared_ptr rtp_packet, + Timestamp send_time) { + rtp_packet_history_.push_back( + {rtp_packet, send_time, GetPacketIndex(rtp_packet->SequenceNumber())}); +} + +int RtpPacketHistory::GetPacketIndex(uint16_t sequence_number) const { + if (packet_history_.empty()) { + return 0; + } + + int first_seq = packet_history_.front().packet_->SequenceNumber(); + if (first_seq == sequence_number) { + return 0; + } + + int packet_index = sequence_number - first_seq; + constexpr int kSeqNumSpan = std::numeric_limits::max() + 1; + + if (IsNewerSequenceNumber(sequence_number, first_seq)) { + if (sequence_number < first_seq) { + // Forward wrap. + packet_index += kSeqNumSpan; + } + } else if (sequence_number > first_seq) { + // Backwards wrap. + packet_index -= kSeqNumSpan; + } + + return packet_index; +} \ No newline at end of file diff --git a/src/rtp/rtp_packet/rtp_packet_history.h b/src/rtp/rtp_packet/rtp_packet_history.h new file mode 100644 index 0000000..bd7478d --- /dev/null +++ b/src/rtp/rtp_packet/rtp_packet_history.h @@ -0,0 +1,38 @@ +/* + * @Author: DI JUNKUN + * @Date: 2025-02-14 + * Copyright (c) 2025 by DI JUNKUN, All Rights Reserved. + */ + +#ifndef _RTP_PACKET_HISTORY_H_ +#define _RTP_PACKET_HISTORY_H_ + +#include + +#include "rtp_packet_to_send.h" + +class RtpPacketHistory { + public: + RtpPacketHistory(); + ~RtpPacketHistory(); + + void AddPacket(std::shared_ptr rtp_packet, + Timestamp send_time); + + private: + int GetPacketIndex(uint16_t sequence_number) const; + + return packet_index; +} + +private : struct RtpPacketToSendInfo { + std::shared_ptr rtp_packet; + Timestamp send_time; + uint64_t index; +}; + +private: +std::deque> rtp_packet_history_; +} + +#endif \ No newline at end of file diff --git a/src/qos/rtp_packet_to_send.cc b/src/rtp/rtp_packet/rtp_packet_to_send.cpp similarity index 100% rename from src/qos/rtp_packet_to_send.cc rename to src/rtp/rtp_packet/rtp_packet_to_send.cpp diff --git a/src/qos/rtp_packet_to_send.h b/src/rtp/rtp_packet/rtp_packet_to_send.h similarity index 95% rename from src/qos/rtp_packet_to_send.h rename to src/rtp/rtp_packet/rtp_packet_to_send.h index e3ed3e3..a4528b0 100644 --- a/src/qos/rtp_packet_to_send.h +++ b/src/rtp/rtp_packet/rtp_packet_to_send.h @@ -18,12 +18,12 @@ #include "api/array_view.h" #include "api/ref_counted_base.h" +#include "api/rtp_rtcp/rtp_rtcp_typedef.h" #include "api/scoped_refptr.h" #include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "api/video/video_timing.h" #include "rtp_packet.h" -#include "rtp_rtcp_defines.h" // Forward declare the RtpPacket class since it is not in the webrtc namespace. class RtpPacket; @@ -34,9 +34,6 @@ namespace webrtc { // create rtp header extensions or other data that is sent over the wire. class RtpPacketToSend : public ::RtpPacket { public: - // RtpPacketToSend::Type is deprecated. Use RtpPacketMediaType directly. - using Type = RtpPacketMediaType; - explicit RtpPacketToSend(); RtpPacketToSend(size_t capacity); RtpPacketToSend(const RtpPacketToSend& packet); @@ -51,9 +48,11 @@ class RtpPacketToSend : public ::RtpPacket { webrtc::Timestamp capture_time() const { return capture_time_; } void set_capture_time(webrtc::Timestamp time) { capture_time_ = time; } - void set_packet_type(RtpPacketMediaType type); + void set_packet_type(webrtc::RtpPacketMediaType type); - std::optional packet_type() const { return packet_type_; } + std::optional packet_type() const { + return packet_type_; + } enum class OriginalType { kAudio, kVideo }; // Original type does not change if packet type is changed to kRetransmission. @@ -157,7 +156,7 @@ class RtpPacketToSend : public ::RtpPacket { private: webrtc::Timestamp capture_time_ = webrtc::Timestamp::Zero(); - std::optional packet_type_; + std::optional packet_type_; std::optional original_packet_type_; std::optional original_ssrc_; std::optional transport_sequence_number_; diff --git a/src/rtp/rtp_packetizer/rtp_packetizer.h b/src/rtp/rtp_packetizer/rtp_packetizer.h index 32db74b..72e3989 100644 --- a/src/rtp/rtp_packetizer/rtp_packetizer.h +++ b/src/rtp/rtp_packetizer/rtp_packetizer.h @@ -12,6 +12,7 @@ #include #include "rtp_packet.h" +#include "rtp_packet_to_send.h" class RtpPacketizer { public: @@ -20,8 +21,8 @@ class RtpPacketizer { virtual ~RtpPacketizer() = default; - virtual std::vector Build(uint8_t* payload, - uint32_t payload_size) = 0; + virtual std::vector> Build( + uint8_t* payload, uint32_t payload_size, bool use_rtp_packet_to_send) = 0; }; #endif \ No newline at end of file diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_av1.cpp b/src/rtp/rtp_packetizer/rtp_packetizer_av1.cpp index 6e08889..38734cd 100644 --- a/src/rtp/rtp_packetizer/rtp_packetizer_av1.cpp +++ b/src/rtp/rtp_packetizer/rtp_packetizer_av1.cpp @@ -4,8 +4,9 @@ RtpPacketizerAv1::RtpPacketizerAv1(uint32_t ssrc) {} RtpPacketizerAv1::~RtpPacketizerAv1() {} -std::vector RtpPacketizerAv1::Build(uint8_t* payload, - uint32_t payload_size) { - std::vector rtp_packets; +std::vector> RtpPacketizerAv1::Build( + uint8_t* payload, uint32_t payload_size, bool use_rtp_packet_to_send) { + std::vector> rtp_packets; + return rtp_packets; -} \ No newline at end of file +} diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_av1.h b/src/rtp/rtp_packetizer/rtp_packetizer_av1.h index f0e6822..7c20928 100644 --- a/src/rtp/rtp_packetizer/rtp_packetizer_av1.h +++ b/src/rtp/rtp_packetizer/rtp_packetizer_av1.h @@ -15,8 +15,9 @@ class RtpPacketizerAv1 : public RtpPacketizer { virtual ~RtpPacketizerAv1(); - std::vector Build(uint8_t* payload, - uint32_t payload_size) override; + std::vector> Build( + uint8_t* payload, uint32_t payload_size, + bool use_rtp_packet_to_send) override; private: uint8_t version_; diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_generic.cpp b/src/rtp/rtp_packetizer/rtp_packetizer_generic.cpp index a412bd0..2a96f2e 100644 --- a/src/rtp/rtp_packetizer/rtp_packetizer_generic.cpp +++ b/src/rtp/rtp_packetizer/rtp_packetizer_generic.cpp @@ -17,8 +17,37 @@ RtpPacketizerGeneric::RtpPacketizerGeneric(uint32_t ssrc) RtpPacketizerGeneric::~RtpPacketizerGeneric() {} -std::vector RtpPacketizerGeneric::Build(uint8_t* payload, - uint32_t payload_size) { +void RtpPacketizerGeneric::AddAbsSendTimeExtension( + std::vector& rtp_packet_frame) { + uint16_t extension_profile = 0xBEDE; // One-byte header extension + uint8_t sub_extension_id = 3; // ID for Absolute Send Time + uint8_t sub_extension_length = + 2; // Length of the extension data in bytes minus 1 + + uint32_t abs_send_time = + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + abs_send_time &= 0x00FFFFFF; // Absolute Send Time is 24 bits + + // Add extension profile + rtp_packet_frame.push_back((extension_profile >> 8) & 0xFF); + rtp_packet_frame.push_back(extension_profile & 0xFF); + + // Add extension length (in 32-bit words, minus one) + rtp_packet_frame.push_back( + 0x00); // Placeholder for length, will be updated later + rtp_packet_frame.push_back(0x01); // One 32-bit word + + // Add Absolute Send Time extension + rtp_packet_frame.push_back((sub_extension_id << 4) | sub_extension_length); + rtp_packet_frame.push_back((abs_send_time >> 16) & 0xFF); + rtp_packet_frame.push_back((abs_send_time >> 8) & 0xFF); + rtp_packet_frame.push_back(abs_send_time & 0xFF); +} + +std::vector> RtpPacketizerGeneric::Build( + uint8_t* payload, uint32_t payload_size, bool use_rtp_packet_to_send) { uint32_t last_packet_size = payload_size % MAX_NALU_LEN; uint32_t packet_num = payload_size / MAX_NALU_LEN + (last_packet_size ? 1 : 0); @@ -28,7 +57,8 @@ std::vector RtpPacketizerGeneric::Build(uint8_t* payload, std::chrono::system_clock::now().time_since_epoch()) .count(); - std::vector rtp_packets; + std::vector> rtp_packets; + for (uint32_t index = 0; index < packet_num; index++) { version_ = kRtpVersion; has_padding_ = false; @@ -77,40 +107,17 @@ std::vector RtpPacketizerGeneric::Build(uint8_t* payload, payload + MAX_NALU_LEN); } - RtpPacket rtp_packet; - rtp_packet.Build(rtp_packet_frame_.data(), rtp_packet_frame_.size()); - - rtp_packets.emplace_back(rtp_packet); + if (use_rtp_packet_to_send) { + std::shared_ptr rtp_packet = + std::make_unique(); + rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size()); + rtp_packets.emplace_back(std::move(rtp_packet)); + } else { + std::shared_ptr rtp_packet = std::make_unique(); + rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size()); + rtp_packets.emplace_back(std::move(rtp_packet)); + } } return rtp_packets; } - -void RtpPacketizerGeneric::AddAbsSendTimeExtension( - std::vector& rtp_packet_frame) { - uint16_t extension_profile = 0xBEDE; // One-byte header extension - uint8_t sub_extension_id = 3; // ID for Absolute Send Time - uint8_t sub_extension_length = - 2; // Length of the extension data in bytes minus 1 - - uint32_t abs_send_time = - std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - .count(); - abs_send_time &= 0x00FFFFFF; // Absolute Send Time is 24 bits - - // Add extension profile - rtp_packet_frame.push_back((extension_profile >> 8) & 0xFF); - rtp_packet_frame.push_back(extension_profile & 0xFF); - - // Add extension length (in 32-bit words, minus one) - rtp_packet_frame.push_back( - 0x00); // Placeholder for length, will be updated later - rtp_packet_frame.push_back(0x01); // One 32-bit word - - // Add Absolute Send Time extension - rtp_packet_frame.push_back((sub_extension_id << 4) | sub_extension_length); - rtp_packet_frame.push_back((abs_send_time >> 16) & 0xFF); - rtp_packet_frame.push_back((abs_send_time >> 8) & 0xFF); - rtp_packet_frame.push_back(abs_send_time & 0xFF); -} \ No newline at end of file diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_generic.h b/src/rtp/rtp_packetizer/rtp_packetizer_generic.h index f2ece73..16c9b3e 100644 --- a/src/rtp/rtp_packetizer/rtp_packetizer_generic.h +++ b/src/rtp/rtp_packetizer/rtp_packetizer_generic.h @@ -15,8 +15,9 @@ class RtpPacketizerGeneric : public RtpPacketizer { virtual ~RtpPacketizerGeneric(); - std::vector Build(uint8_t* payload, - uint32_t payload_size) override; + std::vector> Build( + uint8_t* payload, uint32_t payload_size, + bool use_rtp_packet_to_send) override; private: void AddAbsSendTimeExtension(std::vector& rtp_packet_frame); diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_h264.cpp b/src/rtp/rtp_packetizer/rtp_packetizer_h264.cpp index 54b11e9..db9f778 100644 --- a/src/rtp/rtp_packetizer/rtp_packetizer_h264.cpp +++ b/src/rtp/rtp_packetizer/rtp_packetizer_h264.cpp @@ -17,15 +17,6 @@ RtpPacketizerH264::RtpPacketizerH264(uint32_t ssrc) RtpPacketizerH264::~RtpPacketizerH264() {} -std::vector RtpPacketizerH264::Build(uint8_t* payload, - uint32_t payload_size) { - if (payload_size <= MAX_NALU_LEN) { - return BuildNalu(payload, payload_size); - } else { - return BuildFua(payload, payload_size); - } -} - // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -67,9 +58,18 @@ void RtpPacketizerH264::AddAbsSendTimeExtension( rtp_packet_frame.push_back(abs_send_time & 0xFF); } -std::vector RtpPacketizerH264::BuildNalu(uint8_t* payload, - uint32_t payload_size) { - std::vector rtp_packets; +std::vector> RtpPacketizerH264::Build( + uint8_t* payload, uint32_t payload_size, bool use_rtp_packet_to_send) { + if (payload_size <= MAX_NALU_LEN) { + return BuildNalu(payload, payload_size, use_rtp_packet_to_send); + } else { + return BuildFua(payload, payload_size, use_rtp_packet_to_send); + } +} + +std::vector> RtpPacketizerH264::BuildNalu( + uint8_t* payload, uint32_t payload_size, bool use_rtp_packet_to_send) { + std::vector> rtp_packets; version_ = kRtpVersion; has_padding_ = false; @@ -123,16 +123,23 @@ std::vector RtpPacketizerH264::BuildNalu(uint8_t* payload, rtp_packet_frame_.insert(rtp_packet_frame_.end(), payload, payload + payload_size); - RtpPacket rtp_packet; - rtp_packet.Build(rtp_packet_frame_.data(), rtp_packet_frame_.size()); - rtp_packets.emplace_back(rtp_packet); + if (use_rtp_packet_to_send) { + std::shared_ptr rtp_packet = + std::make_unique(); + rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size()); + rtp_packets.emplace_back(std::move(rtp_packet)); + } else { + std::shared_ptr rtp_packet = std::make_unique(); + rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size()); + rtp_packets.emplace_back(std::move(rtp_packet)); + } return rtp_packets; } -std::vector RtpPacketizerH264::BuildFua(uint8_t* payload, - uint32_t payload_size) { - std::vector rtp_packets; +std::vector> RtpPacketizerH264::BuildFua( + uint8_t* payload, uint32_t payload_size, bool use_rtp_packet_to_send) { + std::vector> rtp_packets; uint32_t last_packet_size = payload_size % MAX_NALU_LEN; uint32_t packet_num = @@ -214,10 +221,16 @@ std::vector RtpPacketizerH264::BuildFua(uint8_t* payload, payload + index * MAX_NALU_LEN + MAX_NALU_LEN); } - RtpPacket rtp_packet; - rtp_packet.Build(rtp_packet_frame_.data(), rtp_packet_frame_.size()); - - rtp_packets.emplace_back(rtp_packet); + if (use_rtp_packet_to_send) { + std::shared_ptr rtp_packet = + std::make_unique(); + rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size()); + rtp_packets.emplace_back(std::move(rtp_packet)); + } else { + std::shared_ptr rtp_packet = std::make_unique(); + rtp_packet->Build(rtp_packet_frame_.data(), rtp_packet_frame_.size()); + rtp_packets.emplace_back(std::move(rtp_packet)); + } } return rtp_packets; diff --git a/src/rtp/rtp_packetizer/rtp_packetizer_h264.h b/src/rtp/rtp_packetizer/rtp_packetizer_h264.h index 5c97153..28bcbd1 100644 --- a/src/rtp/rtp_packetizer/rtp_packetizer_h264.h +++ b/src/rtp/rtp_packetizer/rtp_packetizer_h264.h @@ -15,12 +15,16 @@ class RtpPacketizerH264 : public RtpPacketizer { virtual ~RtpPacketizerH264(); - std::vector Build(uint8_t* payload, - uint32_t payload_size) override; + std::vector> Build( + uint8_t* payload, uint32_t payload_size, + bool use_rtp_packet_to_send) override; - std::vector BuildNalu(uint8_t* payload, uint32_t payload_size); + std::vector> BuildNalu( + uint8_t* payload, uint32_t payload_size, bool use_rtp_packet_to_send); - std::vector BuildFua(uint8_t* payload, uint32_t payload_size); + std::vector> BuildFua(uint8_t* payload, + uint32_t payload_size, + bool use_rtp_packet_to_send); private: bool EncodeH264Fua(RtpPacket& rtp_packet, uint8_t* payload,