了解视频帧中的 PTS 和 DTS [英] Understanding PTS and DTS in video frames

查看:33
本文介绍了了解视频帧中的 PTS 和 DTS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在从 avi 转码到 mp4(x264) 时遇到了 fps 问题.最终问题出在 PTS 和 DTS 值上,因此在 av_interleaved_write_frame 函数之前添加了第 12-15 行:

I had fps issues when transcoding from avi to mp4(x264). Eventually the problem was in PTS and DTS values, so lines 12-15 where added before av_interleaved_write_frame function:

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)

看了很多帖子还是不明白:

After reading many posts I still do not understand:

  1. 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 的情况下,为什么?
  2. outStream->codecoutStream 的 time_base 有什么区别?
  3. 计算 pts av_rescale_q 的作用是:取 2 个 time_base,将它们的分数乘以交叉,然后计算 pts.为什么会这样?在我调试时,encodedPacket.pts 的值增加了 1,那么如果它有值,为什么要更改它?
  4. 开始时 dts 值为 -2,每次重新缩放后它仍然是负数,但尽管如此,视频仍能正确播放!不应该是积极的吗?
  1. outStream->codec->time_base = 1/25 and outStream->time_base = 1/12800. The 1st one was set by me but I cannot figure out why and who set 12800? I noticed that before line (7) outStream->time_base = 1/90000 and right after it it changes to 1/12800, why? When I transcode from avi to avi, meaning changing the line (2) to avformat_alloc_output_context2(&outContainer, NULL, "avi", "c:\test.avi"; , so before and after line (7) outStream->time_base remains always 1/25 and not like in mp4 case, why?
  2. What is the difference between time_base of outStream->codec and outStream?
  3. To calc the pts av_rescale_q does: takes 2 time_base, multiplies their fractions in cross and then compute the pts. Why it does this in this way? As I debugged, the encodedPacket.pts has value incremental by 1, so why changing it if it does has value?
  4. At the beginning the dts value is -2 and after each rescaling it still has negative number, but despite this the video played correctly! Shouldn't it be positive?

推荐答案

  1. 时基只是一个测量单位.不同的单位可用于表示相同的时间(近似值,如果它们不是精确倍数).在某些情况下,容器格式需要特定的时基,并且由复用器设置为该时基.在其他情况下,容器不要求时基,但它有一个您可能必须覆盖的默认值.我不确定具体是 1/12800,我知道 1/600 是 mp4 规范中的一个特殊值.

  1. The time_base is just a unit of measurement. Different units may be used to represent the same times (approximately, if they are not exact multiples). In some cases a container format requires a certain time base and it will be set to that by the muxer. In other cases the container doesn't require a time base but it has a default that you might have to override. I'm not sure about 1/12800 specifically, I know 1/600 is a special value in mp4 spec.

这两个时基是编解码器和容器的时间测量单位.如果使用恒定 fps,编解码器的测量单位通常设置为每帧和下一帧之间的间隔(每帧显示的持续时间),因此帧时间是连续的整数.然而,它不必设置为 1/fps,只要 pts 时间在使用的任何单位中都是正确的.

The two time bases are the units of measurement of time for the codec and for the container. If using constant fps, the codec unit of measurement is commonly set to the interval between each frame and the next (the duration that each frame gets displayed), so that frame times are successive integers. It doesn't have to be set to 1/fps, however, as long as the pts times are correct in whatever units are used.

您所描述的只是将一个单位转换为另一个单位所需要做的事情.(即:乘以旧单位,除以新单位).以a/b为单位的时间t可以转换为c/d单位为t*(a*d)/(b*c)代码>.

What you describe is simply what one would have to do to convert from one unit to another. (ie: multiply by old unit, divide by new). A time t in units of a/b can be converted to units c/d as t*(a*d)/(b*c).

dts 序列可以从任何值开始,dts 0 没有特殊意义.播放开始时,计算挂钟时间与起始 dts 的差值,并将所有未来的 dts 转换为 wall时钟使用那个.dts=-10, -9, -8, ... 的视频流完全没问题.连续dts之间的差异是使用什么,绝对值无关紧要.

The dts sequence can start from any value, there is no special significance to dts 0. At start of playback, the difference between wall clock time and the starting dts is computed, and all future dts are converted to wall clock using that. A video stream with dts=-10, -9, -8, ... is perfectly ok. The difference between successive dts is what is used, the absolute values don't matter.

这篇关于了解视频帧中的 PTS 和 DTS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