音视频同步问题(第一弹)

前言:

大家好,由于最近工作上碰到一些关于音视频不同步的问题,比如音频跟不上视频的播放速度;基于此,今天给大家分享一篇关于音视频同步的问题,本系列文章会分为几篇来分享,先从基础的音视频同步理论开始,然后再进行基于ffplay里面的源码实战来加深音视频同步的理解!

一、音视频同步基础:

首先我们先来了解一下什么是音视频同步,相信之前看过前面几期关于ffplay源码解析的文章的朋友应该知道,在一个播放器进行解码拿到数据这个环节里面,音频和视频各自有自己的线程进行处理各自对应的数据!

那么在这个环节就可能会出现问题,比如说,音频线程和视频线程可能不会同时解出音视频和视频帧,那么这就会造成后面的播放出现不同问题!也就会出现音视频不同的问题,直白的说,音视频同步就好比我们平时用一个播放器去播放一个视频文件(包括音频和视频!),会出现视频画面和视频画面人物说话的声音对应不上,这就会造成非常差的体验感。

所以为了今后更好的解决实际开发问题,我们在此之前需要掌握一些基础理论知识,下面我们来看一下什么是PTS和DTS、timebase,先来说一下理论概念,后期再通过实战来理解它,当前你只要知道有这三个东西就行:

  • DTS(Decoding Time Stamp),也就是解码时间戳,它会告诉播放器在什么时候来解码这一帧的数据.

  • PTS(Presentation Time Stamp),也就是显示时间戳,那么它也会告诉播放器在什么时候来显示这一帧的数据。

  • timebase时基:PTS值的真正时间单位,一般是秒;同时我们要注意在ffplay里面,PTS值的数据类型是double的,比如下面我定义了一个音频的PTS的变量并进行初始化:

double audio_pts = 0.020;

同时在ffplay里面,timebase的类型是结构体AVRational(其中一个结构体成员是表示分子,另外一个是表示分母!),具体代码如下:

typedef struct AVRational{
  int num;
  int den;
}AVRational;

那么通过这个如何来计算出PTS的显示时间呢?

比如说timebase={1,100},表示100毫秒,如果pts=1000,那么1000*1/100=10秒,意思就是这帧数据需要在第10秒的时候被显示出来!

因此在ffmpeg里面有一个关于把AVRational转变成double类型的接口实现,我们利用这个接口来计算pts的显示时间就非常方便了:

34ee28ccfa3a5d3839c0de3e4761372a.png
/**
 * Convert an AVRational to a `double`.
 * @param a AVRational to convert
 * @return `a` in floating-point form
 * @see av_d2q()
 */
static inline double av_q2d(AVRational a){
    return a.num / (double) a.den;
}

所以显示时间戳的时间计算就等于:

pts * av_q2d(参数);

二、常用的音视频同步策略理论解决:

一般有三种解决方法:

  • (1):以音频为基准,同步视频到音频;如果视频慢了,就丢弃部分视频帧(会出现跳帧现象!);如果视频快了,就继续渲染上一帧。

  • (2)以视频为基准,同步音频到视频;如果音频慢了,则加快播放速度,或者也丢弃部分视频帧,不过会出现断音出现;如果音频慢了,就放慢播放速度,或者重复上一帧。但是这里改变播放速度,会涉及重采样的问题!

  • (3)以外部时钟为基准,同步音频和视频到外部时钟

三、总结:

今天的内容就简单分享到这里,更多的是咋们在实际开发过程中,如果遇到类似问题,该如何快速把这种问题解决掉才是关键,这也是需要咋们平时基础的积累!

下期,我们继续!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值