首页 > 应用开发 > IT综合 > 直播卖货系统开发,实现延迟优化才是真道理
视频流为1080P、30fps,直播卖货系统如何优化RTSP直播的延时为大约100ms呢?发现大家对RTSP直播延时优化非常感兴趣,纷纷提问或者给出自己的观点。本文主要是总结,也是与大家探讨RTSP直播的延时优化。
一、修改编译脚本支持RTSP
ijkPlayer默认是没有把RTSP协议编译进去,所以我们得修改编译脚本,原来的disable改为enable:
二、修改播放器的option参数
值得注意的是,ijkPlayer默认使用udp拉流,因为速度比较快。如果需要可靠且减少丢包,可以改为tcp协议:
另外,可以这样开启硬解码,如果打开硬解码失败,再自动切换到软解码:
三、网络抖动的丢包
直播卖货系统在拉流时,音频流、视频流是单独保存到缓冲队列的。如果发生网络抖动,就会引起缓冲抖动(JitBuffer),可以总结为网络卡顿导致音视频缓冲队列增大,从而导致解码滞后、播放滞后。此时,我们需要主动丢包来跟进当前时间戳。因为音视频同步一般以音频时钟为基准,人们对音频更加敏感,所以我们优先丢掉视频队列的包。但是,丢视频数据包时,需要丢掉整个GOP的数据包,因为B帧、P帧依赖I帧来解码,否则会引起直播卖货系统花屏。
四、解码器设为零延时
大家应该听过编码器的零延时(zerolatency),但可能没听过解码器零延时。其实解码器内部默认会缓存几帧数据,用于后续关联帧的解码,大概是3-5帧。经过反复测试,发现解码器的缓存帧会带来100多ms延时。也就是说,直播卖货系统假如能够去掉缓存帧,就可以减少100多ms的延时。而在avcodec.h的文件中AVCodecContext结构体有一个参数(flags)用来设置解码器延时:
为了去掉解码器缓存帧,我们可以把flags设置为CODEC_FLAG_LOW_DELAY。在初始化解码器时进行设置:
五、减少FFmpeg拆帧等待延时
FFmpeg拆帧是根据下一帧的起始码来作为当前帧结束符,起始码一般是:0x00 0x00 0x00 0x01或者0x00 0x00 0x01。这样就会带来一帧的延时,这一帧延时能不能去掉呢?如果有帧结束符,我们以帧结束符来拆帧,这样做就能解决一帧延时。现在,问题变成找到帧结束符,然后替换成下一帧起始码来拆帧。整个调用流程是:read_frame—>read_frame_internal—>parse_packet—>av_parser_parse2—>parser_parse—>ff_combine_frame. 流程图如下:
1、找到当前帧结束符
在rtpdec.c文件的rtp_parse_packet_internal方法里,有获取帧结束符,也就是mark标志位,我们在这里设一个全局变量:
2、去掉parse_packet的while循环
我们在外部调用libavformat模块的utils.c文件的read_frame读取一帧数据,而read_frame调用内部方法read_frame_internal,read_frame_internal接着调用parse_packet方法,在该方法里有一个while循环体。现在把循环体去掉,并且释放申请的内存:
3、 修改av_parser_parse2的帧偏移量
在libavcodec模块的parser.c文件中,parse_packet调用到av_parser_parse2来解释数据包,该方法内部有记录帧偏移量。原先是等待下一帧的起始码,现在改为当前帧结束符,所以要把下一帧起始码这个偏移量长度去掉:
4、去掉parser_parse的寻找帧起始码
av_parser_parse2调用到parser_parse方法,而我们这里使用的是h264解码,所以在libavcodec模块的h264_parser.c有一个结构体ff_h264_parser,把h264_parse赋值给parser_parse:
现在直播卖货系统需要h264_parser.c文件的h264_parse方法,去掉寻找下一帧起始码作为当前帧结束符的过程:
5、修改parser.c的组帧方法
h264_parse又调用parser.c的ff_combine_frame组帧方法,直播卖货系统在这里把mark替换起始码作为帧结束符:
经过以上修改,局域网用电脑推送1080P、30fps的视频流,Android设备拉流解码播放,直播卖货系统整体延时可优化至130ms左右。而手机推流,延时可达到86ms。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70002045/viewspace-2785711/ ,如需转载,请注明出处,否则将追究法律责任。