Browse Source

resume playback (one client only)

split-pipe
Hendrik Langer 4 years ago
parent
commit
ea764da5be
  1. 4
      README.md
  2. 58
      raspberry/roberto/camera/camera_gstreamer_webrtc.py
  3. 11
      raspberry/roberto/views/websocket/routes.py
  4. 2
      raspberry/roberto/views/websocket/templates/camera.html

4
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 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 ## documentation
https://flask-socketio.readthedocs.io/en/latest/ https://flask-socketio.readthedocs.io/en/latest/

58
raspberry/roberto/camera/camera_gstreamer_webrtc.py

@ -2,6 +2,7 @@ import os
import sys import sys
from threading import Thread from threading import Thread
from queue import Queue
import socketio 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. 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): class WebRTCCamera(Thread):
def __init__(self): def __init__(self):
self.pipe = None self.pipe = None
self.webrtc = 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.connected = False
self.exitFlag = False self.server = 'ws://localhost:5000'
self._queue = Queue(maxsize=10)
Thread.__init__(self) Thread.__init__(self)
@ -40,30 +58,52 @@ class WebRTCCamera(Thread):
sys.exit(1) sys.exit(1)
def run(self): def run(self):
print("Starting WebRTCCamera background thread")
self.connect() 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): def connect(self):
sio.connect(self.server, namespaces=['/webrtc'], transports=['websocket']) sio.connect(self.server, namespaces=['/webrtc'], transports=['websocket'])
print('my sid is', sio.sid) print('my sid is', sio.sid)
sio.emit('message', 'starting camera', namespace='/webrtc') self.sid = sio.sid
self.start_pipeline()
self.connected = True self.connected = True
def disconnect(self): def disconnect(self):
self.connected = False self.connected = False
self.close_pipeline()
sio.disconnect() 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.pipe = Gst.parse_launch(PIPELINE_DESC)
self.webrtc = self.pipe.get_by_name('sendrecv') self.webrtc = self.pipe.get_by_name('sendrecv')
self.webrtc.connect('on-negotiation-needed', self.on_negotiation_needed) self.webrtc.connect('on-negotiation-needed', self.on_negotiation_needed)
self.webrtc.connect('on-ice-candidate', self.on_ice_candidate) self.webrtc.connect('on-ice-candidate', self.on_ice_candidate)
self.pipe.set_state(Gst.State.PLAYING) 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.set_state(Gst.State.NULL)
self.pipe = None self.pipe = None
self.webrtc = None self.webrtc = None

11
raspberry/roberto/views/websocket/routes.py

@ -74,18 +74,19 @@ def webrtc_message(data):
def disconnect(): def disconnect():
sid = request.sid sid = request.sid
print("Received Disconnect message from %s" % sid) print("Received Disconnect message from %s" % sid)
if webrtccamera.connected: webrtccamera.disconnect_client(sid)
webrtccamera.disconnect()
@socketio.on('connect', namespace='/webrtc') @socketio.on('connect', namespace='/webrtc')
def connect(): def connect():
sid = request.sid sid = request.sid
print("Received Connect message from %s" % sid) print("Received Connect message from %s" % sid)
if not webrtccamera.connected: webrtccamera.connect_client(sid)
webrtccamera.start()
socketio.emit('message', 'test2', namespace='/webrtc')
@socketio.on_error_default @socketio.on_error_default
def default_error_handler(e): def default_error_handler(e):
print(request.event["message"]) # "my error event" print(request.event["message"]) # "my error event"
print(request.event["args"]) # (data,) print(request.event["args"]) # (data,)
keys = request.keys()
keys.sort()
for key in request:
print('%s: %s' % (key, repr(request[key])))

2
raspberry/roberto/views/websocket/templates/camera.html

@ -10,7 +10,7 @@
<script src="{{ url_for('static', filename='js/jquery.min.js') }}"></script> <script src="{{ url_for('static', filename='js/jquery.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script> <script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/socket.io.js') }}"></script> <script src="{{ url_for('static', filename='js/socket.io.js') }}"></script>
<script type="text/javascript" src="https://webrtc.github.io/adapter/adapter-latest.js"></script><!-- DEBUG REMOVE ME //--> <!--<script type="text/javascript" src="https://webrtc.github.io/adapter/adapter-latest.js"></script>-->
</head> </head>
<body> <body>

Loading…
Cancel
Save