diff --git a/README.md b/README.md index a5645f7..e34c683 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,10 @@ Sender (Pi): gst-launch-1.0 -e v4l2src do-timestamp=true ! video/x-h264,width=64 Receiver: gst-launch-1.0 -v udpsrc port=5000 ! gdpdepay ! rtph264depay ! avdec_h264 ! fpsdisplaysink sync=false text-overlay=false +## debugging + +export GST_DEBUG=*webrtc*:7 + ## documentation https://flask-socketio.readthedocs.io/en/latest/ diff --git a/raspberry/roberto/camera/camera_gstreamer_webrtc.py b/raspberry/roberto/camera/camera_gstreamer_webrtc.py index 7776548..7139159 100644 --- a/raspberry/roberto/camera/camera_gstreamer_webrtc.py +++ b/raspberry/roberto/camera/camera_gstreamer_webrtc.py @@ -2,6 +2,7 @@ import os import sys from threading import Thread +from queue import Queue import socketio @@ -25,13 +26,30 @@ webrtcbin name=sendrecv bundle-policy=max-bundle stun-server=stun://stun.l.googl queue ! application/x-rtp,media=audio,encoding-name=OPUS,payload=96 ! sendrecv. ''' +#PIPELINE_DESC = ''' +#webrtcbin name=webrtcbin stun-server=stun://stun://stun.l.google.com:19302 +#rpicamsrc bitrate=600000 annotation-mode=12 preview=false ! video/x-h264,profile=constrained-baseline,width=640,height=360,level=3.0 ! queue max-size-time=100000000 ! h264parse ! +#rtph264pay config-interval=-1 name=payloader ! +#application/x-rtp,media=video,encoding-name=H264,payload=96 ! sendrecv. +#''' + +#PIPELINE_DESC = ''' +#v4l2src ! queue ! vp8enc ! rtpvp8pay ! +# application/x-rtp,media=video,encoding-name=VP8,payload=96 ! +# webrtcbin name=sendrecv +#''' + + class WebRTCCamera(Thread): def __init__(self): self.pipe = None self.webrtc = None - self.server = 'ws://localhost:5000' + self.sid = None + self.current_client_sid = None + self.num_clients = 0 self.connected = False - self.exitFlag = False + self.server = 'ws://localhost:5000' + self._queue = Queue(maxsize=10) Thread.__init__(self) @@ -40,30 +58,52 @@ class WebRTCCamera(Thread): sys.exit(1) def run(self): + print("Starting WebRTCCamera background thread") self.connect() - while not self.exitFlag: - sio.sleep(1) + + while True: + item = self._queue.get() + if item['job'] == "connect_client": + self.current_client_sid = item['sid'] + self.start_pipeline(item['sid']) + self.num_clients += 1 + elif item['job'] == "disconnect_client": + self.current_client_sid = item['sid'] + self.close_pipeline(item['sid']) + self.num_clients -= 1 + else: + print("unknown job: %s" % item['job']) + self._queue.task_done() + + self.disconnect() + def connect(self): sio.connect(self.server, namespaces=['/webrtc'], transports=['websocket']) print('my sid is', sio.sid) - sio.emit('message', 'starting camera', namespace='/webrtc') - self.start_pipeline() + self.sid = sio.sid self.connected = True def disconnect(self): self.connected = False - self.close_pipeline() sio.disconnect() - def start_pipeline(self): # ok + def connect_client(self, sid): + if not self.is_alive(): + self.start() + self._queue.put({'job':'connect_client', 'sid':sid}) + + def disconnect_client(self, sid): + self._queue.put({'job':'disconnect_client', 'sid':sid}) + + def start_pipeline(self, client_sid): # ok self.pipe = Gst.parse_launch(PIPELINE_DESC) self.webrtc = self.pipe.get_by_name('sendrecv') self.webrtc.connect('on-negotiation-needed', self.on_negotiation_needed) self.webrtc.connect('on-ice-candidate', self.on_ice_candidate) self.pipe.set_state(Gst.State.PLAYING) - def close_pipeline(self): + def close_pipeline(self, client_sid): self.pipe.set_state(Gst.State.NULL) self.pipe = None self.webrtc = None diff --git a/raspberry/roberto/views/websocket/routes.py b/raspberry/roberto/views/websocket/routes.py index 13016f6..9321d2b 100644 --- a/raspberry/roberto/views/websocket/routes.py +++ b/raspberry/roberto/views/websocket/routes.py @@ -74,18 +74,19 @@ def webrtc_message(data): def disconnect(): sid = request.sid print("Received Disconnect message from %s" % sid) - if webrtccamera.connected: - webrtccamera.disconnect() + webrtccamera.disconnect_client(sid) @socketio.on('connect', namespace='/webrtc') def connect(): sid = request.sid print("Received Connect message from %s" % sid) - if not webrtccamera.connected: - webrtccamera.start() - socketio.emit('message', 'test2', namespace='/webrtc') + webrtccamera.connect_client(sid) @socketio.on_error_default def default_error_handler(e): print(request.event["message"]) # "my error event" print(request.event["args"]) # (data,) + keys = request.keys() + keys.sort() + for key in request: + print('%s: %s' % (key, repr(request[key]))) diff --git a/raspberry/roberto/views/websocket/templates/camera.html b/raspberry/roberto/views/websocket/templates/camera.html index 6e0a9e3..8c8d1f4 100644 --- a/raspberry/roberto/views/websocket/templates/camera.html +++ b/raspberry/roberto/views/websocket/templates/camera.html @@ -10,7 +10,7 @@ - +