美文网首页Android开发
ijkplayer 音视频同步时间的计算

ijkplayer 音视频同步时间的计算

作者: 知心大姐 | 来源:发表于2018-09-05 15:26 被阅读3次

从上一篇文章 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 的播放时间。

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

小结

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

相关文章

网友评论

    本文标题:ijkplayer 音视频同步时间的计算

    本文链接:https://www.haomeiwen.com/subject/vevawftx.html