ffmpeg H264和AAC合成MP4时候需要手动写PTS

雷神muxer中手动写pts的部分很不理解。网上也找不到解释,研究半天,感觉理解的差不多了,特此记录。如果有误,请不吝赐教。

//FIX:No PTS (Example: Raw H.264)
//Simple Write PTS
if (pkt.pts == AV_NOPTS_VALUE) {
   //Write PTS
   AVRational time_base1 = in_stream->time_base;
   //Duration between 2 frames (us)
   int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(in_stream->r_frame_rate);
   //Parameters
   pkt.pts = (double)(frame_index*calc_duration) / (double)(av_q2d(time_base1)*AV_TIME_BASE);
   pkt.dts = pkt.pts;
   pkt.duration = (double)calc_duration / (double)(av_q2d(time_base1)*AV_TIME_BASE);
   frame_index++;
}

首先需要先对PTS/DPS有一定的了解
PTS/DPS相关一
PTS/DPS相关二
PTS/DPS相关三

我一开始的疑问是为什么要这样写,这样写的依据是什么。

首先理解:

真正的显示时间的意思是这一帧图像在视频中的显示时刻,设置fps=25,那么第一帧图像的第0s时刻显示,第二帧图像在第0.04s时刻显示,第三帧图像在第0.08s时刻显示。

pts和time_base是成对变化的
但是不管pts和time_base怎么变化,pts * av_q2d(time_base)的真正显示时间是不变的

timestamp(秒) = pts * av_q2d(time_base)
其中 timestamp(秒) 即为真正的显示时间。所以,
真正的显示时间(秒)= pts * av_q2d(time_base) 。所以,
pts = 真正的显示时间(秒)/av_q2d(time_base)

#define AV_TIME_BASE            1000000(us)

通过帧率可以计算真正的显示时间,此时的时间基是{1,AV_TIME_BASE}

假如裸H264流的帧率为25帧,即tbr=25。那么每得到一帧的图像就可以知道这帧图像的帧率时间基的真正的显示时间。第一帧真正的显示时间是1/25(秒)即pts = 4000,第二帧真正的显示时间是2/25(秒)即pts = 8000,第三帧真正的显示时间是3/25(秒)即 pts = 12000,等以此类推。
此时真正的显示时间的时间基是{1,AV_TIME_BASE},这样就可以计算时间基是{1,AV_TIME_BASE} 的pts。接着再转换成输入流的时间基即in_stream->time_base

将雷神的代码改成下边这样,思路更圆滑一些:

if (pkt.pts == AV_NOPTS_VALUE) {
	//内部时间基
	AVRational temp = {1,AV_TIME_BASE};
	//以内部时间基的一帧显示长度,in_duration 单位us
	double in_duration = (double) 1/ av_q2d(in_stream->r_frame_rate);
	//以{1,AV_TIME_BASE}为时间基的pts,
	//frame_index*in_duration真正的显示时间
	pFrame->pts = (double)(frame_index*in_duration)/av_q2d(temp);
	//从时间基{1,AV_TIME_BASE} 转换成 in_stream->time_base的时间基
	pFrame->pts = av_rescale_q_rnd(pFrame->pts , temp, in_stream->time_base,  (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
	frame_index++;
}
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值