對于WebRTC,每一個客戶端成為一個peer,而PeerConnection就是用來管理peer之間的連接過程。
加載so庫
static {
System.loadLibrary("jingle_peerconnection_so");
}
檢測本地candidate的狀態(tài)
public static enum IceGatheringState {
NEW,
GATHERING,
COMPLETE;
private IceGatheringState() {
}
}
| IceGatheringState |
Description |
| NEW |
剛剛創(chuàng)建 |
| GATHERING |
正在收集 |
| COMPLETE |
完成收集 |
檢測遠端candidate的狀態(tài),描述連接的ICE連接狀態(tài)
public static enum IceConnectionState {
NEW,
CHECKING,
CONNECTED,
COMPLETED,
FAILED,
DISCONNECTED,
CLOSED;
private IceConnectionState() {
}
}
| IceConnectionState |
Description |
| NEW |
ICE 代理正在搜集地址或者等待遠程候選可用 |
| CHECKING |
ICE 代理已收到至少一個遠程候選,并進行校驗,無論此時是否有可用連接。同時可能在繼續(xù)收集候選 |
| CONNECTED |
ICE代理至少對每個候選發(fā)現(xiàn)了一個可用的連接,此時仍然會繼續(xù)測試遠程候選以便發(fā)現(xiàn)更優(yōu)的連接,同時可能在繼續(xù)收集候選 |
| COMPLETED |
ICE代理已經(jīng)發(fā)現(xiàn)了可用的連接,不再測試遠程候選 |
| FAILED |
ICE候選測試了所有遠程候選沒有發(fā)現(xiàn)匹配的候選,也可能有些候選中發(fā)現(xiàn)了一些可用連接 |
| DISCONNECTED |
測試不再活躍,這可能是一個暫時的狀態(tài),可以自我恢復 |
| CLOSED |
ICE代理關閉,不再應答任何請求 |
描述本地連接的信令狀態(tài),該值表示在信令交換offer和answer時的狀態(tài)。
public static enum SignalingState {
STABLE,
HAVE_LOCAL_OFFER,
HAVE_LOCAL_PRANSWER,
HAVE_REMOTE_OFFER,
HAVE_REMOTE_PRANSWER,
CLOSED;
private SignalingState() {
}
}
| SignalingState |
Description |
| STABLE |
沒有正在進行的SDP offer/answer交換,這也是連接的初始狀態(tài) |
| HAVE_LOCAL_OFFER |
本地已調(diào)用PeerConnection.setLocalDescription(),傳入代表offer的SDP(調(diào)用PeerConnection.createOffer()創(chuàng)建),并且offer已成功保存到本地 |
| HAVE_REMOTE_OFFER |
遠端創(chuàng)建了一個offer,并通過信令服務器將其發(fā)送到本地,本地通過調(diào)用PeerConnection.setRemoteDescription()將遠端offer保存到本地 |
| HAVE_LOCAL_PRANSWER |
收到遠端發(fā)送的offer并保存在本地,然后創(chuàng)建了answer(調(diào)用PeerConnection.createAnswer()),然后調(diào)用PeerConnection.setLocalDescription()保存answer |
| HAVE_REMOTE_PRANSWER |
已收到并成功保存answer |
| CLOSED |
連接關閉 |
回調(diào)接口,監(jiān)聽變化
public interface Observer {
//SignalingState變化時觸發(fā)
void onSignalingChange(PeerConnection.SignalingState var1);
//IceConnectionState變化時觸發(fā)
void onIceConnectionChange(PeerConnection.IceConnectionState var1);
//ICE連接接收狀態(tài)發(fā)生變化時觸發(fā)
void onIceConnectionReceivingChange(boolean var1);
//IceGatheringState 變化時觸發(fā)
void onIceGatheringChange(PeerConnection.IceGatheringState var1);
//重要的方法,當有新的IceCandidate加入時,就會發(fā)送事件,并觸發(fā)該方法
void onIceCandidate(IceCandidate var1);
//當有IceCandidate移除時,就會發(fā)送事件,并觸發(fā)該方法
void onIceCandidatesRemoved(IceCandidate[] var1);
//重要的方法,該動作是由對端的Peerconnection的addstream動作產(chǎn)生的事件觸發(fā),即發(fā)現(xiàn)新的媒體流時
void onAddStream(MediaStream var1);
//媒體流被關閉時觸發(fā)
void onRemoveStream(MediaStream var1);
//對端打開DataChannel
void onDataChannel(DataChannel var1);
void onRenegotiationNeeded();
//
void onAddTrack(RtpReceiver var1, MediaStream[] var2);
}
IceServer,coturn服務器信息
public static class IceServer {
public final String uri;
public final String username;
public final String password;
public final PeerConnection.TlsCertPolicy tlsCertPolicy;
public final String hostname;
public IceServer(String uri) {
this(uri, "", "");
}
public IceServer(String uri, String username, String password) {
this(uri, username, password, PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_SECURE);
}
public IceServer(String uri, String username, String password, PeerConnection.TlsCertPolicy tlsCertPolicy) {
this(uri, username, password, tlsCertPolicy, "");
}
public IceServer(String uri, String username, String password, PeerConnection.TlsCertPolicy tlsCertPolicy, String hostname) {
this.uri = uri;
this.username = username;
this.password = password;
this.tlsCertPolicy = tlsCertPolicy;
this.hostname = hostname;
}
public String toString() {
return this.uri + " [" + this.username + ":" + this.password + "] [" + this.tlsCertPolicy + "] [" + this.hostname + "]";
}
}
Ice收集策略
public static enum IceTransportsType {
NONE,
RELAY,
NOHOST,
ALL;
private IceTransportsType() {
}
}
| IceTransportsType |
Description |
| NONE |
不收集策略信息,目前作用未知 |
| RELAY |
只使用服務器的策略信息,簡言之就是不通過P2P,只走服務端流量,如果想要保證客戶端的聯(lián)通率,那么RELAY是最好的選擇 |
| NOHOST |
不收集host類的策略信息 |
| ALL |
全部收集,如果想減少流量,那么就用ALL,WebRTC會在能打通P2P情況下使用P2P |
捆綁的策略
public static enum BundlePolicy {
BALANCED,
MAXBUNDLE,
MAXCOMPAT;
private BundlePolicy() {
}
}
實時傳輸控制協(xié)議多路策略
public static enum RtcpMuxPolicy {
NEGOTIATE,
REQUIRE;
private RtcpMuxPolicy() {
}
}
TCP候選策略控制開關
public static enum TcpCandidatePolicy {
ENABLED,
DISABLED;
private TcpCandidatePolicy() {
}
}
候選網(wǎng)絡策略
public static enum CandidateNetworkPolicy {
ALL,
LOW_COST;
private CandidateNetworkPolicy() {
}
}
加密類型
public static enum KeyType {
RSA,
ECDSA;
private KeyType() {
}
}
收集策略時間段
public static enum ContinualGatheringPolicy {
GATHER_ONCE, //只收集一次
GATHER_CONTINUALLY; //不間斷的收集
private ContinualGatheringPolicy() {
}
}
public static class RTCConfiguration {
public PeerConnection.IceTransportsType iceTransportsType;
public List<PeerConnection.IceServer> iceServers;
public PeerConnection.BundlePolicy bundlePolicy;
public PeerConnection.RtcpMuxPolicy rtcpMuxPolicy;
public PeerConnection.TcpCandidatePolicy tcpCandidatePolicy;
public PeerConnection.CandidateNetworkPolicy candidateNetworkPolicy;
public int audioJitterBufferMaxPackets;
public boolean audioJitterBufferFastAccelerate;
public int iceConnectionReceivingTimeout;
public int iceBackupCandidatePairPingInterval;
public PeerConnection.KeyType keyType;
public PeerConnection.ContinualGatheringPolicy continualGatheringPolicy;
public int iceCandidatePoolSize;
public boolean pruneTurnPorts;
public boolean presumeWritableWhenFullyRelayed;
public Integer iceCheckMinInterval;
public boolean disableIPv6OnWifi;
public RTCConfiguration(List<PeerConnection.IceServer> iceServers) {
this.iceTransportsType = PeerConnection.IceTransportsType.ALL;
this.bundlePolicy = PeerConnection.BundlePolicy.BALANCED;
this.rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.REQUIRE;
this.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.ENABLED;
PeerConnection.CandidateNetworkPolicy var10001 = this.candidateNetworkPolicy;
this.candidateNetworkPolicy = PeerConnection.CandidateNetworkPolicy.ALL;
this.iceServers = iceServers;
this.audioJitterBufferMaxPackets = 50;
this.audioJitterBufferFastAccelerate = false;
this.iceConnectionReceivingTimeout = -1;
this.iceBackupCandidatePairPingInterval = -1;
this.keyType = PeerConnection.KeyType.ECDSA;
this.continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy.GATHER_ONCE;
this.iceCandidatePoolSize = 0;
this.pruneTurnPorts = false;
this.presumeWritableWhenFullyRelayed = false;
this.iceCheckMinInterval = null;
this.disableIPv6OnWifi = false;
}
}
幾個參數(shù)
private final List<MediaStream> localStreams;//媒體流
private final long nativePeerConnection;//jni層的鏈接
private final long nativeObserver;//觀察者
private List<RtpSender> senders;//發(fā)送者
private List<RtpReceiver> receivers;//接受者
構(gòu)造方法,傳入一個Connection,還有就是一個回調(diào)的接口
PeerConnection(long nativePeerConnection, long nativeObserver) {
this.nativePeerConnection = nativePeerConnection;
this.nativeObserver = nativeObserver;
this.localStreams = new LinkedList();
this.senders = new LinkedList();
this.receivers = new LinkedList();
}
JSEP(JavaScript Session Establishment Protocol,JavaScript 會話建立協(xié)議)
<--這里的方法都是,我們調(diào)用,然后傳入callback等待結(jié)果-->
//得到本地sdp描述
public native SessionDescription getLocalDescription();
//得到遠端sdp描述
public native SessionDescription getRemoteDescription();
//創(chuàng)建數(shù)據(jù)通道
public native DataChannel createDataChannel(String var1, Init var2);
//創(chuàng)建offer消息
public native void createOffer(SdpObserver var1, MediaConstraints var2);
//創(chuàng)建answer消息
public native void createAnswer(SdpObserver var1, MediaConstraints var2);
//設置本地sdp
public native void setLocalDescription(SdpObserver var1, SessionDescription var2);
//設置遠端sdp
public native void setRemoteDescription(SdpObserver var1, SessionDescription var2);
添加和刪除Ice候選
public boolean addIceCandidate(IceCandidate candidate) {
return this.nativeAddIceCandidate(candidate.sdpMid, candidate.sdpMLineIndex, candidate.sdp);
}
public boolean removeIceCandidates(IceCandidate[] candidates) {
return this.nativeRemoveIceCandidates(candidates);
}
添加和刪除本地媒體流
public boolean addStream(MediaStream stream) {
boolean ret = this.nativeAddLocalStream(stream.nativeStream);
if (!ret) {
return false;
} else {
this.localStreams.add(stream);
return true;
}
}
public void removeStream(MediaStream stream) {
this.nativeRemoveLocalStream(stream.nativeStream);
this.localStreams.remove(stream);
}
添加和獲取發(fā)送者的信息,例如音量信息,網(wǎng)速的信息
public RtpSender createSender(String kind, String stream_id) {
RtpSender new_sender = nativeCreateSender(kind, stream_id);
if (new_sender != null) {
senders.add(new_sender);
}
return new_sender;
}
// Note that calling getSenders will dispose of the senders previously
// returned (and same goes for getReceivers).
public List<RtpSender> getSenders() {
for (RtpSender sender : senders) {
sender.dispose();
}
senders = nativeGetSenders();
return Collections.unmodifiableList(senders);
}
獲取接收者的信息
public List<RtpReceiver> getReceivers() {
Iterator var1 = this.receivers.iterator();
while(var1.hasNext()) {
RtpReceiver receiver = (RtpReceiver)var1.next();
receiver.dispose();
}
this.receivers = this.nativeGetReceivers();
return Collections.unmodifiableList(this.receivers);
}
獲取狀態(tài),在這里面可以獲取到trak的狀態(tài)
/** @deprecated */
@Deprecated
public boolean getStats(StatsObserver observer, MediaStreamTrack track) {
return this.nativeOldGetStats(observer, track == null ? 0L : track.nativeTrack);
}
public void getStats(RTCStatsCollectorCallback callback) {
this.nativeNewGetStats(callback);
}
打印RTC時間Log
public boolean startRtcEventLog(int file_descriptor, int max_size_bytes) {
return this.nativeStartRtcEventLog(file_descriptor, max_size_bytes);
}
public void stopRtcEventLog() {
this.nativeStopRtcEventLog();
}
這里面都是jni層面的代碼,這些方法可以獲取一些狀態(tài)
//得到信令狀態(tài)
public native SignalingState signalingState();
//獲得遠端連接狀態(tài)
public native IceConnectionState iceConnectionState();
//獲得本地連接狀態(tài)
public native IceGatheringState iceGatheringState();
public native void close();
釋放當前流,清空當前PeerConnection
public void dispose() {
this.close();
Iterator var1 = this.localStreams.iterator();
while(var1.hasNext()) {
MediaStream stream = (MediaStream)var1.next();
this.nativeRemoveLocalStream(stream.nativeStream);
stream.dispose();
}
this.localStreams.clear();
var1 = this.senders.iterator();
while(var1.hasNext()) {
RtpSender sender = (RtpSender)var1.next();
sender.dispose();
}
this.senders.clear();
var1 = this.receivers.iterator();
while(var1.hasNext()) {
RtpReceiver receiver = (RtpReceiver)var1.next();
receiver.dispose();
}
this.receivers.clear();
freePeerConnection(this.nativePeerConnection);
freeObserver(this.nativeObserver);
}
JNI層面的代碼,供sdk內(nèi)部調(diào)用的,我們調(diào)用的很多sdk層面的代碼,然后它們調(diào)用這些代碼
//釋放PeerConnection
private static native void freePeerConnection(long var0);
//釋放Observer
private static native void freeObserver(long var0);
public native boolean nativeSetConfiguration(PeerConnection.RTCConfiguration var1, long var2);
//添加新的Candidate
private native boolean nativeAddIceCandidate(String var1, int var2, String var3);
private native boolean nativeRemoveIceCandidates(IceCandidate[] var1);
//添加本地流
private native boolean nativeAddLocalStream(long var1);
//移除本地流
private native void nativeRemoveLocalStream(long var1);
private native boolean nativeOldGetStats(StatsObserver var1, long var2);
private native void nativeNewGetStats(RTCStatsCollectorCallback var1);
private native RtpSender nativeCreateSender(String var1, String var2);
private native List<RtpSender> nativeGetSenders();
private native List<RtpReceiver> nativeGetReceivers();
private native boolean nativeStartRtcEventLog(int var1, int var2);
private native void nativeStopRtcEventLog();