Search by Tags

Audio/Video over RTP (Linux)

 

Compare with Revision

Subscribe for this article updates

Tegra Modules

Legacy instructions for BSP V1·x

UDP/RTP Audio

Setting up receiver and sender.

root@colibri_t20:~# gst-launch -v udpsrc port=5000 ! "application/x-rtp,media=(string)audio, clock-rate=(int)44100, width=16, height=16, encoding-name=(string)L16, encoding-params=(string)1, channels=(int)1, channel-positions=(int)1, payload=(int)96" ! rtpL16depay ! audioconvert ! alsasink device=hw:2,0 sync=false &
Setting pipeline to PAUSED ...
[ 4450.608338] i2s_set_channel_bit_count: enabling non-symmetric mode
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
root@colibri_t20:~# gst-launch audiotestsrc ! audioconvert ! audio/x-raw-int,channels=1,depth=16,width=16,rate=44100 ! rtpL16pay ! udpsink host=localhost port=5000
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = application/x-rtp, media=(string)audio, clock-rate=(int)44100, width=(int)16, height=(int)16, encoding-name=(string)L16, encoding-params=(string)1, channels=(int)1, channel-positions=(int)1, payload=(int)96
/GstPipeline:pipeline0/GstRtpL16Depay:rtpl16depay0.GstPad:src: caps = audio/x-raw-int, endianness=(int)4321, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)44100, channels=(int)1, channel-positions=(GstAudioChannelPosition)< GST_AUDIO_CHANNEL_POSITION_FRONT_MONO >
/GstPipeline:pipeline0/GstRtpL16Depay:rtpl16depay0.GstPad:sink: caps = application/x-rtp, media=(string)audio, clock-rate=(int)44100, width=(int)16, height=(int)16, encoding-name=(string)L16, encoding-params=string)1, channels=(int)1, channel-positions=(int)1, payload=(int)96
/GstPipeline:pipeline0/GstAudioConvert:audioconvert0.GstPad:src: caps = audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)44100, channels=(int)2
/GstPipeline:pipeline0/GstAudioConvert:audioconvert0.GstPad:sink: caps = audio/x-raw-int, endianness=(int)4321, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)44100, channels=(int)1, channel-positions=(GstAudioChannelPosition)< GST_AUDIO_CHANNEL_POSITION_FRONT_MONO >
/GstPipeline:pipeline0/GstAlsaSink:alsasink0.GstPad:sink: caps = audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)44100, channels=(int)2
^CCaught interrupt -- handling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 3755851999 ns.
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

UDP/RTP Audio & Video

First, one has to analyse the stream capabilities at the sender in order to be able to use them at the receiving end (press CTRL-C when status info has appeared):

root@colibri_t20:~# gst-launch -v filesrc location=/home/root/nv_medusa_h264_720_6M_cbr_2p_key60_q90_aac128_44.mp4 ! qtdemux name=demux demux.video_00 ! queue ! rtph264pay pt=96 ! udpsink host=localhost port=5000 demux.audio_00 ! queue ! rtpmp4apay pt=97 ! udpsink host=localhost port=5001
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstQueue:queue0.GstPad:sink: caps = video/x-h264, level=(string)3.2, profile=(string)constrained-baseline, codec_data=(buffer)0142c020ffe100226742c020967402802dd80a0400002edc000afc80d18002dc8000b71d7bdf0784423501000468de3c80, width=(int)1280, height=(int)720, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1
/GstPipeline:pipeline0/GstQueue:queue0.GstPad:src: caps = video/x-h264, level=(string)3.2, profile=(string)constrained-baseline, codec_data=(buffer)0142c020ffe100226742c020967402802dd80a0400002edc000afc80d18002dc8000b71d7bdf0784423501000468de3c80, width=(int)1280, height=(int)720, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1
/GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0.GstPad:src: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)\"Z0LAIJZ0AoAt2AoEAAAu3AAK/IDRgALcgAC3HXvfB4RCNQ\\=\\=\\,aN48gA\\=\\=\", payload=(int)96, ssrc=(uint)3857927412, clock-base=(uint)3864708562, seqnum-base=(uint)43861
/GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0.GstPad:sink: caps = video/x-h264, level=(string)3.2, profile=(string)constrained-baseline, codec_data=(buffer)0142c020ffe100226742c020967402802dd80a0400002edc000afc80d18002dc8000b71d7bdf0784423501000468de3c80, width=(int)1280, height=(int)720, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1
/GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0: timestamp = 3864708562
/GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0: seqnum = 43861
/GstPipeline:pipeline0/GstUDPSink:udpsink0.GstPad:sink: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)\"Z0LAIJZ0AoAt2AoEAAAu3AAK/IDRgALcgAC3HXvfB4RCNQ\\=\\=\\,aN48gA\\=\\=\", payload=(int)96, ssrc=(uint)3857927412, clock-base=(uint)3864708562, seqnum-base=(uint)43861
/GstPipeline:pipeline0/GstQueue:queue1.GstPad:sink: caps = audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, level=(string)2, base-profile=(string)lc, profile=(string)lc, codec_data=(buffer)121056e500, rate=(int)44100, channels=(int)2
/GstPipeline:pipeline0/GstQueue:queue1.GstPad:src: caps = audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, level=(string)2, base-profile=(string)lc, profile=(string)lc, codec_data=(buffer)121056e500, rate=(int)44100, channels=(int)2
/GstPipeline:pipeline0/GstRtpMP4APay:rtpmp4apay0.GstPad:src: caps = application/x-rtp, media=(string)audio, clock-rate=(int)44100, encoding-name=(string)MP4A-LATM, cpresent=(string)0, config=(string)40002420adca00, payload=(int)97, ssrc=(uint)2324768575, clock-base=(uint)2616710116, seqnum-base=(uint)26397
/GstPipeline:pipeline0/GstRtpMP4APay:rtpmp4apay0.GstPad:sink: caps = audio/mpeg, mpegversion=(int)4, framed=(boolean)true, stream-format=(string)raw, level=(string)2, base-profile=(string)lc, profile=(string)lc, codec_data=(buffer)121056e500, rate=(int)44100, channels=(int)2
/GstPipeline:pipeline0/GstRtpMP4APay:rtpmp4apay0: timestamp = 2616710116
/GstPipeline:pipeline0/GstRtpMP4APay:rtpmp4apay0: seqnum = 26397
/GstPipeline:pipeline0/GstUDPSink:udpsink1.GstPad:sink: caps = application/x-rtp, media=(string)audio, clock-rate=(int)44100, encoding-name=(string)MP4A-LATM, cpresent=(string)0, config=(string)40002420adca00, payload=(int)97, ssrc=(uint)2324768575, clock-base=(uint)2616710116, seqnum-base=(uint)26397
Pipeline is PREROLLED ...

