srs源码分析之推流超时

一、背景

在调试srs代码时,发现log中的超时时间有时候不一样,且自己也没有配置过相关参数,所以决定仔细看看源码,分析下原因。

二、推流超时规则

  1. 连接握手结束以后,如果还未接收到真实的音视频包,超时时间默认为20秒
  2. 连接握手结束之后,如果接收过真实的音视频包,超时时间为5秒。

三、推流超时代码分析

代码一共两个协程,一个是握手协程,然后定时循环,
一个是握手结束后,创建的新协程,专门用于接收数据。代码主要是
SrsRtmpConn::do_publishing和SrsPublishRecvThread::consume。

  1. 获取超时时间代码
publish_1stpkt_timeout = _srs_config->get_publish_1stpkt_timeout(req->vhost);  
publish_normal_timeout = _srs_config->get_publish_normal_timeout(req->vhost); 
  1. 判断是否接收过数据包代码
 if (nb_msgs == 0) {        // 根据是否接受过数据包,进行不同的超时时间等待
        // when not got msgs, wait for a larger timeout.
        // @see https://github.com/ossrs/srs/issues/441
        rtrd->wait(publish_1stpkt_timeout);
    } else {
       rtrd->wait(publish_normal_timeout);
    }
  1. 超时退出代码
    if (rtrd->nb_msgs() <= nb_msgs) {    // 如果超时后,接收的数据包没有增长,则退出
        return srs_error_new(ERROR_SOCKET_TIMEOUT, "rtmp: publish timeout %dms, nb_msgs=%d",
            nb_msgs? srsu2msi(publish_normal_timeout) : srsu2msi(publish_1stpkt_timeout), (int)nb_msgs);
    }
    nb_msgs = rtrd->nb_msgs();
  1. 接收的数据包的数量计算位置
srs_error_t SrsPublishRecvThread::consume(SrsCommonMessage* msg)
{
    srs_error_t err = srs_success;
    
    // when cid changed, change it.
    if (ncid.compare(cid)) {
        _srs_context->set_id(ncid);
        cid = ncid;
    }
    
    _nb_msgs++;    // 接收到一个数据包,进行++
    
    if (msg->header.is_video()) {
        video_frames++;
    }
    
    // log to show the time of recv thread.
    srs_verbose("recv thread now=%" PRId64 "us, got msg time=%" PRId64 "ms, size=%d",
                srs_update_system_time(), msg->header.timestamp, msg->size);
    
    // the rtmp connection will handle this message
    err = _conn->handle_publish_message(_source, msg);
    
    // must always free it,
    // the source will copy it if need to use.
    srs_freep(msg);
    
    if (err != srs_success) {
        return srs_error_wrap(err, "handle publish message");
    }

    // Yield to another coroutines.
    // @see https://github.com/ossrs/srs/issues/2194#issuecomment-777463768
    if (++nn_msgs_for_yield_ >= 15) {
        nn_msgs_for_yield_ = 0;
        srs_thread_yield();
    }
    
    return err;
}

四、超时问题扩展

之前以为librtmp有参数设置超时时间,以为可以使用客户端设置,最后查看librtmp代码,发现代码

SET_RCVTIMEO(tv, r->Link.timeout);
if (setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)))

设置的是socket的超时时间,跟rtmp协议无关。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值