Add RTCP Sender/Receiver Report frame (de)allocation routines

This commit is contained in:
Aaro Altonen 2019-06-17 11:56:21 +03:00
parent 89f5e3d708
commit 95e8793149
2 changed files with 160 additions and 15 deletions

View File

@ -1,3 +1,5 @@
#include <cstring>
#include "debug.hh"
#include "frame.hh"
#include "send.hh"
@ -66,6 +68,90 @@ rtp_error_t kvz_rtp::frame::dealloc_frame(kvz_rtp::frame::rtp_frame *frame)
return RTP_OK;
}
kvz_rtp::frame::rtcp_sender_frame *kvz_rtp::frame::alloc_rtcp_sender_frame(size_t nblocks)
{
if (nblocks == 0) {
LOG_ERROR("Cannot send 0 report blocks!");
rtp_errno = RTP_INVALID_VALUE;
return nullptr;
}
size_t total_size =
sizeof(rtcp_header) +
sizeof(rtcp_sender_info) +
sizeof(rtcp_report_block) * nblocks;
auto *frame = (kvz_rtp::frame::rtcp_sender_frame *)malloc(total_size);
if (!frame) {
LOG_ERROR("Failed to allocate memory for RTCP sender report");
rtp_errno = RTP_MEMORY_ERROR;
return nullptr;
}
frame->header.version = 2;
frame->header.padding = 0;
frame->header.pkt_type = kvz_rtp::frame::FRAME_TYPE_RR;
frame->header.length = total_size;
frame->header.report_cnt = nblocks;
/* caller fills these */
memset(&frame->s_info, 0, sizeof(rtcp_sender_info));
memset(frame->blocks, 0, sizeof(rtcp_report_block) * nblocks);
return frame;
}
kvz_rtp::frame::rtcp_receiver_frame *kvz_rtp::frame::alloc_rtcp_receiver_frame(size_t nblocks)
{
if (nblocks == 0) {
LOG_ERROR("Cannot send 0 report blocks!");
rtp_errno = RTP_INVALID_VALUE;
return nullptr;
}
size_t total_size =
sizeof(rtcp_header) +
sizeof(rtcp_report_block) * nblocks;
auto *frame = (kvz_rtp::frame::rtcp_receiver_frame *)malloc(total_size);
if (!frame) {
LOG_ERROR("Failed to allocate memory for RTCP sender report");
rtp_errno = RTP_MEMORY_ERROR;
return nullptr;
}
frame->header.version = 2;
frame->header.padding = 0;
frame->header.pkt_type = kvz_rtp::frame::FRAME_TYPE_RR;
frame->header.length = total_size;
frame->header.report_cnt = nblocks;
/* caller fills these */
memset(frame->blocks, 0, sizeof(rtcp_report_block) * nblocks);
return frame;
}
rtp_error_t kvz_rtp::frame::dealloc_frame(kvz_rtp::frame::rtcp_sender_frame *frame)
{
if (!frame)
return RTP_INVALID_VALUE;
delete frame;
return RTP_OK;
}
rtp_error_t kvz_rtp::frame::dealloc_frame(kvz_rtp::frame::rtcp_receiver_frame *frame)
{
if (!frame)
return RTP_INVALID_VALUE;
delete frame;
return RTP_OK;
}
/* get pointer to RTP Header or nullptr if frame is invalid */
uint8_t *kvz_rtp::frame::get_rtp_header(kvz_rtp::frame::rtp_frame *frame)
{

View File

@ -13,12 +13,21 @@ namespace kvz_rtp {
HEADER_SIZE_HEVC_FU = 1,
};
typedef enum FRAME_TYPE {
FRAME_TYPE_GENERIC = 0, // payload length + RTP Header size (N + 12)
FRAME_TYPE_OPUS = 1, // payload length + RTP Header size + Opus header (N + 12 + 0 [for now])
FRAME_TYPE_HEVC_FU = 2, // payload length + RTP Header size + HEVC NAL Header + FU Header (N + 12 + 2 + 1)
} frame_type_t;
typedef enum RTP_FRAME_TYPE {
FRAME_TYPE_GENERIC = 0, /* payload length + RTP Header size (N + 12) */
FRAME_TYPE_OPUS = 1, /* payload length + RTP Header size + Opus header (N + 12 + 0 [for now]) */
FRAME_TYPE_HEVC_FU = 2, /* payload length + RTP Header size + HEVC NAL Header + FU Header (N + 12 + 2 + 1) */
} rtp_type_t;
typedef enum RTCP_FRAME_TYPE {
FRAME_TYPE_SR = 200, /* Sender report */
FRAME_TYPE_RR = 201, /* Receiver report */
FRAME_TYPE_SDES = 202, /* Source description */
FRAME_TYPE_BYE = 203, /* Goodbye */
FRAME_TYPE_APP = 204 /* Application-specific message */
} rtcp_type_t;
/* TODO: is this actually a useful struct? */
struct rtp_frame {
uint32_t timestamp;
uint32_t ssrc;
@ -34,26 +43,76 @@ namespace kvz_rtp {
uint8_t *payload; /* pointer to actual payload */
rtp_format_t format;
frame_type_t type;
rtp_type_t type;
};
/* TODO: */
rtp_frame *alloc_frame(size_t payload_len, frame_type_t type);
struct rtcp_header {
uint8_t version:2;
uint8_t padding:1;
uint8_t report_cnt:5;
uint8_t pkt_type;
uint16_t length;
};
/* TODO: */
kvz_rtp::rtp_frame *alloc_rtp_frame(size_t payload_len, rtp_type_t type);
rtp_error_t dealloc_frame(kvz_rtp::frame::rtp_frame *frame);
struct rtcp_sender_info {
uint32_t ntp_msw;
uint32_t ntp_lsw;
uint32_t rtp_timestamp;
uint32_t pkt_count;
uint32_t byte_count;
};
struct rtcp_report_block {
uint32_t ssrc;
uint8_t fraction_lost;
uint32_t cumulative_pkt_lost:24;
uint32_t highest_seq_recved;
uint32_t interraival_jitter;
uint32_t last_sr;
uint32_t delay_since_last_sr;
};
struct rtcp_sender_frame {
struct rtcp_header header;
struct rtcp_sender_info s_info;
struct rtcp_report_block blocks[0];
};
struct rtcp_receiver_frame {
struct rtcp_header header;
struct rtcp_report_block blocks[0];
};
struct rtcp_sdes_frame {
int value;
};
struct rtcp_bye_frame {
int value;
};
struct rtcp_app_frame {
int value;
};
rtp_frame *alloc_rtp_frame(size_t payload_len, rtp_type_t type);
rtcp_sender_frame *alloc_rtcp_sender_frame(size_t numblocks);
rtcp_receiver_frame *alloc_rtcp_receiver_frame(size_t numblocks);
rtp_error_t dealloc_frame(rtp_frame *frame);
rtp_error_t dealloc_frame(rtcp_sender_frame *frame);
rtp_error_t dealloc_frame(rtcp_receiver_frame *frame);
/* get pointer to rtp header start or nullptr if frame is invalid */
uint8_t *get_rtp_header(kvz_rtp::frame::rtp_frame *frame);
uint8_t *get_rtp_header(rtp_frame *frame);
/* get pointer to opus header start or nullptr if frame is invalid */
uint8_t *get_opus_header(kvz_rtp::frame::rtp_frame *frame);
uint8_t *get_opus_header(rtp_frame *frame);
/* get pointer to hevc rtp header start or nullptr if frame is invalid */
uint8_t *get_hevc_rtp_header(kvz_rtp::frame::rtp_frame *frame);
uint8_t *get_hevc_rtp_header(rtp_frame *frame);
/* get pointer to hevc fu header start or nullptr if frame is invalid */
uint8_t *get_hevc_fu_header(kvz_rtp::frame::rtp_frame *frame);
uint8_t *get_hevc_fu_header(rtp_frame *frame);
};
};