当前位置: 首页 > news >正文

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左右的。

ffmpeg是音视频必备,但即使从业数年,它似乎依然有无穷的秘密,感兴趣添加笔者微信:YQW1163720468,加入ffmpeg微信群讨论。但记得备注:ffmpeg爱好者

相关文章:

USB采集卡如何打pts

一、使用采集卡提供的pts 二、手动打pts 1.usb采集设备pts的问题 2.采集卡驱动&#xff0c;UVC/UAC&#xff0c;ffmpeg的关系 3.如何自己打pts 4.音视频同步调优 5.NTP等联网调时工具带来的不同步问题 一、使用采集卡提供的pts 我们用使用pc摄像头和使用pc麦克风声卡里的方法&…...

机器学习实战13-超导体材料的临界温度预测与分析(决策树回归,梯度提升回归,随机森林回归和Bagging回归)

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下机器学习实战13-超导体材料的临界温度预测与分析(决策树回归,梯度提升回归,随机森林回归和Bagging回归)&#xff0c;这几天引爆网络的科技大新闻就是韩国科研团队宣称发现了室温超导材料-LK-99&#xff0c;这种材料…...

小研究 - 一种复杂微服务系统异常行为分析与定位算法(二)

针对极端学生化偏差&#xff08;&#xff25;&#xff58;&#xff54;&#xff52;&#xff45;&#xff4d;&#xff45; &#xff33;&#xff54;&#xff55;&#xff44;&#xff45;&#xff4e;&#xff54;&#xff49;&#xff5a;&#xff45;&#xff44; &#…...

Docker 安装 MySQL5.6

方法一、docker pull mysql 查找Docker Hub上的mysql镜像 #docker search mysql 这里我们拉取官方的镜像,标签为5.6 #docker pull mysql:5.6 &#xff08;第一次启动Docker-MySql主要是查看Docker里面MySQL的默认配置&#xff0c;数据位置&#xff0c;日志位置&#xff0c;配…...

vue组件跳层级时的事件处理 (事件的广播与派发)

相信大家一定用过elementui这个组件库&#xff0c;那么对里面的表单组件一定不陌生。 最常用的几个组件就是el-form&#xff0c;el-form-item&#xff0c;el-input&#xff0c;表单校验时的错误提示功能是交给el-form-item来实现的。当el-input填写时触发校验规则&#xff0c;…...

毫米波雷达 TI IWR6843 官方测试程序(Out Of Box Demo)

1.硬件准备 1.IWR6843AOP板子 2.两个USB转串口模块&#xff08;因为我的是自己做的板子&#xff0c;板子上没有集成USB转串口芯片&#xff09; 2.软件准备 1.最新版本的CCS&#xff0c;注意后缀没有THEIA https://www.ti.com/tool/CCSTUDIO?DCMPdsp_ccs_v4&HQSccs 2.最…...

中大标了 5813万

汗水浇灌收获&#xff0c;实干笃定前行。刚刚进入八月&#xff0c;鸿雁政企事业部就传来了特大喜讯——鸿雁中标浙江丽水国际会展中心电线电缆项目&#xff0c;中标总金额达5813万&#xff01;一举刷新鸿雁单体项目中最高中标金额。 据了解&#xff0c;浙江丽水国际会展中心项…...

Java电子招投标采购系统源码-适合于招标代理、政府采购、企业采购、等业务的企业 tbms

​ 功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查…...

RocketMQ安装和简单使用

说明&#xff1a;RocketMQ与RabbitMQ一样&#xff0c;是分布式架构中的一个组件&#xff0c;用来解决微服务之间的异步调用。同类的还有两个&#xff0c;各自的特点如下&#xff1a; Rocket结构 服务启动时 发送消息时 其中各个部分的功能如下&#xff1a; &#xff08;1&…...

Codeforces Round 869 (Div. 2)

C 求最长似递增子序列 是子序列&#xff01; 我误以为是最长上升子序列的变式&#xff0c;但是这个题目和那个题目&#xff0c;并不是很一样 我们选择观察样例&#xff1a; 1 2 4 3 3 5 6 2 1 其实样例当中就给我们了答案&#xff0c;我们能感觉的出来&#xff0c;应该是用长…...

