def setReceiver(self, offer_sdp): ''' ''' print('setReceiver thread:', threading.get_ident()) result, offer = GstSdp.SDPMessage.new() assert (result == GstSdp.SDPResult.OK) GstSdp.sdp_message_parse_buffer(offer_sdp.encode(), offer) description = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.OFFER, offer) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', description, promise) promise.interrupt() direction_audio = GstWebRTC.WebRTCRTPTransceiverDirection.SENDRECV caps_audio = Gst.caps_from_string( "application/x-rtp,media=audio,encoding-name=OPUS,payload=111") direction_video = GstWebRTC.WebRTCRTPTransceiverDirection.SENDRECV caps_vedio = Gst.caps_from_string( "application/x-rtp,media=video,encoding-name=VP8,payload=96") self.webrtc.emit('add-transceiver', direction_audio, caps_audio) self.webrtc.emit('add-transceiver', direction_video, caps_vedio) promise = Gst.Promise.new() self.webrtc.emit('create-answer', None, promise) promise.wait() reply = promise.get_reply() answer = reply.get_value('answer') # promise = Gst.Promise.new_with_change_func(self.onSetLocalDescription, 'myaatga') promise = Gst.Promise.new() self.webrtc.emit('set-local-description', answer, promise) promise.wait() return answer.sdp.as_text()
async def handle_sdp(self, message): if self.state != 'publish': return assert (self.webrtc) if message['message'] == 'setRemoteSDP': sdp = message['data'][1] res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) # Flashphoner returns a sdp that doesn't have the "setup" attribute # Which Gstreamer rejects. # So we add it back for i in range(N_MEDIA): sdpmedia = sdpmsg.get_media(i) if not sdpmedia.get_attribute_val("setup") in [ "actpass", "active", "passive" ]: print("Setting 'setup' attribute for media %d" % i) sdpmedia.add_attribute("setup", "active") answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt() for i in range(N_MEDIA): sdpmedia = sdpmsg.get_media(i) candidate = sdpmedia.get_attribute_val_n('candidate', 0) self.webrtc.emit('add-ice-candidate', i, 'a=candidate:' + candidate)
def msg_handler(self, msg): #print("receiver", msg) if msg.startswith("ROOM_OK"): self.em.emit("change_label", label_id="receiver_room_id_label", new_text=self.room_id) self.em.emit("remove_container", container_id="receiver_connect_container", window="receiver") elif msg.startswith('ROOM_PEER_MSG'): data = json.loads(msg.split(maxsplit=2)[2]) if "sdp" in data: sdp = data["sdp"] res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) offer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.OFFER, sdpmsg) promise = Gst.Promise.new_with_change_func( self.on_remote_dec_set, None) self.webrtcbin.emit("set-remote-description", offer, promise) elif "ice" in data: mline_index = int(data["ice"]["sdpMLineIndex"]) candidate = data["ice"]["candidate"] self.webrtcbin.emit("add-ice-candidate", mline_index, candidate)
def handle_sdp(self, message): assert (self.webrtc) msg = json.loads(message) if 'sdp' in msg: sdp = msg['sdp'] print(str(sdp)) if (sdp['type'] == 'answer'): time.sleep(2) sdp = sdp['sdp'] print('Received answer:\n%s' % sdp) res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt() # loop = asyncio.get_event_loop() # loop.run_until_complete(self.send_data()) elif (sdp['type'] == 'offer'): # peer = sdp['peer_id'] sdp = sdp['sdp'] peer = 2 print('Received offer:\n%s' % sdp) elif 'ice' in msg: ice = msg['ice'] candidate = ice['candidate'] sdpmlineindex = ice['sdpMLineIndex'] self.webrtc.emit('add-ice-candidate', sdpmlineindex, candidate)
def set_sdp(self, sdp_type, sdp): """Sets remote SDP received by peer. Arguments: sdp_type {string} -- type of sdp, offer or answer sdp {object} -- SDP object Raises: GSTWebRTCAppError -- thrown if SDP is recevied before session has been started. GSTWebRTCAppError -- thrown if SDP type is not 'answer', this script initiates the call, not the peer. """ if not self.webrtcbin: raise GSTWebRTCAppError('Received SDP before session started') if sdp_type != 'answer': raise GSTWebRTCAppError('ERROR: sdp type was not "answer"') _, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtcbin.emit('set-remote-description', answer, promise) promise.interrupt()
async def connection_handler(self, ws): print("Connection attempt") self.current_ws = ws self.start_pipeline() await ws.send(self.sdp_queue.get()) while True: await ws.send(self.ice_queue.get()) msg = await ws.recv() msg = json.loads(msg) print(msg) if msg['type'] == 'sdp': sdp = msg['data'] sdp = sdp['sdp'] print('Received answer:\n%s' % sdp) res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt() if msg['type'] == 'ice': print('Received ICE:\n%s' % sdp) ice = msg['data'] candidate = ice['candidate'] sdpmlineindex = ice['sdpMLineIndex'] self.webrtc.emit('add-ice-candidate', sdpmlineindex, candidate) else: print('Unsupported message type')
async def on_message(self, conn, path): while True: data = await conn.recv(); print(f'{data}') datas = data.split(' ') if datas[0] == 'HELLO': await conn.send('HELLO') elif datas[0] == 'SESSION': await conn.send('SESSION_OK') else: msg = json.loads(data) if 'sdp' in msg: sdp = msg['sdp'] assert(sdp['type'] == 'offer') sdp = sdp['sdp'] sdp = 'v=0\no=- 249052402997811464 2 IN IP4 127.0.0.1\ns=-\nt=0 0\na=group:BUNDLE 0 1\na=extmap-allow-mixed\na=msid-semantic: WMS\nm=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\nc=IN IP4 0.0.0.0\na=rtcp:9 IN IP4 0.0.0.0\na=ice-ufrag:09iz\na=ice-pwd:TDNEa4DNQNu5vntI7paNKKgV\na=ice-options:trickle\na=fingerprint:sha-256 4F:12:50:51:FE:1A:76:0E:74:6D:79:31:DB:C0:E5:42:41:4F:AA:9D:AA:C9:29:AD:A2:49:6E:F3:AF:0F:3A:14\na=setup:actpass\na=mid:0\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\na=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\na=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\na=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\na=sendonly\na=rtcp-mux\na=rtpmap:111 opus/48000/2\na=rtcp-fb:111 transport-cc\na=fmtp:111 minptime=10;useinbandfec=1\na=rtpmap:103 ISAC/16000\na=rtpmap:104 ISAC/32000\na=rtpmap:9 G722/8000\na=rtpmap:0 PCMU/8000\na=rtpmap:8 PCMA/8000\na=rtpmap:106 CN/32000\na=rtpmap:105 CN/16000\na=rtpmap:13 CN/8000\na=rtpmap:110 telephone-event/48000\na=rtpmap:112 telephone-event/32000\na=rtpmap:113 telephone-event/16000\na=rtpmap:126 telephone-event/8000\nm=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 122 102 121 127 120 125 107 108 109 124 119 123 118 114 115 116 35\nc=IN IP4 0.0.0.0\na=rtcp:9 IN IP4 0.0.0.0\na=ice-ufrag:09iz\na=ice-pwd:TDNEa4DNQNu5vntI7paNKKgV\na=ice-options:trickle\na=fingerprint:sha-256 4F:12:50:51:FE:1A:76:0E:74:6D:79:31:DB:C0:E5:42:41:4F:AA:9D:AA:C9:29:AD:A2:49:6E:F3:AF:0F:3A:14\na=setup:actpass\na=mid:1\na=extmap:14 urn:ietf:params:rtp-hdrext:toffset\na=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\na=extmap:13 urn:3gpp:video-orientation\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\na=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\na=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type\na=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing\na=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\na=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\na=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\na=sendonly\na=rtcp-mux\na=rtcp-rsize\na=rtpmap:96 VP8/90000\na=rtcp-fb:96 goog-remb\na=rtcp-fb:96 transport-cc\na=rtcp-fb:96 ccm fir\na=rtcp-fb:96 nack\na=rtcp-fb:96 nack pli\na=rtpmap:97 rtx/90000\na=fmtp:97 apt=96\na=rtpmap:98 VP9/90000\na=rtcp-fb:98 goog-remb\na=rtcp-fb:98 transport-cc\na=rtcp-fb:98 ccm fir\na=rtcp-fb:98 nack\na=rtcp-fb:98 nack pli\na=fmtp:98 profile-id=0\na=rtpmap:99 rtx/90000\na=fmtp:99 apt=98\na=rtpmap:100 VP9/90000\na=rtcp-fb:100 goog-remb\na=rtcp-fb:100 transport-cc\na=rtcp-fb:100 ccm fir\na=rtcp-fb:100 nack\na=rtcp-fb:100 nack pli\na=fmtp:100 profile-id=2\na=rtpmap:101 rtx/90000\na=fmtp:101 apt=100\na=rtpmap:122 VP9/90000\na=rtcp-fb:122 goog-remb\na=rtcp-fb:122 transport-cc\na=rtcp-fb:122 ccm fir\na=rtcp-fb:122 nack\na=rtcp-fb:122 nack pli\na=fmtp:122 profile-id=1\na=rtpmap:102 H264/90000\na=rtcp-fb:102 goog-remb\na=rtcp-fb:102 transport-cc\na=rtcp-fb:102 ccm fir\na=rtcp-fb:102 nack\na=rtcp-fb:102 nack pli\na=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f\na=rtpmap:121 rtx/90000\na=fmtp:121 apt=102\na=rtpmap:127 H264/90000\na=rtcp-fb:127 goog-remb\na=rtcp-fb:127 transport-cc\na=rtcp-fb:127 ccm fir\na=rtcp-fb:127 nack\na=rtcp-fb:127 nack pli\na=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f\na=rtpmap:120 rtx/90000\na=fmtp:120 apt=127\na=rtpmap:125 H264/90000\na=rtcp-fb:125 goog-remb\na=rtcp-fb:125 transport-cc\na=rtcp-fb:125 ccm fir\na=rtcp-fb:125 nack\na=rtcp-fb:125 nack pli\na=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f\na=rtpmap:107 rtx/90000\na=fmtp:107 apt=125\na=rtpmap:108 H264/90000\na=rtcp-fb:108 goog-remb\na=rtcp-fb:108 transport-cc\na=rtcp-fb:108 ccm fir\na=rtcp-fb:108 nack\na=rtcp-fb:108 nack pli\na=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f\na=rtpmap:109 rtx/90000\na=fmtp:109 apt=108\na=rtpmap:124 H264/90000\na=rtcp-fb:124 goog-remb\na=rtcp-fb:124 transport-cc\na=rtcp-fb:124 ccm fir\na=rtcp-fb:124 nack\na=rtcp-fb:124 nack pli\na=fmtp:124 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f\na=rtpmap:119 rtx/90000\na=fmtp:119 apt=124\na=rtpmap:123 H264/90000\na=rtcp-fb:123 goog-remb\na=rtcp-fb:123 transport-cc\na=rtcp-fb:123 ccm fir\na=rtcp-fb:123 nack\na=rtcp-fb:123 nack pli\na=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f\na=rtpmap:118 rtx/90000\na=fmtp:118 apt=123\na=rtpmap:114 red/90000\na=rtpmap:115 rtx/90000\na=fmtp:115 apt=114\na=rtpmap:116 ulpfec/90000\na=rtpmap:35 flexfec-03/90000\na=rtcp-fb:35 goog-remb\na=rtcp-fb:35 transport-cc\na=fmtp:35 repair-window=10000000\n' self.start_pipeline(conn) print('set-remote-description') res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) offer = GstWebRTC.WebRTCSessionDescription.new(GstWebRTC.WebRTCSDPType.OFFER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', offer, promise) promise.interrupt() promise = Gst.Promise.new_with_change_func(self.on_answer_created, conn, None) self.webrtc.emit('create-answer', None, promise) elif 'ice' in msg: print('[RECV] ice:', msg) ice = msg['ice'] candidate = ice['candidate'] sdpmlineindex = ice['sdpMLineIndex'] self.webrtc.emit('add-ice-candidate', sdpmlineindex, candidate)
def handle_sdp(self, message): msg = json.loads(message) if 'sdp' in msg: sdp = msg['sdp'] sdp_type_str = sdp['type'] sdp_msg_str = sdp['sdp'] #parse sdp['sdp'] back to a GstSdp.SDPMessage _res, sdp_msg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp_msg_str.encode()), sdp_msg) #parse sdp['type'] back to a GstWebRTC.WebRTCSDPType sdp_type = parse_WebRTCSDPType(sdp_type_str) if sdp_type == None: self.node.get_logger().error('invalid sdp type') return # combine the parsed sdp into a GstWebRTC.WebRTCSessionDescription remote_sdp = GstWebRTC.WebRTCSessionDescription.new(sdp_type, sdp_msg) if self.remote_sends_sdp_cb != None: self.remote_sends_sdp_cb(remote_sdp) elif 'ice' in msg: ice = msg['ice'] candidate = ice['candidate'] sdpmlineindex = ice['sdpMLineIndex'] if self.remote_sends_ice_cb != None: self.remote_sends_ice_cb(sdpmlineindex, candidate)
def start_pipeline(self): self.pipe = Gst.parse_launch(PIPELINE_DESC) self.webrtc = self.pipe.get_by_name('sendrecv') self.webrtc.connect('on-ice-candidate', self.send_ice_candidate_message) self.webrtc.connect('pad-added', self.on_incoming_stream) self.pipe.set_state(Gst.State.PLAYING) offer = 'v=0\no=- 249052402997811464 2 IN IP4 127.0.0.1\ns=-\nt=0 0\na=group:BUNDLE 0 1\na=extmap-allow-mixed\na=msid-semantic: WMS\nm=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\nc=IN IP4 0.0.0.0\na=rtcp:9 IN IP4 0.0.0.0\na=ice-ufrag:09iz\na=ice-pwd:TDNEa4DNQNu5vntI7paNKKgV\na=ice-options:trickle\na=fingerprint:sha-256 4F:12:50:51:FE:1A:76:0E:74:6D:79:31:DB:C0:E5:42:41:4F:AA:9D:AA:C9:29:AD:A2:49:6E:F3:AF:0F:3A:14\na=setup:actpass\na=mid:0\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\na=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\na=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\na=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\na=sendrecv\na=rtcp-mux\na=rtpmap:111 opus/48000/2\na=rtcp-fb:111 transport-cc\na=fmtp:111 minptime=10;useinbandfec=1\na=rtpmap:103 ISAC/16000\na=rtpmap:104 ISAC/32000\na=rtpmap:9 G722/8000\na=rtpmap:0 PCMU/8000\na=rtpmap:8 PCMA/8000\na=rtpmap:106 CN/32000\na=rtpmap:105 CN/16000\na=rtpmap:13 CN/8000\na=rtpmap:110 telephone-event/48000\na=rtpmap:112 telephone-event/32000\na=rtpmap:113 telephone-event/16000\na=rtpmap:126 telephone-event/8000\nm=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 122 102 121 127 120 125 107 108 109 124 119 123 118 114 115 116 35\nc=IN IP4 0.0.0.0\na=rtcp:9 IN IP4 0.0.0.0\na=ice-ufrag:09iz\na=ice-pwd:TDNEa4DNQNu5vntI7paNKKgV\na=ice-options:trickle\na=fingerprint:sha-256 4F:12:50:51:FE:1A:76:0E:74:6D:79:31:DB:C0:E5:42:41:4F:AA:9D:AA:C9:29:AD:A2:49:6E:F3:AF:0F:3A:14\na=setup:actpass\na=mid:1\na=extmap:14 urn:ietf:params:rtp-hdrext:toffset\na=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\na=extmap:13 urn:3gpp:video-orientation\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\na=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\na=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type\na=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing\na=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\na=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\na=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\na=sendrecv\na=rtcp-mux\na=rtcp-rsize\na=rtpmap:96 VP8/90000\na=rtcp-fb:96 goog-remb\na=rtcp-fb:96 transport-cc\na=rtcp-fb:96 ccm fir\na=rtcp-fb:96 nack\na=rtcp-fb:96 nack pli\na=rtpmap:97 rtx/90000\na=fmtp:97 apt=96\na=rtpmap:98 VP9/90000\na=rtcp-fb:98 goog-remb\na=rtcp-fb:98 transport-cc\na=rtcp-fb:98 ccm fir\na=rtcp-fb:98 nack\na=rtcp-fb:98 nack pli\na=fmtp:98 profile-id=0\na=rtpmap:99 rtx/90000\na=fmtp:99 apt=98\na=rtpmap:100 VP9/90000\na=rtcp-fb:100 goog-remb\na=rtcp-fb:100 transport-cc\na=rtcp-fb:100 ccm fir\na=rtcp-fb:100 nack\na=rtcp-fb:100 nack pli\na=fmtp:100 profile-id=2\na=rtpmap:101 rtx/90000\na=fmtp:101 apt=100\na=rtpmap:122 VP9/90000\na=rtcp-fb:122 goog-remb\na=rtcp-fb:122 transport-cc\na=rtcp-fb:122 ccm fir\na=rtcp-fb:122 nack\na=rtcp-fb:122 nack pli\na=fmtp:122 profile-id=1\na=rtpmap:102 H264/90000\na=rtcp-fb:102 goog-remb\na=rtcp-fb:102 transport-cc\na=rtcp-fb:102 ccm fir\na=rtcp-fb:102 nack\na=rtcp-fb:102 nack pli\na=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f\na=rtpmap:121 rtx/90000\na=fmtp:121 apt=102\na=rtpmap:127 H264/90000\na=rtcp-fb:127 goog-remb\na=rtcp-fb:127 transport-cc\na=rtcp-fb:127 ccm fir\na=rtcp-fb:127 nack\na=rtcp-fb:127 nack pli\na=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f\na=rtpmap:120 rtx/90000\na=fmtp:120 apt=127\na=rtpmap:125 H264/90000\na=rtcp-fb:125 goog-remb\na=rtcp-fb:125 transport-cc\na=rtcp-fb:125 ccm fir\na=rtcp-fb:125 nack\na=rtcp-fb:125 nack pli\na=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f\na=rtpmap:107 rtx/90000\na=fmtp:107 apt=125\na=rtpmap:108 H264/90000\na=rtcp-fb:108 goog-remb\na=rtcp-fb:108 transport-cc\na=rtcp-fb:108 ccm fir\na=rtcp-fb:108 nack\na=rtcp-fb:108 nack pli\na=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f\na=rtpmap:109 rtx/90000\na=fmtp:109 apt=108\na=rtpmap:124 H264/90000\na=rtcp-fb:124 goog-remb\na=rtcp-fb:124 transport-cc\na=rtcp-fb:124 ccm fir\na=rtcp-fb:124 nack\na=rtcp-fb:124 nack pli\na=fmtp:124 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f\na=rtpmap:119 rtx/90000\na=fmtp:119 apt=124\na=rtpmap:123 H264/90000\na=rtcp-fb:123 goog-remb\na=rtcp-fb:123 transport-cc\na=rtcp-fb:123 ccm fir\na=rtcp-fb:123 nack\na=rtcp-fb:123 nack pli\na=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f\na=rtpmap:118 rtx/90000\na=fmtp:118 apt=123\na=rtpmap:114 red/90000\na=rtpmap:115 rtx/90000\na=fmtp:115 apt=114\na=rtpmap:116 ulpfec/90000\na=rtpmap:35 flexfec-03/90000\na=rtcp-fb:35 goog-remb\na=rtcp-fb:35 transport-cc\na=fmtp:35 repair-window=10000000\n' print('offer sdp : ' , offer) sdp = offer res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) offer = GstWebRTC.WebRTCSessionDescription.new(GstWebRTC.WebRTCSDPType.OFFER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', offer, promise) promise.interrupt() direction_a = GstWebRTC.WebRTCRTPTransceiverDirection.SENDONLY caps_a = Gst.caps_from_string("application/x-rtp,media=audio,encoding-name=OPUS,payload=111") direction_v = GstWebRTC.WebRTCRTPTransceiverDirection.SENDONLY caps_v = Gst.caps_from_string("application/x-rtp,media=video,encoding-name=VP8,payload=96") self.webrtc.emit('add-transceiver', direction_a, caps_a) self.webrtc.emit('add-transceiver', direction_v, caps_v) promise = Gst.Promise.new_with_change_func(self.on_answer_created, None, None) self.webrtc.emit('create-answer', None, promise)
async def signaling(request, ws): logging.debug("is called!") clients.append(id(ws)) self.websocket = ws while True: #pprint(ws) #print("websocket id: {id}".format(id=id(ws))) # a Python object (dict): data = {"name": "John"} logging.debug('Sending: ' + str(data)) await ws.send(json.dumps(data)) message = await ws.recv() logging.debug('Received: ' + message) # https://realpython.com/python-json/ msg = json.loads(message) if msg.get('join'): self.rtcClient.create_offer() if msg.get('answer'): sdp = msg['answer'] _, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) self.rtcClient.set_remote_description(answer) if msg.get('candidate') and msg['candidate'].get('candidate'): print('add_ice_candidate') self.rtcClient.add_ice_candidate(msg['candidate'])
def _deepcopy_session_description(self, desc): # XXX: passing 'offer' to both a promise and an action signal without # a deepcopy will segfault... new_sdp = GstSdp.SDPMessage.new()[1] GstSdp.sdp_message_parse_buffer(bytes(desc.sdp.as_text().encode()), new_sdp) return GstWebRTC.WebRTCSessionDescription.new(desc.type, new_sdp)
def take_configuration(self, data): assert (self.webrtc) assert(data['type'] == 'answer') res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(data['sdp'].encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new(GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt()
def setRemoteDescription(self, desc): sdp = desc['sdp'] t = GstWebRTC.WebRTCSDPType.ANSWER if (desc['type'] == 'offer'): t = GstWebRTC.WebRTCSDPType.OFFER _, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new(t, sdpmsg) promise = Gst.Promise.new_with_change_func(self.onRemoteAnswerSet, None) self.webrtc.emit('set-remote-description', answer, promise)
def setAnswer(self, sdp): ''' ''' res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt() print('set-remote-description end..')
async def sdp_message_from_peer(self, ws, sdp): ''' Called when the peer (client) has sent (via websocket) an SDP message ''' assert(sdp['type'] == 'answer') sdp = sdp['sdp'] res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new(GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.peers[ws]['webrtcbin'].emit('set-remote-description', answer, promise) promise.interrupt()
async def handle_sdp(self, sdp): assert self.webrtc assert (sdp['type'] == 'answer') sdp = sdp['sdp'] print('Received answer:\n%s' % sdp) res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt()
def set_remote_sdp(self, sdp: str): """Set remote session description. :param sdp: Session description :type sdp: str """ log.info("Setting remote session description") _, sdp_msg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdp_msg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdp_msg) promise = Gst.Promise.new() self.webrtc.emit("set-remote-description", answer, promise) promise.interrupt()
def have_json(msg): if 'sdp' in msg: sdp = msg['sdp'] res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp['sdp'].encode()), sdpmsg) sdptype = GstWebRTC.WebRTCSDPType.ANSWER if sdp[ 'type'] == 'answer' else GstWebRTC.WebRTCSDPType.OFFER desc = GstWebRTC.WebRTCSessionDescription.new(sdptype, sdpmsg) self.client.set_remote_description(desc) elif 'ice' in msg: ice = msg['ice'] candidate = ice['candidate'] sdpmlineindex = ice['sdpMLineIndex'] self.client.add_ice_candidate(sdpmlineindex, candidate)
def handle_offer(self, msg, UUID): print("HANDLE SDP OFFER") client = self.clients[UUID] if not client or not client['webrtc']: return if 'sdp' in msg: print("INCOMDING OFFER SDP TYPE: "+msg['type']); assert(msg['type'] == 'offer') sdp = msg['sdp'] res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) offer = GstWebRTC.WebRTCSessionDescription.new(GstWebRTC.WebRTCSDPType.OFFER, sdpmsg) promise = Gst.Promise.new() client['webrtc'].emit('set-remote-description', offer, promise) promise.interrupt() promise2 = Gst.Promise.new_with_change_func(self.on_answer_created, client['webrtc'], client) client['webrtc'].emit('create-answer', None, promise2) else: print("No SDP as expected")
def handle_sdp(self, msg): assert (self.webrtc) res, sdpmsg = GstSdp.SDPMessage.new() result = GstSdp.sdp_message_parse_buffer(bytes(msg.encode()), sdpmsg) print("handle_sdp: ", result, sdpmsg, msg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt()
def handle_sdp(webrtc, message): msg = json.loads(message) if "sdp" in msg: sdp = msg["sdp"] assert sdp["type"] == "answer" sdp = sdp["sdp"] logger.info("Received answer:\n%s", sdp) res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() webrtc.emit("set-remote-description", answer, promise) promise.interrupt() elif "ice" in msg: ice = msg["ice"] candidate = ice["candidate"] sdpmlineindex = ice["sdpMLineIndex"] webrtc.emit("add-ice-candidate", sdpmlineindex, candidate)
def handle_sdp(self, msg): if 'sdpAnswer' in msg: sdp = msg['sdpAnswer'] res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt() elif 'candidate' in msg: ice = msg['candidate'] candidate = ice['candidate'] if not self.check_ice_candidate(candidate): return sdpmlineindex = ice['sdpMLineIndex'] self.webrtc.emit('add-ice-candidate', sdpmlineindex, candidate)
def handle_sdp(self, message): assert (self.webrtc) msg = json.loads(message) if 'sdp' in msg: sdp = msg['sdp'] assert(sdp['type'] == 'answer') sdp = sdp['sdp'] print ('Received answer, whee:\n%s' % sdp) res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new(GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt() elif 'ice' in msg: ice = msg['ice'] candidate = ice['candidate'] sdpmlineindex = ice['sdpMLineIndex'] self.webrtc.emit('add-ice-candidate', sdpmlineindex, candidate)
def handle_sdp(self, message): msg = json.loads(message) if 'sdpAnswer' in msg: sdp = msg['sdpAnswer'] print('received sdp answer') print(sdp) res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new(GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt() elif 'candidate' in msg: ice = msg['candidate'] candidate = ice['candidate'] #print("got ice candidate: %s" % candidate) sdpmlineindex = ice['sdpMLineIndex'] self.webrtc.emit('add-ice-candidate', sdpmlineindex, candidate) else: print(msg)
async def handle_peer_msg(self, message, peer_id): assert (self.webrtc[peer_id]) msg = json.loads(message) if 'sdp' in msg: sdp = msg['sdp'] assert(sdp['type'] == 'answer') sdp = sdp['sdp'] with open('webrtc.log', 'a+') as log: log.write('Received answer:\n%s\n' % sdp) res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new(GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc[peer_id].emit('set-remote-description', answer, promise) promise.interrupt() elif 'ice' in msg: ice = msg['ice'] candidate = ice['candidate'] sdpmlineindex = ice['sdpMLineIndex'] self.webrtc[peer_id].emit('add-ice-candidate', sdpmlineindex, candidate)
def handle_sdp_ice(self, msg, UUID): client = self.clients[UUID] if not client or not client['webrtc']: return if 'sdp' in msg: print("INCOMING ANSWER SDP TYPE: "+msg['type']) assert(msg['type'] == 'answer') sdp = msg['sdp'] # print ('Received answer:\n%s' % sdp) res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new(GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() client['webrtc'].emit('set-remote-description', answer, promise) promise.interrupt() elif 'candidate' in msg: print("HANDLE ICE") candidate = msg['candidate'] sdpmlineindex = msg['sdpMLineIndex'] client['webrtc'].emit('add-ice-candidate', sdpmlineindex, candidate) else: print("UNEXPECTED INCOMING")
def setRemoteDescription(self, offer_sdp): ''' ''' print('setRemoteDescription thread:', threading.get_ident()) result, offer = GstSdp.SDPMessage.new() assert (result == GstSdp.SDPResult.OK) GstSdp.sdp_message_parse_buffer(offer_sdp.encode(), offer) description = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.OFFER, offer) self.webrtc.emit('set-remote-description', description, None) promise = Gst.Promise.new() self.webrtc.emit('create-answer', None, promise) promise.wait() reply = promise.get_reply() answer = reply.get_value('answer') # promise = Gst.Promise.new_with_change_func(self.onSetLocalDescription, 'myaatga') promise = Gst.Promise.new() self.webrtc.emit('set-local-description', answer, promise) promise.wait() return answer.sdp.as_text()
async def on_message(self, conn, path): while True: data = await conn.recv() print(f'{data}') datas = data.split(' ') if datas[0] == 'HELLO': await conn.send('HELLO') elif datas[0] == 'SESSION': await conn.send('SESSION_OK') else: msg = json.loads(data) if 'sdp' in msg: sdp = msg['sdp'] assert (sdp['type'] == 'offer') sdp = sdp['sdp'] self.start_pipeline(conn) print('set-remote-description') res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) offer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.OFFER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', offer, promise) promise.interrupt() promise = Gst.Promise.new_with_change_func( self.on_answer_created, conn, None) self.webrtc.emit('create-answer', None, promise) elif 'ice' in msg: print('[RECV] ice:', msg) ice = msg['ice'] candidate = ice['candidate'] sdpmlineindex = ice['sdpMLineIndex'] self.webrtc.emit('add-ice-candidate', sdpmlineindex, candidate)
async def handle_message(self, message): #assert (self.webrtc) msg = json.loads(message) if 'webrtc' in msg: video_formats = msg.get('webrtc_video') audio_only = not video_formats self.launch_x11vnc(audio_only) time.sleep(1) print('sending ice credentials') await self.send_ice_credentials() self.start_pipeline(video_formats, audio_only) if 'ms_audio' in msg: ms_audio = msg['ms_audio'] if ms_audio == 'reset': self.sending = False else: await self.start_ms_audio(ms_audio) if 'sdp' in msg: sdp = msg['sdp'] assert (sdp['type'] == 'answer') sdp = sdp['sdp'] print('Received answer:\n%s' % sdp) res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt() elif 'ice' in msg: ice = msg['ice'] candidate = ice['candidate'] sdpmlineindex = ice['sdpMLineIndex'] self.webrtc.emit('add-ice-candidate', sdpmlineindex, candidate)
async def handle_sdp(self, msg): print(msg) if 'sdp' in msg: sdp = msg['sdp'] assert (msg['type'] == 'answer') print('Received answer:\n%s' % sdp) res, sdpmsg = GstSdp.SDPMessage.new() GstSdp.sdp_message_parse_buffer(bytes(sdp.encode()), sdpmsg) answer = GstWebRTC.WebRTCSessionDescription.new( GstWebRTC.WebRTCSDPType.ANSWER, sdpmsg) promise = Gst.Promise.new() self.webrtc.emit('set-remote-description', answer, promise) promise.interrupt() # Extract ICE candidates from the SDP to work around a GStreamer # limitation in (at least) 1.16.2 and below self.extract_ice_from_sdp(sdp) elif 'ice' in msg: ice = msg['ice'] candidate = ice['candidate'] sdpmlineindex = ice['sdpMLineIndex'] self.webrtc.emit('add-ice-candidate', sdpmlineindex, candidate)