pts_dts解析

在ffmpeg中,经常看到avpriv_set_pts_info(st, 33, 1, 90000);用来设置AVStream的time_base。

void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)

但是,为什么pts_wrap_bits为33,pts_den为90000,我们并不知道原因。本文将详细讲解,为什么pts、dts的采样频率为90KHz。

ISO/IEC 13818-1标准或ITU-T H.222.0 标准都是指MPEG-2标准。

H.222标准中规定,系统时钟频率(system clock frequency)为27MHz。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x219wqNK-1613904470548)(system_clock_frequency.png)]

H.222标准中规定,PTS和DTS由33个bits来表示,time scale 为90000(system_clock_frequency/300)

pts_dts解析

pts_dts解析

pts_dts解析

pts_dts解析

对于PTS, t p n ( k ) = P T S ( k ) 90 K H z tp_n(k)=\frac {PTS(k)}{90KHz} tpn​(k)=90KHzPTS(k)​;PTS(k)是以系统时钟频率的300分频为单位的计数值, t p n ( k ) tp_n(k) tpn​(k)是以秒为单位的显示时间戳;

对于DTS, t d n ( k ) = D T S ( k ) 90 K H z td_n(k)=\frac {DTS(k)}{90KHz} tdn​(k)=90KHzDTS(k)​;DTS(k)是以系统时钟频率的300分频为单位的计数值, t d n ( k ) td_n(k) tdn​(k)是以秒为单位的解码时间戳;

这里可将 s y s t e m _ c l o c k _ f r e q u e n c y 300 \frac {system\_clock\_frequency}{300} 300system_clock_frequency​叫做time_scale。time_scale = 90000,time_base = 1/90000(s)

pts_dts解析

最后再梳理一下avpriv_set_pts_info

void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits,
                         unsigned int pts_num, unsigned int pts_den)
{
    AVRational new_tb;
    if (av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)) {
        if (new_tb.num != pts_num)
            av_log(NULL, AV_LOG_DEBUG,
                   "st:%d removing common factor %d from timebase\n",
                   s->index, pts_num / new_tb.num);
    } else
        av_log(NULL, AV_LOG_WARNING,
               "st:%d has too large timebase, reducing\n", s->index);

    if (new_tb.num <= 0 || new_tb.den <= 0) {
        av_log(NULL, AV_LOG_ERROR,
               "Ignoring attempt to set invalid timebase %d/%d for st:%d\n",
               new_tb.num, new_tb.den,
               s->index);
        return;
    }
    s->time_base     = new_tb; // 设置AVStream的时间基准
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
    s->codec->pkt_timebase = new_tb;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
    s->internal->avctx->pkt_timebase = new_tb; // 设置AVCodecContext的时间基准
    s->pts_wrap_bits = pts_wrap_bits; // 记录pts存储所需的位数,33bits
}

avpriv_set_pts_info(st, 33, 1, 90000);最终s->time_base = {1, 90000}。通过AVRational的num/den,即1/90000就可以非常容易的将pts转为pts_time。

总之,ffmpeg中所谓的time_base,time_scale不管它怎么变,本质上就是一个pts(dts)和pts_time(dts_time)转换的问题。

上一篇:linux 系统管理--进程管理


下一篇:Eclipse上Spring-tool的安装