FFMPEG 关于对时间戳转换的理解

转自:FFMPEG 关于对时间戳转换的理解

首先介绍转换函数:

av_rescale_q_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) 

此函数主要用于对于不同时间戳的转换。具体来说是将以 “时钟基c” 表示的 数值a 转换成以 “时钟基b” 来表示。

FFMPEG很多结构中有AVRationaltime_base;

这样的一个成员,它是AVRational结构的:

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

AVRational这个结构标识一个分数,num为分数,den为分母。

实际上time_base的意思就是时间的刻度:
如(1,25),那么时间刻度就是1/25 (1,9000),那么时间刻度就是1/90000 那么,在刻度为1/25的体系下的time=5,转换成在刻度为1/90000体系下的时间time为(5*1/25) / (1/90000) = 3600*5 = 18000,ffmpeg中做pts计算时,存在大量这种转换。

time_base在以下结构中都有:
AVCodecContext:编解码上下文。
AVStream:文件或其它容器中的某一条流。

如果由某个解码器产生固定帧率的码流 AVCodecContext中的AVRational根据帧率来设定,如25帧,那么num = 1,den=25。

AVStream中的time_base一般根据其采样频率设定,如(1,90000)

在某些场景下涉及到PTS的计算时,就涉及到两个Time的转换,以及到底取哪里的time_base进行转换:

场景1:
编码器产生的帧,直接存入某个容器的AVStream中,那么此时packet的Time要从AVCodecContext的time转换成目标AVStream的time

场景2:
从一种容器中demux出来的源AVStream的frame,存入另一个容器中某个目的AVStream。此时的时间刻度应该从源AVStream的time,转换成目的AVStream timebase下的时间。

其实,问题的关键还是要理解,不同的场景下取到的数据帧的time是相对哪个时间体系的。
demux出来的帧的time:是相对于AVStream的timebase
编码器出来的帧的time:是相对于AVCodecContext的timebase
mux存入文件等容器的time:是相对于目的AVStream的timebase 这里的time指pts。

转码时:
在解码之前需要进行如下转换:

packet.pts = av_rescale_q_rnd(
		packet.pts,
 		ic->streams[videoindex]->time_base,
 		ic->streams[videoindex]->codec->time_base,
 		(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)
); 

在编码后写到file之前需要进行如下转换:

pkt.pts = av_rescale_q_rnd(
		pkt.pts,
		oc->streams[videoindex]->codec->time_base,
		oc->streams[videoindex]->time_base,
		(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)
);
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值