ffmpeg接收rtsp流问题

项目使用mingw环境g++5.3,C++调用ffmpeg接收rtsp流,再通过C#显示。结构上是C#调用C++的so文件,读取得到的视频帧(RGB888格式),通过图片控件显示。

一开始是使用opencv打开视频源,本地文件和rtsp的源使用一样的接口,方便使用。但是通过opencv打开rtsp源的时候,发现720p2Mbit的视频能够正常打开,但1080p的视频打开后出马赛克,卡顿比较多。

而同样的视频源,使用VLC就能流畅的打开,不过延时很高,大约1s。

后来又发现,使用i3低电压版CPU的笔记本上,连720p也有卡顿和马赛克。使用3代i5处理器的笔记本能够流畅播放720p,1080p的会出马赛克。一开始认为是opencv的问题,所以换成了用ffmpeg打开rtsp流。但是效果与opencv的完全一致。

由于解码的CPU占用率很高,而且性能高的笔记本问题就少,所以怀疑是解码时间长,导致丢数据。所以在ffmpeg打开rtsp流之前加了强制使用tcp的选项:

AVDictionary* options = NULL;
av_dict_set(&options, "rtsp_transport", "tcp", 0);  //强制使用tcp,udp在1080p下会丢包导致花屏
result = avformat_open_input(&fmt_ctx, video_url.c_str(), NULL, &options); //打开文件

这样就解决了丢包问题,本以为就完美了,后来视频源经过图传传输到笔记本上,使用1080p 2Mbit,这一版程序的就出现了大量的马赛克,卡顿严重。

分析认为是网络图传限制了最大传输带宽为6Mbit,且延时大约30ms,可能对rtsp传输有影响。所以又恢复了之前udp的方式,结果效果就好多了,但是和之前一样,还是会出马赛克。

使用tcp的方式无法通过图传,也就否定了这种解决方案。所以还是需要解决udp方式丢包的问题。

对于udp丢包的问题,可以使用增加缓存的方式解决,而我在网上没有查到有关ffmpeg打开rtsp流增加udp缓存的方法,所以还是到ffmpeg源码中搜索avformat_open_input函数的源码,和rtsp_transport等关键字,最后搜到了这个函数的所有配置,发现buffer_size这个选项最终在socket中修改了udp的接收缓存。默认64K,修改为1MB以后,视频流畅播放了:

AVDictionary* options = NULL;
av_dict_set(&options, "buffer_size", "1024000", 0);  //设置udp的接收缓冲
result = avformat_open_input(&fmt_ctx, video_url.c_str(), NULL, &options); //打开文件

 

posted on 2017-06-24 17:11  yangzifb  阅读(3527)  评论(0编辑  收藏  举报