乐趣区

关于c:FFmpeg小点记AVPKTFLAGDISCARD

记录一下踩到的 AV_PKT_FLAG_DISCARD 一个坑。

背景

做一个 取帧 的性能,可能传入指定工夫,并获取该工夫点的帧。

实现步骤如下:

  1. 获取视频流的 duration
    因为局部格局的素材须要做适配,所以这里是通过取 pkt->pts + pkt->duration 的最大值来计算的。
  2. 依据 duration 做容错, 大于或等于 duration 时,就取 duration 工夫点的帧。
  3. 取帧的判断条件是:

    if (frame->pts <= clock && clock < frame->pts + frame->duration) {// 采纳的是左闭右开的形式 [pts, pts+duration) 取帧
    }

问题

看似都比拟失常,然而奇怪的事件呈现了,视频流的 duration6133 (即: {pkt->pts: 6100, pkt->duration: 33})
然而解码进去最初一帧 AVFramepts 却是 6067

这就导致了依照上述的取帧形式始终取不到工夫点为 大于 6100 的帧。

解决

经排查,发现在计算视频流 duration 的时候,最初一个 AVPacketflags 字段中蕴含了 AV_PKT_FLAG_DISCARD 标记。该标记的作用如下:

/**
 * Flag is used to discard packets which are required to maintain valid
 * decoder state but are not required for output and should be dropped
 * after decoding.
 **/
#define AV_PKT_FLAG_DISCARD   0x0004

大抵的意思能够简略的了解为: 带有该标记的 AVPacket 所携带的数据为解码器相干的信息,不会被解码出一幅图像。

起因找到了,计算 duration 的时候因为 AV_PKT_FLAG_DISCARD 标记的影响多计算了一帧的工夫,导致无奈获取到最初一帧。解决形式就是在计算 duration 的时候判断如果是该标记就跳过就好了。

退出移动版