[FFmpeg + OpenGL + OpenSL ES]音视频同步- 8

音视频同步实现理论

PTS和time_base

PTS即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。time_base即时间度量单位(时间基),可以类比:米、千克这种单位。

分别获取音频和视频的PTS(播放时间戳):

PTS = avFrame->pts * av_q2d(avStream->time_base);

获取音视频PTS差值,根据差值来设置视频的睡眠时间达到和音频的相对同步。视频快了就休眠久点,视频慢了就休眠少点,来达到同步。


在    Video.h     中声明一个    audio    成员变量和    clock    成员属性用来保存当前视频的时间戳    并且声明一个函数用来计算音频视频的差值

//音频对象
WlAudio *audio = NULL;

//时钟
double clock = 0;
double getFrameDiffTime(AVFrame *avFrame);

在    Video.cpp    中写方法声明

double WlVideo::getFrameDiffTime(AVFrame *avFrame) {
    //返回当前avFrame的显示时间戳
    double pts = av_frame_get_best_effort_timestamp(avFrame);
    if (pts == AV_NOPTS_VALUE) {
        pts = 0;
    }
    pts *= av_q2d(time_base);
    if (pts > 0) {
        clock = pts;
    }
    double diff = audio->clock - clock;
    return diff;
}

在    FFmpeg.cpp    中的    start    函数中将    audio    赋值给    video

//把video设置到视频当中
video->audio = audio;

在    video.cpp    渲染之前调用函数计算diff

double diff = video->getFrameDiffTime(avFrame);

根据音频和视频时间戳的差值增大或减小视频渲染的睡眠时长

在    video.h    中新建三个成员变量用来计算

//时钟
double clock = 0;

double delayTime = 0;

double defaultDelayTime = 0.004;

声明一个根据音视频时间戳差值  增大或减小视频渲染的睡眠时长的函数

 double getDelayTime(double diff);

在    video.cpp    写这个函数的实现

double WlVideo::getDelayTime(double diff) {
    if (diff > 0.003) {
        delayTime = delayTime * 2 / 3;
        if (delayTime < defaultDelayTime / 2) {
            delayTime = defaultDelayTime * 2 / 3;
        } else if (delayTime > defaultDelayTime * 2) {
            delayTime = defaultDelayTime * 2;
        }
    } else if (diff < -0.003) {
        delayTime = delayTime * 3 / 2;
        if (delayTime < defaultDelayTime / 2) {
            delayTime = defaultDelayTime * 2 / 3;
        } else if (delayTime > defaultDelayTime * 2) {
            delayTime = defaultDelayTime * 2;
        }
    } else if (diff == 0.003) {

    }
    if (diff >= 0.5) {
        delayTime = 0;
    } else if (diff <= 0.5) {
        delayTime = defaultDelayTime * 2;
    }
    if (fabs(diff) > 10) {
        //音频不存在
        delayTime = defaultDelayTime;
    }
    return delayTime;
}

在渲染下面调用

av_usleep(video->getDelayTime(diff) * 1000 * 1000);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值