Now we set environment variables from the udpsink0.GstPad:sink and udpsink1.GstPad:sink, probably ssrc, clock-base, seqnum-base can be omitted:

root@colibri_t20:~# VCAPS="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)\"Z0LAIJZ0AoAt2AoEAAAu3AAK/IDRgALcgAC3HXvfB4RCNQ\\=\\=\\,aN48gA\\=\\=\", payload=(int)96"
root@colibri_t20:~# ACAPS="application/x-rtp, media=(string)audio, clock-rate=(int)44100, encoding-name=(string)MP4A-LATM, cpresent=(string)0, config=(string)40002420adca00, payload=(int)97"

Start receiver as a background process:

root@colibri_t20:~# gst-launch udpsrc port=5000 ! $VCAPS ! rtph264depay ! nv_omx_h264dec ! nv_gl_videosink rendertarget=0 udpsrc port=5001 ! $ACAPS ! rtpmp4adepay ! nv_omx_aacdec ! alsasink device=hw:2,0 &

Sender/Receiver on Localhost

Then start sender with the same command-line as above:

root@colibri_t20:~# gst-launch filesrc location=/home/root/nv_medusa_h264_720_6M_cbr_2p_key60_q90_aac128_44.mp4 ! qtdemux name=demux demux.video_00 ! queue ! rtph264pay pt=96 ! udpsink host=localhost port=5000 demux.audio_00 ! queue ! rtpmp4apay pt=97 ! udpsink host=localhost port=5001

Sending Point-to-Point

Of course it makes much more fun to stream over an actual real network. This time we run the sender on an Ubuntu Desktop 12.04 LTS 64-bit machine as follows:

gst-launch-0.10 filesrc location=nv_medusa_h264_720_6M_cbr_2p_key60_q90_aac128_44.mp4 ! qtdemux name=demux demux.video_00 ! queue ! rtph264pay pt=96 ! udpsink host=192.168.10.2 port=5000 demux.audio_00 ! queue ! rtpmp4apay pt=97 ! udpsink host=192.168.10.2 port=5001

Please note that the Colibri T20 target is assumed to have an assigned IP address of 192.168.10.2.

Sending Multicast

But the real eye catcher is when you stream the same video to multiple Colibri T20 targets!

First make sure to add a corresponding multicast route on the sender side as follows:

sudo route add -net 224.0.0.0 netmask 240.0.0.0 dev eth2

Where eth2 is the Ethernet interface towards your little Colibri T20 cluster.

And then stream just like before but now to a multicast address:

gst-launch-0.10 filesrc location=nv_medusa_h264_720_6M_cbr_2p_key60_q90_aac128_44.mp4 ! qtdemux name=demux demux.video_00 ! queue ! rtph264pay pt=96 ! udpsink host=224.0.0.1 port=5000    demux.audio_00 ! queue ! rtpmp4apay pt=97 ! udpsink host=224.0.0.1 port=5001

