我已经从google repo编译了WebRTC源,并且已经在Android Binding Library项目中使用了jar以及各个体系结构文件夹中的本机库(.so文件)。该库编译没有错误。
我有主要的Android应用程序,并引用了绑定库的输出(.dll)。该应用程序也编译没有错误。
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");
}
}
}
}
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);
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
任何人都可以看看并告诉我是否有任何遗漏?
答案 0 :(得分:1)
行。我明白了。
两件事:
1.会话描述格式不正确,TURN服务器将拒绝任何格式不正确的信息。
2.与TURN服务器的所有通信都应该在单个线程中,而不是并行线程。 IScheduledExecutorService接口的方法NewSingleThreadScheduledExecutor()
就是这样做的。应该重用构造函数中实例化的接口的对象来执行IRunnable处理程序。这将确保应用程序是线程安全的,并且事件在触发时进行处理。