注意:低延迟会带来性能的下降, 如SRS2.0一次writev多个packet支持10000客户端。
低延时配置文件如下:
listen              1935;
vhost __defaultVhost__ {tcp_nodelay     on;min_latency     on;play {gop_cache       off;queue_length    10;mw_latency      100;}publish {mr off;}
}
1、tcp_nodelay:tcp关闭Nagle算法,不再缓存发送
srs_error_t SrsTcpConnection::set_tcp_nodelay(bool v)
{srs_error_t err = srs_success;int r0 = 0;socklen_t nb_v = sizeof(int);int fd = srs_netfd_fileno(stfd);int ov = 0;if ((r0 = getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &ov, &nb_v)) != 0) {return srs_error_new(ERROR_SOCKET_NO_NODELAY, "getsockopt fd=%d, r0=%d", fd, r0);}#ifndef SRS_PERF_TCP_NODELAYsrs_warn("ignore TCP_NODELAY, fd=%d, ov=%d", fd, ov);return err;
#endifint iv = (v? 1:0);if ((r0 = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &iv, nb_v)) != 0) {return srs_error_new(ERROR_SOCKET_NO_NODELAY, "setsockopt fd=%d, r0=%d", fd, r0);}if ((r0 = getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &iv, &nb_v)) != 0) {return srs_error_new(ERROR_SOCKET_NO_NODELAY, "getsockopt fd=%d, r0=%d", fd, r0);}srs_trace("set fd=%d TCP_NODELAY %d=>%d", fd, ov, iv);return err;
}
2、min_latency:开启最小延迟模式
当开启最低延迟配置后,SRS会禁用mr(merged-read),并且在consumer队列中使用超时等待,大约每收到1-2个视频包就发送给客户端,达到最低延迟目标。
测试vp6纯视频流能达到0.1秒延迟
vhost mrw.srs.com {# whether enable min delay mode for vhost.# for min latence mode:# 1. disable the publish.mr for vhost.# 2. use timeout for cond wait for consumer queue.# @see https://github.com/ossrs/srs/issues/257# default: offmin_latency     off;
}
3、queue_length: 设置队列大小
srs_utime_t queue_size = _srs_config->get_queue_length(req->vhost);
publish_edge->set_queue_size(queue_size);
...
void SrsMessageQueue::set_queue_size(srs_utime_t queue_size)
{max_queue_size = queue_size;
}
...
srs_error_t SrsMessageQueue::enqueue(SrsSharedPtrMessage* msg, bool* is_overflow)
{srs_error_t err = srs_success;msgs.push_back(msg);// If jitter is off, the timestamp of first sequence header is zero, which wll cause SRS to shrink and drop the// keyframes even if there is not overflow packets in queue, so we must ignore the zero timestamps, please// @see https://github.com/ossrs/srs/pull/2186#issuecomment-953383063if (msg->is_av() && msg->timestamp != 0) {if (av_start_time == -1) {av_start_time = srs_utime_t(msg->timestamp * SRS_UTIME_MILLISECONDS);}av_end_time = srs_utime_t(msg->timestamp * SRS_UTIME_MILLISECONDS);}if (max_queue_size <= 0) {return err;}while (av_end_time - av_start_time > max_queue_size) {// notice the caller queue already overflow and shrinked.if (is_overflow) {*is_overflow = true;}shrink();}return err;
}
...
srs_error_t SrsLiveConsumer::enqueue(SrsSharedPtrMessage* shared_msg, bool atc, SrsRtmpJitterAlgorithm ag)
{srs_error_t err = srs_success;SrsSharedPtrMessage* msg = shared_msg->copy();if (!atc) {if ((err = jitter->correct(msg, ag)) != srs_success) {return srs_error_wrap(err, "consume message");}}if ((err = queue->enqueue(msg, NULL)) != srs_success) {return srs_error_wrap(err, "enqueue message");}return err;
}
4、gop_cache: 关闭两个IDR帧间的数据缓存
srs_error_t SrsRtmpConn::stream_service_cycle()
{
...bool enabled_cache = _srs_config->get_gop_cache(req->vhost);srs_trace("source url=%s, ip=%s, cache=%d, is_edge=%d, source_id=%s/%s",req->get_stream_url().c_str(), ip.c_str(), enabled_cache, info->edge, source->source_id().c_str(), source->pre_source_id().c_str());source->set_cache(enabled_cache);
...
void SrsLiveSource::set_cache(bool enabled)
{gop_cache->set(enabled);
}
...
void SrsGopCache::set(bool v)
{enable_gop_cache = v;if (!v) {clear();return;}
}
...
srs_error_t SrsGopCache::cache(SrsSharedPtrMessage* shared_msg)
{srs_error_t err = srs_success;if (!enable_gop_cache) {return err;}// the gop cache know when to gop it.SrsSharedPtrMessage* msg = shared_msg;// got video, update the video count if acceptableif (msg->is_video()) {// drop video when not h.264if (!SrsFlvVideo::h264(msg->payload, msg->size)) {return err;}cached_video_count++;audio_after_last_video_count = 0;}// no acceptable video or pure audio, disable the cache.if (pure_audio()) {return err;}// ok, gop cache enabled, and got an audio.if (msg->is_audio()) {audio_after_last_video_count++;}// clear gop cache when pure audio count overflowif (audio_after_last_video_count > SRS_PURE_AUDIO_GUESS_COUNT) {srs_warn("clear gop cache for guess pure audio overflow");clear();return err;}// clear gop cache when got key frameif (msg->is_video() && SrsFlvVideo::keyframe(msg->payload, msg->size)) {clear();// curent msg is video frame, so we set to 1.cached_video_count = 1;}// cache the frame.gop_cache.push_back(msg->copy());return err;
}
5、mw_latency: merge wirte混合写的延迟
srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{
...
srs_utime_t mw_sleep = _srs_config->get_mw_sleep(req->vhost);
if ((err = rohc->set_socket_buffer(mw_sleep)) != srs_success) {return srs_error_wrap(err, "set mw_sleep %" PRId64, mw_sleep);
}
...
srs_error_t SrsRtmpConn::do_playing(SrsLiveSource* source, SrsLiveConsumer* consumer, SrsQueueRecvThread* rtrd)
{
...
mw_sleep = _srs_config->get_mw_sleep(req->vhost);
skt->set_socket_buffer(mw_sleep);
...
srs_error_t SrsTcpConnection::set_socket_buffer(srs_utime_t buffer_v)
{srs_error_t err = srs_success;int r0 = 0;int fd = srs_netfd_fileno(stfd);socklen_t nb_v = sizeof(int);int ov = 0;if ((r0 = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &ov, &nb_v)) != 0) {return srs_error_new(ERROR_SOCKET_SNDBUF, "getsockopt fd=%d, r0=%d", fd, r0);}// the bytes://      4KB=4096, 8KB=8192, 16KB=16384, 32KB=32768, 64KB=65536,//      128KB=131072, 256KB=262144, 512KB=524288// the buffer should set to sleep*kbps/8,// for example, your system delivery stream in 1000kbps,// sleep 800ms for small bytes, the buffer should set to://      800*1000/8=100000B(about 128KB).// other examples://      2000*3000/8=750000B(about 732KB).//      2000*5000/8=1250000B(about 1220KB).int kbps = 4000;int iv = srsu2ms(buffer_v) * kbps / 8;// socket send buffer, system will double it.iv = iv / 2;// set the socket send buffer when required larger bufferif (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &iv, nb_v) < 0) {return srs_error_new(ERROR_SOCKET_SNDBUF, "setsockopt fd=%d, r0=%d", fd, r0);}if ((r0 = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &iv, &nb_v)) != 0) {return srs_error_new(ERROR_SOCKET_SNDBUF, "getsockopt fd=%d, r0=%d", fd, r0);}srs_trace("set fd=%d, SO_SNDBUF=%d=>%d, buffer=%dms", fd, ov, iv, srsu2ms(buffer_v));return err;
}
6、mr off:merge read关闭混合度
SrsPublishRecvThread::SrsPublishRecvThread(SrsRtmpServer* rtmp_sdk, SrsRequest* _req,int mr_sock_fd, srs_utime_t tm, SrsRtmpConn* conn, SrsLiveSource* source, SrsContextId parent_cid): trd(this, rtmp_sdk, tm, parent_cid)
{
...
mr_sleep = _srs_config->get_mr_sleep(req->vhost);
...
void SrsPublishRecvThread::on_start()
{// we donot set the auto response to false,// for the main thread never send message.#ifdef SRS_PERF_MERGED_READif (mr) {// set underlayer buffer sizeset_socket_buffer(mr_sleep);// disable the merge readrtmp->set_merge_read(true, this);}
#endif
}
...
void SrsPublishRecvThread::set_socket_buffer(srs_utime_t sleep_v)
{// the bytes://      4KB=4096, 8KB=8192, 16KB=16384, 32KB=32768, 64KB=65536,//      128KB=131072, 256KB=262144, 512KB=524288// the buffer should set to sleep*kbps/8,// for example, your system delivery stream in 1000kbps,// sleep 800ms for small bytes, the buffer should set to://      800*1000/8=100000B(about 128KB).// other examples://      2000*3000/8=750000B(about 732KB).//      2000*5000/8=1250000B(about 1220KB).int kbps = 5000;int socket_buffer_size = srsu2msi(sleep_v) * kbps / 8;int fd = mr_fd;int onb_rbuf = 0;socklen_t sock_buf_size = sizeof(int);getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &onb_rbuf, &sock_buf_size);// socket recv buffer, system will double it.int nb_rbuf = socket_buffer_size / 2;if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &nb_rbuf, sock_buf_size) < 0) {srs_warn("set sock SO_RCVBUF=%d failed.", nb_rbuf);}getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &nb_rbuf, &sock_buf_size);srs_trace("mr change sleep %d=>%d, erbuf=%d, rbuf %d=>%d, sbytes=%d, realtime=%d",srsu2msi(mr_sleep), srsu2msi(sleep_v), socket_buffer_size, onb_rbuf, nb_rbuf,SRS_MR_SMALL_BYTES, realtime);rtmp->set_recv_buffer(nb_rbuf);
}

SRS低延时配置分析相关推荐

  1. 量化延时法时间测量_「交易技术前沿」交易系统低延时测试与分析

    本文选自 <交易技术前沿>总第三十三期文章(2018年12月) 证券期货行业测试中心(中金所) 魏畅 陈冬严 张鸿晔 摘要:订单延时(Latency)是衡量交易系统性能的重要指标.本文利用 ...

  2. 分析一下H5直播、微信直播、抓娃娃、低延时的方案

    微信直播,HTML5直播,主要方案有如下几种: 1.基于hls切片直播,前前是应用的主流,服务器可以选fms,wowza,nginx,srs之类 优点:集成方便,支持度高,兼容性好,主流手都支持,是目 ...

  3. 京东智联云分布式低延时RTC系统

    本文由京东智联云的魏伟在LiveVideoStackCon2020线上峰会的演讲内容整理而成,他会从逻辑结构.系统业务流程和弱网增强等方面介绍京东智联云在RTC方面所做的工作. 文 / 魏伟 整理 / ...

  4. 实时音视频聊天中的延时问题一篇就够,低延时场景及优化

    1.前言 音视频实时通讯的应用场景已经随处可见,从"吃鸡"的语音对讲.直播连麦.直播答题组队开黑,再到银行视频开户等.对于开发者来讲,除了关注如何能快速实现不同应用场景重点额音视频 ...

  5. 基于 RTS 超低延时直播优化强互动场景体验

    RTS 在阿里云视频直播的基础上进行底层技术优化,通过集成阿里云播放器 SDK,支持在千万级并发场景下节点间毫秒级延时直播的能力,弥补了传统直播存在 3~6 秒延时的问题,确保了超低延时.低卡顿.秒开 ...

  6. EasyNVR无插件摄像机直播之:摄像机网页低延时无插件直播实现

    背景需求 对于摄像机直播,客户反馈的最多就是实现web直播.摆脱插件,可以自定义集成等问题, 对于熟悉EasyNVR已经完美的解决了这些问题.然而对于web播放也存在一些问题,通常我们web播放RTM ...

  7. 详解音视频直播中的低延时 1

    音视频实时通讯的应用场景已经随处可见,从"吃鸡"的语音对讲.直播连麦.直播答题组队开黑,再到银行视频开户等.对于开发者来讲,除了关注如何能快速实现不同应用场景重点额音视频通讯,另一 ...

  8. 淘宝直播技术干货:高清、低延时的实时视频直播技术解密

    本文由淘宝直播音视频算法团队原创分享,原题"5G时代|淘宝直播高画质低延时技术探索",收录时有改动. 1.引言 目前,5G技术应用正在逐步推进,相比目前广泛使用的4G, 它具有更高 ...

  9. srs流媒体服务器性能,srs流媒体服务器 配置

    srs流媒体服务器 配置 内容精选 换一换 SRS是一款开源流媒体,适合直播以及低延时流媒体领域,但是从来不设限,可以应用在直播.视频会议.在线教育等场景.同时视频领域还有两大块.广电和视频监控,随着 ...

最新文章

  1. NHibernate Issues之1255:联合主键(composite-id)
  2. CSS,给我们不一样的体验
  3. 从入门到放弃,C++ 真这么难?
  4. socket网络编程tcp
  5. 阿里1682亿背后的协同研发云——云效公共云正式商业化 1
  6. 大一计算机word排版试题,Word排版练习题
  7. Linux安装Nvidia显卡驱动
  8. 基于Matlab与Logistic Regression(逻辑回归)的瓶子密封性检测
  9. 压缩文件密码暴力破解——cRARk使用方法
  10. 相机靶面尺寸详解+工业相机选型
  11. 中钰睿泓分享:设计LOGO的思路和流程
  12. 笔记———计算机网络原理(二)
  13. 计算机图形学矩形_《交互式计算机图形学》读书笔记 —— 第一章、图形系统和模型...
  14. 解决索尼WH-1000XM3使用蓝牙连接电脑无法使用麦克风的问题
  15. GIS中快速添加天地图、查看历史影像
  16. java ppt转图片 解决图片不清晰问题
  17. Java Web和Java后端学习之路
  18. 计算机技术电子出版参考文献,参考文献规范
  19. 多点定位MLAT系统解决方案
  20. 中国慕课c语言入门视频,程序设计入门——C语言

热门文章

  1. 【程设作业】魔兽世界三:开战
  2. 顶级黑客泄密事件啼笑皆非
  3. mysql 锁设置_MySQL锁之二:锁相关的配置参数
  4. 计算机考研408考试关键词、专有名词、术语等英文缩写和全称
  5. 计算机组成与结构习题答案,计算机组成与结构习题及答案
  6. 玩转软路由 篇二:软路由中Esxi 7.0 安装教程和避坑指南
  7. 用二极管、三极管和MOS管搭建逻辑门电路,你确定这些电路图不收藏?
  8. 腾讯企鹅辅导 H5 性能极致优化总结
  9. PS使得画布大小迅速和图像大小保持一致,裁切功能
  10. python 交互redis 的ZADD方法异常: AttributeError: ‘int‘ object has no attribute ‘items‘