FFMPEG4.1 - 时间戳相关的pts、dts与time_base

一、先说说time_base

1、time_base的定义:

time_base的意思是时间刻度,即给定一个时间,比如1秒,然后分成25等份,那么这个时间刻度就是1/25秒

2、time_base的结构体
/**
 * 分数 (分子与分母的组合).
 */
typedef struct AVRational{
    int num; ///< 分子
    int den; ///< 分母
} AVRational;
3、time_base的常用转换函数
// 创建一个time_base
static inline AVRational av_make_q(int num, int den)
{
    AVRational r = { num, den };
    return r;
}
// time_base转换为浮点数
static inline double av_q2d(AVRational a){
    return a.num / (double) a.den;
}
// 浮点数转换为time_base
AVRational av_d2q(double d, int max) av_const;
// time_base取反
static av_always_inline AVRational av_inv_q(AVRational q)
{
    AVRational r = { q.den, q.num };
    return r;
}
4、ffmpeg中常用的时间刻度
  • ffmpeg内部使用的时间刻度
// 表示为整数的内部使用的时间刻度
#define AV_TIME_BASE            1000000
// 表示为分数的内部使用的时间刻度
#define AV_TIME_BASE_Q          (AVRational){1, AV_TIME_BASE}
  • AVStream使用的时间刻度
	/**
	 * 这是表示帧时间戳的基本时间单位(秒)。
	 *
	 * 解码:由libavformat设置
	 * 编码:可以由调用方在avformat_write_header()之前设置,以便向编码器提供有关所需时基的提示。
	 * 在avformat_write_header()中,编码器将会重新估值,有可能变成更高的精度,如(1, 90000)。
	 */
    AVRational time_base;
  • AVCodecContext使用的时间刻度
    /**
     * 这是表示帧时间戳的基本时间单位(秒)。
     * 
     * 对于固定fps的视频帧,时间刻度为帧率取反,时间刻度的增量梯步为1。
     * 对非固定fps的视频帧,该时间刻度只表示平均值。
     * 
     * 解码:不建议使用,请使用framerate进行替代。
     * 编码:需要用户设置,一般为帧率取反。
     */
    AVRational time_base;

二、AVPacket与AVFrame的pts与dts

1、pts与dts的定义

pts是帧显示的时间戳,dts是帧解码的时间戳,所以dts<=pts,因为需要先解码才能显示。

2、AVPacket相关
    /**
     * 以AVStream->time_base为刻度的显示的时间戳; 
     * 如果文件中没有定义,那么就是AV_NOPTS_VALUE.
     * pts一定是大于等于dts的,因为显示不可能发生在解码之前. 
     * 在存储到文件中之前,必须以AVStream->time_base为刻度进行正确转换。
     */
    int64_t pts;
    /**
     * 以AVStream->time_base为刻度的解码的时间戳; 
     * 如果文件中没有定义,那么就是AV_NOPTS_VALUE.
     */
    int64_t dts;

PS:编码后,必须调用av_packet_rescale_ts进行pts与dts的转换,然后再写入文件。

3、AVFrame相关
    /**
     * 以AVCodecContext->time_base为时间刻度的显示的时间戳.
     */
    int64_t pts;

    /**
     * 从packet中拷贝来的pts
     */
    int64_t pkt_pts;

    /**
     * 从packet中拷贝来的dts
     */
    int64_t pkt_dts;

PS:解码后,必须调用av_rescale_q进行pts的转换成以AVCodecContext->time_base为基的正确的显示时间戳。

你可能感兴趣的:(CC++)