学校网站建设 应用情况,软文500字范文,做网站卖广告位赚钱,seo准一、使用采集卡提供的pts 二、手动打pts 1.usb采集设备pts的问题 2.采集卡驱动#xff0c;UVC/UAC#xff0c;ffmpeg的关系 3.如何自己打pts 4.音视频同步调优 5.NTP等联网调时工具带来的不同步问题 一、使用采集卡提供的pts
我们用使用pc摄像头和使用pc麦克风声卡里的方法UVC/UACffmpeg的关系 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/UACffmpeg的关系 在与原厂电话微信后对usb的采集卡有初步的了解对于音频来说采集卡的驱动并不会提供pts给系统因为对于音频来说确定好采样率声道数位深那么在播放端它的采样数对应的播放时间是固定的采集卡只有一个晶振在控制着采集频率音频从采集卡采集到其提供给系统延时可以忽略。 视频采集卡的驱动也不会有pts它的启动只会对上层提供类似于123…等视频的序号的标签采集卡从采集到提供给系统可能会有几帧如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左右的。