音视频-帧、DTS、PTS
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了音视频-帧、DTS、PTS相关的知识,希望对你有一定的参考价值。
参考技术A I帧 :帧内编码帧,不依赖前后帧P帧 :帧间预测编码帧,需参考前面的I帧才能进行编码。表示当前帧与前一个I帧或者P帧的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。
B帧 :双向预测编码帧,记录的是本帧与前后帧的差别。解码时不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面与本帧数据的叠加取得最终画面。
I帧只考虑本帧;P帧记录与前一帧(前一个I帧或者P帧)的差别;B帧记录的是前一帧及后一帧的差别
音视频同步,通常需要选择一个参考时钟,参考时钟上的时间是线性递增的,编码音视频流时依据参考时钟上的时间给每一帧数据打上时间戳。播放时,读取数据帧上的时间戳,同时参考当前参考时钟上的时间来安排播放。
了解视频帧中的 PTS 和 DTS
【中文标题】了解视频帧中的 PTS 和 DTS【英文标题】:Understanding PTS and DTS in video frames 【发布时间】:2012-11-15 17:26:17 【问题描述】:从 avi 转码为 mp4(x264) 时出现 fps 问题。最终问题出在 PTS 和 DTS 值中,因此在 av_interleaved_write_frame 函数之前添加了第 12-15 行:
1. AVFormatContext* outContainer = NULL;
2. avformat_alloc_output_context2(&outContainer, NULL, "mp4", "c:\\test.mp4";
3. AVCodec *encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
4. AVStream *outStream = avformat_new_stream(outContainer, encoder);
5. // outStream->codec initiation
6. // ...
7. avformat_write_header(outContainer, NULL);
8. // reading and decoding packet
9. // ...
10. avcodec_encode_video2(outStream->codec, &encodedPacket, decodedFrame, &got_frame)
11.
12. if (encodedPacket.pts != AV_NOPTS_VALUE)
13. encodedPacket.pts = av_rescale_q(encodedPacket.pts, outStream->codec->time_base, outStream->time_base);
14. if (encodedPacket.dts != AV_NOPTS_VALUE)
15. encodedPacket.dts = av_rescale_q(encodedPacket.dts, outStream->codec->time_base, outStream->time_base);
16.
17. av_interleaved_write_frame(outContainer, &encodedPacket)
看了很多帖子还是不明白:
outStream->codec->time_base
= 1/25 和 outStream->time_base
= 1/12800。第一个是我设置的,但我不知道为什么以及谁设置了 12800?我注意到在第 (7) 行之前 outStream->time_base
= 1/90000 并且在它更改为 1/12800 之后,为什么?
当我从 avi 转码为 avi 时,意味着将第 (2) 行更改为 avformat_alloc_output_context2(&outContainer, NULL, "avi", "c:\\test.avi";
,因此第 (7) 行之前和之后 outStream->time_base
始终保持 1/25,而不像在 mp4 情况下那样,为什么?
outStream->codec
和outStream
的time_base有什么区别?
计算 pts av_rescale_q
的方法是:使用 2 个 time_base,将它们的分数相乘,然后计算 pts。为什么会这样?正如我调试的那样,encodedPacket.pts
的值递增了 1,那么如果它确实有值,为什么要更改它呢?
一开始 dts 的值为 -2,每次重新缩放后仍为负数,但尽管如此,视频仍能正常播放!不应该是积极的吗?
【问题讨论】:
【参考方案1】:时基只是一个单位的度量。可以使用不同的单位来表示相同的时间(如果它们不是精确的倍数,则为近似值)。在某些情况下,容器格式需要特定的时基,并且将由复用器设置为该时基。在其他情况下,容器不需要时基,但它具有您可能必须覆盖的默认值。我不确定具体是 1/12800,我知道 1/600 是 mp4 规范中的一个特殊值。
这两个时基是编解码器和容器的时间测量单位。如果使用恒定 fps,则编解码器的测量单位通常设置为每帧和下一帧之间的间隔(每帧显示的持续时间),因此帧时间是连续的整数。但是,它不必设置为 1/fps,只要 pts 时间在使用的任何单位中都是正确的。
您所描述的只是从一种单位转换为另一种单位所需要做的事情。 (即:乘以旧单位,除以新单位)。以a/b
为单位的时间t 可以转换为c/d
单位为t*(a*d)/(b*c)
。
dts 序列可以从任意值开始,dts 0 没有特殊意义。播放开始时,计算挂钟时间与开始 dts 的差值,并将所有未来的 dts 转换为 wall使用它的时钟。 dts=-10, -9, -8, ... 的视频流完全可以。连续dts之间的区别是使用什么,绝对值无关紧要。
【讨论】:
对不起,我没有看到你的答案。第二段没看懂。 “一帧的持续时间”是什么意思?如果我使用 25 fps,那么 pts 的间隔将是 40 (1/25)? @theateist:一帧的持续时间是 1 秒 / fps(将帧之间的间隔称为可能更清楚,但这也是一帧应该显示多长时间的持续时间)。所以在 25fps 时,它是 0.040 秒。如果时基设置为 1/25 并且您的流是 25fps,那么帧时间(时基单位中的点)将只是 1、2、3、... 我认为时基决定了 fps,我的意思是如果时基是 1/25 那么 fps 是 25,如果时基是 1/40 那么 fps 是 40,不是吗? @theateist:时基和 fps 是独立的,但有些相关。您可以有 fps 25 和时基(例如)1/1000。然后连续帧的时间间隔为 (1/25) / (1/1000) = 40 个时基单位。如果两者不能相互整除,则帧时间必须是近似的/四舍五入的。这就是为什么习惯选择(例如)时基 30/1001 来获得 29.97 fps 的原因。时基是时间测量的单位,习惯上选择一个简单的分数单位,它要么等于 1/fps,要么是 1/fps 的整数部分。 P.S.这也是传输流具有 1/90000 或 1/27000000 时基的原因:这些单位足够小,所有常见的 fps 几乎都可以精确表示,最常见的 fps(25、24、30)是精确的。以上是关于音视频-帧、DTS、PTS的主要内容,如果未能解决你的问题,请参考以下文章
视频压缩编码 gop(Group of Pictures)(I帧间隔)的概念IDRI帧(关键帧,intra picture)P帧B帧帧内压缩帧间压缩pts(显示时间)dts(解码时间)