opencv拉流出现missing picture in access unit with size 4错误解决

0、应用场景问题

我们使用opencv作为拉流客户端,获取画面后进行图像处理并推流(使用ffmpeg库)。 opencv解码同样使用ffmpeg库。

我们要求opencv能根据业务不断进行拉流操作,等效的逻辑代码如下:

while(1) {printf("start open rtmp\n");cv::VideoCapture cap;if(!cap.open("rtmp://192.168.3.100:1935/live/1581F5FHB228R00200S3", cv::CAP_FFMPEG))  // // 无流时会有20-30s超时时间{printf("reopen rtmp\n");continue;}// 推流初始化 ...while(1) {cap.read(frame);  // 无流时会有20-30s超时时间if(frame.empty()) {printf("frame empty\n");break; }cv::imshow("v", frame);cv::waitKey(1);// 图像处理 ...// 推流 ...}// 推流反初始化 ...
}

注意代码中 // 无流时会有20-30s超时时间 注释的地方cap.open() 和 cap.read(frame),后面会用到。

在一次偶然测试中,发现opencv拉流时,控制台会出现如下错误:

[NULL @ 000001bb1f721400] missing picture in access unit with size 4
[h264 @ 000001bb1f71f880] Error splitting the input into NAL units.

导致后续获取frame为空,认为流断开触发重新进行拉流的操作,导致后续视频处理、推流业务有短暂停顿,客户端播放会出现响应的短暂黑屏问题。
在这里插入图片描述

1、解决思路

出现前面情况的可能原因:

可能是因为网络问题引起数据丢失,使得解码出现问题,是一段(秒级以上)时间的发生频率。 我们不去处理视频源、opencv底层的亲在问题,仅从应用层上规避该原因带来的问题,也就是不将这个报错信息作为拉流断开来处理。

1.1、方式一:

我们简单操作修改代码如下。流存在时,如果frame为空不作为错误,直接continue进行下一次读取。

        if(frame.empty()) {printf("frame empty\n");// break; continue; // 不进行重新拉流}

实际测试时,能够跳过当前空帧,并能再次重新成功获取新的frame。
在这里插入图片描述

但是,会存一下可能的问题:

  • 1)无法区分流真正断开的情况,导致程序会卡在读取frame的循环中

  • 2)断开流超过 cap.read(frame) 超时时间后,再次连接后无法解码

    这个错误在1)的基础之上出现,导致流不能解码(需要重新拉流?或其他未知设置?)。如下图
    在这里插入图片描述

1.2、方式二:

