记录一下踩到的 AV_PKT_FLAG_DISCARD
一个坑。
背景
做一个 取帧 的功能,能够传入指定时间,并获取该时间点的帧。
实现步骤如下:
- 获取视频流的
duration
。
由于部分格式的素材需要做适配,所以这里是通过取pkt->pts + pkt->duration
的最大值来计算的。 - 根据
duration
做容错,大于或等于duration
时,就取duration
时间点的帧。 -
取帧的判断条件是:
if (frame->pts <= clock && clock < frame->pts + frame->duration) { // 采用的是左闭右开的方式 [pts, pts+duration) 取帧 }
问题
看似都比较正常,但是奇怪的事情出现了,视频流的 duration
为 6133 (即: {pkt->pts: 6100, pkt->duration: 33})
。
但是解码出来最后一帧 AVFrame
的 pts
却是 6067
。
这就导致了按照上述的取帧方式始终取不到时间点为 大于6100
的帧。
解决
经排查,发现在计算视频流 duration
的时候,最后一个 AVPacket
的 flags
字段中包含了 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
的时候判断如果是该标志就跳过就好了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。