srs3.x代码阅读

srs使用了state-threads协程库,是单线程多协程模型。不用考虑线程安全,数据不用加锁。
int SrsServer::listen()中启动if ((ret = listen_rtmp()) != ERROR_SUCCESS)
进一步启动:SrsListener* listener = new SrsBufferListener(this, SrsListenerRtmpStream);
然后启动:
SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, string i, int p)
{
    handler = h;
    ip = i;
    port = p;
    lfd = NULL;
    trd = new SrsDummyCoroutine();
}
在协程的cycle中,会调用到if ((ret = handler->on_tcp_client(client_stfd)) != ERROR_SUCCESS)
在on_tcp_client()中,会调用if ((ret = server->accept_client(type, stfd)) != ERROR_SUCCESS)
int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
中调用fd2conn(SrsListenerType type, srs_netfd_t stfd, SrsConnection** pconn)
这是建立rtmp/tcp连接最为重要的func。根据连接类型,生成相应的实例来处理。
    if (type == SrsListenerRtmpStream) {
        *pconn = new SrsRtmpConn(this, stfd, ip);
    } else if (type == SrsListenerHttpApi) {
        *pconn = new SrsHttpApi(this, stfd, http_api_mux, ip);
    } else if (type == SrsListenerHttpStream) {
        *pconn = new SrsResponseOnlyHttpConn(this, stfd, http_server, ip);
    } else {
        srs_warn("close for no service handler. fd=%d, ip=%s", fd, ip.c_str());
        srs_close_stfd(stfd);
        return err;
    }
协程将调度单位减小到函数,上下文切换不需要内核参与,开销降到最低。
没有锁竞争,没有信号处理。保留了程序对请求的线性处理逻辑,提高了程序的开发效率,可扩展性和可维护性。
协程库state threads library(以下简称st)是一个基于setjmp/longjmp实现的C语言版用户线程库或协程库(user level thread)。

SrsRtmpConn会继承SrsConnection,生成一个srs协程SrsSTCoroutine。
SrsConnection::SrsConnection(IConnectionManager* cm, srs_netfd_t c, string cip)
{
    manager = cm;
    stfd = c;
    ip = cip;
    create_time = srsu2ms(srs_get_system_time());
    
    skt = new SrsStSocket();
    clk = new SrsWallClock();
    kbps = new SrsKbps(clk);
    kbps->set_io(skt, skt);
    
    trd = new SrsSTCoroutine("conn", this);
}
协程int SrsConnection::cycle()调用了do_cycle(),派生类实现了这个方法。
在这儿正式进入rtmp协议处理阶段。先进行握手:rtmp->handshake()等操作,然后进入service_cycle();。
srs_error_t SrsRtmpConn::stream_service_cycle()
{
    先进行tmp->identify_client客户端身份识别。
    然后根据根据客户端类型(type)进入不同分支。
    SrsRtmpConnPlay是客户端播流。
    SrsRtmpConnFMLEPublish 是Rtmp推流到服务器。
}
对于发布流(推流到srs)来说,看SrsRtmpConnFMLEPublish。
对于拉流(从SRS拉流)来说,看SrsRtmpConnPlay。
        case SrsRtmpConnFMLEPublish: {
            if ((err = rtmp->start_fmle_publish(info->res->stream_id)) != srs_success) {
                return srs_error_wrap(err, "rtmp: start FMLE publish");
            }
            
            return publishing(source);
        }

主处理函数:publishing(source);        
    if ((err = http_hooks_on_publish()) != srs_success) {    //这里可以是推流鉴权hook
        return srs_error_wrap(err, "rtmp: callback on publish");
    }
协程处理:
srs_error_t SrsRtmpConn::do_publishing(SrsSource* source, SrsPublishRecvThread* rtrd)
srs_error_t SrsPublishRecvThread::consume(SrsCommonMessage* msg)
这个consume()函数是rtmp协议处理主体。
录像dvr是SRS的重要功能,也一样用协程来完成的。
class SrsDvrFlvSegmenter是处理flv格式录像的主体类。
class SrsDvrMp4Segmenter是处理mp4格式录像的主体类。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

草根大哥

进军大神程序员路上,谢谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值