USB采集卡如何打pts

一、使用采集卡提供的pts
二、手动打pts
1.usb采集设备pts的问题
2.采集卡驱动,UVC/UAC,ffmpeg的关系
3.如何自己打pts
4.音视频同步调优
5.NTP等联网调时工具带来的不同步问题

一、使用采集卡提供的pts

我们用使用pc摄像头和使用pc麦克风声卡里的方法,用ffmpeg采集后会得到音视频的pts。
我们应该尽量用好这些pts,因为他们的时间间隔很精准,比如48000,每次采集1024,发现每帧间隔21ms;视频采集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。
因此数据的传输是这样的,采集卡->采集卡驱动->系统内核->UVC/UAC->ffmpeg
硬件厂商改一个问题,要改好几个版本,经常引入其他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爱好者

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

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

相关文章

Butterfly 安装文档(一) 快速开始

安装 在你的Hexo根目录里面 git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly 应用主题 修改 Hexo 根目录下的 _config.yml&#xff0c;把主题改为 butterfly theme: butterfly 安装插件 如果你没有 pug 以及 stylus 的渲染…

阻抗是什么?什么时候要考虑阻抗匹配?

在电路设计中&#xff0c;我们常常碰到跟阻抗有关的问题&#xff0c;那么到底什么是阻抗&#xff1f; 在具有电阻、电感和电容的电路里&#xff0c;对电路中电流所起的阻碍作用叫做阻抗。常用Z来表示&#xff0c;它的值由交流电的频率、电阻R、电感L、电容C相互作用来决定。由…

RocketMQ使用

