在前面的一个章节,做kms
的集群时,引入了RtpEndpoint
,这个是一个新的类,我们之前使用的都是WebrtcEndpoint
,这两个类有什么区别呢?如果直接用WebrtcEndpoint
,能不能实现集群的连通呢。
我们来看看,文档中的关于几个重要的Endpoint
,继承图如下:
但是从详细的文档上来看,RtpEndpoint
和WebrtcEndpoint
都是继承BaseRtpEndpoint
的。
从文档上来看,RtpEndpoint
和WebrtcEndpoint
应该区别不大,因为他有一个共同的基类BaseRtpEndpoint
。
在对比下两者文档的区别:
RtpEndpoint
:
WebRtcEndpoint
:
从文档上来看,RtpEndpoint
和WebrtcEndpoint
的区别在于 RtpEndpoint
可以直接通过SDP
就能完成相互的连接,WebrtcEndpoint
要实现连接,不仅仅需要SDP
还需要ICE
。
也就是RtpEndpoint
在设计的时候,就可以通过SDP
建立连接,那么在SDP
中必将包含着 IP
和端口的信息了。
在源代码kms_sdp_agent_create_offer_impl
中可以看到生成的SDP
,存在在相应的 IP
和端口信息。
v=0
o=- 3864705878 3864705878 IN IP4 192.168.100.130
s=Kurento Media Server
c=IN IP4 192.168.100.130
t=0 0
m=audio 5198 RTP/AVPF 96 0 97
a=setup:actpass
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=rtpmap:96 opus/48000/2
a=rtpmap:97 AMR/8000
a=rtcp:5199
a=sendrecv
a=mid:audio0
a=ssrc:1665516295 cname:user345388121@host-4c885f6d
m=video 1420 RTP/AVPF 102 103
a=setup:actpass
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=rtpmap:102 VP8/90000
a=rtpmap:103 H264/90000
a=fmtp:103 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtcp:1421
a=sendrecv
a=mid:video0
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 ccm fir
a=rtcp-fb:103 nack
a=rtcp-fb:103 nack pli
a=rtcp-fb:103 ccm fir
a=ssrc:2557383214 cname:user345388121@host-4c885f6d
这样两个 RtpEndpoint
就能够协商连接上。
而WebrtcEndpoint
中生成的SDP
,并没有包含IP
和端口信息,这一点可以继续的跟进kms_sdp_agent_create_offer_impl
,看看到底是为什么。这样的协议,是个浏览器的webrtc
一样样的。
那如果使用 WebrtcEndpoint
能否实现集群呢?应该是可以的,但是比起RtpEndpoint
自然会复杂一点,因为他涉及到 ICE
的步骤了。
如果也需要,可以用下面的代码进行实现。
private synchronized void presenter(final WebSocketSession session, JsonObject jsonMessage)
throws IOException {
if (presenterUserSession == null) {
presenterUserSession = new UserSession(session);
pipeline = kurento.createMediaPipeline();
presenterUserSession.setWebRtcEndpoint(new WebRtcEndpoint.Builder(pipeline).build());
WebRtcEndpoint presenterWebRtc = presenterUserSession.getWebRtcEndpoint();
pipeline_B = kurento.createMediaPipeline();
presenterUserSession.setWebRtcEndpoint_A(new WebRtcEndpoint.Builder(pipeline).build());
WebRtcEndpoint presenterWebRtc_A = presenterUserSession.getWebRtcEndpoint_A();
presenterUserSession.setWebRtcEndpoint_B(new WebRtcEndpoint.Builder(pipeline_B).build());
WebRtcEndpoint presenterWebRtc_B = presenterUserSession.getWebRtcEndpoint_B();
presenterUserSession.getWebRtcEndpoint().connect(presenterWebRtc_A);
String offerString = presenterWebRtc_A.generateOffer();
String sdpAnswerViewer = presenterWebRtc_B.processOffer(offerString);
presenterWebRtc_A.processAnswer(sdpAnswerViewer);
log.info(offerString);
presenterWebRtc_A.addIceCandidateFoundListener(new EventListener<IceCandidateFoundEvent>() {
@Override
public void onEvent(IceCandidateFoundEvent event) {
log.info("presenterWebRtc_A.addIceCandidateFoundListener");
presenterWebRtc_B.addIceCandidate(event.getCandidate());
}
});
presenterWebRtc_B.addIceCandidateFoundListener(new EventListener<IceCandidateFoundEvent>() {
@Override
public void onEvent(IceCandidateFoundEvent event) {
log.info("presenterWebRtc_B.addIceCandidateFoundListener");
//presenterWebRtc_A.addIceCandidate(event.getCandidate());
}
});
presenterWebRtc.addIceCandidateFoundListener(new EventListener<IceCandidateFoundEvent>() {
@Override
public void onEvent(IceCandidateFoundEvent event) {
JsonObject response = new JsonObject();
response.addProperty("id", "iceCandidate");
response.add("candidate", JsonUtils.toJsonObject(event.getCandidate()));
try {
synchronized (session) {
session.sendMessage(new TextMessage(response.toString()));
}
} catch (IOException e) {
log.debug(e.getMessage());
}
}
});
String sdpOffer = jsonMessage.getAsJsonPrimitive("sdpOffer").getAsString();
String sdpAnswer = presenterWebRtc.processOffer(sdpOffer);
JsonObject response = new JsonObject();
response.addProperty("id", "presenterResponse");
response.addProperty("response", "accepted");
response.addProperty("sdpAnswer", sdpAnswer);
synchronized (session) {
presenterUserSession.sendMessage(response);
}
presenterWebRtc.gatherCandidates();
presenterWebRtc_A.gatherCandidates();
presenterWebRtc_B.gatherCandidates();
} else {
JsonObject response = new JsonObject();
response.addProperty("id", "presenterResponse");
response.addProperty("response", "rejected");
response.addProperty("message",
"Another user is currently acting as sender. Try again later ...");
session.sendMessage(new TextMessage(response.toString()));
}
}