USB采集卡如何打pts
一、使用采集卡提供的pts
二、手动打pts
1.usb采集设备pts的问题
2.采集卡驱动,UVC/UAC,ffmpeg的关系
3.如何自己打pts
4.音视频同步调优
5.NTP等联网调时工具带来的不同步问题
一、使用采集卡提供的pts
我们用使用pc摄像头和使用pc麦克风声卡里的方法,用ffmpeg采集后会得到音视频的pts。
我们应该尽量用好这些pts,因为他们的时间间隔很精准,比如48000,每次采集2048,发现每帧间隔23ms;视频采集1080p25,每帧间隔40ms。
使用之前我们需要把他们同步到同一个时间戳,其中一个方法是:
dif = 格林威治时间 - 第一帧采集到的视频时间戳
然后以后每次pts = pts + dif。
V:
AVDictionary *options = NULL;
av_dict_set(&options, “video_size”, “1920x1080”, 0);
av_dict_set(&options, “framerate”, “30”, 0);
//以上参数如果不设置的话,ffmpeg就会用默认值,但默认值摄像头不一定支持
int re = avformat_open_input(&ic, “/dev/video0”, ifmt, &options);
A:
av_dict_set(&options, "sample_rate", "48000", 0); // 只能是48000不支持改动
av_dict_set(&options, "channels", "2", 0); // 无法改,不支持改动
long long GetCurTime()
{struct timeval tv;gettimeofday(&tv, NULL);// ZlogInfo("second:%ld\n",tv.tv_sec); //秒// ZlogInfo("millisecond:%ld\n",tv.tv_sec*1000 + tv.tv_usec/1000); //毫秒// ZlogInfo("microsecond:%ld\n",tv.tv_sec*1000000 + tv.tv_usec); //微秒long long temp_time = tv.tv_sec * 1000000 + tv.tv_usec;return temp_time;
}
if(this->dif_PTS == 0) this->dif_PTS = GetCurTime() - read_pkt.pts;
read_pkt.pts = read_pkt.pts + this->dif_PTS;
二、手动打pts
1.usb采集设备pts的问题
decklink的采集卡,会把音视频的pts给好,并且是可靠的。但小的厂商就不一定了。我这里使了一个台湾和国内的厂商,一个是pci采集卡(sdi/hdmi采集转pci口),这个采集卡支持UVC和UAC协议,另一个是usb(hdmi转usb口)采集卡。这两个价格都在千元左右。
跟这两个采集卡的原厂技术沟通,pts存在以下问题
1:音频和视频的pts没有关系,没有共同的起点或相关的联系。
2.pts经过一夜测试后发现,有跳变的现象。
3.采集1080p30时,视频的pts,每帧之间只增加20ms,而不是33ms,其他分辨率无此问题。
因为这些设备的用户大多数不是开发者,所以这些问题都不会用到,对于开发者来说则需要原厂定制开发了。
2.采集卡驱动,UVC/UAC,ffmpeg的关系
在与原厂电话微信后,对usb的采集卡有初步的了解,对于音频来说,采集卡的驱动并不会提供pts给系统,因为对于音频来说,确定好采样率,声道数,位深,那么在播放端,它的采样数对应的播放时间是固定的,采集卡只有一个晶振在控制着采集频率,音频从采集卡采集到其提供给驱动,延时可以忽略。
视频采集卡的驱动也不会有pts,它的启动只会对上层提供类似于1,2,3…等视频的序号的标签,采集卡从采集到提供给驱动,可能会有几帧,如4帧延时。
那么我们用ffmpeg采集到的音视频,都含有pts,那么这些pts是什么呢。音频是1970年开始到现在的us,视频则是开机的时间us。他们都是UVC和UAC协议对采集卡驱动提供的音视频帧打的pts。
硬件厂商改一个问题,要改好几个版本,经常引入其他bug,看来天下程序员都一样。
3.如何自己打pts
那么我们该怎么自己打pts呢?
在两个线程里分别采集音视频:
av_read_frame()
我们把格林威治的PTS赋值给每次采集到的音视频数据。
A:
re = av_read_frame(ic_a, &read_pkt_a);
read_pkt_a.pts = GetCurTime();
V:
re = av_read_frame(ic, &read_pkt);
read_pkt.pts = GetCurTime();
ZlogInfo("dif:%ld\n", (shm_->GetCurTime() - LAST_PTS) / 1000);
LAST_PTS = shm_->GetCurTime();
视频每次从这个函数返回的时间间隔分别是:
//1080p25 39 40 39 40 39 40 39 40 39 40 39 40 ms
音频分别是:
//1080p25 41 0 42 0 42 0 41 0 41 0 42 0 ms
有时是
//1080p25 21 0 41 21 0 40 22 0 41 1 40 0 42 0 41 22 0 41 0 42 0 42 1 40 22 0 41 21 1 40
0并非没有间隔而是小于1ms,这里有精度损失。
可以看到间隔并不标准,因为av_read_frame()维护了一个缓存,他每次从采集卡拿到一阵或多帧音频或视频数据放入缓存,然后分包,返回一帧音频或视频数据,下次再调用直接去缓存里拿,如果缓存没有则阻塞住,直到采集卡提供了数据。
我们需要让他们的时间间隔相对均匀,那么每次的pts就和上次比较,如果少于一定时间则睡眠。
ZlogInfo("dif:%ld\n", (shm_->GetCurTime() - LAST_PTS) / 1000);
if((shm_->GetCurTime() - LAST_PTS) / 1000 < 10) usleep(10000);
pkt->pts = shm_->GetCurTime();
ZlogInfo("dif_last:%ld\n", (shm_->GetCurTime() - LAST_PTS) / 1000);
LAST_PTS = shm_->GetCurTime();
那么再次打印如下:
V:
//39 40 39 40 39 40 39 40 39 39 39 39 40 40
A:
//1080p25 31 12 30 10 32 10 31 11 31 10 32 11 30 10 32 10 32 10 30 10 31 11 31 10 31 10
4.音视频同步调优
因为采集视频到交给ffmpeg可能有几帧的缓存,因此每次的视频数据可以减去100ms左右,看看播出后的视频效果。
pkt->pts = shm_->GetCurTime() - 100000;
播放器的音视频同步策略一般都是按以音频为基准,音频是线性均匀的,那么音频的pts本身是没有意义的,两帧之间的间隔并不代表播放的时间间隔,它的意义主要是用于视频与他同步。
如果想要音频的间隔再均匀一些,可以调节以下睡眠的时间。
5.NTP等联网调时工具带来的不同步问题
pc每次开机联网后,系统自带NTP开始核对时间,并改变自身时间,那么你每次打的pts就会产生突变。NTP每次调剂的幅度可能在500ms左右,可以关闭它,或换小一点的工具,每次调解幅度在10ms左右的。

