为什么 libavcodec 只能提供时间戳的估计值?
Why is libavcodec only able to provide an estimate of the timestamp?
当试图获取 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
是否小于或等于上一帧所见来确定它是否有问题。然后它 returns 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 的容器,它们通常会在解复用数据包之前清理时间戳,因此尽力而为应该等于设置值。任何 'correction' 应该在几帧间隔的数量级上。
当试图获取 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
是否小于或等于上一帧所见来确定它是否有问题。然后它 returns 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 的容器,它们通常会在解复用数据包之前清理时间戳,因此尽力而为应该等于设置值。任何 'correction' 应该在几帧间隔的数量级上。