当尝试获取 AVFrame
的时间戳时,有一个名为 best_effort_timestamp
的字段它描述为:
frame timestamp estimated using various heuristics, in stream time base
查看代码库,我可以看到计算此值的函数由 guess_correct_pts
给出.源代码如下:
static int64_t guess_correct_pts(AVCodecContext *ctx,
int64_t reordered_pts, int64_t dts)
{
int64_t pts = AV_NOPTS_VALUE;
if (dts != AV_NOPTS_VALUE) {
ctx->pts_correction_num_faulty_dts += dts <= ctx->pts_correction_last_dts;
ctx->pts_correction_last_dts = dts;
} else if (reordered_pts != AV_NOPTS_VALUE)
ctx->pts_correction_last_dts = reordered_pts;
if (reordered_pts != AV_NOPTS_VALUE) {
ctx->pts_correction_num_faulty_pts += reordered_pts <= ctx->pts_correction_last_pts;
ctx->pts_correction_last_pts = reordered_pts;
} else if(dts != AV_NOPTS_VALUE)
ctx->pts_correction_last_pts = dts;
if ((ctx->pts_correction_num_faulty_pts<=ctx->pts_correction_num_faulty_dts || dts == AV_NOPTS_VALUE)
&& reordered_pts != AV_NOPTS_VALUE)
pts = reordered_pts;
else
pts = dts;
return pts;
}
据我所知,每次调用此函数时,它都会通过查看是否小于或等于看到的值来确定 pts
或 dts
是否有问题最后一帧。然后它返回 pts
或 dts
,具体取决于总错误值较少的那个。
虽然代码看起来简单易懂,但它并没有真正解释为什么这些是必要的,也没有解释 best_effort_timestamp
不正确的常见情况。
我的主要问题是:
- 什么会导致视频有错误的
pts
或dts
值? - 视频的错误值是否很常见?
- 当存在错误值时,
best_effort_timestamp
可以有多不准确?我们是在谈论几毫秒还是可能很多秒?
最佳答案
似乎已添加代码以确保从可能仅包含 DTS 的容器中解复用的流的单调 PTS,并且流存储由于 B 帧而重新排序的帧。
参见 http://www.ffmpeg.org/pipermail/ffmpeg-devel/2011-January/108014.html进行相关讨论。这在当时是有争议的。
对于同时具有 PTS 和 DTS 的容器,它们通常在对数据包进行多路分解之前清理时间戳,因此尽力而为应该等于设置值。任何“校正”都应该在几帧间隔的数量级上。
关于video - 为什么 libavcodec 只能提供时间戳的估计值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57641774/