音视频基础学习之【04.音视频同步优化方案】

本文详细探讨了音视频同步的三种方案,重点介绍了将视频同步到音频时钟的方法。通过计算视频和音频时钟,确保播放过程中音视频保持一致。在本地播放器场景下,通常选择音频作为参考时钟,避免音频卡顿或视频加速,提供更好的观感体验。此外,还讨论了如何根据时钟差值调整视频播放,确保音视频精确同步。
摘要由CSDN通过智能技术生成

目录

音视频同步的几种方案

各个方案的比较

视频时钟的计算方式

音频时钟的计算方式

视频同步到音频时钟的方法

参考


音视频同步的几种方案

  1. 音频同步到视频
  2. 视频同步到音频
  3. 音视频都同步到外部时钟

各个方案的比较

第一种方案,势必会出现音频的卡顿或加速,非常影响观感体验

第二种方案比第一种更加合理,因为音频一般和外部时钟是相同的,而且考虑到人对声音的敏感度要强于视频,所以一般会以音频时钟为参考时钟,视频同步到音频上

第三种方案,通常在播放网络流或者视频源没有音频时钟的情况下使用,是更加通用的一种方案

考虑到现阶段实现的是本地播放器,而大部分视频源都是有音频时钟的,所以采用了第二种方案

下面记录怎么获取视频和音频时钟

视频时钟的计算方式

在视频解码线程中,先从AVPacket中获取包,查看解码时间戳

第一个if判断中的含义是:

如果AVPacket的H.264流没有解码时间戳,而AVFrame的YUV流中有时间戳,视频时钟就赋值为YUV流中的时间戳

如果AVPacket的H.264流有解码时间戳,就赋值给它H.264流的解码时间戳

如果都没有赋值为0

//计算视频时钟
if (packet->dts == AV_NOPTS_VALUE && 
    pFrame->opaque && 
    *(uint64_t*)pFrame->opaque != AV_NOPTS_VALUE)
{
    video_pts = *(uint64_t *) pFrame->opaque;
}
else if (packet->dts != AV_NOPTS_VALUE)
{
    video_pts = packet->dts;
}
else
{
    video_pts = 0;
}
//视频时钟补偿
video_pts *= 1000000 *av_q2d(is->video_st->time_base);
video_pts = synchronize_video(is, pFrame, video_pts);

//时间补偿函数--视频延时
double synchronize_video(VideoState *is, AVFrame *src_frame, double pts)
{
    double frame_delay;
    if (pts != 0) {
        //如果传入的时间戳不为0 存到结构体里
        is->video_clock = pts;
    } else {
        //如果传入的时间戳为0 把结构体里的时间戳赋值给它
        pts = is->video_clock;
    } 
    //重新计算时基
    frame_delay = av_q2d(is->video_st->codec->time_base);
    //
    frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
    is->video_clock += frame_delay;
    return pts;
}

音频时钟的计算方式

在音频解码线程中

下一次音频时钟 = 上一次音频时钟 + 一帧数据的时间

一帧数据的时间 = 一帧音频的字节数(单位:位) / (单次采样字节数(单位:位)*采样频率(单位(1/s))

得到一帧数据的时间是秒数,与音频时钟统一单位,乘以1000000转换为微秒

视频同步到音频时钟的方法

在视频解码线程中添加下面这段代码

其含义是,如果视频时钟 > 音频时钟 计算两者差值delayTime,转换为毫秒,如果毫秒数大于5,视频延时5毫秒,如果不大于5,视频延时delayTime

当视频时钟 <= 音频时钟时跳出死循环

//视频同步到音频上
while(1)
{
    //获取音频时钟,当 视频时钟 <= 音频时钟时 跳出播放
    audio_pts = is->audio_clock;
    if (video_pts <= audio_pts) break;
    int delayTime = (video_pts - audio_pts) * 1000;
    delayTime = delayTime > 5 ? 5:delayTime;
    SDL_Delay(delayTime);
}

后续待补充音视频同步到外部时钟的内容

参考

音频和视频同步ffplay5原理

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值