From dc494747a43873e28f88ce10b6faccf20ec56e7e Mon Sep 17 00:00:00 2001 From: Aaro Altonen Date: Thu, 30 Jul 2020 13:40:16 +0300 Subject: [PATCH] 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. --- include/rtp.hh | 8 +++++++ src/formats/generic.cc | 16 ++++++++------ src/formats/hevc.cc | 48 ++++++++++++++++++++++-------------------- src/rtp.cc | 13 +++++++++++- 4 files changed, 54 insertions(+), 31 deletions(-) diff --git a/include/rtp.hh b/include/rtp.hh index e4fbffb..cfee988 100644 --- a/include/rtp.hh +++ b/include/rtp.hh @@ -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_; }; }; diff --git a/src/formats/generic.cc b/src/formats/generic.cc index 3e06050..1af5571 100644 --- a/src/formats/generic.cc +++ b/src/formats/generic.cc @@ -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)); diff --git a/src/formats/hevc.cc b/src/formats/hevc.cc index 0d00e61..9387192 100644 --- a/src/formats/hevc.cc +++ b/src/formats/hevc.cc @@ -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); diff --git a/src/rtp.cc b/src/rtp.cc index 971e6cf..bcd8369 100644 --- a/src/rtp.cc +++ b/src/rtp.cc @@ -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_; +}