diff --git a/include/re_rtp.h b/include/re_rtp.h index c7d098f4d..9b7a0421f 100644 --- a/include/re_rtp.h +++ b/include/re_rtp.h @@ -69,6 +69,7 @@ enum rtcp_rtpfb { enum rtcp_psfb { RTCP_PSFB_PLI = 1, /**< Picture Loss Indication (PLI) */ RTCP_PSFB_SLI = 2, /**< Slice Loss Indication (SLI) */ + RTCP_PSFB_FIR = 4, /**< Full INTRA-frame Request (FIR) (RFC 5104) */ RTCP_PSFB_AFB = 15, /**< Application layer Feedback Messages */ }; @@ -167,6 +168,10 @@ struct rtcp_msg { uint16_t number; uint8_t picid; } *sliv; + struct fir_rfc5104 { + uint32_t ssrc; + uint8_t seq_n; + } *firv; struct twcc { uint16_t seq; uint16_t count; @@ -237,6 +242,8 @@ int rtcp_send_app(struct rtp_sock *rs, const char name[4], int rtcp_send_fir(struct rtp_sock *rs, uint32_t ssrc); int rtcp_send_nack(struct rtp_sock *rs, uint16_t fsn, uint16_t blp); int rtcp_send_pli(struct rtp_sock *rs, uint32_t fb_ssrc); +int rtcp_send_fir_rfc5104(struct rtp_sock *rs, uint32_t ssrc, + uint8_t fir_seqn); int rtcp_debug(struct re_printf *pf, const struct rtp_sock *rs); void *rtcp_sock(const struct rtp_sock *rs); int rtcp_stats(struct rtp_sock *rs, uint32_t ssrc, struct rtcp_stats *stats); diff --git a/src/rtp/fb.c b/src/rtp/fb.c index c430cdf63..a6989f3f9 100644 --- a/src/rtp/fb.c +++ b/src/rtp/fb.c @@ -22,6 +22,7 @@ enum { GNACK_SIZE = 4, + FIR_SIZE = 8, SLI_SIZE = 4 }; @@ -253,6 +254,22 @@ int rtcp_psfb_decode(struct mbuf *mb, struct rtcp_msg *msg) mbuf_advance(mb, sz); break; + case RTCP_PSFB_FIR: + msg->r.fb.n /= 2u; /* each FCI entry size is 2 32-bit words */ + sz = msg->r.fb.n * sizeof(*msg->r.fb.fci.firv); + msg->r.fb.fci.firv = mem_alloc(sz, NULL); + if (!msg->r.fb.fci.firv) + return ENOMEM; + + if (mbuf_get_left(mb) < msg->r.fb.n * FIR_SIZE) + return EBADMSG; + for (i=0; ir.fb.n; i++) { + msg->r.fb.fci.firv[i].ssrc = ntohl(mbuf_read_u32(mb)); + msg->r.fb.fci.firv[i].seq_n = mbuf_read_u8(mb); + mbuf_advance(mb, 3); + } + break; + default: DEBUG_NOTICE("unknown PSFB fmt %d\n", msg->hdr.count); break; diff --git a/src/rtp/rtcp.c b/src/rtp/rtcp.c index 24cac1434..c74c377dd 100644 --- a/src/rtp/rtcp.c +++ b/src/rtp/rtcp.c @@ -103,6 +103,33 @@ int rtcp_send_pli(struct rtp_sock *rs, uint32_t fb_ssrc) rtp_sess_ssrc(rs), fb_ssrc, NULL, NULL); } +static int encode_fir_rfc5104_fci(struct mbuf *mb, void *arg) +{ + struct fir_rfc5104 *fci = arg; + int err = mbuf_write_u32(mb, htonl(fci->ssrc)); + err |= mbuf_write_u8(mb, fci->seq_n); + err |= mbuf_write_u8(mb, 0); + err |= mbuf_write_u8(mb, 0); + err |= mbuf_write_u8(mb, 0); + return err; +} + +/** + * Send an RTCP Full INTRA-frame Request (FIR) packet according to RFC 5104 + * + * @param rs RTP Socket + * @param ssrc SSRC of the target encoder + * @param fir_seqn FIR sequence number + * + * @return 0 for success, otherwise errorcode + */ +int rtcp_send_fir_rfc5104(struct rtp_sock *rs, uint32_t ssrc, uint8_t fir_seqn) +{ + struct fir_rfc5104 fci = { ssrc, fir_seqn }; + return rtcp_quick_send(rs, RTCP_PSFB, RTCP_PSFB_FIR, + rtp_sess_ssrc(rs), (uint32_t)0u, + &encode_fir_rfc5104_fci, &fci); +} const char *rtcp_type_name(enum rtcp_type type) { @@ -272,6 +299,15 @@ int rtcp_msg_print(struct re_printf *pf, const struct rtcp_msg *msg) err |= re_hprintf(pf, " AFB %u bytes", msg->r.fb.n * 4); } + else if (msg->hdr.count == RTCP_PSFB_FIR) { + err |= re_hprintf(pf, " FIR (RFC5104)"); + for (i=0; ir.fb.n; i++) { + err |= re_hprintf(pf, + " {ssrc=%08x seq_n=%02x}", + msg->r.fb.fci.firv[i].ssrc, + msg->r.fb.fci.firv[i].seq_n); + } + } break; default: