Ejemplo n.º 1
0
        ///<summary> 创建 IceSocket
        /// IceSocket 是可靠的TCP传输
        ///</summary>
        ///<param name="rtcConfiguration"> 服务器地址</param>
        ///<param name="rtcIceParameters"> 可选的来源标识</param>
        ///<param name="isCaller"> 是否为主叫</param>
        ///<param name="observer"> 事件侦听器</param>
        static public IceSocket Connect(string rtcConfiguration, string rtcIceParameters, bool isCaller, RTCSocketObserver observer)
        {
            if (observer == null)
            {
                throw new ArgumentNullException();
            }

            int index = 1;

            while (index < OBSERVERS.Length && OBSERVERS[index] != null)
            {
                ++index;
            }
            if (index == OBSERVERS.Length)
            {
                throw new OverflowException();
            }

            OBSERVERS[index] = observer;
            IntPtr iface = JSEP._CreateIceSocket(rtcConfiguration, rtcIceParameters, isCaller, (IntPtr)index, IceSocketCallback);

            if (iface == IntPtr.Zero)
            {
                OBSERVERS[index] = null;
                throw new ArgumentException();
            }
            IceSocket self = new IceSocket();

            SOCKETS.Add(iface, self);
            self.iface = iface;
            return(self);
        }
Ejemplo n.º 2
0
        ///<summary> 创建P2P通信实例
        ///</summary>
        ///<param name="config"> 配置参数,JSON格式. 例如{'iceServers': [{'url': url}]}</param>
        ///<param name="zmfAudioPump"> 是否使用内置的'全局音频泵',可与外部音频流对接, @see JSEP_AUDIO_PUMP</param>
        ///<param name="isCaller"> 是否为主叫</param>
        ///<param name="observer"> 事件侦听器</param>
        ///<remarks>
        /// config 支持的配置参数
        ///     - STRUN 服务器地址
        ///         iceServers: [{
        ///             urls:'url'
        ///             username:''
        ///             credential:''
        ///         }]
        ///     - bundlePolicy:'balanced'
        ///     - rtcpMuxPolicy:'require' | 'negotiate'
        ///     - iceTransportPolicy:'all'
        ///     - zmfAudioPump: false //全局设置,使用JSEP内置的音频流泵,可与外部音频流对接
        ///
        /// constraints 支持的限制
        ///     - googIPv6: true
        ///     - googDscp: true
        ///     - DtlsSrtpKeyAgreement: true
        ///     - RtpDataChannels: false
        ///     - googSuspendBelowMinBitrate: true
        ///     - googNumUnsignalledRecvStreams: 20
        ///     - googScreencastMinBitrate:int
        ///     - googHighStartBitrate:int
        ///     - googHighBitrate:true
        ///     - googVeryHighBitrate:true
        ///     - googCombinedAudioVideoBwe:true
        ///</remarks>
        public RTCPeerConnection(string config, bool zmfAudioPump, bool isCaller, RTCSessionObserver observer)
        {
            if (observer == null)
            {
                throw new ArgumentNullException();
            }

            int index = 1;

            while (index < OBSERVERS.Length && OBSERVERS[index] != null)
            {
                ++index;
            }
            if (index == OBSERVERS.Length)
            {
                throw new OverflowException();
            }

            OBSERVERS[index] = observer;
            iface            = JSEP._CreatePeerConnection(config, zmfAudioPump, isCaller, (IntPtr)index, RTCSessionCallback);
            if (iface == IntPtr.Zero)
            {
                OBSERVERS[index] = null;
                throw new ArgumentException();
            }
        }
Ejemplo n.º 3
0
        ///<summary> 创建 WebSocket 服务器并侦听客户的连接
        /// WebSocket 是可靠的TCP传输
        ///</summary>
        ///<param name="wsURL"> 服务器地址</param>
        ///<param name="rtcWebSocketInit"> 配置参数</param>
        ///<param name="observer"> 事件侦听器</param>
        static public WebSocket Listen(string wsURL, string rtcWebSocketInit, RTCSocketObserver observer)
        {
            if (observer == null)
            {
                throw new ArgumentNullException();
            }

            int index = 1;

            while (index < OBSERVERS.Length && OBSERVERS[index] != null)
            {
                ++index;
            }
            if (index == OBSERVERS.Length)
            {
                throw new OverflowException();
            }

            OBSERVERS[index] = observer;
            IntPtr iface = JSEP._CreateWebSocketServer(wsURL, rtcWebSocketInit, (IntPtr)index, WebSocketCallback);

            if (iface == IntPtr.Zero)
            {
                OBSERVERS[index] = null;
                throw new ArgumentException();
            }
            WebSocket self = new WebSocket();

            SOCKETS.Add(iface, self);
            self.iface = iface;
            return(self);
        }
Ejemplo n.º 4
0
 ///<summary> 销毁所有资源
 ///</summary>
 ///<param name="isDisposing"> 是否是主动丢弃</param>
 protected virtual void Dispose(bool isDisposing)
 {
     if (iface != IntPtr.Zero)
     {
         OBSERVERS[(int)JSEP._ReleasePeerConnection(iface)] = null;
     }
     iface = IntPtr.Zero;
 }
