Any FreeRTOS data structures suitable for UDP / RTP packet re-orderting?

Hello,

It seems like there aren’t any suitable data structures included in FreeRTOS to re-order incoming UDP into their sequential order (based on the RTP sequence ID) before passing it on when reading from a typical socket.

I’ve implemented a MessageQueue so far, but realized xQueuePeek is only to the top of the queue, so there is no way to traverse the queue to see if I still have the option to insert this out of order packet into the MessageQueue (rather than discarding it).

I suppose this could be done rater in pure C with a fixed size array then use one of the Semaphore options, but still want to check if anyone else has approached this using FreeRTOS constructs.

Regards,

There is nothing built in - but happy to accept pull requests should you implement something :wink: Interested in how @htibosch does this for his audio streaming use cases.

I have had to do anything like that, but my guess is you don’t want to be copying the frames around, but you might want to make a linked list that you put things in sorted by the sequence ID, and perhaps the built in xList structure might work, but I might be more tempted to just code up a sorted linked list of the data blocks.

1 Like

Thank you @rtel, @richard-damon, I went with a simple list that is sort with qsort and a comparator before being passed into the MessageQueue

@rtel wrote:

Interested in how @htibosch does this for his audio streaming use cases.

I wrote loads of streaming-audio applications. Most were based on http (TCP) which already guarantees a correct order of the packets.

If you are required to use the UDP protocol, then RTP might indeed be useful.

Does your UDP stream come from the Internet, or from a local device?

If you can use TCP, I would recommend trying that. TCP will make sure the packets arrive in the right order.
But also: TCP already has a smart buffering mechanism.

I once made an internet-radio application that connects to a live stream, and plays it on a DAC. Before it starts playing, it will wait for a “full reception buffer”.

FreeRTOS+TCP has a special mechanism, rarely mentioned: the application can send stop/resume to the TCP sliding window.

First you set the TCP sliding windows parameters using the socket option FREERTOS_SO_WIN_PROPERTIES.
For an audio player, the TX sizes will be very small, the RX size will be large.

And then you can configure a lower and an upper limit of the reception stream:

LowHighWater_t xLimits;
 xLimits.uxLittleSpace = 2048U; /**< Send a STOP when buffer space drops below X bytes */
xLimits.uxEnoughSpace = 8192U; /**< Send a GO when buffer space grows above X bytes */

FreeRTOS_setsockopt( xSocket,
                     0,
                     FREERTOS_SO_SET_LOW_HIGH_WATER,
                     ( void * ) &xLimits,
                     sizeof( xLimits ) );

The socket option will set these two fields:

    pxSocket->u.xTCP.uxLittleSpace;
    pxSocket->u.xTCP.uxEnoughSpace;

Their default values will be resp. 20 and 80 % of the RX stream size.

2 Likes