コード例 #1
0
 def __remove_point(self, point):
     assert type(point) is PointController
     LOG.debug("MC: removing point [%s]", point.point_id)
     try:
         self.__manager.remove_point(point.point_id)
     except ManagerError as e:
         LOG.warning(str(e))
コード例 #2
0
 def __send_dtmf(self, message):
     point_id = str(message.point_id)
     point = self.__get_point_by_id(point_id)
     if point is None:
         LOG.warning("Attempt to unjoin with unexisting point")
         return
     point.event("SEND_DTMF", dtmf=str(message.get("dtmf", "")))
コード例 #3
0
 def __on_message_join(self, message):
     try:
         point_id = str(message.point_id)
         room_id = str(message.room_id)
         self.__manager.join_room(point_id, room_id)
     except ManagerError as e:
         LOG.warning(str(e))
コード例 #4
0
    def on_message(self, message, transport):
        """
        received message from bus
        :param message: message object
        """
        assert type(message) is messaging.Message
        message_type = message.type

        if message_type == MessageType.CREATE_POINT:
            self.__on_message_create_point(message)

        elif message_type == MessageType.REMOVE_POINT:
            self.__on_message_remove_point(message)

        elif message_type == MessageType.JOIN_ROOM:
            self.__on_message_join(message)

        elif message_type == MessageType.UNJOIN_ROOM:
            self.__on_message_unjoin(message)

        elif message_type == MessageType.SDP_ANSWER:
            self.set_remote_sdp(message)

        elif message_type == MessageType.SEND_DTMF:
            self.__send_dtmf(message)

        else:
            LOG.warning("Unknown message type: %s", repr(message_type))
コード例 #5
0
    def set_remote_sdp(self, message):
        point_id = str(message.point_id)
        point = self.__get_point_by_id(point_id)

        if point is not None:
            point.event(PointEvent.SDP_ANSWER, sdp=str(message.get("sdp", "")))
        else:
            LOG.warning("Unknown point " + str(point_id))
コード例 #6
0
 def unjoin(self, media_point):
     assert isinstance(media_point, IMediaPoint)
     if media_point in self.__points:
         if len(self.__points) == 2:
             LOG.debug("MediaRoom.stopping pipeline")
             self.__context.stop()
         self.__points.remove(media_point)
         self.__remove_point_from_pipeline(media_point)
コード例 #7
0
    def __check_conn_ready(self):
        if self.__remote_conn and self.__local_rtp_conn and self.__local_rtcp_conn:
            LOG.info("SrtpConn.check_conn_ready: %s -> %d, %d",
                     self.__remote_conn,
                     self.__local_rtp_conn.port,
                     self.__local_rtcp_conn.port)
            self.__local_media_description.add_candidate(self.__remote_conn.port, self.__profile.ip)

            if self._listener is not None:
                self._listener.media_point_frontend_ready(self)
コード例 #8
0
    def set_remote_media_description(self, remote_media_description):
        assert type(remote_media_description) is MediaDescription
        self._remote_media = remote_media_description
        remote_media_description.set_addr(self.__local_rtp_conn.port, "127.0.0.1")
        remote_media_description.rtcp.port = self.__local_rtcp_conn.port

        self._media_point.set_remote_media_description(remote_media_description)

        add_point_message = dict(
            type="ADD_POINT",
            id=self.point_id,
            localRtp=self.__local_rtp_conn.id,
            localRtcp=self.__local_rtcp_conn.id,
            remoteRtp=self.__remote_conn.id,
            remoteRtcp=self.__remote_conn.id,
            localIce=self.__local_media_description.ice.ufrag + ":" + self.__local_media_description.ice.pwd,
            remoteIce=self._remote_media.ice.ufrag + ":" + self._remote_media.ice.pwd)
        self.__agent.send_message(add_point_message)

        local_crypto_key = binascii.b2a_hex(binascii.a2b_base64(self.__local_media_description.crypto.key))
        self.__agent.send_message({
            "type": "ADD_LOCAL_STREAM",
            "pointId": self.point_id,
            "key": local_crypto_key,
            "ssrc": self.__local_media_description.streams[0].ssrc_id})

        remote_crypto_key = binascii.b2a_hex(binascii.a2b_base64(self._remote_media.crypto.key))
        if len(self._remote_media.streams):
            self.__agent.send_message({
                "type": "ADD_REMOTE_STREAM",
                "pointId": self.point_id,
                "key": remote_crypto_key,
                "ssrc": self._remote_media.streams[0].ssrc_id,
                "rtp": "udp://127.0.0.1:" + str(self._media_point.rtp_port),
                "rtcp": "udp://127.0.0.1:" + str(self._media_point.rtcp_port)})

        ####### draw debug scheme
        LOG.debug("""
                                +-- ice --+                   +-- gst -- +
                                !         !                   !          !
                                !        %05d <----rtp----> %05d       !
        Chrome ? <----------->%05d       !                   !          !
                                !        %05d <----rtcp---> %05d       !
                                !         !                   !          !
                                +---------+                   +----------+

        """,
                  self.__local_rtp_conn.port, self._media_point.rtp_port,
                  self.__remote_conn.port,
                  self.__local_rtcp_conn.port, self._media_point.rtcp_port)
