From f939e0a89405d395599e1d788c9e73ac213ef6f0 Mon Sep 17 00:00:00 2001 From: xia-chu <771730766@qq.com> Date: Tue, 13 Apr 2021 18:50:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=80=E4=BA=9Brtcp=20fci?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Rtcp/Rtcp.cpp | 10 +++ src/Rtcp/Rtcp.h | 57 ++++++++++++++++- src/Rtcp/RtcpFCI.cpp | 5 ++ src/Rtcp/RtcpFCI.h | 148 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 src/Rtcp/RtcpFCI.cpp create mode 100644 src/Rtcp/RtcpFCI.h diff --git a/src/Rtcp/Rtcp.cpp b/src/Rtcp/Rtcp.cpp index 912999b9..aa958665 100644 --- a/src/Rtcp/Rtcp.cpp +++ b/src/Rtcp/Rtcp.cpp @@ -33,6 +33,15 @@ const char *sdesTypeToStr(SdesType type){ } } +const char *psfbTypeToStr(PSFBType type) { + switch (type){ +#define SWITCH_CASE(key, value) case PSFBType::key : return #value "(" #key ")"; + PSFB_TYPE_MAP(SWITCH_CASE) +#undef SWITCH_CASE + default: return "unknown payload-specific fb message (rfc4585) type"; + } +} + static size_t alignSize(size_t bytes) { return (size_t)((bytes + 3) / 4) << 2; } @@ -136,6 +145,7 @@ void RtcpHeader::net2Host(size_t len){ case RtcpType::RTCP_RTPFB: { //todo 支持rtcp-fb相关功能 + net2Host(); break; } default: throw std::runtime_error(StrPrinter << "未处理的rtcp包:" << rtcpTypeToStr((RtcpType) this->pt)); diff --git a/src/Rtcp/Rtcp.h b/src/Rtcp/Rtcp.h index c7a1556f..c257420f 100644 --- a/src/Rtcp/Rtcp.h +++ b/src/Rtcp/Rtcp.h @@ -55,6 +55,33 @@ namespace mediakit { XX(RTCP_SDES_NOTE, 7) \ XX(RTCP_SDES_PRIVATE, 8) +//https://datatracker.ietf.org/doc/rfc4585/?include_text=1 +//6.3. Payload-Specific Feedback Messages +// +// Payload-Specific FB messages are identified by the value PT=PSFB as +// RTCP message type. +// +// Three payload-specific FB messages are defined so far plus an +// application layer FB message. They are identified by means of the +// FMT parameter as follows: +// +// 0: unassigned +// 1: Picture Loss Indication (PLI) +// 2: Slice Loss Indication (SLI) +// 3: Reference Picture Selection Indication (RPSI) +// 4-14: unassigned +// 15: Application layer FB (AFB) message +// 16-30: unassigned +// 31: reserved for future expansion of the sequence number space + +#define PSFB_TYPE_MAP(XX) \ + XX(RTCP_PSFB_PLI, 1) \ + XX(RTCP_PSFB_SLI, 2) \ + XX(RTCP_PSFB_RPSI, 3) \ + XX(RTCP_PSFB_FIR, 4) \ + XX(RTCP_PSFB_TSTR, 5) \ + XX(RTCP_PSFB_AFB, 15) + //rtcp类型枚举 enum class RtcpType : uint8_t { #define XX(key, value) key = value, @@ -69,6 +96,13 @@ enum class SdesType : uint8_t { #undef XX }; +//psfb类型枚举 +enum class PSFBType : uint8_t { +#define XX(key, value) key = value, + PSFB_TYPE_MAP(XX) +#undef XX +}; + /** * RtcpType转描述字符串 */ @@ -79,6 +113,11 @@ const char *rtcpTypeToStr(RtcpType type); */ const char *sdesTypeToStr(SdesType type); +/** + * psfb枚举转描述字符串 + */ +const char *psfbTypeToStr(PSFBType type); + class RtcpHeader { public: #if __BYTE_ORDER == __BIG_ENDIAN @@ -462,7 +501,23 @@ private: void net2Host(size_t size); } PACKED; -//PLI +//6.1. Common Packet Format for Feedback Messages +// +// All FB messages MUST use a common packet format that is depicted in +// Figure 3: +// +// 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 | PT | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of packet sender | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of media source | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// : Feedback Control Information (FCI) : +// : : + class RtcpPli : public RtcpHeader { public: friend class RtcpHeader; diff --git a/src/Rtcp/RtcpFCI.cpp b/src/Rtcp/RtcpFCI.cpp new file mode 100644 index 00000000..724f03b2 --- /dev/null +++ b/src/Rtcp/RtcpFCI.cpp @@ -0,0 +1,5 @@ +// +// Created by xzl on 2021/4/13. +// + +#include "RtcpFCI.h" diff --git a/src/Rtcp/RtcpFCI.h b/src/Rtcp/RtcpFCI.h new file mode 100644 index 00000000..d55ef1ea --- /dev/null +++ b/src/Rtcp/RtcpFCI.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit). + * + * Use of this source code is governed by MIT license that can be found in the + * LICENSE file in the root of the source tree. All contributing project authors + * may be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef ZLMEDIAKIT_RTCPFCI_H +#define ZLMEDIAKIT_RTCPFCI_H + +#include "Rtcp.h" + +//https://tools.ietf.org/html/rfc4585 + +namespace mediakit { + +//https://tools.ietf.org/html/rfc4585#section-6.2.1 +// 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 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | PID | BLP | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Figure 4: Syntax for the Generic NACK message + +class FCI_NACK { +public: + // The PID field is used to specify a lost packet. The PID field + // refers to the RTP sequence number of the lost packet. + uint16_t pid; + // bitmask of following lost packets (BLP): 16 bits + uint16_t blp; +} PACKED; + +//https://tools.ietf.org/html/rfc4585#section-6.3.2.2 +// The Slice Loss Indication uses one additional FCI field, the content +// of which is depicted in Figure 6. The length of the FB message MUST +// be set to 2+n, with n being the number of SLIs contained in the FCI +// field. +// +// 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 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | First | Number | PictureID | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Figure 6: Syntax of the Slice Loss Indication (SLI) +// +class FCI_SLI { +public: + uint32_t first : 13; + uint32_t number : 13; + uint32_t pic_id : 6; +} PACKED; + +//https://tools.ietf.org/html/rfc4585#section-6.3.3.2 +//6.3.3.2. Format +// +// The FCI for the RPSI message follows the format depicted in Figure 7: +// +// 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 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | PB |0| Payload Type| Native RPSI bit string | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | defined per codec ... | Padding (0) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Figure 7: Syntax of the Reference Picture Selection Indication (RPSI) +class FCI_RPSI { +public: + //The number of unused bits required to pad the length of the RPSI + // message to a multiple of 32 bits. + uint8_t pb; + +#if __BYTE_ORDER == __BIG_ENDIAN + //0: 1 bit + // MUST be set to zero upon transmission and ignored upon reception. + uint8_t zero : 1; + //Payload Type: 7 bits + // Indicates the RTP payload type in the context of which the native + // RPSI bit string MUST be interpreted. + uint8_t pt : 7; +#else + uint8_t pt: 7; + uint8_t zero: 1; +#endif + + // Native RPSI bit string: variable length + // The RPSI information as natively defined by the video codec. + char str[1]; + + //Padding: #PB bits + // A number of bits set to zero to fill up the contents of the RPSI + // message to the next 32-bit boundary. The number of padding bits + // MUST be indicated by the PB field. +} PACKED; + +//tools.ietf.org/html/draft-alvestrand-rmcat-remb-03 +// 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=206 | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of packet sender | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of media source | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Unique identifier 'R' 'E' 'M' 'B' | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Num SSRC | BR Exp | BR Mantissa | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC feedback | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | ... | +class FCI_REMB { +public: + //Unique identifier 'R' 'E' 'M' 'B' + char magic[4]; + + //Number of SSRCs in this message. + uint32_t num_ssrc : 8; + + // BR Exp (6 bits): The exponential scaling of the mantissa for the + // maximum total media bit rate value, ignoring all packet + // overhead. The value is an unsigned integer [0..63], as + // in RFC 5104 section 4.2.2.1. + uint32_t br_exp : 6; + + //BR Mantissa (18 bits): The mantissa of the maximum total media bit + // rate (ignoring all packet overhead) that the sender of + // the REMB estimates. The BR is the estimate of the + // traveled path for the SSRCs reported in this message. + // The value is an unsigned integer in number of bits per + // second. + uint32_t br_mantissa : 18; + + // SSRC feedback (32 bits) Consists of one or more SSRC entries which + // this feedback message applies to. + uint32_t ssrc_feedback; + +} PACKED; + +} //namespace mediakit +#endif //ZLMEDIAKIT_RTCPFCI_H