6.音视频同步算法

音视频同步算法

题外话

物理中,音调指乐音的高低,响度指声音的大小强弱,音色指声音的特色,要区分开。

视频:色深、色域、亮度。

人耳的听觉范围是20Hz-20KHz,这个范围内的信号成为音频信号,称为可闻声,而人耳对中频段1-4KHz最敏感;

对声音的主观感受:音色 - 知乎 (zhihu.com)

对于音色来说,在众多因素中影响较大的是声音的频谱分布 (Spectral Envelope) 以及时间包络曲线 (Time Envelope) 。除此之外,平均频率 (Mean Frequencies) 、声音中的噪声 (Noise) 、频谱中心 (Spectral Centroid) 、一些随机成分 (Irregularity Parameters) 和频谱的变化 (Spectral Flux) 等也会对音色造成影响。 [1] [2]

不同的声源之间,最主要的区别便是形状与材质的区别。而形状与材质的不同,则决定了物体振动模态的不同。振动模态不同便导致了其振动产生的频谱不同。因此,频谱分布是区分不同声源的一个重要特征。

音视频播放流程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由于视频播放和音频播放的差异,所以需要将两者进行同步化,否则就会出现音画不同步。

为什么需要音视频同步

声卡和显卡均是以一帧数据来作为播放单位,如果单纯依赖帧率及采样率来进行播放,在理想条件下,应该是同步的,不会出现偏差。

视频按帧率播放,音频按采样率播放,二者没有同步机制,即使一开始音视频是同步的,随着时间的流逝,音视频会渐渐失去同步,并且不同步的现象会随着时间会越来越严重。这是因为:

  1. 播放时间难以精确控制。音视频解码及渲染的耗时不同,可能造成每一帧输出有一点细微差距,长久累计,不同步便越来越明显。(例如受限于性能,42ms才能输出一帧)
  2. 音频输出是线性的,而视频输出可能是非线性,从而导致有偏差。
  3. 媒体流本身音视频有差距。(特别是TS实时流,音视频能播放的第一个帧起点不同)

所以,必须要采用一定的同步策略,不断对音视频的时间差作校正,使图像显示与声音播放总体保持一致。

所以,解决音视频同步问题,引入了时间戳:首先选择一个参考时钟(要求参考时钟上的时间是线性递增的);编码时依据参考时钟上的给每个音视频数据块都打上时间戳;播放时,根据音视频时间戳及参考时钟,来调整播放。所以,视频和音频的同步实际上是一个动态的过程,同步是暂时的,不同步则是常态。以参考时钟为标准,放快了就减慢播放速度;播放快了就加快播放的速度。

音视频中的时间戳

由于编码方式的不同,视频中的画面帧就分为了不同的类别,其中包括:I 帧、P 帧、B 帧:

I 帧(Intra coded frames)图像采用帧I 帧使用帧内压缩,不使用运动补偿,由于 I 帧不依赖其它帧,可以独立解码。I 帧图像的压缩倍数相对较低,周期性出现在图像序列中的,出现频率可由编码器选择。

P 帧(Predicted frames)采用帧间编码方式,即同时利用了空间和时间上的相关性。P 帧图像只采用前向时间预测,可以提高压缩效率和图像质量。P 帧图像中可以包含帧内编码的部分,即 P 帧中的每一个宏块可以是前向预测,也可以是帧内编码。

B 帧(Bi-directional predicted frames)图像采用帧间编码方式,且采用双向时间预测,可以大大提高压缩倍数。也就是其在时间相关性上,还依赖后面的视频帧,也正是由于 B 帧图像采用了后面的帧作为参考,因此造成视频帧的传输顺序和显示顺序是不同的。