【雕爷学编程】MicroPython动手做(28)——物联网之Yeelight 3

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了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 长轮询&#xff1f; Web 应用程序最初是围绕客户端/服务器模型开发的&#xff0c;其中 Web 客户端始终是事务的发起者&#xff0c;向服务器请求数据。因此&#xff0c;没有任何机制可以让服务器在没有客户端先发出请求的情况下独立地向客户端发送或推送数据。 为…...

操作系统用户态和核心态和CPU上下文切换

目录 操作系统用户态和核心态用户态和核心态操作系统用户态和核心态是如何交换的系统调用 CPU上下文什么是CPU上下文和CPU上下文切换CPU为什么要进行上下文切换 操作系统用户态和核心态 用户态和核心态 操作系统两种状态&#xff1a;用户态和内核态。 操作系统的用户态和内核态…...

TSINGSEE青犀视频汇聚平台EasyCVR视频广场面包屑侧边栏支持拖拽操作

TSINGSEE青犀视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;能对外分发RTSP、RTMP、FLV、HLS、Web…...

RocketMQ发送消息超时异常

说明&#xff1a;在使用RocketMQ发送消息时&#xff0c;出现下面这个异常&#xff08;org.springframework.messging.MessgingException&#xff1a;sendDefaultImpl call timeout……&#xff09;&#xff1b; 解决&#xff1a;修改RocketMQ中broke.conf配置&#xff0c;添加下…...

WordPress做权重站:二级目录伪静态写法

我喜欢用WordPress建站&#xff0c;但是每个网站我都会写3个以上的二级目录&#xff0c;为什么了&#xff0c;因为WordPress数据量过大会导致数据库很大很卡&#xff0c;所以这种做法可以减轻数据库的负荷。我一般每个目录的文章达到15万篇就不会再更新了&#xff0c;3个目录加…...

浅谈下API初步认知

当我们谈论API&#xff0c;我们指的是应用程序接口&#xff08;Application Programming Interface&#xff09;。API允许不同的软件应用程序之间互相通信和交互。它定义了一组规定和协议&#xff0c;用于确定数据传输和请求的格式、方法和功能。 API的作用是在软件开发中提供一…...

LeetCode--剑指Offer75(2)

目录 题目描述&#xff1a;剑指 Offer 58 - II. 左旋转字符串&#xff08;简单&#xff09;题目接口解题思路1代码解题思路2代码 PS: 题目描述&#xff1a;剑指 Offer 58 - II. 左旋转字符串&#xff08;简单&#xff09; 字符串的左旋转操作是把字符串前面的若干个字符转移到…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...

聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇

根据 QYResearch 发布的市场报告显示&#xff0c;全球市场规模预计在 2031 年达到 9848 万美元&#xff0c;2025 - 2031 年期间年复合增长率&#xff08;CAGR&#xff09;为 3.7%。在竞争格局上&#xff0c;市场集中度较高&#xff0c;2024 年全球前十强厂商占据约 74.0% 的市场…...

C#中用于控制自定义特性(Attribute)

我们来详细解释一下 [AttributeUsage(AttributeTargets.Class, AllowMultiple false, Inherited false)] 这个 C# 属性。 在 C# 中&#xff0c;Attribute&#xff08;特性&#xff09;是一种用于向程序元素&#xff08;如类、方法、属性等&#xff09;添加元数据的机制。Attr…...

window 显示驱动开发-如何查询视频处理功能(三)

​D3DDDICAPS_GETPROCAMPRANGE请求类型 UMD 返回指向 DXVADDI_VALUERANGE 结构的指针&#xff0c;该结构包含特定视频流上特定 ProcAmp 控件属性允许的值范围。 Direct3D 运行时在D3DDDIARG_GETCAPS的 pInfo 成员指向的变量中为特定视频流的 ProcAmp 控件属性指定DXVADDI_QUER…...