相关文章:
USB采集卡如何打pts
一、使用采集卡提供的pts 二、手动打pts 1.usb采集设备pts的问题 2.采集卡驱动,UVC/UAC,ffmpeg的关系 3.如何自己打pts 4.音视频同步调优 5.NTP等联网调时工具带来的不同步问题 一、使用采集卡提供的pts 我们用使用pc摄像头和使用pc麦克风声卡里的方法&…...
机器学习实战13-超导体材料的临界温度预测与分析(决策树回归,梯度提升回归,随机森林回归和Bagging回归)
大家好,我是微学AI,今天给大家介绍一下机器学习实战13-超导体材料的临界温度预测与分析(决策树回归,梯度提升回归,随机森林回归和Bagging回归),这几天引爆网络的科技大新闻就是韩国科研团队宣称发现了室温超导材料-LK-99,这种材料…...
小研究 - 一种复杂微服务系统异常行为分析与定位算法(二)
针对极端学生化偏差(Extreme Studentized &#…...
Docker 安装 MySQL5.6
方法一、docker pull mysql 查找Docker Hub上的mysql镜像 #docker search mysql 这里我们拉取官方的镜像,标签为5.6 #docker pull mysql:5.6 (第一次启动Docker-MySql主要是查看Docker里面MySQL的默认配置,数据位置,日志位置,配…...
vue组件跳层级时的事件处理 (事件的广播与派发)
相信大家一定用过elementui这个组件库,那么对里面的表单组件一定不陌生。 最常用的几个组件就是el-form,el-form-item,el-input,表单校验时的错误提示功能是交给el-form-item来实现的。当el-input填写时触发校验规则,…...
毫米波雷达 TI IWR6843 官方测试程序(Out Of Box Demo)
1.硬件准备 1.IWR6843AOP板子 2.两个USB转串口模块(因为我的是自己做的板子,板子上没有集成USB转串口芯片) 2.软件准备 1.最新版本的CCS,注意后缀没有THEIA https://www.ti.com/tool/CCSTUDIO?DCMPdsp_ccs_v4&HQSccs 2.最…...
中大标了 5813万
汗水浇灌收获,实干笃定前行。刚刚进入八月,鸿雁政企事业部就传来了特大喜讯——鸿雁中标浙江丽水国际会展中心电线电缆项目,中标总金额达5813万!一举刷新鸿雁单体项目中最高中标金额。 据了解,浙江丽水国际会展中心项…...
Java电子招投标采购系统源码-适合于招标代理、政府采购、企业采购、等业务的企业 tbms
功能描述 1、门户管理:所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含:招标公告、非招标公告、系统通知、政策法规。 2、立项管理:企业用户可对需要采购的项目进行立项申请,并提交审批,查…...
RocketMQ安装和简单使用
说明:RocketMQ与RabbitMQ一样,是分布式架构中的一个组件,用来解决微服务之间的异步调用。同类的还有两个,各自的特点如下: Rocket结构 服务启动时 发送消息时 其中各个部分的功能如下: (1&…...
Codeforces Round 869 (Div. 2)
C 求最长似递增子序列 是子序列! 我误以为是最长上升子序列的变式,但是这个题目和那个题目,并不是很一样 我们选择观察样例: 1 2 4 3 3 5 6 2 1 其实样例当中就给我们了答案,我们能感觉的出来,应该是用长…...
【雕爷学编程】MicroPython动手做(28)——物联网之Yeelight 3
知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…...
CTFSHOW php 特性
web89 数组绕过正则 include("flag.php"); highlight_file(__FILE__);if(isset($_GET[num])){$num $_GET[num]; get numif(preg_match("/[0-9]/", $num)){ 是数字 就输出 nodie("no no no!");}if(intval($num)){ 如果是存在整数 输出 flagecho …...
2、认识O(nlogn)的排序
归并排序 分两半,谁小拷贝谁 public class Test{public static void mergeSort(int[] arr) {if (arr == null || arr.length < 2) {return;}mergeSort(arr, 0, arr.length - 1);}public static void mergeSort(int[] arr, int l, int r) {if (l == r) {return;}int mid =…...
什么是 HTTP 长轮询?
什么是 HTTP 长轮询? Web 应用程序最初是围绕客户端/服务器模型开发的,其中 Web 客户端始终是事务的发起者,向服务器请求数据。因此,没有任何机制可以让服务器在没有客户端先发出请求的情况下独立地向客户端发送或推送数据。 为…...
操作系统用户态和核心态和CPU上下文切换
目录 操作系统用户态和核心态用户态和核心态操作系统用户态和核心态是如何交换的系统调用 CPU上下文什么是CPU上下文和CPU上下文切换CPU为什么要进行上下文切换 操作系统用户态和核心态 用户态和核心态 操作系统两种状态:用户态和内核态。 操作系统的用户态和内核态…...
TSINGSEE青犀视频汇聚平台EasyCVR视频广场面包屑侧边栏支持拖拽操作
TSINGSEE青犀视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等,能对外分发RTSP、RTMP、FLV、HLS、Web…...
RocketMQ发送消息超时异常
说明:在使用RocketMQ发送消息时,出现下面这个异常(org.springframework.messging.MessgingException:sendDefaultImpl call timeout……); 解决:修改RocketMQ中broke.conf配置,添加下…...
WordPress做权重站:二级目录伪静态写法
我喜欢用WordPress建站,但是每个网站我都会写3个以上的二级目录,为什么了,因为WordPress数据量过大会导致数据库很大很卡,所以这种做法可以减轻数据库的负荷。我一般每个目录的文章达到15万篇就不会再更新了,3个目录加…...
浅谈下API初步认知
当我们谈论API,我们指的是应用程序接口(Application Programming Interface)。API允许不同的软件应用程序之间互相通信和交互。它定义了一组规定和协议,用于确定数据传输和请求的格式、方法和功能。 API的作用是在软件开发中提供一…...
LeetCode--剑指Offer75(2)
目录 题目描述:剑指 Offer 58 - II. 左旋转字符串(简单)题目接口解题思路1代码解题思路2代码 PS: 题目描述:剑指 Offer 58 - II. 左旋转字符串(简单) 字符串的左旋转操作是把字符串前面的若干个字符转移到…...
告别命令行!用Python脚本批量管理Docker容器,效率提升不止一点点
告别命令行!用Python脚本批量管理Docker容器,效率提升不止一点点每次在终端敲入docker ps、docker stop、docker rm时,你是否想过——当容器数量超过两位数,这种重复劳动是否在消耗你的生命?去年我们团队在迁移微服务架…...
从多路复用到三维光阵:Arduino驱动8x8x8 LED立方体全解析
1. 项目概述:用Arduino点亮一个三维世界几年前,我第一次在创客展上看到一个8x8x8的LED立方体,那种由数百个光点构成的、在三维空间中流动的动画效果,瞬间就把我吸引住了。它不像普通的平面LED屏,而是真正有“深度”的光…...
Arduino PWM转4-20mA工业电流信号:二阶滤波与V/I转换电路设计
1. 项目概述:从PWM到工业标准电流信号在工业自动化、过程控制和传感器领域,4-20 mA电流环是一个几乎无处不在的标准。它用4 mA代表测量值的下限(如0C),20 mA代表上限(如100C),这种设…...
【紧急预警】92%的DeepSeek测试用例生成失败源于这4个隐性配置缺陷——资深SDET连夜整理修复清单
更多请点击: https://codechina.net 第一章:DeepSeek测试用例生成的现状与危机本质 当前,DeepSeek系列大模型(如DeepSeek-Coder、DeepSeek-VL)在代码生成与理解任务中展现出强大能力,但其测试用例自动生成…...
独立站内容分层:一层给 SEO,一层给 GEO
你的内容在喂两个完全不同的"阅读者" 你的博客文章,从来都不只有一个读者。 传统认知里,独立站内容的读者只有两类:真人访客和搜索引擎爬虫。SEO 优化的一切工作,本质上都是在讨好后者,顺带服务前者。 但…...
Windows文件夹共享
目标:同一局域网实现在一台计算机上共享文件夹,在另一台电脑访问一、电脑A 1.点击要共享的文件夹 -> 属性 -> 共享2.添加Everyone用户组3.控制面板中网络共享关闭密码保存,在访问时不用输入账号密码。二、电脑B 1.在文件资源管理器路径…...
第三卷第4章:原型模式设计思想
第三卷第4章:原型模式设计思想 目录介绍 01.案例引入与思考 1.1 痛点场景 1.2 它哪里不舒服 1.3 引出本篇主角 02.原型模式介绍 2.1 原型模式由来 2.2 原型模式定义...
解密高校教师必会的Gemini 3.1 Pro五大科研隐藏技能:从论文评估到创新点锁定
各位同仁好,我是七哥。一个在高校里从事人工智能相关领域研究,钻研用大模型AI实操的学术人。可以和七哥交流学术写作或Gemini、GPT、Claude等大模型学术实操相关问题,多多交流,相互成就,共同进步。 科研路上,有人发完顶刊顺利晋升,有人还在为创新点抓耳挠腮。 大多数教…...
当 AI Coding 进入复杂企业系统,为什么提效远没有宣传里那么美好 ?
以 Claude Code、Codex 为代表的自主编码智能体(Coding Agents),正在以惊人的速度席卷软件开发者生态。与此同时,类似“10 倍开发效率”“普通人也能随手构建软件”“程序员即将失业”的说法,也随处可见。这种不分场景…...
基于MAX78000的离线鸟类声音识别:边缘AI从数据到部署全流程解析
1. 项目概述:当边缘AI“听懂”鸟鸣在野外生态监测或自家后院观鸟时,你是否有过这样的经历:听到一阵清脆或婉转的鸟鸣,却完全不知道是哪位“歌唱家”在表演?传统的鸟类识别依赖专家经验和图鉴比对,不仅门槛高…...
