RTP
Overview
This sample demonstrates how to use the Zephyr RTP API to transmit and receive
an audio stream over a UDP multicast socket. The role is selected at build time
via an extra configuration file: source.conf for a transmitter or
sink.conf for a receiver. Both roles share the multicast address
239.0.1.1 on port 5004. Adding the ipv6.conf extra configuration
file switches the session to the IPv6 multicast address ff02::5004 on the
same port instead.
The source role sends a 100 Hz sine wave (16-bit mono, 8000 samples/s) as RTP packets using payload type 97. Packets are sent every 50 ms, each carrying 800 samples (one complete period of the tone).
The sink role joins the multicast group and receives the stream using a callback-based API. It logs a heartbeat everty 5 seconds with the received number of packets, and logs a warning if no packet arrives within 500 ms.
Requirements
Running on native_sim
To run this sample on the Native simulator - native_sim board, first set up the
zeth tap interface on the host by following Networking with the host system.
When testing with FFmpeg, the Linux kernel requires an explicit route for the
multicast address so it delivers packets on zeth rather than the default
network interface. After the zeth interface is up, run:
sudo ip route add 239.0.1.1 dev zeth
Building
Build as a source (transmitter):
west build -b <board to use> samples/net/rtp -- -DCONF_FILE=source.conf
Build as a sink (receiver):
west build -b <board to use> samples/net/rtp -- -DCONF_FILE=sink.conf
Faster RTP Stack with net_pkt
The net_pkt.conf extra configuration file tunes the network packet pool for
higher throughput. It can be combined with either role:
west build -b <board to use> samples/net/rtp -- -DCONF_FILE="source.conf net_pkt.conf"
west build -t run
west build -b <board to use> samples/net/rtp -- -DCONF_FILE="sink.conf net_pkt.conf"
west build -t run
Building with IPv6
The ipv6.conf extra configuration file switches the RTP session to the
IPv6 multicast address ff02::5004. It can be combined with either role,
and with net_pkt.conf:
west build -b <board to use> samples/net/rtp -- -DCONF_FILE="source.conf ipv6.conf"
west build -t run
west build -b <board to use> samples/net/rtp -- -DCONF_FILE="sink.conf ipv6.conf"
west build -t run
Testing with FFmpeg
The sample can be tested against FFmpeg on either side.
Testing the Source
To receive the stream from the source role with FFmpeg, first create a
stream.sdp file describing the RTP session:
v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 239.0.1.1
t=0 0
a=tool:libavformat 58.76.100
m=audio 5004 RTP/AVP 97
a=rtpmap:97 L16/8000/1
Then run FFmpeg to receive and save the stream to a WAV file:
ffmpeg -protocol_whitelist file,udp,rtp -i stream.sdp \
-acodec pcm_s16le -ar 8000 -ac 1 \
-f wav out.wav
Testing the Sink
To feed the sink role from FFmpeg, run the following command to send a silent mono stream at 8 kHz over RTP multicast:
ffmpeg -re -f lavfi -i anullsrc=r=8000:cl=mono \
-acodec pcm_s16le \
-f rtp -rtp_flags latm \
-pkt_size 1440 \
rtp://239.0.1.1:5004
Sample Output
Source
*** Booting Zephyr OS build v4.4.0-3146-g5ef8f883a77f ***
[00:00:00.000,000] <inf> net_config: Initializing network
[00:00:00.000,000] <inf> net_config: IPv4 address: 192.0.2.102
[00:00:00.000,000] <inf> main: RTP source on native_sim
[00:00:00.000,000] <dbg> rtp.rtp_session_start_tx: (0x428e60): my_rtp_session started transmitter to 239.0.1.1:5004
[00:00:00.000,000] <inf> main: Start sending RTP packets
Sink
*** Booting Zephyr OS build v4.4.0-3146-g5ef8f883a77f ***
[00:00:00.000,000] <inf> net_config: Initializing network
[00:00:00.000,000] <inf> net_config: IPv4 address: 192.0.2.101
[00:00:00.000,000] <inf> main: RTP sink on native_sim
[00:00:00.000,000] <dbg> rtp.rtp_session_start_rx: (0x420fc0): my_rtp_session started receiver on 239.0.1.1:5004
When the source is running alongside, the sink produces:
[00:00:00.120,000] <inf> main: Receiving rtp stream
[00:00:05.120,000] <inf> main: Received 100 packets
[00:00:10.120,000] <inf> main: Received 200 packets
...
If the source stops, a timeout warning is logged after 500 ms:
[00:00:10.620,000] <wrn> main: Timeout occurred