在webrtc中,如果只是做一对一的连接,服务器的处理相对还是比较简单的,如果这台服务器满了,可以直接在开启另外一台服务器,但是在一对多的直播中,这种方式就行不通了。
在kms中,能够实现一对多的直播功能,是因为在kms服务器中有一个WebRtcEndpoint
,我们把它理解为在kms上相当于创建了一个webrtc客户端,相当于一个虚拟的 客户端,他能接受主播通过webrtc推送的协议,这个虚拟的客户端获得了主播的流,在和观看者进行连接,把流推给观看者。
这种模式下,能容纳多少个观看者,取决于单台服务器A的极限,假设一台服务器的流量只能支持200个的观看者,那么主播的最多只能有200个观看者,这样极限就非常的大了。
有没有办法解决这个问题呢?
通常解决这列问题的方式,都有现成的解决方案了,就是拓展服务器,也就是先把流推一路到服务器B,依次类推,这样就可以到达理想中的任意人数。
而在webrtc
中,关键就是把rtp
的流推到另外的服务器上。
在kms中有几个Endpoint
,我们是要注意的,一个是前面讲的WebRtcEndpoint
,另外一个是RtpEndpoint
,看看官方文档是怎么介绍的。
文档 告诉我们,RtpEndpoint
可以用来建立RTP
的连接,可以通过SDP
的沟通后自动建立连接,这个跟我们的webrtc的连接是一样的,除了一点,他不用进行ICE
的沟通。
具体的流程如下:
媒体服务器A 在连通了主播以后,需要创建出RtpEndpoint
,连接到原来的WebRtcEndpoint
上,并生成RtpEndpoint
的SDP
,创建服务器B 上的媒体管道,通过管道创建RtpEndpoint
,并处理A的SDP
,A的RtpEndpoint
应答SDP
,服务器B创建出WebRtcEndpoint
连接到自家的RtpEndpoint
上,就可以用WebRtcEndpoint
来进行观看者连接了。
时序图如下:
流程的代码如下:
RtpEndpoint rtpEndpoint = new RtpEndpoint.Builder(presenter.getPipeline()).build();
presenterWebRtc.connect(rtpEndpoint);
KurentoClient kurentoB = KurentoClient.create("ws://xxxx/kurento");
MediaPipeline pipelineB = kurentoB .createMediaPipeline();
RtpEndpoint rtpEndpointB = new RtpEndpoint.Builder(pipelineB).build();
String offerString = rtpEndpoint.generateOffer();
String sdpAnswerViewer = rtpEndpointB .processOffer(offerString);
rtpEndpoint.processAnswer(sdpAnswerViewer);
...
rtpEndpointB .connect(viewerWebRtc);
看看kms
的源代码,看看kms
在处理完SDP
后,会做什么动作,深入到最后,我们会发现,在kms_utils_depayloader_monitor_pts_out
下会 生成1个新的pts输出。
void
kms_utils_depayloader_monitor_pts_out (GstElement * depayloader)
{
GstPad *src_pad;
GST_INFO_OBJECT (depayloader, "Add probe: Adjust depayloader PTS out");
src_pad = gst_element_get_static_pad (depayloader, "src");
gst_pad_add_probe (src_pad,
GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BUFFER_LIST,
(GstPadProbeCallback) kms_utils_depayloader_pts_out_probe,
kms_utils_adjust_pts_data_new (depayloader),
(GDestroyNotify) kms_utils_adjust_pts_data_destroy);
g_object_unref (src_pad);
}
这就是 KMS
在不同服务器上拉RTP
流的过程和原理了。