为什么 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;
}

据我所知,每次调用此函数时,它都会通过查看 ptsdts 是否小于或等于上一帧所见来确定它是否有问题。然后它 returns ptsdts 取决于哪一个的总故障值较少。

虽然代码看起来很容易理解,但它并没有真正解释为什么这些是必要的,也没有解释 best_effort_timestamp 错误的常见程度。

我的主要问题是:

  1. 什么会导致视频有错误的 ptsdts 值?
  2. 视频有错误值是否很常见?
  3. 当存在错误值时,best_effort_timestamp 可以有多不准确?我们是在谈论几毫秒还是可能很多秒?

似乎已添加代码以确保从可能仅包含 DTS 的容器中解复用的流的单调 PTS,并且流存储由于 B 帧而重新排序的帧。

有关相关讨论,请参阅 http://www.ffmpeg.org/pipermail/ffmpeg-devel/2011-January/108014.html。当时是有争议的。

对于同时具有 PTS 和 DTS 的容器,它们通常会在解复用数据包之前清理时间戳,因此尽力而为应该等于设置值。任何 'correction' 应该在几帧间隔的数量级上。