ijkplayer 音视频同步时间的计算

作者: 土豆, 时间: 2018.6 .18



从上一篇文章 ijkplayer音视频同步流程分析 中对Ijkplayer的音视频同步有所了解之后,那么 这个音视频的时间是怎么计算的呢?

首先得理解ipb 帧的概念,可以阅读这篇文章 An ffmpeg and SDL Tutorial

其次就是 AVRational 这个结构体了, ijkplayer 源码中的很多结构体中都有这个成员,比如 AVStreamAVPacket 等等。

AVRational 的定义如下:

typedef struct AVRational{
    int num; //numerator
    int den; //denominator
} AVRational;复制代码

从代码中得知得到某一帧的播放时间的计算方式是

pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb)复制代码

av_q2d 方法如下

static inline double av_q2d(AVRational a){
    return a.num / (double) a.den;
}复制代码

视频

对于 视频的frame 而言属性 pts 就是当前这一帧的位置,假如一个视频的帧率是25的话,那么 tb 就是 AVRational{1, 25},所以根据上面的计算方式,可以得出每个视频帧是以0.04s 递增的。

那每一帧的 pts 是怎么来的,从代码中可以看出来,每读一个 AVPacket 的时候都要从 AVIOContext 解析 chunks 那 pts 就是从中得到的,然后在解码后赋值给 frame。

static int read_packet(AVFormatContext *s, AVPacket *pkt)
{
    WtvContext *wtv = s->priv_data;
    AVIOContext *pb = wtv->pb;
    int stream_index, len, ret;
​
    // 解析chunks
    stream_index = parse_chunks(s, SEEK_TO_DATA, 0, &len);
    if (stream_index < 0)
        return stream_index;
​
    ret = av_get_packet(pb, pkt, len - 32);
    if (ret < 0)
        return ret;
    pkt->stream_index = stream_index;
    //从解析中得到的pts 赋值给 avpacket 的 pts
    pkt->pts          = wtv->pts;
    avio_skip(pb, WTV_PAD8(len) - len);
    return 0;
}复制代码

在H.264 的编码过程中,每一帧都会有一个pts的写入,再编码成 AVPacket。这个可以从 ffmpeg 的编码 sample 中看到,在doc/example/decoding_encoding.c 文件中。

音频

音频和视频有点不一样,本身音频是没有pts 这个概念的,但是为了适应和视频的同步的计算,还是得有一个播放时间。假如说音频的采样率是44.1K,表示的意思是一秒有44.1K的采样。在解码后的 AVFrame 中可以得到一个参数叫 nb_samples 表示当前音频帧几个采样,再累加起来,那么就可以知道当前这一个AVFrame 的播放时间。

当然这只是我的理解,如果有有误,请提示。

小结

所以音视频同步时间的计算,就是视频时间对音频时间在一定的区间内的追赶、延迟或者跳帧。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值