ffmpeg音视频同步

先讲一个概念:

pts :音视频显示时间。

dts:音视频解码时间。

time_base: 时间刻度单位,时间基。例如视频播放30fps,表示1秒钟播放30张图片,视频的时间基time_base等于{1,30};如果音频的采样率是44100Hz,音频的时间基是{1,44100}

timebase,在ffmpeg数据结构表示

typedef struct AVRational{
  int num; ///< Numerator
  int den; ///< Denominator
} AVRational;

duration:视频的总时长。time(秒) = st->duration * av_q2d(st->time_base);

在ffmpeg中。av_q2d(time_base)=每个刻度是多少秒。pts*av_q2d(time_base)才是帧的显示时间。

时间转换

因为数据状态不同(不同的封装格式,压缩前、压缩后的数据以及封装前和封装后的数据不一样),对于封装格式来说:flv 封装格式的 time_base 为{1,1000},ts 封装格式的 time_base 为{1,90000}。时间基不一样,所以我们必须转换,在1/30时间刻度下占10格,在1/90000下是占多少格。这就是pts时间戳的转换。

ffmpeg,给到av_rescale_q(int64_t a, AVRational bq, AVRational cq)函数

这个函数的作用是计算a*bq / cq(pts的转换)来把时间戳从一个时间基调整到另外一个时间基。在进行时间基转换的时候,应该首先用这个函数,因为它可以避免溢出的情况发生。

函数表示在bq下的占a个格子,在cq下是多少。

音质为例44100Hz的采样率,假设一帧音频包含1024个采样数据,那么1秒钟的音频大约有43帧。在编码阶段无论是视频还是音频我们都需要提供一个基础的pts作为参考。代表视频的vpts每次自增1即可,而代表音频的apts需要每次自增1024。

编码器到容器需要做时间转换,视频H264时间基{1,30},转换成flv{1,1000},音频的时间基{1,44100}转换成flv{1,1000},使用av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)函数进行转换,其实内部也是根据av_rescale_q实现。

音视频同步:

视频和音频的同步实际上是一个动态的过程,同步是暂时的,不同步则是常态。以选择的播放速度量为标准,快的等待慢的,慢的则加快速度,是一个你等我赶的过程。

播放速度标准量的的选择一般来说有以下三种:

  • 将视频同步到音频上,就是以音频的播放速度为基准来同步视频。视频比音频播放慢了,加快其播放速度;快了,则延迟播放。
  • 将音频同步到视频上,就是以视频的播放速度为基准来同步音频。
  • 将视频和音频同步外部的时钟上,选择一个外部时钟为基准,视频和音频的播放速度都以该时钟为标准。

推流工作,将视频的pts和音频的pts设置正确。pts一般累加1,音频是加1024 没做任何处理

不过累加的方式有2种情况可能会有问题,1)输入帧率不稳定 2)视频处理时间过久,到时客户端接收的PTS超过expireTime,被丢弃。

第一个问题的话,其实和驱动和硬件有关系。

驱动要把读取到的帧率正确设置给编码器

所以此时要用av_compare_ts去做比较

int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)

假如av_compare_ts(vpts, pVideoCodecCtx->time_base, apts, pAudioCodecCtx->time_base);

比较音视频pts,大于0表示音视频时间快于视频,音频需要连续编码。小于0表示,视频时间快于音频,应该至少编码一帧视频。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小昭dedug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值