ffmpeg中的时间 DTS、PTS、AV_TIME_BASE、AV_TIME_BASE_Q 介绍

本文介绍了FFmpeg中视频流的时间戳概念,包括DTS(解码时间戳)和PTS(显示时间戳)的区别及作用,并详细阐述了ffmpeg内部时间单位AV_TIME_BASE与AV_TIME_BASE_Q的定义与使用方法。
摘要由CSDN通过智能技术生成

ffmpeg中的时间 DTS、PTS、AV_TIME_BASE、AV_TIME_BASE_Q等介绍 

         原文:http://www.cnblogs.com/yinxiangpei/articles/3892982.html   作者:裴银祥

         I,P,B帧和PTS,DTS的关系

目录 [hide]

视频的显示和存放原理

对于一个电影,帧是这样来显示的:I B B P。现在我们需要在显示B帧之前知道P帧中的信息。因此,帧可能会按照这样的方式来存储:IPBB。这就是为什么我们会有一个解码时间戳和一个显示时间戳的原因。解码时间戳告诉我们什么时候需要解码,显示时间戳告诉我们什么时候需要显示。所以,在这种情况下,我们的流可以是这样的:

PTS: 1 4 2 3
DTS: 1 2 3 4
Stream: I P B B

通常PTS和DTS只有在流中有B帧的时候会不同。

DTS和PTS

音频和视频流都有一些关于以多快速度和什么时间来播放它们的信息在里面。音频流有采样,视频流有每秒的帧率。然而,如果我们只是简单的通过数帧和乘以帧率的方式来同步视频,那么就很有可能会失去同步。于是作为一种补充,在流中的包有种叫做DTS(解码时间戳)和PTS(显示时间戳)的机制。为了这两个参数,你需要了解电影存放的方式。像MPEG等格式,使用被叫做B帧(B表示双向bidrectional)的方式。另外两种帧被叫做I帧和P帧(I表示关键帧,P表示预测帧)。I帧包含了某个特定的完整图像。P帧依赖于前面的I帧和P帧并且使用比较或者差分的方式来编码。B帧与P帧有点类似,但是它是依赖于前面和后面的帧的信息的。这也就解释了为什么我们可能在调用avcodec_decode_video以后会得不到一帧图像。

ffmpeg中的时间单位

AV_TIME_BASE

ffmpeg中的内部计时单位(时间基),ffmepg中的所有时间都是于它为一个单位,比如AVStream中的duration即以为着这个流的长度为duration个AV_TIME_BASE。AV_TIME_BASE定义为:

#define         AV_TIME_BASE   1000000

 

AV_TIME_BASE_Q

ffmpeg内部时间基的分数表示,实际上它是AV_TIME_BASE的倒数。从它的定义能很清楚的看到这点:

#define         AV_TIME_BASE_Q   (AVRational){1, AV_TIME_BASE}

 

AVRatioal的定义如下:

typedef struct AVRational{
int num; //numerator
int den; //denominator
} AVRational;

ffmpeg提供了一个把AVRatioal结构转换成double的函数:

复制代码
static inline double av_q2d(AVRational a){
/**
* Convert rational to double.
* @param a rational to convert
**/
    return a.num / (double) a.den;
}
复制代码

现在可以根据pts来计算一桢在整个视频中的时间位置:

timestamp(秒) = pts * av_q2d(st->time_base)
 

计算视频长度的方法:

time(秒) = st->duration * av_q2d(st->time_base)
 

这里的st是一个AVStream对象指针。

时间基转换公式

  • timestamp(ffmpeg内部时间戳) = AV_TIME_BASE * time(秒)
  • time(秒) = AV_TIME_BASE_Q * timestamp(ffmpeg内部时间戳)

所以当需要把视频跳转到N秒的时候可以使用下面的方法:

int64_t timestamp = N * AV_TIME_BASE; 
2
av_seek_frame(fmtctx, index_of_video, timestamp, AVSEEK_FLAG_BACKWARD);

ffmpeg同样为我们提供了不同时间基之间的转换函数:

int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)

这个函数的作用是计算a * bq / cq,来把时间戳从一个时基调整到另外一个时基。在进行时基转换的时候,我们应该首选这个函数,因为它可以避免溢出的情况发生。

AV_TIME_BASEFFmpeg定义的一个宏,它表示时间单位的基准。具体地说,它表示每秒钟的时间单位数。在FFmpeg时间单位被表示为有理数,即分子和分母的形式。AV_TIME_BASE的值为1000000,表示每秒钟有1000000个时间单位。 提到了不同的time_base。在FFmpeg,每个AVStream(音视频流)都有一个time_base字段,用于表示该流时间单位。AVStream的time_baseAVCodecContext的time_base字段有关。AVStream的time_baseAVCodecContext的time_base精度更高,即分子的值更小。例如,AVStream的time_base为1/90000,而AVCodecContext的time_base为1/30(假设frame_rate为30)。在相同的ptsdts情况下,以AVStream的time_base为单位的数值会比以AVCodecContext的time_base为单位的数值大。 因此,AV_TIME_BASE是一个重要的宏,用于在FFmpeg进行时间单位的换算和处理。了解AV_TIME_BASE的含义和使用方式对于阅读和理解FFmpeg的代码非常重要。 来源:ffmpeg存在多个时间基准(time_base),对应不同的阶段(结构体),每个time_base具体的值不一样,ffmpeg提供函数在各个time_base进行切换。搞清楚各个time_base的来源,对于阅读ffmpeg的代码很重要。 来源:InputStream(AV_TIME_BASE) 到 AVPacket(AVStream->time_base) 来源:AVStream->time_baseAVCodecContext->time_base 精度要高(数值要小),比如AVStream->time_base为1/90000,而AVCodecContext->time_base为1/30(假设frame_rate为30);同样的ptsdts,以AVStream->time_base为单位,数值要比以AVCodecContext->time_base为单位要大。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值