Ejemplo n.º 5
0
 ///<summary> 销毁所有资源
 ///</summary>
 ///<param name="isDisposing"> 是否是主动丢弃</param>
 protected virtual void Dispose(bool isDisposing)
 {
     if (iface != IntPtr.Zero)
     {
         OBSERVERS[(int)JSEP._CloseSocket(iface)] = null;
         SOCKETS.Remove(iface);
         iface = IntPtr.Zero;
     }
 }
Ejemplo n.º 6
0
 ///<summary> 手工设置发送码率
 ///</summary>
 ///<param name="current_bitrate_bps"> 当前码率,若不大于0,则不设置</param>
 ///<param name="max_bitrate_bps"> 允许的最大码率,若不大于0,则不设置</param>
 ///<param name="min_bitrate_bps"> 允许的最小码率,若不大于0,则不设置</param>
 ///<returns> 成功返回0</returns>
 public int SetBitrate(int current_bitrate_bps, int max_bitrate_bps, int min_bitrate_bps)
 {
     return(JSEP._SetBitrate(iface, current_bitrate_bps, max_bitrate_bps, min_bitrate_bps));
 }
Ejemplo n.º 7
0
 ///<summary> 开始/停止记录通信事件
 ///</summary>
 ///<param name="filename"> 日志文件名,空或null则停止记录</param>
 ///<param name="max_size_mb"> 日志文件允许大小MB</param>
 ///<returns> 成功返回0</returns>
 public int LogRtcEvent(string filename, int max_size_mb)
 {
     return(JSEP._LogRtcEvent(iface, Encoding.UTF8.GetBytes(filename), max_size_mb));
 }
Ejemplo n.º 8
0
 ///<summary> 获取统计
 ///</summary>
 ///<param name="statsType"> 统计类别,""或null表示获取所有统计</param>
 ///<param name="bDebug"> 是否更详细的调试级别</param>
 ///<returns> 成功返回0, 将触发 JsepEventStatsReport 事件</returns>
 public int GetStats(string statsType, bool bDebug)
 {
     return(JSEP._GetStats(iface, statsType, bDebug));
 }
Ejemplo n.º 9
0
 ///<summary> 创建offer SDP
 ///</summary>
 ///<param name="constraints"> 可选的SDP的限制参数.JSON格式</param>
 ///<returns> 无效参数立即返回-1,反之异步过程,结果由JsepEventCreateDescription 事件返回</returns>
 ///<remarks>
 /// constraints 支持如下限制
 /// - OfferToReceiveAudio: true
 /// - OfferToReceiveVideo: true
 /// - VoiceActivityDetection: true
 /// - IceRestart: false
 /// - googUseRtpMUX: true
 ///</remarks>
 public int CreateOffer(string constraints)
 {
     return(JSEP._CreateOffer(iface, constraints));
 }
Ejemplo n.º 10
0
 ///<summary> 配置对端(发送)的SDP
 ///</summary>
 ///<param name="desc"> SDP的JSON串,通常对端由 JsepEventCreateDescription 事件的JsepSdp获得</param>
 ///<returns> 无效参数立即返回-1,反之异步过程,结果由JsepEventSetDescription 事件返回 </returns>
 public int SetRemoteDescription(string desc)
 {
     return(JSEP._SetRemoteDescription(iface, desc));
 }
Ejemplo n.º 11
0
 ///<summary> 移除本地媒体流
 ///</summary>
 ///<param name="streamId"> 媒体流ID,若""或null则移除所有本地流</param>
 public void RemoveLocalStream(string streamId)
 {
     JSEP._RemoveLocalStream(iface, streamId);
 }
Ejemplo n.º 12
0
 ///<summary> 添加对端的ICE备选地址
 ///</summary>
 ///<param name="candidate"> 备选地址,通常对端由 JsepEventIceCandidate 事件的JsepIceCandidate字段获得</param>
 ///<returns> 成功返回0 </returns>
 public int AddIceCandidate(string candidate)
 {
     return(JSEP._AddIceCandidate(iface, candidate));
 }
Ejemplo n.º 13
0
 ///<summary> 发送自定义数据
 ///</summary>
 ///<param name="channelId"> 通道ID</param>
 ///<param name="message"> 消息 </param>
 ///<returns> 成功返回0 </returns>
 public int SendMessage(string channelId, string message)
 {
     byte[] buffer = Encoding.UTF8.GetBytes(message);
     return(JSEP._SendMessage(iface, channelId, buffer, buffer.Length));
 }
Ejemplo n.º 14
0
 ///<summary> 设置对端的ICE参数
 ///</summary>
 ///<param name="rtcIceParameters">对端参数, @see RTCIceParameters</param>
 ///<returns> 成功返回0 </returns>
 public int SetRemoteParameters(string rtcIceParameters)
 {
     return(JSEP._SetSocketIceParameters(iface, rtcIceParameters));
 }
