publish的流和play的流怎么连接呢?这个恐怕是最绕的地方了。看了一上午的代码,淹没于各种数据结构与流程之中后,俺终于发现了连接publish和play的关键连个类是
SrsSource
SrsConsumer
负责连接着连个类实例的是
SrsRtmpConn
下面我们详细讲解连接过程
上片我们说到。在底层客户端连接上来后,会经过一系列处理,最后绕到SrsRtmpConn类的循环函数中。就是下面的函数
int SrsConnection::cycle()
{
int ret = ERROR_SUCCESS;
_srs_context->generate_id();
id = _srs_context->get_id();
ip = srs_get_peer_ip(st_netfd_fileno(stfd));
ret = do_cycle();
// if socket io error, set to closed.
if (srs_is_client_gracefully_close(ret)) {
ret = ERROR_SOCKET_CLOSED;
}
// success.
if (ret == ERROR_SUCCESS) {
srs_trace("client finished.");
}
// client close peer.
if (ret == ERROR_SOCKET_CLOSED) {
srs_warn("client disconnect peer. ret=%d", ret);
}
return ERROR_SUCCESS;
}
这个是SrsRtmpConn的基类SrsConnection的函数。在基类里,do_cycle()是个纯虚函数。具体实现完全是靠这子类来的。
那么rtmp类型的这个子类,到底有多么的变态呢,先看看我画的一个流程图,都没有画完。一张放不下,的截好几张
够长的,这里我还只是画到了播放的时候,发布流程还没有画。因为太复杂了。
下面开始一步一步的分析
首先看do_cycle()函数这个函数主要负责握手和连命令。并在成功后。获取流的配置信息。关键代码如下
if ((ret = rtmp->handshake()) != ERROR_SUCCESS) {
srs_error("rtmp handshake failed. ret=%d", ret);
return ret;
}
srs_verbose("rtmp handshake success");
if ((ret = rtmp->connect_app(req)) != ERROR_SUCCESS) {
srs_error("rtmp connect vhost/app failed. ret=%d", ret);
return ret;
}
srs_verbose("rtmp connect app success");
注意这里有一个比较重要的数据结构
SrsRequest* req
在各种分析后,进入下一个cycle,service_cycle()函数
service_cycly()函数在做了一些设置工作,设置比如chunk size。代码如下
if ((ret = rtmp->set_window_ack_size((int)(2.5 * 1000 * 1000))) != ERROR_SUCCESS) {
srs_error("set window acknowledgement size failed. ret=%d", ret);
return ret;
}
srs_verbose("set window acknowledgement size success");
if ((ret = rtmp->set_peer_bandwidth((int)(2.5 * 1000 * 1000), 2)) != ERROR_SUCCESS) {
srs_error("set peer bandwidth failed. ret=%d", ret);
return ret;
}
下面一段代码没有看明白。这个是一个补丁打上去的,说说为了做do token traverse。这个暂时先不研究了。
if (true) {
bool vhost_is_edge = _srs_config->get_vhost_is_edge(req->vhost);
bool edge_traverse = _srs_config->get_vhost_edge_token_traverse(req->vhost);
if (vhost_is_edge && edge_traverse) {
if ((ret = check_edge_token_traverse_auth()) != ERROR_SUCCESS) {
srs_warn("token auth failed, ret=%d", ret);
return ret;
}
}
}
接着设置chunk 的大小
int chunk_size = _srs_config->get_chunk_size(req->vhost);
if ((ret = rtmp->se