In order to get better results when streaming over a slightly congested network one can add an additional jitter buffer stage to the pipeline. But first things first, let's install such a Gstreamer plugin:

root@colibri_t20:~# opkg install gst-plugin-rtpmanager
Installing gst-plugin-rtpmanager (0.10.26-r11.0.9) to root...
Downloading http://feeds.angstrom-distribution.org/feeds/next/ipk/eglibc/armv7a-vfp/gstreamer/gst-plugin-rtpmanager_0.10.26-r11.0.9_armv7a-vfp.ipk.
Configuring gst-plugin-rtpmanager.

And then use it as follows:

root@colibri_t20:~# gst-launch udpsrc port=5000 ! $VCAPS ! gstrtpjitterbuffer ! rtph264depay ! nv_omx_h264dec ! nv_gl_videosink rendertarget=0 sync=false udpsrc port=5001 ! $ACAPS ! rtpmp4adepay ! nv_omx_aacdec ! alsasink device=hw:2,0

i.MX6 Modules

UDP/RTP Video

Note: Please verify the path for your Webcam that appears as element property of v4l2src. Generally, in Apalis i.MX6 the webcam appears in /dev/video3 however in Colibri i.MX6 it appears in /dev/video0

Sender/Receiver on Localhost

Start a receiver as a background process

gst-launch-1.0 udpsrc port=5000 ! "application/x-rtp, payload=96" ! rtph264depay ! vpudec ! videoconvert ! imxv4l2sink sync=false &

Then start the sender:

gst-launch-1.0 -v v4l2src device=/dev/video0 ! 'video/x-raw, width=640, height=480, framerate=30/1' ! videoconvert ! vpuenc_h264  quant=20  ! rtph264pay pt=96 ! udpsink host=< IP > port=5000

Sending Point-to-Point

Of course it makes much more fun to steam over an actual real network. This time we run the sender on an Colibri i.MX6 as follows:

gst-launch-1.0 udpsrc port=5000 ! "application/x-rtp, payload=96" ! rtph264depay ! vpudec ! videoconvert ! imxv4l2sink sync=false

Note: 'Change < IP > to the receiver's IP.

gst-launch-1.0 -v v4l2src device=/dev/video0 ! 'video/x-raw, width=640, height=480, framerate=30/1' ! videoconvert ! vpuenc_h264  quant=20  ! rtph264pay pt=96 ! udpsink host=< IP > port=5000

Sending Broadcast

