Store maximum payload size to RTP context

Store the size to context because different streams may have different
maximum payload sizes. For example, an SRTP stream with RTP authentication
enabled has a smaller payload size than a normal RTP stream.
This commit is contained in:
Aaro Altonen 2020-07-30 13:40:16 +03:00
parent 7d31f0ba08
commit dc494747a4
4 changed files with 54 additions and 31 deletions

View File

@ -14,6 +14,7 @@ namespace uvg_rtp {
uint32_t get_ssrc();
uint16_t get_sequence();
uint32_t get_clock_rate();
size_t get_payload_size();
void inc_sent_pkts();
void inc_sequence();
@ -22,6 +23,7 @@ namespace uvg_rtp {
void set_payload(rtp_format_t fmt);
void set_dynamic_payload(uint8_t payload);
void set_timestamp(uint64_t timestamp);
void set_payload_size(size_t payload_size);
void fill_header(uint8_t *buffer);
void update_sequence(uint8_t *buffer);
@ -41,6 +43,12 @@ namespace uvg_rtp {
/* Use custom timestamp for the outgoing RTP packets */
uint64_t timestamp_;
/* What is the maximum size of the payload available for this RTP instance
*
* By default, the value is set to 1443
* (maximum amount of payload bytes when MTU is 1500) */
size_t payload_size_;
};
};

View File

@ -26,10 +26,11 @@ rtp_error_t uvg_rtp::generic::push_frame(uvg_rtp::sender *sender, uint8_t *data,
{
(void)flags;
size_t payload_size = sender->get_rtp_ctx()->get_payload_size();
uint8_t header[uvg_rtp::frame::HEADER_SIZE_RTP];
sender->get_rtp_ctx()->fill_header(header);
if (data_len > MAX_PAYLOAD) {
if (data_len > payload_size) {
if (sender->get_conf().flags & RCE_FRAGMENT_GENERIC) {
rtp_error_t ret = RTP_OK;
@ -39,16 +40,16 @@ rtp_error_t uvg_rtp::generic::push_frame(uvg_rtp::sender *sender, uint8_t *data,
/* set marker bit for the first fragment */
header[1] |= (1 << 7);
while (data_left > MAX_PAYLOAD) {
ret = uvg_rtp::send::send_frame(sender, header, sizeof(header), data + data_pos, MAX_PAYLOAD);
while (data_left > (ssize_t)payload_size) {
ret = uvg_rtp::send::send_frame(sender, header, sizeof(header), data + data_pos, payload_size);
if (ret != RTP_OK)
return ret;
sender->get_rtp_ctx()->update_sequence(header);
data_pos += MAX_PAYLOAD;
data_left -= MAX_PAYLOAD;
data_pos += payload_size;
data_left -= payload_size;
/* clear marker bit for middle fragments */
header[1] &= 0x7f;
@ -59,7 +60,7 @@ rtp_error_t uvg_rtp::generic::push_frame(uvg_rtp::sender *sender, uint8_t *data,
return uvg_rtp::send::send_frame(sender, header, sizeof(header), data + data_pos, data_left);
} else {
LOG_WARN("packet is larger (%zu bytes) than MAX_PAYLOAD (%u bytes)", data_len, MAX_PAYLOAD);
LOG_WARN("packet is larger (%zu bytes) than payload_size (%zu bytes)", data_len, payload_size);
}
}
@ -79,6 +80,7 @@ static rtp_error_t __fragment_receiver(uvg_rtp::receiver *receiver)
sockaddr_in sender_addr;
rtp_error_t ret = RTP_OK;
uvg_rtp::socket socket = receiver->get_socket();
size_t payload_size = receiver->get_rtp_ctx()->get_payload_size();
uvg_rtp::frame::rtp_frame *frame;
struct frame_info {
@ -160,7 +162,7 @@ static rtp_error_t __fragment_receiver(uvg_rtp::receiver *receiver)
recv = frames[ts].e_seq - frames[ts].s_seq + 1;
if (recv == frames[ts].npkts) {
auto retframe = uvg_rtp::frame::alloc_rtp_frame(recv * MAX_PAYLOAD);
auto retframe = uvg_rtp::frame::alloc_rtp_frame(recv * payload_size);
size_t ptr = 0;
std::memcpy(&retframe->header, &frame->header, sizeof(frame->header));

View File

@ -241,13 +241,14 @@ static rtp_error_t __push_hevc_nal(
if (data_len <= 3)
return RTP_INVALID_VALUE;
uint8_t nalType = (data[0] >> 1) & 0x3F;
rtp_error_t ret = RTP_OK;
size_t data_left = data_len;
size_t data_pos = 0;
uint8_t nalType = (data[0] >> 1) & 0x3F;
rtp_error_t ret = RTP_OK;
size_t data_left = data_len;
size_t data_pos = 0;
size_t payload_size = sender->get_rtp_ctx()->get_payload_size();
#ifdef __linux__
if (data_len - 3 <= MAX_PAYLOAD) {
if (data_len - 3 <= payload_size) {
if ((ret = fqueue->enqueue_message(sender, data, data_len)) != RTP_OK) {
LOG_ERROR("enqeueu failed for small packet");
return ret;
@ -278,13 +279,13 @@ static rtp_error_t __push_hevc_nal(
buffers.push_back(std::make_pair(sizeof(headers->nal_header), headers->nal_header));
buffers.push_back(std::make_pair(sizeof(uint8_t), &headers->fu_headers[0]));
buffers.push_back(std::make_pair(MAX_PAYLOAD, nullptr));
buffers.push_back(std::make_pair(payload_size, nullptr));
data_pos = uvg_rtp::frame::HEADER_SIZE_HEVC_NAL;
data_left -= uvg_rtp::frame::HEADER_SIZE_HEVC_NAL;
while (data_left > MAX_PAYLOAD) {
buffers.at(2).first = MAX_PAYLOAD;
while (data_left > payload_size) {
buffers.at(2).first = payload_size;
buffers.at(2).second = &data[data_pos];
if ((ret = fqueue->enqueue_message(sender, buffers)) != RTP_OK) {
@ -293,8 +294,8 @@ static rtp_error_t __push_hevc_nal(
return ret;
}
data_pos += MAX_PAYLOAD;
data_left -= MAX_PAYLOAD;
data_pos += payload_size;
data_left -= payload_size;
/* from now on, use the FU header meant for middle fragments */
buffers.at(1).second = &headers->fu_headers[1];
@ -316,7 +317,7 @@ static rtp_error_t __push_hevc_nal(
return RTP_NOT_READY;
return fqueue->flush_queue(sender);
#else
if (data_len - 3 <= MAX_PAYLOAD) {
if (data_len - 3 <= payload_size) {
LOG_DEBUG("send unfrag size %zu, type %u", data_len, nalType);
if ((ret = uvg_rtp::generic::push_frame(sender, data, data_len, 0)) != RTP_OK) {
@ -334,7 +335,7 @@ static rtp_error_t __push_hevc_nal(
uvg_rtp::frame::HEADER_SIZE_HEVC_NAL +
uvg_rtp::frame::HEADER_SIZE_HEVC_FU;
uint8_t buffer[HEADER_SIZE + MAX_PAYLOAD] = { 0 };
uint8_t buffer[HEADER_SIZE + payload_size] = { 0 };
sender->get_rtp_ctx()->fill_header(buffer);
@ -346,16 +347,16 @@ static rtp_error_t __push_hevc_nal(
data_pos = uvg_rtp::frame::HEADER_SIZE_HEVC_NAL;
data_left -= uvg_rtp::frame::HEADER_SIZE_HEVC_NAL;
while (data_left > MAX_PAYLOAD) {
memcpy(&buffer[HEADER_SIZE], &data[data_pos], MAX_PAYLOAD);
while (data_left > payload_size) {
memcpy(&buffer[HEADER_SIZE], &data[data_pos], payload_size);
if ((ret = uvg_rtp::send::send_frame(sender, buffer, sizeof(buffer))) != RTP_OK)
return RTP_GENERIC_ERROR;
sender->get_rtp_ctx()->update_sequence(buffer);
data_pos += MAX_PAYLOAD;
data_left -= MAX_PAYLOAD;
data_pos += payload_size;
data_left -= payload_size;
/* Clear extra bits */
buffer[uvg_rtp::frame::HEADER_SIZE_RTP +
@ -392,7 +393,7 @@ static rtp_error_t __push_hevc_slice(
return RTP_INVALID_VALUE;
}
if (data_len >= MAX_PAYLOAD) {
if (data_len >= sender->get_rtp_ctx()->get_payload_size()) {
LOG_ERROR("slice is too big!");
(void)fqueue->deinit_transaction();
return RTP_INVALID_VALUE;
@ -422,13 +423,14 @@ static rtp_error_t __push_hevc_frame(
#ifdef __linux__
/* find first start code */
uint8_t start_len = 0;
int offset = __get_hevc_start(data, data_len, 0, start_len);
int prev_offset = offset;
size_t r_off = 0;
rtp_error_t ret = RTP_GENERIC_ERROR;
uint8_t start_len = 0;
int offset = __get_hevc_start(data, data_len, 0, start_len);
int prev_offset = offset;
size_t r_off = 0;
rtp_error_t ret = RTP_GENERIC_ERROR;
size_t payload_size = sender->get_rtp_ctx()->get_payload_size();
if (data_len < MAX_PAYLOAD) {
if (data_len < payload_size) {
r_off = (offset < 0) ? 0 : offset; /* TODO: this looks ugly */
fqueue->deinit_transaction();
return uvg_rtp::generic::push_frame(sender, data + r_off, data_len - r_off, flags);

View File

@ -15,7 +15,8 @@
uvg_rtp::rtp::rtp(rtp_format_t fmt):
wc_start_(0),
sent_pkts_(0),
timestamp_(INVALID_TS)
timestamp_(INVALID_TS),
payload_size_(MAX_PAYLOAD)
{
seq_ = uvg_rtp::random::generate_32() & 0xffff;
ts_ = uvg_rtp::random::generate_32();
@ -121,3 +122,13 @@ uint32_t uvg_rtp::rtp::get_clock_rate(void)
{
return clock_rate_;
}
void uvg_rtp::rtp::set_payload_size(size_t payload_size)
{
payload_size_ = payload_size;
}
size_t uvg_rtp::rtp::get_payload_size()
{
return payload_size_;
}