formats: Modify RCE_FRAGMENT_GENERIC to follow existing definitions

I noticed that H263 uses a very similar fragmentation as
RCE_FRAGMENT_GENERIC and this commit modifies the implementation to use
the exactly same scheme in case we want to support H263 at some point.
This commit is contained in:
Joni Räsänen 2022-09-05 09:48:09 +03:00
parent f55c4578a8
commit d359371040
2 changed files with 28 additions and 17 deletions

View File

@ -166,18 +166,11 @@ enum RTP_CTX_ENABLE_FLAGS {
arrived. Does not work if the dependencies are not in monotonic order. */
RCE_H26X_DEPENDENCY_ENFORCEMENT = 1 << 4,
/** Fragment generic frames into RTP packets of 1500 bytes.
/** Fragment frames into RTP packets of MTU size (1500 bytes).
*
* If RCE_FRAGMENT_GENERIC is given to create_stream(), uvgRTP will split frames
* of type RTP_FORMAT_GENERIC into packets of 1500 bytes automatically and reconstruct
* the full frame from the fragments in the receiver
*
* This behavior is not from any specification and only supported by uvgRTP so it
* will break interoperability between libraries if enabled.
*
* RCE_FRAGMENT_GENERIC can be used, for example, when you're using uvgRTP for
* both sender and receiver and the media stream you wish to stream is not supported
* by uvgRTP but requires packetization because MEDIA_FRAME_SIZE > MTU */
* Some RTP profiles define fragmentation with marker bit indicating the end of frame.
* You can enable this functionality using this flag at both sender and receiver.
*/
RCE_FRAGMENT_GENERIC = 1 << 5,
/** If SRTP is enabled and RCE_INPLACE_ENCRYPTION flag is *not* given,

View File

@ -49,14 +49,22 @@ rtp_error_t uvgrtp::formats::media::push_media_frame(uint8_t *data, size_t data_
return ret;
}
if (!(rce_flags_ & RCE_FRAGMENT_GENERIC) || data_len <= rtp_ctx_->get_payload_size()) {
// TODO: Some RTP formats use this fragmentation, enable it if support for those formats is added
bool fragmentation = (rce_flags_ & RCE_FRAGMENT_GENERIC);
bool set_marker = false;
if (!fragmentation || data_len <= rtp_ctx_->get_payload_size()) {
set_marker = fragmentation;
if (data_len > rtp_ctx_->get_payload_size()) {
UVG_LOG_WARN("Packet is larger (%zu bytes) than maximum payload size (%zu bytes)",
data_len, rtp_ctx_->get_payload_size());
UVG_LOG_WARN("Consider using RCE_FRAGMENT_GENERIC!");
}
if ((ret = fqueue_->enqueue_message(data, data_len)) != RTP_OK) {
if ((ret = fqueue_->enqueue_message(data, data_len, set_marker)) != RTP_OK) {
UVG_LOG_ERROR("Failed to enqueue message: %d", ret);
(void)fqueue_->deinit_transaction();
return ret;
@ -68,7 +76,6 @@ rtp_error_t uvgrtp::formats::media::push_media_frame(uint8_t *data, size_t data_
size_t payload_size = rtp_ctx_->get_payload_size();
ssize_t data_left = data_len;
ssize_t data_pos = 0;
bool set_marker = true;
while (data_left > (ssize_t)payload_size) {
if ((ret = fqueue_->enqueue_message(data + data_pos, payload_size, set_marker)) != RTP_OK) {
@ -102,10 +109,14 @@ rtp_error_t uvgrtp::formats::media::packet_handler(void *arg, int rce_flags, uvg
uint32_t seq = frame->header.seq;
uint32_t recv = 0;
bool fragmentation = (rce_flags & RCE_FRAGMENT_GENERIC);
/* If fragmentation of generic frame has not been enabled, we can just return the frame
* in "out" because RTP packet handler has done all the necessasry stuff for small RTP packets */
if (!(rce_flags & RCE_FRAGMENT_GENERIC))
if (!fragmentation)
{
return RTP_PKT_READY;
}
if (minfo->frames.find(ts) != minfo->frames.end()) {
minfo->frames[ts].npkts++;
@ -119,7 +130,14 @@ rtp_error_t uvgrtp::formats::media::packet_handler(void *arg, int rce_flags, uvg
*out = nullptr;
if (frame->header.marker)
{
minfo->frames[ts].e_seq = seq;
}
else if (seq == minfo->frames[ts].s_seq - 1)
{
// try to detect if the start seq was ordered wrong
minfo->frames[ts].s_seq = seq;
}
if (minfo->frames[ts].e_seq != INVALID_SEQ && minfo->frames[ts].s_seq != INVALID_SEQ) {
if (minfo->frames[ts].s_seq > minfo->frames[ts].e_seq)
@ -154,7 +172,7 @@ rtp_error_t uvgrtp::formats::media::packet_handler(void *arg, int rce_flags, uvg
}
}
} else {
if (frame->header.marker) {
if (!(frame->header.marker)) {
minfo->frames[ts].npkts = 1;
minfo->frames[ts].s_seq = seq;
minfo->frames[ts].e_seq = INVALID_SEQ;
@ -162,7 +180,7 @@ rtp_error_t uvgrtp::formats::media::packet_handler(void *arg, int rce_flags, uvg
minfo->frames[ts].size = frame->payload_len;
*out = nullptr;
} else {
return RTP_PKT_READY;
return RTP_PKT_READY; // fragmentation is used, but there was only one packet for this frame
}
}