RocketMQ角色 RocketMQ的基本概念 同步发送消息 /*** author* create 2023-04-08 17:24* 发送同步消息* 适用于重要的消息 例如消息通知&#xff0c;短信通知*/ public class SyncProducer {public static void main(String[] args) throws Exception {String topic"…

re学习(29)攻防世界-CatFly(复原反汇编)

因为这是一个.dll文件&#xff0c;在Linux上运行一下&#xff1a; 找到主要函数&#xff1a;&#xff08;以及由上面三部分对应的代码部分&#xff09; __int64 __fastcall main(int a1, char **a2, char **a3) {size_t v3; // rbx__int16 v5[4]; // [rsp10h] [rbp-4B0h] B…

【MCU学习】GD32F427VG开发

&#xff08;一&#xff09;学习文档和例程 兆易创新GD32 MCU参考资料下载 1.GD232F4xx的Keil芯片支持包 2.标准固件库和示例程序 3.GD32F4xx_固件库使用指南_Rev1.2 4.用户手册&#xff1a;GD32F4xx_User_Manual_Rev2.8_CN 5.数据手册&#xff1a;GD32F427xx_Datasheet_Rev…

通过MySQL删除Hive元数据信息

之前遇到过一个问题&#xff0c;在进行Hive的元数据采集时&#xff0c;因为Hive表的文件已经被删除了&#xff0c;当时是无法删除表&#xff0c;导致元数据采集也发生了问题&#xff0c;所以希望通过删除Hive表的元数据解决上述问题。 之前安装时&#xff0c;经过特定的配置后…

SpringBoot使用@Autowired将实现类注入到List或者Map集合中

前言 最近看到RuoYi-Vue-Plus翻译功能 Translation的翻译模块配置类TranslationConfig&#xff0c;其中有一个注入TranslationInterface翻译接口实现类的写法让我感到很新颖&#xff0c;但这种写法在Spring 3.0版本以后就已经支持注入List和Map&#xff0c;平时都没有注意到这…

WEB集群——http、tomcat

1. 简述静态网页和动态网页的区别。 2. 简述 Webl.0 和 Web2.0 的区别。 3. 安装tomcat8&#xff0c;配置服务启动脚本&#xff0c;部署jpress应用。 1. 简述静态网页和动态网页的区别。 1&#xff09;、静态网页 &#xff08;1&#xff09;、什么是静态网页 请求响应信息&…

基于fpga的电子时钟

文章目录 前言实验手册一、实验目的二、实验原理1&#xff0e;理论原理2&#xff0e;硬件原理 三、系统架构设计四、模块说明1&#xff0e;模块端口信号列表按键消抖模块&#xff08;key&#xff09;计数器模块&#xff08;counter&#xff09;蜂鸣器乐谱模块(music)蜂鸣器发声…

GD32F103VE侵入事件

GD32F103VE的TAMPER引脚(PC13)&#xff0c;当PC13输入低电平时&#xff0c;会产生一个侵入检测事件。它会将所有“数据备份寄存器”内容清除。 这个功能有什么用&#xff1f; 一是防止被人开壳&#xff0c;抄袭。二是自毁功能。 直奔主题&#xff0c;多一句就是浪费时间。测试…

flutter开发实战-flutter_spinkit实现多种风格进度指示器

flutter开发实战-flutter_spinkit实现多种风格进度指示器 最近开发过程中flutter_spinkit&#xff0c;这个拥有多种种风格加载指示器 一、flutter_spinkit 引入flutter_spinkit # 多种风格的模糊进度指示器flutter_spinkit: ^5.1.0效果示例 const spinkit SpinKitRotatingC…

如何找到死锁的线程?_java都学什么

在Java中&#xff0c;死锁是指两个或多个线程被无限地阻塞&#xff0c;等待彼此持有的资源&#xff0c;从而导致程序无法继续执行的情况。死锁通常是由于线程之间循环等待资源而产生的。要找到死锁的线程&#xff0c;可以采用以下方法&#xff1a; 1.线程转储(Thread Dump) 通过…

6.6 实现卷积神经网络LeNet训练并预测手写体数字

模型架构 代码实现 import torch from torch import nn from d2l import torch as d2lnet nn.Sequential(nn.Conv2d(1,6,kernel_size5,padding2),nn.Sigmoid(),#padding2补偿5x5卷积核导致的特征减少。nn.AvgPool2d(kernel_size2,stride2),nn.Conv2d(6,16,kernel_size5),nn.S…

OpenStreetMap数据转3D场景【Python + PostgreSQL】

很长一段时间以来&#xff0c;我对 GIS 和渲染感兴趣&#xff0c;在分别尝试这两者之后&#xff0c;我决定最终尝试以 3D 方式渲染 OpenStreetMap 中的地理数据&#xff0c;重点关注不超过城市的小规模。 在本文中&#xff0c;我将介绍从建筑形状生成三角形网格、以适合 Blend…

iperf3-性能测试

iperf3-性能测试 安装1.apt安装2.源码安装 使用方法iperf原理测试参考文档性能测试客户端服务端 官方文档&#xff1a;https://iperf.fr/iperf-doc.php 安装 1.apt安装 sudo apt-get install iperf32.源码安装 # 按照官方说明安装 ./configure make sudo make install执行编…

GATK ApplyBQSRSpark 过程中因No space left on device终止

Error&#xff1a; GATK ApplyBQSRSpark 过程中因No space left on device终止 执行命令&#xff1a; nohup time ./gatk --java-options "-Xmx128G" ApplyBQSRSpark --spark-master local[20] -R ../../alignment/hg38/hg38.fa -I ../../alignment/bam/P368T.s…

微信小程序nodejs+vue+uniapp高校食堂线上预约点餐系统

本次设计任务是要设计一个食堂线上预约点餐系统&#xff0c;通过这个系统能够满足管理员及学生的食堂线上预约点餐分享功能。系统的主要包括首页、个人中心、学生管理、菜品分类管理、菜品管理、关于我们管理、意见反馈、系统管理、订单管理等功能。 开发语言 node.js 框架&am…

【论文阅读】对抗溯源图主机入侵检测系统的模仿攻击(NDSS-2023)

作者&#xff1a;伊利诺伊大学芝加哥分校-Akul Goyal、Gang Wang、Adam Bates&#xff1b;维克森林大学-Xueyuan Han、 引用&#xff1a;Goyal A, Han X, Wang G, et al. Sometimes, You Aren’t What You Do: Mimicry Attacks against Provenance Graph Host Intrusion Detect…

BenchmarkSQL 支持 TiDB 驱动以及 tidb-loadbalance

作者&#xff1a; GangShen 原文来源&#xff1a; https://tidb.net/blog/3c274180 使用 BenchmarkSQL 对 TiDB 进行 TPC-C 测试 众所周知 TiDB 是一个兼容 MySQL 协议的分布式关系型数据库&#xff0c;用户可以使用 MySQL 的驱动以及连接方式连接 TiDB 进行使用&#xff0…

Git从远程仓库中删除文件,并上传新文件

目录 删除&#xff1a; 拉取远程分支的更新&#xff1a; ​编辑 首先查看git状态&#xff1a; ​编辑 删除文件并提交版本库&#xff1a; 提交&#xff1a; 上传新文件&#xff1a; 首先查看git状态&#xff1a; 提交到暂存区&#xff1a; 提交到版本库&#xff1a; 上…