nicktendo
nicktendo

Reputation: 607

Relay RTP Stream with NodeJS

I'm attempting to relay RTP packets from a Raspberry Pi to my Macbook Air using NodeJS.

Here is the gstreamer command I'm using to create the video feed on my Raspberry Pi:

gst-launch-1.0 rpicamsrc bitrate=1000000 \
    ! 'video/x-h264,width=640,height=480' \
    ! h264parse \
    ! queue \
    ! rtph264pay config-interval=1 pt=96 \
    ! gdppay \
    ! udpsink host=10.0.0.157 port=3333

I then receive the datagrams from my Raspberry Pi on my Mac via NodeJS and forward them to port 5000 on my Mac with the following code:

var udp = require('dgram');
var server = udp.createSocket('udp4');

server.on('message',function(msg,info){
    server.send(msg,5000,'0.0.0.0', function(){

    });
});

server.bind(3333);

Here is the gstreamer command I run on my mac to receive the RTP datagram stream on port 5000:

gst-launch-1.0 udpsrc port=5000 \
    ! gdpdepay \
    ! rtph264depay \
    ! avdec_h264 \
    ! videoconvert \
    ! osxvideosink sync=false

The stream works fine going directly from the Raspberry Pi to gstreamer on port 5000, however, when I attempt to use the NodeJS app as the intermediary to forward the packets I receive the following error from gstreamer on my Mac:

ERROR: from element /GstPipeline:pipeline0/GstGDPDepay:gdpdepay0: Could not decode stream.
Additional debug info:
gstgdpdepay.c(490): gst_gdp_depay_chain (): /GstPipeline:pipeline0/GstGDPDepay:gdpdepay0:
Received a buffer without first receiving caps

Is there a way in which I can use NodeJS as an intermediary to forward RTP packets to a gstreamer client?

Upvotes: 6

Views: 6148

Answers (1)

nicktendo
nicktendo

Reputation: 607

I was able to successfully relay the RTP stream from the Raspberry Pi via NodeJS by changing the order in which I initiated the servers/RTP stream.

Gstreamer was throwing the error Received a buffer without first receiving caps because I was starting up the Raspberry Pi video stream prior to launching the NodeJS UDP relay server. Gstreamer uses a process called "Caps Negotation" to determine the "optimal solution for the complete pipeline". This process happens prior to the stream being played on the client side. When the Raspberry Pi stream is started prior to the NodeJS relay server the gstreamer client misses out on the caps negotiation process and doesn't know how to handle the data buffer.

The order of operations to make this setup function is as follows:

(1) Launch gstreamer on the client machine:

gst-launch-1.0 udpsrc port=5000 \
    ! gdpdepay \
    ! rtph264depay \
    ! avdec_h264 \
    ! videoconvert \
    ! osxvideosink sync=false

(2) Launch the NodeJS relay server on the client machine:

var udp = require('dgram');
var server = udp.createSocket('udp4');

server.on('message',function(msg,info){
    server.send(msg,5000,'0.0.0.0', function(){

    });
});

(3) Launch the video stream on the Raspberry Pi

gst-launch-1.0 rpicamsrc bitrate=1000000 \
    ! 'video/x-h264,width=640,height=480' \
    ! h264parse \
    ! queue \
    ! rtph264pay config-interval=1 pt=96 \
    ! gdppay \
    ! udpsink host=[CLIENT_MACHINE_IP_HERE] port=3333

Upvotes: 3

Related Questions