#!/bin/sh # Send RTP video and audio streams set -e RECIP=${RECIP:-$1} # destination host - default: use multicast group VDEVICES=${2:-$(find /dev -maxdepth 1 -type c -name 'video*' | sort)} #ADEVICES=${3:-$(arecord -L | grep -Po '^hw:\S+')} #ADEVICES=${3:-$(arecord -L | grep -Pom1 '^hw:\S+')} ADEVICES=${3:-} # FIXME: Detect/blacklist and skip faulty devices VFORMAT=${VFORMAT:-$4} # H264 VP8 RAW - default: RAW AFORMAT=${AFORMAT:-$5} # AMR OPUS RAW - default: RAW set -u # set multicast groups (also for recorder host) if camera host is wildcard [ -n "$RECIP" ] || RECMIP=239.255.0.1 [ -n "$RECIP" ] || CAMMIP=239.255.0.2 RECHOST="${RECIP:+host=$RECIP}${RECMIP:+host=$RECMIP auto-multicast=true}" CAMHOST="${CAMMIP:+address=$CAMMIP auto-multicast=true}" HEIGHT=240 FRAMERATE=25 AUDIORATE=48000 VCAPS=video/x-raw,height="$HEIGHT" ACAPS=audio/x-raw,rate="$AUDIORATE",channels=2,depth=16 # * http://stackoverflow.com/a/42237307 ABUFFERS=20000 # * force threads using queues - see http://stackoverflow.com/a/30738533 # * generous queue sizes inspired by https://wiki.xiph.org/GST_cookbook QUEUE=" queue max-size-bytes=100000000 max-size-time=0" case "$VFORMAT" in H264) # * let x264 use low-latency sliced-threads (i.e. don't disable treads) VENC="x264enc speed-preset=ultrafast tune=zerolatency bitrate=800 byte-stream=true key-int-max=15 intra-refresh=true option-string=\"slice-max-size=8192:vbv-maxrate=80:vbv-bufsize=10\" ! video/x-h264,profile=baseline ! $QUEUE ! rtph264pay" ;; VP8) VENC="vp8enc min_quantizer=10 max_quantizer=10 cpu-used=10 deadline=1000000 ! video/x-vp8 ! $QUEUE ! rtpvp8pay" ;; RAW|'') VENC="rtpvrawpay" ;; *) echo "ERROR: Unsupported video format: \"$VFORMAT\"" exit 1 ;; esac case "$AFORMAT" in AMR) AENC="amrnbenc ! $QUEUE ! rtpamrpay" ;; OPUS) AENC="opusenc ! $QUEUE ! rtpopuspay" ;; RAW|'') AENC="rtpL16pay" ;; *) echo "ERROR: Unsupported audio format: \"$AFORMAT\"" exit 1 ;; esac stream() { ID=$1 SRC=$2 echo \ $SRC \ ! "rtpbin.send_rtp_sink_$ID" \ rtpbin."send_rtp_src_$ID" ! queue \ ! udpsink name="rtp_sink_$ID" port=$((5000+ID-1)) $RECHOST \ rtpbin.send_rtcp_src_$ID \ ! udpsink name="rtcp_sink_$ID" port=$((5010+ID-1)) $RECHOST sync=false async=false \ udpsrc name="rtp_src_$ID" port=$((5020+ID-1)) $CAMHOST \ ! rtpbin."recv_rtcp_sink_$ID" } n=0 gst-launch-1.0 -v \ rtpbin name=rtpbin \ $(for dev in $VDEVICES; do n=$((n+1)); stream "$n" "v4l2src device=$dev ! $QUEUE ! videoconvert ! $VCAPS ! $QUEUE ! $VENC ! $QUEUE"; done; \ for dev in $ADEVICES; do n=$((n+1)); stream "$n" "alsasrc device=$dev buffer-time=$ABUFFERS ! $QUEUE ! audioconvert ! $QUEUE ! $AENC ! $QUEUE"; done) set -e