当前位置: 首页 > news >正文

基于rk3568 Android H265推流SRS低延迟网页播放方案

       在音视频领域,融合推流,低码流,低延迟,浏览器H5化是一个降低成本,提升用户体验的重要手段。同时适配现有直播的生态也是一个必要条件。

      在满足上述要求的情况下,我做了以下实践,取得了良好的效果。

     在实践中,我们选择采用了成熟的rtmp做为推流的主要手段,srs直播多媒体服务器的顶级生态位不可或缺,H265作为良好的视频编解码协议,在节约40%以上的码流带宽情况下比H264拥有更清晰的画质和更好的运动画面表现力,新兴的浏览器传输硬解渲染技术作为跨平台web化的门户比起桌面播放器有太多优势。

       在设备端推流选取了性价比很高的瑞星微rk3568作为硬件载体,其拥有60fps 1080p H265编码能力,内置opengl可以实现低延迟零拷贝的多窗口实时渲染能力。在实践中,我们做了大量的优化工作,提升了多路网络摄像头和本地摄像头及桌面的采集编码和转发推流能力。

       srs作为国内开源多媒体服务器的翘楚,拥有大量的用户,积极拥抱其生态是必然选择,在对接srs rtmp推流时,因为其有严格的格式验证,需要格外小心,不然会导致解析码流失败,当然这个跟良好兼容性形成了鲜明的对比,当然这个是见仁见智的。我们在对接过程中就遇到了一些坑,在这里也提醒其他玩家特别注意。

 下面就是我们处理码流进行推流的核心代码,贴出来以供参考

