android rtsp 延时,ijkplayer 单视频流直播延迟问题解决过程

一开始我尝试是通过设置ijkplayer的参数去修改延迟,参数的修改能把ijkplayer的开播延迟拉到200ms左右,但是随着播放时间增加延迟也在增加,然后带着问题去网上寻找答案,找到暴走大牙和Gongjia两位大神的解决方案,但是这种方案仅适用于带有音频流的,现在适配的流仅有视频流,用了这两位的方案后,丢帧是可以,但是延迟的问题并没有解决,因为没有音频流的视频的时间基准是用视频流的时间,丢完帧后视频会卡顿等待视频的时间基准。后来我在ijkplayer的issue上找了很多关于卡顿的问题,都没有找到解决方案,后面尝试通过变速的方式去解决这个问题,找到了Mr_xkHuang的一篇ijkplayer-音视频变速播放实现,才了解到了单视频流的视频和有音视频流的视频关于时间基准的差别。修改了时间基准之后,长时直播的延迟问题解决了。

ff_ffplay.c代码修改如下:

static int read_thread(void *arg)

{

.....

if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {

stream_component_open(ffp,st_index[AVMEDIA_TYPE_AUDIO]);

} else {

//添加新代码

ffp->av_sync_type = AV_SYNC_EXTERNAL_CLOCK;

//注释掉原有代码

// ffp->av_sync_type = AV_SYNC_VIDEO_MASTER;

is->av_sync_type = ffp->av_sync_type;

}

.....

}

经过上面的修改,长时放置直播软解码延迟稳定在400ms左右硬解码延迟稳定在200ms左右,但是出现了一个更加严重的问题,那就是闪退

代码会在renderer_yuv420sp_vtb.m这个类

static GLboolean yuv420sp_vtb_uploadTexture(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)

{

.....

}

这个方法内的随机几行代码奔溃,报的错误是EXC_BAD_ACCESS,通过打开僵尸对象检测,发现是

CVPixelBufferRef pixel_buffer

这个对象的原因,然后通过和一个做c语言的大神沟通后他告诉我要从对象初始化和查对象被释放这两个地方入手。

经过一番查找,找到pixel_buffer是通过SDL_VoutOverlay *overlay这个类拿到的,然后我就在ijksdl_vout_overlay_videotoolbox.m这个类的overlay的初始化方法里面加了

SDL_VoutOverlay *SDL_VoutVideoToolBox_CreateOverlay(int width, int height, SDL_Vout *display)

{

...

//add

if (opaque->pixel_buffer != NULL) {

CVBufferRelease(opaque->pixel_buffer);

}

opaque->pixel_buffer = NULL;

return overlay;

}

当时我是用的模拟器测试的,结果很美好,没有闪退了,年轻的我以为bug已经解决了,但是我想用真机测试下延迟问题时,突然发现闪退依然存在。然后我就继续去找还有没有哪里有使用pixel_buffer这个结构体的。但是仅有创建pixel_buffer的ijksdl_vout_overlay_videotoolbox.m和使用pixel_buffer的renderer_yuv420sp_vtb.m这两个类使用了pixel_buffer,一时间大神给的方向找不到路了。

后面我考虑到既然是EXC_BAD_ACCESS,那么久应该是野指针的问题,我就冲这个方向入手,在使用pixel_buffer的地方对这个结构体进行retain操作,增加它的引用计数使它不被释放,结果是有一点用处,奔溃的概率降低了,以前1-5分钟就会奔溃的代码现在可以到20-30分钟奔溃,这让我以为找到了一条正确的路,结果确实我把引用计数增加做到了极致,仍然会有闪退。

这时候我知道我是找错了方向,之后想到pixel_buffer是通过解码后的frame数据转换而来的,有没有可能是frame被释放了导致pixel_buffer这个结构体内部的指针形成野指针。带着这样的疑问,我开始打印所有释放frame的地方,结果真的找到了,每次奔溃的时候都连着调用了两次释放frame。后面我顺着这个释放的流程,将渲染与释放的各个地方按上打印,终于理清楚了ijkplayer渲染的流程。

edd5c0d7a606

通过对这里流程的理清楚,我发现终于找到了为什么会发生这样的问题,既然知道了是由于在渲染之前frame就被释放了,这样就好解决问题了。

整体是frame在还么有进行渲染就进行了引用释放,释放后frame在进行渲染时就会导致上面的情况

我的最终如下:

修改对ijksdl_vout.h 文件overlay的定义位置添加了一个属性:

struct SDL_VoutOverlay {

//add

bool nowUseing;//当前是否还在使用中

}

然后在ijksdl_vout_overlay_videotoolbox.m这个类中

//这是overlay的frame数据重载方法

static int func_fill_frame(SDL_VoutOverlay *overlay, const AVFrame *frame)

{

//add

// printf("new func_fill_frame :%p\n",overlay);

if (overlay->NowUseing) {//如果当前frame正在使用中,就不进行数据加载

// printf("nowUsing want new func_fill_frame:%p\n",overlay);

return 1;

}

overlay->nowUseing = true;//数据重载后将overlay的使用状态置为true

....

}