コード例 #9
0
 def join(self, media_point):
     assert isinstance(media_point, IMediaPoint)
     if media_point in self.__points:
         return
     assert len(
         self.__points) <= 1  # currently no more than 2 points in room
     self.__points.append(media_point)
     self.__add_point_to_pipeline(media_point)
     if len(self.__points) == 2:
         self.__link_points(self.__points[0], self.__points[1])
         self.__link_points(self.__points[1], self.__points[0])
         LOG.debug("MediaRoom.starting pipeline")
         self.__context.play()
         for p in self.__points:
             p.force_key_unit()
コード例 #10
0
ファイル: room.py プロジェクト: rcslabs/a3-media-controller
    def join(self, point):
        # we have PointController here
        # TODO: create RoomController
        point = point.point
        assert isinstance(point, Point)
        if point in self.__points:
            LOG.warning("Attempt to join room %s more than once", self.__room_id)
            return

        self.__points.append(point)

        if point.audio_point:
            self.__get_audio_room().join(point.audio_point)

        if point.video_point:
            self.__get_video_room().join(point.video_point)
コード例 #11
0
    def media_point_frontend_ready(self, media_point):
        LOG.debug("SrtpMediaPoint.media_point_frontend_ready")
        self.__local_media_description.direction = SdpDirection.SEND_RECV

        media_type = self.__local_media_description.media_type
        #ssrc_id = 2222L if media_type is MediaType.VIDEO else 1111L
        ssrc_id = self._media_point.transcoder.ssrc_id

        self.__local_media_description.streams.generate(ssrc_id=ssrc_id, media_type=media_type)
        #self._media_point.transcoder.ssrc_id = self.__local_media_description.streams[0].ssrc_id
        self._media_point.transcoder.cname = self.__local_media_description.streams[0].cname

        remote_profile = self.__profile
        local_profile = self.__config.profile("local")
        self.__agent.request_conn(remote_profile, lambda conn: self.__remote_conn_created(conn))
        self.__agent.request_conn(local_profile, lambda conn: self.__local_rtp_conn_created(conn))
        self.__agent.request_conn(local_profile, lambda conn: self.__local_rtcp_conn_created(conn))
コード例 #12
0
    def __init__(self, raw_media):
        """

        :param raw_media: raw media object
        :param pt_reserver: payload type reserver
        """
        assert type(raw_media) is raw.media.Media
        self.__raw_media = raw_media
        self.__rtp_codecs = []

        for payload_type in self.payload_types:
            try:
                rtp_codec = create_codec_from_attributes(raw_media.media_type,
                                                         payload_type,
                                                         self.__raw_media.attributes)
                self.__rtp_codecs.append(rtp_codec)
            except UnknownCodecError as e:
                LOG.warn("Unknown codec with payload type %d", e.value)
コード例 #13
0
    def __on_message_create_point(self, message):
        try:
            point = self.__manager.create_point(
                point_id=str(message.point_id),
                initiator_message=message,
                config=self.__config,
                balancer=self.__balancer,
                transcoding_factory=self.__transcoding_factory)

            if message.has("cc") and message.has("vv"):
                profile_name = message.get("profile", "")
                profile = self.__config.profile(profile_name)
                assert profile is not None
                try:
                    point.event(PointEvent.CREATE_OFFER,
                                cc=message.get("cc"),
                                vv=message.get("vv"),
                                profile=profile)
                except PointControllerError:
                    self.__remove_point(point)
            else:
                LOG.warning("No cc or vv in initiator message")
                LOG.warning("Answer model not implemented")
        except ManagerError as e:
            LOG.warning(str(e))
