Skip to content

Commit

Permalink
Video: Add multicast for RTP
Browse files Browse the repository at this point in the history
  • Loading branch information
stephendade committed May 23, 2024
1 parent df4ff6a commit f6dd036
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
15 changes: 15 additions & 0 deletions python/rtsp-server.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import os
import platform
from netifaces import interfaces, ifaddresses, AF_INET
import ipaddress

gi.require_version("Gst", "1.0")
gi.require_version("GstRtsp", "1.0")
Expand All @@ -34,6 +35,16 @@ def is_debian_bookworm():
return False


def is_multicast(ip: str) -> bool:
try:
ip_obj = ipaddress.ip_address(ip)
# Multicast addresses are in the range 224.0.0.0 to 239.255.255.255
return ip_obj.is_multicast
except ValueError:
# If the IP address is not valid, return False
return False


def getPipeline(device, height, width, bitrate, format, rotation, framerate, timestamp):
# rotation
if device in ["0rpicam", "1rpicam"]:
Expand Down Expand Up @@ -228,6 +239,7 @@ def addStream(self, device, h, w, bitrate, format, rotation, framerate, timestam
print("Exiting RTSP Server")
loop.quit()
elif args.udp.split(':')[0] == "0":
# RTSP
s = GstServer()
s.addStream(args.videosource, args.height, args.width, args.bitrate,
args.format, args.rotation, args.fps, args.timestamp)
Expand All @@ -238,10 +250,13 @@ def addStream(self, device, h, w, bitrate, format, rotation, framerate, timestam
print("Exiting RTSP Server")
loop.quit()
else:
# RTP
pipeline_str = getPipeline(args.videosource, args.height, args.width,
args.bitrate, args.format, args.rotation, args.fps, args.timestamp)
pipeline_str += " ! udpsink host={0} port={1}".format(
args.udp.split(':')[0], args.udp.split(':')[1])
if is_multicast(args.udp.split(':')[0]):
pipeline_str += " auto-multicast=true"
pipeline = Gst.parse_launch(pipeline_str)
pipeline.set_state(Gst.State.PLAYING)

Expand Down
34 changes: 27 additions & 7 deletions src/video.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ class VideoPage extends basePage {
infoMessage: null,
timestamp: false,
enableCameraHeartbeat: false,
mavStreamSelected: this.props.mavStreamSelected
mavStreamSelected: this.props.mavStreamSelected,
multicastString: " "
}
}

componentDidMount() {
fetch(`/api/videodevices`).then(response => response.json()).then(state => { this.setState(state); this.loadDone() });
fetch(`/api/videodevices`).then(response => response.json()).then(state => { this.setState(state); this.isMulticastUpdateIP(state.useUDPIP); this.loadDone() });
}

handleVideoChange = (value, action) => {
Expand Down Expand Up @@ -72,9 +73,28 @@ class VideoPage extends basePage {
this.setState({ UDPChecked: event.target.value==="rtp" });
}

isMulticastUpdateIP(ip) {
// Split the IP address into its four octets
const octets = ip.split('.').map(Number);
let udpmult = " ";

// Check if the IP address has 4 octets and all are within the valid range
if (octets.length !== 4 || octets.some(octet => isNaN(octet) || octet < 0 || octet > 255)) {
udpmult = "multicast-group=" + ip + " ";
}

// Check if the first octet is within the multicast range (224-239)
if (octets[0] >= 224 && octets[0] <= 239) {
udpmult = "multicast-group=" + ip + " ";
}

this.setState({multicastString: udpmult});
}

handleUDPIPChange = (event) => {
//bitrate spinner new value
this.setState({ useUDPIP: event.target.value });
//IP address new value
this.isMulticastUpdateIP(event.target.value);
this.setState({ useUDPIP: event.target.value,});
}

handleUDPPortChange = (event) => {
Expand Down Expand Up @@ -144,7 +164,7 @@ class VideoPage extends basePage {
renderContent() {
return (
<Form style={{ width: 600 }}>
<p><i>Stream live video from any connected camera devices. Only 1 camera can be streamed at a time.</i></p>
<p><i>Stream live video from any connected camera devices. Only 1 camera can be streamed at a time. Multicast IP addresses are supported in RTP mode.</i></p>
<h2>Configuration</h2>
<div className="form-group row" style={{ marginBottom: '5px' }}>
<label className="col-sm-4 col-form-label">Streaming Mode</label>
Expand Down Expand Up @@ -290,15 +310,15 @@ class VideoPage extends basePage {
+ GStreamer
</Accordion.Header>
<Accordion.Body>
<p style={{ fontFamily: "monospace" }}>gst-launch-1.0 udpsrc port={this.state.useUDPPort} caps='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264' ! rtpjitterbuffer ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! autovideosink sync=false</p>
<p style={{ fontFamily: "monospace" }}>gst-launch-1.0 udpsrc {this.state.multicastString}port={this.state.useUDPPort} caps='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264' ! rtpjitterbuffer ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! autovideosink sync=false</p>
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="2">
<Accordion.Header>
+ Mission Planner Connection Strings
</Accordion.Header>
<Accordion.Body>
<p style={{ fontFamily: "monospace" }}>udpsrc port={this.state.useUDPPort} buffer-size=90000 ! application/x-rtp ! rtpjitterbuffer ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink sync=false</p>
<p style={{ fontFamily: "monospace" }}>udpsrc {this.state.multicastString}port={this.state.useUDPPort} buffer-size=90000 ! application/x-rtp ! rtpjitterbuffer ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink sync=false</p>
</Accordion.Body>
</Accordion.Item>
</Accordion>
Expand Down

0 comments on commit f6dd036

Please sign in to comment.