Ejemplo n.º 15
0
 ///<summary> 添加对端的ICE地址
 ///</summary>
 ///<param name="candidate">对端地址</param>
 ///<returns> 成功返回0 </returns>
 public int AddRemoteCandidate(string candidate)
 {
     return(JSEP._AddSocketIceCandidate(iface, candidate));
 }
Ejemplo n.º 16
0
 ///<summary> 发送DTMF
 ///</summary>
 ///<param name="tones"> DMTF的音符,0-9,A-D或a-d,#,*. 忽略无法识别的字符</param>
 ///<param name="duration"> 每个音符的持续毫秒MS,不能超过6000或小于70</param>
 ///<param name="inter_tone_gap"> 音符间隔,必须至少为50ms,但应尽可能短</param>
 ///<returns> 成功返回0,将触发 JsepEventToneChange 事件 </returns>
 ///<remarks>
 /// 队列化发送DTMF 任务.
 /// ','表示延迟2秒处理下一个字符
 /// 若调用时,上次仍在运行,则之前的任务将被取消
 ///</remarks>
 public int InsertDtmf(string tones, int duration, int inter_tone_gap)
 {
     return(JSEP._InsertDtmf(iface, tones, duration, inter_tone_gap));
 }
Ejemplo n.º 17
0
 ///<summary> 将媒体流发布到ZMF中
 ///</summary>
 ///<param name="streamId"> 对端媒体流ID</param>
 ///<param name="renderOrCapturerBits"> 按位将视频轨道作为0-ZMF渲染,1-ZMF镜头</param>
 ///<param name="videoTrackMask"> 上个参数renderOrCapturerBits中的有效位掩码</param>
 ///<returns> 成功返回0 </returns>
 public int PublishRemoteStream(string streamId, int renderOrCapturerBits, int videoTrackMask)
 {
     return(JSEP._PublishRemoteStream(iface, streamId, renderOrCapturerBits, videoTrackMask));
 }
Ejemplo n.º 18
0
 ///<summary> 添加本地媒体流
 ///</summary>
 ///<param name="streamId"> 媒体流ID</param>
 ///<param name="bAudio"> 是否含音频</param>
 ///<param name="bVideo"> 是否含视频</param>
 ///<param name="constraints"> 媒体流的限制参数,JSON格式</param>
 ///<returns> 成功返回0,成功返回0, bAudio, bVideo分别指示是否含音视频 </returns>
 ///<remarks>
 /// 本地媒体流通常在协商前添加,对端媒体流是自动添加的.
 /// streamId 要保证唯一性,通常用账户ID.
 ///
 /// constraints 目前支持
 /// - 视频
 ///   video: {
 ///     zmfCapture:Id0      //ZMF采集源ID
 ///     zmfRender:Id0       //ZMF第三方渲染源ID,转接为采集
 ///   }
 /// - 音频
 ///   audio: {
 ///     DTMF:false          //不使用JSEP_InsertDtmf函数,可节省些内存.
 ///   }
 ///</remarks>
 public int AddLocalStream(string streamId, ref bool bAudio, ref bool bVideo, string constraints)
 {
     return(JSEP._AddLocalStream(iface, streamId, ref bAudio, ref bVideo, constraints));
 }
Ejemplo n.º 19
0
 ///<summary> 配置本地(接收)的SDP
 ///</summary>
 ///<param name="desc"> desc SDP的JSON串,通常对端由 JsepEventCreateDescription 事件的JsepSdp获得</param>
 ///<returns> 无效参数立即返回-1,反之异步过程,结果由JsepEventSetDescription 事件返回 </returns>
 public int SetLocalDescription(string desc)
 {
     return(JSEP._SetLocalDescription(iface, desc));
 }
Ejemplo n.º 20
0
 ///<summary> 关闭数据通道
 ///</summary>
 ///<param name="channelId"> 通道ID</param>
 public void CloseDataChannel(string channelId)
 {
     JSEP._CloseDataChannel(iface, channelId);
 }
Ejemplo n.º 21
0
 ///<summary> 发送数据
 ///</summary>
 ///<param name="message"> 消息 </param>
 ///<returns> 成功返回0 </returns>
 public int Send(string message)
 {
     byte[] buffer = Encoding.UTF8.GetBytes(message);
     return(JSEP._SendSocket(iface, buffer, buffer.Length, 0));
 }
Ejemplo n.º 22
0
 ///<summary> 动态创建数据通道
 ///</summary>
 ///<param name="channelId"> 通道ID</param>
 ///<param name="constraints"> 配置参数</param>
 ///<returns> 成功返回0</returns>
 ///<remarks>
 /// 支持的配置参数
 /// - ordered:true,       //是否保证次序,默认true
 /// - maxPacketLifeTime:0,//超过限时,将不重发.默认-1,始终重发
 /// - maxRetransmits:0,   //超过次数,将不重发,默认-1,,始终重发
 /// - negotiated:false,   //是否由上层应用负责协商建立过程,
 ///                         即不触发DataChannelOpen事件.默认false由内部自动完成
 /// - protocol:'',        //自定义的上层应用协议名,默认空
 ///</remarks>
 public int CreateDataChannel(string channelId, string constraints)
 {
     return(JSEP._CreateDataChannel(iface, channelId, constraints));
 }