It is possible to send video broadcasting to every device on the same network. In order to do so, there is only one small change in the sender. The address used to broadcast can be calculated accordingly to the subnet mask. (Read more)[https://www.wikihow.com/Calculate-Network-and-Broadcast-Address]

gst-launch-1.0 -v v4l2src device=/dev/video0 ! 'video/x-raw, width=640, height=480, framerate=30/1' ! videoconvert ! vpuenc_h264  quant=20  ! rtph264pay pt=96 ! udpsink host=< BROADCAST ADDRESS > port=5000

The receivers maintain the same pipeline

gst-launch-1.0 udpsrc port=5000 ! "application/x-rtp, payload=96" ! rtph264depay ! vpudec ! videoconvert ! imxv4l2sink sync=false

UDP/RTP Audio

Start the receiver on a remote Colibri iMX6 host:

gst-launch-1.0 udpsrc port=5001 ! application/x-rtp, clock-rate=44100, payload=97 ! rtpL16depay ! audioconvert ! alsasink sync=false

Then start to stream audio data:

gst-launch-1.0 audiotestsrc ! audioconvert ! audio/x-raw,channels=1,depth=16,width=16,rate=44100 ! rtpL16pay pt=97 ! udpsink host=< IP > port=5001

UDP/RTP Audio/Video

Combine the Audio and Video pipelines from above and use two different ports 5000/5001:

Start the receiver on a remote Colibri iMX6 host:

gst-launch-1.0 udpsrc port=5001 ! application/x-rtp, clock-rate=44100, payload=97 ! rtpL16depay ! audioconvert ! alsasink sync=false udpsrc port=5000 ! "application/x-rtp, payload=96" ! rtph264depay ! vpudec ! videoconvert  ! imxv4l2sink sync=false

Then start to stream audio/video data:

gst-launch-1.0 -v audiotestsrc ! audioconvert ! audio/x-raw,channels=1,depth=16,width=16,rate=44100 ! rtpL16pay pt=97 ! udpsink host=< IP > port=5001 v4l2src device=/dev/video0 ! 'video/x-raw, width=640, height=480, framerate=30/1' ! videoconvert ! vpuenc_h264  quant=20  ! rtph264pay pt=96 ! udpsink host=< IP > port=5000

Vybrid and Colibri i.MX6 ULL & i.MX7 Modules

Attention: Vybrid and Colibri i.MX6 ULL & i.MX7 modules lack the hardware accelerated decoding and the memory bandwidth is limited. Therefore, software decoders must be used. Depending on the videos resolution and encoding the performance may be poor.

Install prerequisites

opkg update
opkg install gstreamer1.0-plugins-good-rtp gstreamer1.0-plugins-good-udp gstreamer1.0-plugins-base-videoconvert gstreamer1.0-plugins-good-video4linux2 gstreamer1.0-plugins-base-autodetect 

UDP/RTP Audio & Video

First, one has to analyse the stream capabilities at the sender in order to be able to use them at the receiving end (press CTRL-C when status info has appeared). To verify audio:

gst-launch-1.0 -v audiotestsrc ! audioconvert ! "audio/x-raw,format=(string)S16BE,channels=(int)1,rate=(int)44100" ! rtpL16pay pt=97 ! udpsink host=localhost port=5001

To verify video stream capabilities with a UVC Webcam:

gst-launch-1.0 -v v4l2src device=/dev/video0 ! videoconvert ! videoscale ! video/x-raw,width=320,height=240,framerate=30/1 ! theoraenc ! rtptheorapay pt=96! udpsink host=localhost port=5000

Attention: Theora makes the same controversial design decision that Vorbis made to include the entire probability model for the DCT coecients and all the quantization parameters in the bitstream headers. This is often several hundred elds. It is therefore impossible to decode any frame in the stream without having previously fetched the codec info and codec setup headers. Read more at Theora Specification Document

From the video capabilities above:

VCAPS='application/x-rtp, media=video, clock-rate=90000, encoding-name=THEORA, sampling=YCbCr-4:2:2, width=320, height=240, configuration=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\=\=\, delivery-method=inline, payload=96, ssrc=1408436608, timestamp-offset=1869046222, seqnum-offset=26455, a-framerate=30'

Now launch a receiver on a remote device:


Due to Vorbis/Theora's requirement to add bitstream headers to the pipeline, the next command-lines will use RAW format, which means no encoding.

Start the receiver:

Warning: Streaming RAW video with no compression may occupy a large bandwidth. To avoid image artifacts, decrease the resolution

Start a receiver as background process:

gst-launch-1.0 udpsrc port=5000 ! "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)RAW, sampling=(string)YCbCr-4:2:2, depth=(string)8, width=(string)160, height=(string)120,  ssrc=(uint)1825678493, payload=(int)96, clock-base=(uint)4068866987, seqnum-base=(uint)24582" ! rtpvrawdepay ! queue ! videoconvert ! autovideosink &

Verify your UVC Webcam sampling with command-line

 
v4l2-ctl -d /dev/video0 --list-formats-ext

Sender/Receiver on Localhost

Then start sender with the next command line

gst-launch-1.0 -v v4l2src ! 'video/x-raw, width=(int)160, height=(int)120, framerate=10/1' ! videoconvert ! queue ! rtpvrawpay ! queue ! udpsink host=localhost port=5000

Sending Point-to-Point

Of course it makes much more fun to steam over an actual real network. This time we run the receiver on a Colibri i.MX7D as follows:

gst-launch-1.0 udpsrc port=5000 ! "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)RAW, sampling=(string)YCbCr-4:2:2, depth=(string)8, width=(string)160, height=(string)120,  ssrc=(uint)1825678493, payload=(int)96, clock-base=(uint)4068866987, seqnum-base=(uint)24582" ! rtpvrawdepay ! queue ! videoconvert ! autovideosink

The pipeline to send video to our receiver is

gst-launch-1.0 -v v4l2src ! 'video/x-raw, width=(int)160, height=(int)120, framerate=10/1' ! videoconvert ! queue ! rtpvrawpay ! queue ! udpsink host=< HOST_IP > port=5000

Sending Broadcast

It is possible to send video broadcasting to every device on the same network. In order to do so, there is only one small change in the sender. The address used to broadcast can be calculated accordingly to the subnet mask. ()[https://www.wikihow.com/Calculate-Network-and-Broadcast-Address]

gst-launch-1.0 -v v4l2src ! 'video/x-raw, width=(int)160, height=(int)120, framerate=10/1' ! videoconvert ! queue ! rtpvrawpay ! queue ! udpsink host=< BROADCAST ADDRESS > port=5000

The receivers maintain the same pipeline

gst-launch-1.0 udpsrc port=5000 ! "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)RAW, sampling=(string)YCbCr-4:2:2, depth=(string)8, width=(string)160, height=(string)120,  ssrc=(uint)1825678493, payload=(int)96, clock-base=(uint)4068866987, seqnum-base=(uint)24582" ! rtpvrawdepay ! queue ! videoconvert ! autovideosink