//overlay的初始化方法

SDL_VoutOverlay *SDL_VoutVideoToolBox_CreateOverlay(int width, int height, SDL_Vout *display)

{

.....

//add

overlay->nowUseing = false;//初始化nowUsing

//初始化pixel_buffer

if (opaque->pixel_buffer != NULL) {

CVBufferRelease(opaque->pixel_buffer);

}

opaque->pixel_buffer = NULL;

return overlay;

}

在renderer_yuv420sp_vtb.m这个类中

//渲染的方法

static GLboolean yuv420sp_vtb_uploadTexture(IJK_GLES2_Renderer *renderer, SDL_VoutOverlay *overlay)

{

//add

if (!overlay->nowUseing) {

return GL_FALSE;

}

.....

//add

// printf("display over:%p\n",overlay);

overlay->nowUseing = false;

return GL_TRUE;

}

在ff_ffplay.c这个类中

//这是item的引用释放方法,修改为如果该frame还没有渲染,这不释放引用。

static void frame_queue_unref_item(Frame *vp)

{

//添加这行,防止刚启动APP或者切换前后台bmp为null,bmp->nowUseing闪退

if (!vp->bmp) {

av_frame_unref(vp->frame);

vp->frame = NULL;

SDL_VoutUnrefYUVOverlay(vp->bmp);

avsubtitle_free(&vp->sub);

return;

}

if (vp->bmp->nowUseing) {

printf("nowUsing wait av_frame_unref:%p\n",vp->bmp);

}else {

// printf("SDL_VoutUnrefYUVOverlay(vp->bmp):%p\n",vp->bmp);

av_frame_unref(vp->frame);

vp->frame = NULL;

SDL_VoutUnrefYUVOverlay(vp->bmp);

avsubtitle_free(&vp->sub);

}

}

这个解决办法并不完美,只是粗暴的处理不让程序崩溃,我觉得最好的解决办法应该是找到为什么overlay会在使用前释放。然后让这种情况不再出现。最近没有时间去处理这个问题,后面有时间了再来解决。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/563391.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

html5svg在线编辑器,SVG to Canvas在线转换工具

https://github.com/samsha/svg2canvascanvg.js是的确实有人在做这样的事,canvg.js 就是一个将SVG转换成Canvas的工具库,甚至有些SVG的动画效果也能得到实现,但是canvg.js存在很多问题:不可避免的SVG兼容问题SVG是一种很复杂的矢量…

python3 上传文件到目标机器_通过python模块实现服务器和本地机器之间快速拷贝文件...

在实际的开发过程中,很多时候我们都不直接在本机上开发,一般都在远程服务器上开发并运行程序。比如三胖在实际开发中就会使用到很多台服务器:我有一台笔记本电脑,通过 ssh 连接着很多台服务器,我需要经常在不同的服务器…

鸿蒙系统有那些上市,鸿蒙上市整套系统究竟意味着什么

大家期待的鸿蒙系统已经上市,首先鸿蒙系统从自家的生态产品适配,大家熟知的华为笔记本,华为手机,华为平板,华为手表等,相比目前市场上的操作系统,IOS,安卓,微软Windows&a…

c# 时间格式化为英文_C# DateTime日期格式化

1. 分类DateTime调用ToString()传入的参数可分为制式和自定义两种:1) 制式:系统自带的,转入特定的单个字符就可转换为系统已设定好的格式。2) 自定义:自由组合日期代码(y、M、d、h、m、s、f)来展示丰富的日期格式。2. 制式类型说明…

html多个单元格合并单元格内容,excel怎样快速把多个单元格内容合并 合并多个单元格内容的设置方法...

excel是我们常用的办公软件,有时我们需要把多个单元个的内容合并到一个单元格里,那么excel怎样快速把多个单元格内容合并?下面小编带来合并多个单元格内容的设置方法,希望对大家有所帮助。合并多个单元格内容的设置方法&#xff1…

mysql5.5客户端_MySQL 5.5/5.6——概述 MySQL 客户端程序