void VideoPushChannel::onencodeData(AVPacket *packet,int encodertype) {uint8_t *ptr   =packet->data;size_t len  = packet->size;uint64_t dts=packet->dts;uint64_t pts=packet->pts;uint16_t frametype=0;bool isH265=false;if(ptr==NULL||len<=0) return;unsigned char * psrc=ptr;unsigned int srclen=len;unsigned int packelen=0;unsigned char  nalutype=0;unsigned int scrindex=0;unsigned char destCount=0;bool bend=false;do {
//        GetNaluSlice2(unsigned char *  scr,uint32_t scrlen,uint32_t *packetlen,uint8_t * nalutype ,uint16_t * frametype,bool * endframe,uint32_t *pscroffset,uint8_t *destCount,bool* isH265);int result = Nalu::GetNaluSlice2(psrc, srclen, &packelen, &nalutype, &frametype, &bend, &scrindex, &isH265,&destCount);if (result == -1) {break;} else {if (isH265) {processH265Nalu(psrc, scrindex, packelen, nalutype,pts,dts);} else {processH264Nalu(psrc, scrindex, packelen, nalutype,pts,dts);}}// 更新psrc和srclen以处理下一个NALUpsrc += scrindex + packelen;srclen -= scrindex + packelen;} while (!bend && srclen > 0);
}

在rtmp推流组包时,网上基本上就是建议以下的方式

    body[i++] = 0x01; //configurationVersion 必须为1//general_profile_idc 8bitbody[i++] = sps[1]; //HEVCProfileIndication//general_profile_compatibility_flags 32 bitbody[i++] = sps[2];//profile_compatibilitybody[i++] = sps[3];//HEVCLevelIndicationbody[i++] = 0x03;//sps[4];//lengthSizeMinusOne 0x03body[i++] = 0xE1;//sps[5];//sps number SPS的序号,是0xE1// 48 bit NUll nothing deal in rtmp general_constraint_indicator_flags: 48bitsbody[i++] = sps[6];body[i++] = sps[7];body[i++] = sps[8];body[i++] = sps[9];body[i++] = sps[10];body[i++] = sps[11];//general_level_idc  //general_level_idc: 8bitsbody[i++] = sps[12];// 48 bit NUll nothing deal in rtmp//min_spatial_segmentation_idc: xxxx 14bits//parallelism_type: xxxx xx 2bits//chroma_format: xxxx xx 2bits//bit_depth_luma_minus8: xxxx x 3bits//bit_depth_chroma_minus8: xxxx x 3bitsbody[i++] = 0x00;body[i++] = 0x00;body[i++] = 0x00;body[i++] = 0x00;body[i++] = 0x00;body[i++] = 0x00;//bit(16) avgFrameRate;body[i++] = 0x00;body[i++] = 0x00;// bit(2) constantFrameRate;// bit(3) numTemporalLayers;// bit(1) temporalIdNested;body[i++] = 0x00;// unsigned int(8) numOfArrays; 03body[i++] = 0x03;

但是用这个组包方式肯定是调不通的,需要解析vps sps pps得到HEVCDecoderConfigurationRecord,然后填充进去,因为srs做了严格的HEVCDecoderConfigurationRecord解析,所以大家还是不要偷懒

    ff_buff_write_hvcc(&body[i],pps,pps_len,sps,sps_len,vps,vps_len);i+=22;// unsigned int(8) numOfArrays; 03body[i++] = 0x03;

按这个对接后基本上就可以愉快的用srs自带的播放器进行H265预览了,需要注意的是srs启动时采用./objs/srs -c ./conf/hevc.flv.conf 这个配置,不得不说,srs作为开源的项目能够做的这么完备还是非常牛的,在这里给他一个大大的赞!

      当然做完这些,我们并不满足,因为预览的延迟,并没有达到毫秒级,于是我们做了无插件H265网页低延迟播放器,从srs拉取rtmp流,而不是flv流,实现了webrtc级的低延迟预览,下面是对比测试效果。

当然如果直接采用我们自己的架构延迟会更低

音视频是很复杂 的一门综合性应用,值得深入挖掘,特别是结合实际的落地还有很长的路要走,希望能在漫漫长路的旅途中与志同道合的您结识并相伴而行

相关文章:

  • Node.js--》node环境配置及nvm和nvm-desktop安装教程
  • 数字IC设计流程
  • MongoDB 数据类型
  • WPF 消息日志打印帮助类:HandyControl+NLog+彩色控制台打印+全局异常捕捉
  • Matlab仿真2ASK/OOK、2FSK、2PSK、QPSK、4QAM在加性高斯白噪声信道中的误码率与归一化信噪比的关系
  • Python入门学习篇(十四)——模块文件操作
  • java之树筛选
  • 判断电话号码是否重复-excel
  • x-cmd pkg | openssl - 密码学开源工具集
  • 【JavaFX】基于JavaFX11 构建可编辑、对象存储、修改立即保存、支持条件过滤的TableView
  • LeetCode976. Largest Perimeter Triangle
  • docker +gitee+ jenkins +maven项目 (一)
  • C语言 指针初阶
  • 【Redis-08】Redis主从复制的实现原理
  • Linux驱动开发之杂项设备注册和Linux2.6设备注册
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • C学习-枚举(九)
  • jdbc就是这么简单
  • js继承的实现方法
  • laravel5.5 视图共享数据
  • quasar-framework cnodejs社区
  • React-redux的原理以及使用
  • Vue.js-Day01
  • vue学习系列(二)vue-cli
  • Yeoman_Bower_Grunt
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 猴子数据域名防封接口降低小说被封的风险
  • 技术胖1-4季视频复习— (看视频笔记)
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 前端性能优化--懒加载和预加载
  • 首页查询功能的一次实现过程
  • Spring第一个helloWorld
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • ​iOS实时查看App运行日志
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • $NOIp2018$劝退记
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (SERIES12)DM性能优化
  • (SpringBoot)第七章:SpringBoot日志文件
  • (二)fiber的基本认识
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (五)Python 垃圾回收机制
  • (转)重识new
  • (转载)从 Java 代码到 Java 堆
  • ***详解账号泄露:全球约1亿用户已泄露
  • .gitignore
  • .libPaths()设置包加载目录
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .Net 应用中使用dot trace进行性能诊断