コード例 #14
0
    def event(self, event_type, **kwargs):
        if event_type != Event.TIMER:
            LOG.debug("PointController[%s]: Got event %s in state %s",
                      self.__point_id, repr(event_type), repr(self.__state))

        if self.state == State.START:
            if event_type == Event.CREATE_OFFER:
                self.__create_offer(**kwargs)
            else:
                self.__unhandled_event(event_type)

        elif self.state == State.CREATING_OFFER:
            if event_type == Event.CONN_READY:
                LOG.debug("PointController.LOCAL-SDP=%s", self.__point.local_sdp)
                self.state = State.WAITING_REMOTE_SDP
                self.reply(MessageType.SDP_OFFER, {"sdp": str(self.__point.local_sdp)})
            elif event_type == Event.REMOVE:
                self.__remove()
                self.reply(MessageType.REMOVE_POINT_OK)
            elif event_type == Event.TIMER:
                pass
            else:
                self.__unhandled_event(event_type)

        elif self.state == State.WAITING_REMOTE_SDP:
            if event_type == Event.SDP_ANSWER:
                try:
                    self.state = State.CONNECTED
                    self.__on_remote_sdp(**kwargs)
                    self.reply(MessageType.CREATE_POINT_OK)
                except (ParseError, AssertionError) as err:
                    LOG.exception("Exception while parsing SDP-ANSWER: %s", str(err))
                    self.state = State.ERROR
                    self.reply(MessageType.CREATE_POINT_FAILED)

            elif event_type == Event.REMOVE:
                self.__remove()
                self.reply(MessageType.REMOVE_POINT_OK)
            elif event_type == Event.TIMER:
                pass
            else:
                self.__unhandled_event(event_type)

        elif self.state == State.CONNECTED:
            if event_type == Event.REMOVE:
                self.__remove()
                self.reply(MessageType.REMOVE_POINT_OK)
            elif event_type == Event.TIMER:
                self.__point.on_timer()
            elif event_type == "SEND_DTMF":
                self.__point.send_dtmf(kwargs["dtmf"])
            else:
                self.__unhandled_event(event_type)

        else:
            self.__unhandled_event(event_type)
コード例 #15
0
    def start(self):
        LOG.debug("RtmpMediaPoint %s: starting", self.__point_id)
        assert self.__profile
        #
        # Currently we accept points with local media description set before start
        #
        assert self.__local_media_description
        media_type = self.__local_media_description.media_type
        self.__rtmp_frontend = self.__transcoding_factory.create_rtmp_frontend(
            media_type, self.__profile)
        assert isinstance(self.__rtmp_frontend, IRtmpFrontend)

        # fill local sdp with opened ports
        LOG.debug("RtmpMediaPoint: pub: %s, sub: %s", self.__rtmp_frontend.pub,
                  self.__rtmp_frontend.sub)

        self.__local_media_description.raw_media.attributes.append(
            Attribute("rtmp-sub", StrAttributeValue(self.__rtmp_frontend.sub)))

        self.__local_media_description.raw_media.attributes.append(
            Attribute("rtmp-pub", StrAttributeValue(self.__rtmp_frontend.pub)))

        if self.__listener is not None:
            self.__listener.media_point_frontend_ready(self)
コード例 #16
0
 def __add_point_to_pipeline(self, media_point):
     LOG.debug("MediaRoom.add_point %s", media_point.point_id)
     assert isinstance(media_point, IMediaPoint)
     media_point.set_context(self.__context)
コード例 #17
0
 def __unhandled_event(self, event_type):
     LOG.warning("PointController: Unhandled event " + repr(event_type) + " in state " + repr(self.state))
コード例 #18
0
 def __error(self, message):
     LOG.warning("PointController: Error: " + repr(message))
     self.state = State.ERROR
     raise PointControllerError(message)
コード例 #19
0
 def __on_remote_sdp(self, sdp):
     assert type(sdp) is str
     LOG.debug("PointController: remote SDP: %s", sdp)
     self.__point.remote_sdp = SdpFactory.create_from_string(sdp)
コード例 #20
0
 def point_conn_ready(self):
     LOG.debug("PointController.point_conn_ready")
     self.event(Event.CONN_READY)
コード例 #21
0
 def dispose(self):
     LOG.debug("RtmpMediaPoint.dispose")
     self.__rtmp_frontend.dispose()
     self.__rtmp_frontend = None
コード例 #22
0
 def state(self, new_state):
     LOG.debug("PointController[%s]: transition %s -> %s", self.__point_id, self.__state, new_state)
     self.__state = new_state
コード例 #23
0
 def __remote_conn_created(self, conn):
     LOG.debug("SrtpMediaPoint.remote_conn_created %s", str(conn))
     self.__remote_conn = conn
     self.__check_conn_ready()