时间戳DTS、PTS

  • DTS(Decoding Time Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。
  • PTS(Presentation Time Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。

当视频流中没有 B 帧时,通常 DTS 和 PTS 的顺序是一致的。但如果有 B 帧时,就回到了我们前面说的问题:解码顺序和播放顺序不一致了,即视频输出是非线性的。

同步策略

时间戳就是PTS,那么参考时钟的选择一般来说有以下三种:

  1. 将视频同步到音频上:就是以音频的播放速度为基准来同步视频。
  2. 将音频同步到视频上:就是以视频的播放速度为基准来同步音频。
  3. 将视频和音频同步外部的时钟上:选择一个外部时钟为基准,视频和音频的播放速度都以该时钟为标准。

当播放源比参考时钟慢,则加快其播放速度,或者丢弃;快了,则延迟播放。

考虑到人对声音的敏感度要强于视频,频繁调节音频会带来较差的观感体验,且音频的播放时钟为线性增长,所以一般会以音频时钟为参考时钟,视频同步到音频上。

阈值

  1. 无法察觉:音频和视频的时间戳差值在:-100ms ~ +25ms 之间
  2. 能够察觉:音频滞后了 100ms 以上,或者超前了 25ms 以上
  3. 无法接受:音频滞后了 185ms 以上,或者超前了 90ms 以上

同步算法

MediaSync | Android Developers (google.cn)

此方法应该可以实现相关的同步,但是改写自己的代码工程量较大,暂时没有依靠此api来实现该功能。

音视频开发—音视频同步算法_基于播放时限的流内同步算法-CSDN博客

在这里插入图片描述

直接根据diff的值来决策下一帧要延时的时间。

音视频同步原理及实现_音视频同步策略-CSDN博客

以audio为参考时钟,video同步到音频的示例代码:

  1. 获取当前要显示的video PTS,减去上一帧视频PTS,则得出上一帧视频应该显示的时长delay;
    当前video PTS与参考时钟当前audio PTS比较,得出音视频差距diff;
  2. 获取同步阈值sync_threshold,为一帧视频差距,范围为10ms-100ms;
    diff小于sync_threshold,则认为不需要同步;否则delay+diff值,则是正确纠正delay;
  3. 如果超过sync_threshold,且视频落后于音频,那么需要减小delay(FFMAX(0, delay + diff)),让当前帧尽快显示。
  4. 如果视频落后超过1秒,且之前10次都快速输出视频帧,那么需要反馈给音频源减慢,同时反馈视频源进行丢帧处理,让视频尽快追上音频。因为这很可能是视频解码跟不上了,再怎么调整delay也没用。
  5. 如果超过sync_threshold,且视频快于音频,那么需要加大delay,让当前帧延迟显示。
    将delay*2慢慢调整差距,这是为了平缓调整差距,因为直接delay+diff,会让画面画面迟滞。
  6. 如果视频前一帧本身显示时间很长,那么直接delay+diff一步调整到位,因为这种情况再慢慢调整也没太大意义。
  7. 考虑到渲染的耗时,还需进行调整。frame_timer为一帧显示的系统时间,frame_timer+delay- curr_time,则得出正在需要延迟显示当前帧的时间。

深入理解Android音视频同步机制(一)概述-CSDN博客

这个博客给出了一系列视频播放器的同步机制:

在这里插入图片描述

Code

假设音频是跟系统时间同步,视频向系统时间靠拢。

因为暂时没有办法获得音频相关的时间轴信息,只能获得视频的播放时间轴,但是音频播放是通过audiotrack来播放,它跟系统时间一致,所以我们调整视频。

//延迟渲染
private boolean adjustPlay(long videoTimeUs, long sysTimeMs) {
    long diff = videoTimeUs / 1000 - (System.currentTimeMillis() - sysTimeMs);
Log.i(TAG, "The diff is " + diff);
    if (diff >= 10 && diff <= 100) {
        return true;
}
    if (diff > 100) {
        try {
            DecodeVideoThread.sleep(diff);
} catch (InterruptedException e) {
            e.printStackTrace();
}
        return true;
}
    if (diff < 0) {
        return false;
}
    return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值