本文内容 mysqlmysqladminmysqlcheckmysqldumpmysqlimportmysqlshowmysqlslap参考资料mysqlmysql 是一个可以输入行的 SQL 外壳,输入行可以编辑。它支持交互和非交互。当使用交互式,查询结果以一个 ASCII 表格式来显示。当使用非交互时(例如,…

第一次使用mysql_第一次使用mysql,求帮忙

我用的是navicate,怎么把里面的数据库备份出来放到另外一个服务器里面啊,那个里面也装的是navicate回复讨论(解决方案)没用过navicate,它是一个图形化工具,应该有导入导出的按钮,找找看。没用过navicate,它是一个图形化…

mac 如何配置mysql_MAC下安装与配置MySQL

一 下载MySQL访问MySQL的官网http://www.mysql.com/downloads/ 然后在页面中会看到“MySQL Community Server”下方有一个“download”点击。进入MySQL的下载界面(http://www.mysql.com/downloads/mysql/),如果你是用的Mac OS来访问的话那么就会默认为你选好了Mac O…

计算机专硕专业课难度,计算机考研:20考研的408难度如何?

原标题:计算机考研:20考研的408难度如何?2020年对于计算机考研来说风云突变的一年,去年夏天“专业课改考”一度成为计算机考研小伙伴们之间的热词。不少院校或改变、或增加专业课科目,借此提高专业课难度,增…

barrons ap计算机科学,巴朗ap心理学barrons ap psychology, 5th edition-201-240.pdf

巴朗ap心理学barrons ap psychology, 5th edition-201-240.pdf (C)Arousaltheorydescribesmotivationbyreferringtostagesinourresponsestostress(thegeneraladaptationsyndrome).Achievementmotivationisnotusedtodescribemotivationduetostress.(D)Apersonwithalowoptimumlev…

递归算法1加到100_五种循环方法计算1加到100

上文讲过1加到100,详细解释了计算的过程&#xff0c;如果理解了以前的文章&#xff0c;就容易理解今天的内容了。1加到100使用VBA我能使用十来种方法&#xff0c;以下也是一种方法。While ……wend循环 Private Sub CommandButton1_Click()s 0i 1While i < 100s s ii …

武汉大学计算机学院参考书目,2020武汉大学计算机与软件工程考研初试科目、参考书目及复试详情...

原标题&#xff1a;2020武汉大学计算机与软件工程考研初试科目、参考书目及复试详情本文将由新祥旭徐老师全方位的对武汉大学计算机专业考研进行解析&#xff0c;主要有以下几个板块&#xff1a;学院介绍&#xff0c;专业情况介绍&#xff0c;2019录取情况分析&#xff0c;考研…

培训学校计算机助教是干嘛的,【助教】的意思是什么?【助教】是什么意思?...

【助教】的意思是什么&#xff1f;【助教】是什么意思&#xff1f;以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;【助教】的意思是什么&#xff1f;【助教】是什么意思&#xff1f; 【助教…

云服务器怎么管理,第一次使用云服务器,如何使用和管理云服务器

云服务器的两节课和管理使用其实非常简单,windows 自带了一个远程桌面的软件,利用这个远程桌面,我们可以很轻松容易的管理远在天边的服务器,就和您亲自做在远程服务器的电脑前一样!现在我们看看如何使用他吧!在开始 - 程序 - 附件 - 远程桌面 ,如图:如在附件里面找不到这个 远程…

163邮箱有传真服务器,网易企业邮箱邮件传真功能使用说明

网易企业邮箱邮件传真功能是网易在用户购买网易企业邮箱时附赠的增值服务&#xff0c;管理员通过在企业邮箱管理后台给员工邮箱设置邮件传真号码&#xff0c;员工便可在WebMail直接收发电子传真&#xff0c;无需通过传真机。此功能需要联系经销商协助开通。一、管理员端如何开通…

ajax 折叠,ASP.NET AJAX可折叠面板Accordion应用实例

通常来讲&#xff0c;将一个无比长的列表直接显示给用户是一种极不礼貌的行为。对此&#xff0c;解决方案有很多&#xff0c;归类显示就是其中之一。类似我们常见的QQ或MSNMessage的联系人归类等&#xff0c;系统将用户管理中心的操作菜单归类显示&#xff0c;并应用背景图片&a…

navicat mysql 建表语句_Navicat for MySQL怎么/如何创建数据表?Navicat for MySQL创建数据表教程_斗蟹游戏网...

【斗蟹攻略】Navicat for MySQL是针对MySQL数据库管理而研发的管理工具&#xff0c;创建数据表是其最基本操作&#xff0c;下面就由斗蟹小编介绍Navicat for MySQL创建数据表的方法。Navicat for MySQL创建数据表教程步骤一&#xff1a;新建连接运行Navicat数据库管理工具&…

华为服务器显示003,设置BIOS - RH2288H V3 服务器 V100R003 用户指南 41 - 华为

在服务器的远程虚拟控制台的菜单栏中&#xff0c;单击。关于登录远程虚拟控制台的详细操作步骤&#xff0c;请参见登录远程虚拟控制台。选择“重启”。弹出“你确认要执行这个操作吗&#xff1f;”提示框。单击“是”。服务器进行重启。服务器重启时&#xff0c;当出现如下界面…

java前端开发_Java前端开发学习什么内容

Java是一门高级编程语言&#xff0c;现在java工程师需求很大&#xff0c;所以java的前景很好&#xff0c;有些朋友往java前端开发方向发展&#xff0c;那么&#xff0c;Java前端开发学习什么内容呢?动力节点java学院小编来告诉你。就目前市场行情来看&#xff0c;Java最流行的…

用友t3显示无法解析服务器名称,用友T3软件进入用友通提示不能解析端口,不能登录服务器...

用友软件增加明细科目时提示新增会计科目是&#xff0c;提示上级科目已经使用&#xff0c;新增科目将自动改为上级科目的设置已经使用的科目如何增加明细科目在软件操作过程中&#xff0c;经常会遇到对已经使用的科目&#xff0c;要求增加其明细科目的问题。科目已经使用&#…