ffmpeg 问答系列-> mux 部分
author: hjjdebug
date: 2025年 08月 24日 星期日 09:47:08 CST
descrip: ffmpeg 问答系列-> mux 部分
文章目录
- 1. frame->pts 和 packet->pts 是什么关系?
- 2 问pts 和 dts, 哪一个时间戳是严格递增的?
- 3. av_interleaved_write_frame 的工作原理
mux 部分对frame 的pts, packet的pts, dts 要求十分严格,
这里对时间戳概念pts,dts进行一下辨析.
pts 是演播时间戳. dts 是解码时间戳. 时间戳的基准单位根据上下文可以自己设置.
frame中有时间戳pts,
packet中不仅有pts, 还有dts.
mpeg 音频frame 被编码为packet,
1. frame->pts 和 packet->pts 是什么关系?
一般是直接copy 的关系, 但也有可能差一个偏移.
对mpegaudio 而言, 其关系为:
参考代码: libavcodec/mpegaudioenc_template.c:773
if (frame->pts != AV_NOPTS_VALUE)
avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding)
其中avctx->initial_padding 是481, 所以pkt->pts 总是比frame->pts 小481
当frame->pts=0时, pkt->pts=-481
mpeg 视频frame 被编码为packet, packet有pts 和 dts,
2 问pts 和 dts, 哪一个时间戳是严格递增的?
首先frame->pts 是严格递增的,它就是frame的个数.
然后看一下实测结果. mpeg2 编码视频.
从实验中看出, pkt->dts 是严格递增的.
vframe->pts:0 第一个frame, 被缓存,编不出pkt
--
vframe->pts:1 第2个frame, 被缓存,编不出pkt
--
vframe->pts:2 第2个frame, 得pkt->pts=0, pkt->dts=-1
只所以有dts, 解码时间戳,或者说为什么引入dts概念, 就是要你按解码时间戳来解码, 它是严格递增的.
pts 由于有b帧的存在, 呈现小幅波动, 例如测试的编码例子为0,3,1,2,6,4,5,9... 像喝醉酒一样往上长!pkt before rescale, pts:0,dts:-1
--
vframe->pts:3
pkt before rescale, pts:3,dts:0
--
vframe->pts:4
pkt before rescale, pts:1,dts:1
--
vframe->pts:5
pkt before rescale, pts:2,dts:2
--
vframe->pts:6
pkt before rescale, pts:6,dts:3
--
vframe->pts:7
pkt before rescale, pts:4,dts:4
--
vframe->pts:8
pkt before rescale, pts:5,dts:5
--
vframe->pts:9
pkt before rescale, pts:9,dts:6
--
vframe->pts:10
pkt before rescale, pts:7,dts:7
--
vframe->pts:11
pkt before rescale, pts:8,dts:8
--
vframe->pts:12
pkt before rescale, pts:12,dts:9
3. av_interleaved_write_frame 的工作原理
ret = av_interleaved_write_frame(fmt_ctx, pkt);
- 检查并修正输入AVPacket的pts/dts
- 设置有pkt 的链表缓冲, 通过ff_interleave_packet_per_dts默认算法按解码时间戳(DTS)排序.
- 先缓存数据包,当时间戳满足连续性条件时批量写入. 例如音视频包都存在且满足连续性条件.开始写入.
- 由AVFormatContext->max_interleave_delta参数控制最大缓冲时长. 超过该容忍度强制写入.
里边内容还是挺多的, 可以调试源码获得第一手资料.