コード例 #24
0
 def __on_message_remove_point(self, message):
     try:
         self.__manager.remove_point(str(message.point_id))
     except ManagerError as e:
         LOG.warning(str(e))
コード例 #25
0
 def __local_rtcp_conn_created(self, conn):
     LOG.debug("SrtpMediaPoint.local_rtcp_conn_created %s", str(conn))
     self.__local_rtcp_conn = conn
     self.__check_conn_ready()
コード例 #26
0
            self.__manager.unjoin(point_id)
        except ManagerError as e:
            LOG.warning(str(e))

    def __send_dtmf(self, message):
        point_id = str(message.point_id)
        point = self.__get_point_by_id(point_id)
        if point is None:
            LOG.warning("Attempt to unjoin with unexisting point")
            return
        point.event("SEND_DTMF", dtmf=str(message.get("dtmf", "")))


if __name__ == "__main__":
    from a3.config import CommandLineConfig, IniConfig, DefaultConfig
    from a3.transcoding.gst1.factory import Gst1TranscodingFactory

    config = CommandLineConfig(IniConfig(DefaultConfig()))
    LOG.info("Config:\n%s", config)

    # TODO: implement configuration-based tanscoding
    transcoding_factory = Gst1TranscodingFactory()

    media_controller = MediaController(config, transcoding_factory)

    messaging.create(config.mq, media_controller).listen()

    while True:
        time.sleep(1)
        media_controller.on_timer()
コード例 #27
0
 def __remove_point_from_pipeline(self, media_point):
     LOG.debug("MediaRoom.remove_point %s", media_point.point_id)
     assert isinstance(media_point, IMediaPoint)
     media_point.set_context(None)
コード例 #28
0
    def create_offer(cls, cc, vv, supported_codecs):
        assert type(cc) is capabilities.Cc
        assert type(vv) is capabilities.Vv
        assert isinstance(supported_codecs, collections.Iterable)
        sdp = SessionDescription()

        if cc.bundle:
            sdp.group_semantics = GroupSemantics.BUNDLE

        for media_type in vv.media_types:
            assert media_type in [MediaType.AUDIO, MediaType.VIDEO]

            codecs = [
                codec for codec in cc.get_codecs(media_type)
                if codec in supported_codecs
            ]
            LOG.debug(
                "Cc: Creating media description (%s) based on codecs: %s",
                str(media_type), ",".join([str(codec) for codec in codecs]))

            raw_media = raw.media.Media(media_type=media_type)
            media = sdp.add_raw_media(raw_media)

            if cc.rtcp_mux:
                media.rtcp_mux = True

            for codec in codecs:
                media.add_codec(codec)

            media.raw_media.media_description.proto = cc.profile

            if cc.profile == MediaDescriptionProto.RTP_SAVPF:
                media.crypto.generate_AES_CM_128_HMAC_SHA1_80()

            if cc.ssrc_required:
                media.direction = SdpDirection.RECV_ONLY

            if cc.ice:
                media.raw_media.connection_data = ConnectionData(
                    NetType.IN, AddrType.IP4, "0.0.0.0")
                media.rtcp.port = 1
                media.rtcp.connection_address = "0.0.0.0"
                media.ice.generate_google_ice()

            if media_type is MediaType.AUDIO:
                #
                # some hacks
                #
                #media.packet_time = 20
                #media.silence_supp_enable = False
                #media.codecs.add(Codec("telephone-event", 8000))
                pass
                # fmtp:101 0-15

        #if self._ice:
        #    #sdp.host = None                                          # ??? ERROR???
        #    ice_ufrag, ice_pwd = gen_ice_pair()
        #    sdp.set_ice(ice_ufrag, ice_pwd, "google-ice")
        #else:
        #    sdp.host = host

        # http://code.google.com/p/webrtc/issues/detail?id=757
        # As per the latest draft when you use BUNDLE in offer/answer than rtcp-mux attribute must be specified.
        # In your case you are using BUNDLE in answer without rtcp-mux. Please refer to section 6.1 in the below draft.
        #http://datatracker.ietf.org/doc/draft-ietf-mmusic-sdp-bundle-negotiation/?include_text=1
        #
        #if cc.rtcp_mux:
        #    sdp.group_bundle()

        return sdp
コード例 #29
0
 def __on_message_unjoin(self, message):
     try:
         point_id = str(message.point_id)
         self.__manager.unjoin(point_id)
     except ManagerError as e:
         LOG.warning(str(e))