WebRTC - Xamarin。尝试设置本地描述失败

时间:2017-02-13 10:31:47

标签: c# xamarin xamarin.android webrtc

我已经从google repo编译了WebRTC源,并且已经在Android Binding Library项目中使用了jar以及各个体系结构文件夹中的本机库(.so文件)。该库编译没有错误。

我有主要的Android应用程序,并引用了绑定库的输出(.dll)。该应用程序也编译没有错误。

  1. 我可以添加音轨和视频轨道,然后相机就会出现。
  2. 这是我的ISDPObserver实施
  3. public class SDPObserver: Java.Lang.Object, ISDPObserver
    {
        public void OnCreateFailure(string error)
        {
            _classContext.ReportError("createSDP error: " + error);
        }
        public void OnCreateSuccess(SessionDescription origSdp)
        {
            if (_localSdp != null)
            {
                _classContext.ReportError("Multiple SDP create.");
                return;
            }
            string sdpDescription = origSdp.Description;
            if (_preferIsac)
            {
                sdpDescription = PreferCodec(sdpDescription, _AUDIO_CODEC_ISAC, true);
            }
            if (_videoCallEnabled)
            {
                sdpDescription = PreferCodec(sdpDescription, _preferredVideoCodec, false);
            }
            SessionDescription sdp = new SessionDescription(origSdp.Type, sdpDescription);
            _localSdp = sdp;
            _executor.Execute(new SDPOnCreateSuccessHandler(sdp));
        }
        // THIS IS WHERE THE FREAKING THING FAILS. SESSION DESCRIPTION IS NULL
        public void OnSetFailure(string error)
        {
            _classContext.ReportError("setSDP error: " + error);
        }
        public void OnSetSuccess()
        {
            _executor.Execute(new SDPOnSetSuccessHandler(_localSdp));
        }
    }
    public class SDPOnCreateSuccessHandler: Java.Lang.Object, Java.Lang.IRunnable
    {
        private SessionDescription __sdp;
        public SDPOnCreateSuccessHandler(SessionDescription sdp)
        {
            __sdp = sdp;
        }
        public void Run()
        {
            if (_peerConnection != null && !_isError)
            {
                try
                {
                    Log.Debug(TAG, "Set local SDP from " + __sdp.Type);
                    _peerConnection.SetLocalDescription(_sdpObserver, __sdp);
                }
                catch (Java.Lang.Exception e)
                {}
                catch (System.Exception e)
                {}
            }
        }
    }
    public class SDPOnSetSuccessHandler: Java.Lang.Object, Java.Lang.IRunnable
    {
        private SessionDescription __localSdp;
        public SDPOnSetSuccessHandler(SessionDescription localSdp)
        {
            __localSdp = localSdp;
        }
        public void Run()
        {
            if (_peerConnection == null || _isError)
            {
                return;
            }
            if (_isInitiator)
            {
                // For offering peer connection we first create offer and set
                // local SDP, then after receiving answer set remote SDP.
                if (_peerConnection.RemoteDescription == null)
                {
                    // We've just set our local SDP so time to send it.
                    Log.Debug(TAG, "Local SDP set succesfully");
                    _events.OnLocalDescription(__localSdp);
                }
                else
                {
                    // We've just set remote description, so drain remote
                    // and send local ICE candidates.
                    Log.Debug(TAG, "Remote SDP set succesfully");
                    DrainCandidates();
                }
            }
            else
            {
                // For answering peer connection we set remote SDP and then
                // create answer and set local SDP.
                if (_peerConnection.LocalDescription != null)
                {
                    // We've just set our local SDP so time to send it, drain
                    // remote and send local ICE candidates.
                    Log.Debug(TAG, "Local SDP set succesfully");
                    _events.OnLocalDescription(__localSdp);
                    DrainCandidates();
                }
                else
                {
                    // We've just set remote SDP - do nothing for now -
                    // answer will be created soon.
                    Log.Debug(TAG, "Remote SDP set succesfully");
                }
            }
        }
    }
    
    1. OnCreateSuccess按预期触发,我可以使用autio编解码器和cideo编解码器值更新SessionDescription。接下来,执行Run方法 SDPOnCreateSuccessHandler 。这是它无法设置本地描述的地方。 _peerConnection.SetLocalDescription(_sdpObserver,__sdp)调用.NET生成的代码,如下所示(抱歉格式化,无论我做什么,它都没有预算):
    2. static IntPtr id_setLocalDescription_Lorg_webrtc_SdpObserver_Lorg_webrtc_SessionDescription_;
      // Metadata.xml XPath method reference: path="/api/package[@name='org.webrtc']/class[@name='PeerConnection']/method[@name='setLocalDescription' and count(parameter)=2 and parameter[1][@type='org.webrtc.SdpObserver'] and parameter[2][@type='org.webrtc.SessionDescription']]"
      [Register("setLocalDescription", "(Lorg/webrtc/SdpObserver;Lorg/webrtc/SessionDescription;)V", "GetSetLocalDescription_Lorg_webrtc_SdpObserver_Lorg_webrtc_SessionDescription_Handler")]
      public virtual unsafe void SetLocalDescription(global::Org.Webrtc.ISdpObserver p0, global::Org.Webrtc.SessionDescription p1)
      {
      if (id_setLocalDescription_Lorg_webrtc_SdpObserver_Lorg_webrtc_SessionDescription_ == IntPtr.Zero)
          id_setLocalDescription_Lorg_webrtc_SdpObserver_Lorg_webrtc_SessionDescription_ = JNIEnv.GetMethodID(class_ref, "setLocalDescription", "(Lorg/webrtc/SdpObserver;Lorg/webrtc/SessionDescription;)V");
      try
      {
          JValue * __args = stackalloc JValue[2];
          __args[0] = new JValue(p0);
          __args[1] = new JValue(p1);
          if (GetType() == ThresholdType)
              JNIEnv.CallVoidMethod(((global::Java.Lang.Object) this).Handle, id_setLocalDescription_Lorg_webrtc_SdpObserver_Lorg_webrtc_SessionDescription_, __args);
          else
              JNIEnv.CallNonvirtualVoidMethod(((global::Java.Lang.Object) this).Handle, ThresholdClass, JNIEnv.GetMethodID(ThresholdClass, "setLocalDescription", "(Lorg/webrtc/SdpObserver;Lorg/webrtc/SessionDescription;)V"), __args);
      }
      finally
      {}
      }
      

      该函数评估为" if"条件并在行中失败:

      JNIEnv.CallVoidMethod (((global::Java.Lang.Object) this).Handle, id_setLocalDescription_Lorg_webrtc_SdpObserver_Lorg_webrtc_SessionDescription_, __args);
      
      1. 这是更新的会话描述值:
      2. v = 0
        o = -5449345243432399727 2 IN IP4 127.0.0.1
        s = - t = 0 0
        a = group: BUNDLE audio video data
        a = msid - semantic: WMS ARDAMS
        m = audio 9 UDP / TLS / RTP / SAVPF 111 103 104 9 102 0 8 106 105 13 110 112 113 126
        c = IN IP4 0.0.0.0
        a = rtcp: 9 IN IP4 0.0.0.0
        a = ice - ufrag: Jyke
        a = ice - pwd: j85eXW9UUZMcqKnQ7ZOErU28
        a = ice - options: renomination
        a = fingerprint: sha - 256 E8: 3A: 8B: 26: CC: 6D: 9C: 8B: 7F: 48: A0: E7: D0: 81: 3F: B2: 2E: E1: 2E: 9A: 07: 4C: CC: 66: 77: F3: 64: FC: 51: 1C: 9B: 85
        a = setup: actpass
        a = mid: audio
        a = extmap: 1 urn: ietf: params: rtp - hdrext: ssrc - audio - level
        a = sendrecv
        a = rtcp - mux
        a = rtpmap: 111 opus / 48000 / 2
        a = rtcp - fb: 111 transport - cc
        a = fmtp: 111 minptime = 10;
        useinbandfec = 1
        a = rtpmap: 103 ISAC / 16000
        a = rtpmap: 104 ISAC / 32000
        a = rtpmap: 9 G722 / 8000
        a = rtpmap: 102 ILBC / 8000
        a = rtpmap: 0 PCMU / 8000
        a = rtpmap: 8 PCMA / 8000
        a = rtpmap: 106 CN / 32000
        a = rtpmap: 105 CN / 16000
        a = rtpmap: 13 CN / 8000
        a = rtpmap: 110 telephone - event / 48000
        a = rtpmap: 112 telephone - event / 32000
        a = rtpmap: 113 telephone - event / 16000
        a = rtpmap: 126 telephone - event / 8000
        a = ssrc: 701282247 cname: rwclcMyxn371tKuJ
        a = ssrc: 701282247 msid: ARDAMS ARDAMSa0
        a = ssrc: 701282247 mslabel: ARDAMS
        a = ssrc: 701282247 label: ARDAMSa0
        m = video 9 UDP / TLS / RTP / SAVPF 96 98 100 127 125 97 99 101 124
        c = IN IP4 0.0.0.0
        a = rtcp: 9 IN IP4 0.0.0.0
        a = ice - ufrag: Jyke
        a = ice - pwd: j85eXW9UUZMcqKnQ7ZOErU28
        a = ice - options: renomination
        a = fingerprint: sha - 256 E8: 3A: 8B: 26: CC: 6D: 9C: 8B: 7F: 48: A0: E7: D0: 81: 3F: B2: 2E: E1: 2E: 9A: 07: 4C: CC: 66: 77: F3: 64: FC: 51: 1C: 9B: 85
        a = setup: actpass
        a = mid: video
        a = extmap: 2 urn: ietf: params: rtp - hdrext: toffset
        a = extmap: 3 http: //www.webrtc.org/experiments/rtp-hdrext/abs-send-time
        a = extmap: 4 urn: 3gpp: video - orientation
        a = extmap: 5 http: //www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
        a = extmap: 6 http: //www.webrtc.org/experiments/rtp-hdrext/playout-delay
        a = sendrecv
        a = rtcp - mux
        a = rtcp - rsize
        a = rtpmap: 96 VP8 / 90000
        a = rtcp - fb: 96 ccm fir
        a = rtcp - fb: 96 nack
        a = rtcp - fb: 96 nack pli
        a = rtcp - fb: 96 goog - remb
        a = rtcp - fb: 96 transport - cc
        a = rtpmap: 98 VP9 / 90000
        a = rtcp - fb: 98 ccm fir
        a = rtcp - fb: 98 nack
        a = rtcp - fb: 98 nack pli
        a = rtcp - fb: 98 goog - remb
        a = rtcp - fb: 98 transport - cc
        a = rtpmap: 100 red / 90000
        a = rtpmap: 127 ulpfec / 90000
        a = rtpmap: 125 H264 / 90000
        a = rtcp - fb: 125 ccm fir
        a = rtcp - fb: 125 nack
        a = rtcp - fb: 125 nack pli
        a = rtcp - fb: 125 goog - remb
        a = rtcp - fb: 125 transport - cc
        a = fmtp: 125 level - asymmetry - allowed = 1;
        packetization - mode = 1;
        profile - level - id = 42e01f
        a = rtpmap: 97 rtx / 90000
        a = fmtp: 97 apt = 96
        a = rtpmap: 99 rtx / 90000
        a = fmtp: 99 apt = 98a = rtpmap: 101 rtx / 90000
        a = fmtp: 101 apt = 100
        a = rtpmap: 124 rtx / 90000
        a = fmtp: 124 apt = 125
        a = ssrc - group: FID 1610329415 966940881
        a = ssrc: 1610329415 cname: rwclcMyxn371tKuJ
        a = ssrc: 1610329415 msid: ARDAMS ARDAMSv0
        a = ssrc: 1610329415 mslabel: ARDAMS
        a = ssrc: 1610329415 label: ARDAMSv0
        a = ssrc: 966940881 cname: rwclcMyxn371tKuJ
        a = ssrc: 966940881 msid: ARDAMS ARDAMSv0
        a = ssrc: 966940881 mslabel: ARDAMS
        a = ssrc: 966940881 label: ARDAMSv0
        m = application 9 UDP / TLS / RTP / SAVPF 109
        c = IN IP4 0.0.0.0
        b = AS: 30
        a = rtcp: 9 IN IP4 0.0.0.0
        a = ice - ufrag: Jyke
        a = ice - pwd: j85eXW9UUZMcqKnQ7ZOErU28
        a = ice - options: renomination
        a = fingerprint: sha - 256 E8: 3A: 8B: 26: CC: 6D: 9C: 8B: 7F: 48: A0: E7: D0: 81: 3F: B2: 2E: E1: 2E: 9A: 07: 4C: CC: 66: 77: F3: 64: FC: 51: 1C: 9B: 85
        a = setup: actpass
        a = mid: data
        a = sendrecv
        a = rtcp - mux
        a = rtpmap: 109 google - data / 90000
        a = ssrc: 3087089883 cname: rwclcMyxn371tKuJ
        a = ssrc: 3087089883 msid: ApprtcDemo data ApprtcDemo data
        a = ssrc: 3087089883 mslabel: ApprtcDemo data
        a = ssrc: 3087089883 label: ApprtcDemo data
        

        任何人都可以看看并告诉我是否有任何遗漏?

1 个答案:

答案 0 :(得分:1)

行。我明白了。

两件事:

1.会话描述格式不正确,TURN服务器将拒绝任何格式不正确的信息。

2.与TURN服务器的所有通信都应该在单个线程中,而不是并行线程。 IScheduledExecutorService接口的方法NewSingleThreadScheduledExecutor()就是这样做的。应该重用构造函数中实例化的接口的对象来执行IRunnable处理程序。这将确保应用程序是线程安全的,并且事件在触发时进行处理。