我们设置一个frame.empty()为空的次数限制,当达到一定次数(如3次)认为是流断开连接。

    while(1) {cap.read(frame); // 无流时会有20-30s超时时间if(frame.empty()) {printf("frame empty\n"); if(cnt++ == 3) {cnt = 0;printf("grab failed at 3 times, reopen rtmp\n");break;}continue;}// 其他操作...}

当流正常确认断开后,cap.read(frame) 会阻塞,阻塞3次(约60~90s)后将退出当前while循环,进行重新拉流。这种逻辑是符合业务的,新拉流可能参数配置改变,需要重新进行推流参数的调整(推流反初始化、推流初始化)。

在这里插入图片描述

当以cap.read(frame) 超时以20s,不同时间端重连时,说明如下情况:

  • 若在 20s 内流重新连接时,能正常获取非空的 frame。

  • 在 20~60s 之内重新获取流时,cap.read(frame) 不再超时且以流帧率进行执行,例如 30fps 时会再后续第 3x20 = 60ms 后 break 退出当前循环、重新拉流。

  • 在 60s 后,break 退出当前循环、重新拉流。

存在问题:

前面代码中,若正常获取非空 frame 后未将 cnt 置零,会出现每次累计出现文首错误(读到空frame )到第 3 次 必将 break 退出当前循环、重新拉流。因此需要在 if 语句后面后对 cnt 重置。

1.3、方式三:

方式二的等效代码,只不过是使用了 VideoCapture 的另外一种接口方式。

    while(1) { if(!cap.grab()) {  // 无流时会有20-30s超时时间if(cnt++ == 3) {cnt = 0;printf("grab failed at 10 times, reopen rtmp\n");break;}continue;}cnt = 0; // 重置if(!cap.retrieve(frame)) {printf("retrieve failed\n");continue;}// 其他操作...}

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

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

相关文章

MATLAB最小二乘法曲线拟合及消除多项式趋势项代码实例

1.最小二乘法拟合基本概念 MATLAB最小二乘法曲线拟合及消除多项式趋势项代码实例 最小二乘法是一种数学优化技术,它通过最小化误差的平方和寻找数据的最佳函数匹配。优化是找到最小值或等式的数值解的问题。而线性回归就是要求样本回归函数尽可能好地拟合目标函数值,也就是说…

gazebo模型库目录(国内源)

这个是比较普遍的,一般用途: GitCode - 开发者的代码家园https://gitcode.com/geniusChinaHN/osrf.gazebo_models/tree/master/ambulance这个主要是车辆: car_demo: osrf汽车模型库https://gitee.com/geniuschinahn/car_demo还有这个是以前…

YOLOv6s,map值打印成两位小数(原本是显示0.538,变成显示为53.79)

显示结果 更改前: 更改后: 方法 将tools/eval.py中的--do_pr_metric后面改为defaultTrue即可打印出map值原本是显示0.538,变成显示为53.79,方法为👇 在YOLOv6-main/yolov6/core/evaler.py中做如下更改&#xff1a…

对回调函数的各种讲解说明

有没有跟我师弟一样的童靴~,学习和使用ROS节点时,对其中的callback函数一直摸不着头脑的,以下这么多回调函数的讲解,挨个看,你总会懂的O.o 回调函数怎么调用,如何定义回调函数: 回调函数怎么调用,如何定义…

最大公共子串

解题思路: 解题代码: UP主运用的方法很巧妙。厉害。

IPv6路由协议----BGP4+

BGP基本概念 边界网关协议BGP(Border Gateway Protocol)是一种实现自治系统AS(Autonomous System)之间的路由可达,并选择最佳路由的距离矢量路由协议。 MP-BGP是对BGP4进行了扩展达到在不同网络中应用的目的,BGP4原有的消息机制和路由机制并没有改变。MP-BGP在IPv6单播网…

day1·算法-双指针

今天是第一天,GUNDOM带你学算法,跟上我的节奏吗,一起闪击蓝桥杯! 正文展开,今天先上点小菜供大家想用,如有错误或者建议直接放评论区,我会一个一个仔细查看的哦。 双方指针问题一般是在数组中…

QT 小组件 列表框以及微调框

.cpp文件 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);QListWidgetItem *pPhone new QListWidgetItem;pPhone->setText("西瓜");pPhone->…

SSM整合(实现简单查询功能)

在名为ssm的数据库内创建表 CREATE TABLE account (id int(11) NOT NULL AUTO_INCREMENT,name varchar(20) DEFAULT NULL,money double DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8; 创建工程 pom.xml <?xml version"1.0" encoding&quo…

git hooks

介绍 当我们在执行git管理仓库代码时&#xff0c;想规范下每个用户的commit内容&#xff1f;想检查下提交的代码规范&#xff1f;想检查下PR是否通过&#xff0c;那么这个时候就需要用到git hooks&#xff0c;git hooks可以在我们进行git操作的关键时机插入我们想要执行的“脚…

Find My游戏手柄|苹果Find My技术与手柄结合,智能防丢,全球定位

游戏手柄是一种常见电子游戏机的部件&#xff0c;通过操纵其按钮等&#xff0c;实现对游戏虚拟角色的控制。随着游戏设备硬件的升级换代&#xff0c;现代游戏手柄又增加了&#xff1a;类比摇杆&#xff08;方向及视角&#xff09;&#xff0c;扳机键以及HOME菜单键等。现在的游…

2024年实时获取地图边界数据方法,省市区县街道多级联动【附实时geoJson数据下载】

首先&#xff0c;来看下效果图 在线体验地址&#xff1a;https://geojson.hxkj.vip&#xff0c;并提供实时geoJson数据文件下载 可下载的数据包含省级geojson行政边界数据、市级geojson行政边界数据、区/县级geojson行政边界数据、省市区县街道行政编码四级联动数据&#xff0…

字符串最后一个单词的长度【C语言】

【华为机试题 HJ1】 字符串最后一个单词的长度 描述输入描述:输出描述:示例1参考代码1背景知识点 ```scanf("%s", u8Str) != EOF```参考代码2参考代码 不使用 strlen()描述 计算字符串最后一个单词的长度,单词以空格隔开,字符串长度小于5000。(注:字符串末尾不…

Postman接口测试神器从安装到精通

Postman 的优点&#xff1a; 支持各种的请求类型: get、post、put、patch、delete 等支持在线存储数据&#xff0c;通过账号就可以进行迁移数据很方便的支持请求 header 和请求参数的设置支持不同的认证机制&#xff0c;包括 Basic Auth&#xff0c;Digest Auth&#xff0c;OAu…

gitlab部署

系统版本 [rootlocalhost ~]# cat /etc/redhat-release Red Hat Enterprise Linux release 9.1 (Plow)gitlab包位置 https://mirrors.tuna.tsinghua.edu.cn/gitlab-ee/yum/el9/gitlab-ee-16.7.2-ee.0.el9.x86_64.rpm关闭防火墙 [rootlocalhost data]# systemctl stop firew…

使用 Docker 部署 Halo 博客系统

:::info 项目地址&#xff1a;https://github.com/halo-dev/halo ::: 一、Halo 介绍 1&#xff09;Halo 简介 Halo 是一款强大易用的开源建站工具&#xff0c;它让你无需太多的技术知识就可以快速搭建一个博客、网站或者内容管理系统。具备可插拔架构、主题套用、富文本编辑器…

Hive数据定义(1)

hive数据定义是hive的基础知识&#xff0c;所包含的知识点有&#xff1a;数据仓库的创建、数据仓库的查询、数据仓库的修改、数据仓库的删除、表的创建、表的删除、表的修改、内部表、外部表、分区表、桶表、表的修改、视图。本篇文章先介绍&#xff1a;数据仓库的创建、数据仓…

CCF模拟题 202305-1 重复局面

试题编号&#xff1a; 202305-1 试题名称&#xff1a; 重复局面 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 512.0MB 题目背景 国际象棋在对局时&#xff0c;同一局面连续或间断出现3次或3次以上&#xff0c;可由任意一方提出和棋。 问题描述 国际象棋每一个局面可以用…

Postman接口测试工具最全实用教程

一、postman简介 1、postman的特点 postman只做http协议的接口的测试&#xff0c;是一种最广泛REST接口测试客户端软件。postman支持http协议的所有请求方式&#xff0c;包括get、post、head、put、delete等。postman支持各种额外的头部字段的添加。postman除了可以模拟普通表…

C语言快速排序——qsort函数

上面的是我们标准C语言库里面对qsort函数的介绍&#xff0c;我们先来从排序说起&#xff1a; 这就不得不提出编程中最最基础的排序算法---冒泡排序 对于一个任意的无序数列&#xff0c;我们如果想要把他排成顺序数列的话&#xff0c;我们就可以让每一项跟后面的一项去比较&…