一 源码

static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue) {
return stream_id < 0 ||
queue->abort_request ||
(st->disposition & AV_DISPOSITION_ATTACHED_PIC) ||
queue->nb_packets > MIN_FRAMES && (!queue->duration || av_q2d(st->time_base) * queue->duration > 1.0);
}

这是 ffplay.c 源码中的一个函数,用于校验是否有必要继续向缓冲区中添加 AVPacket 。可是 “道理我都懂”,但是,st->disposition & AV_DISPOSITION_ATTACHED_PIC 是个什么骚操作,为什么这个操作可以决定是否有必要继续向缓冲区中添加内容?

二 分析

1 找到一个带封面的MP3文件
2 还是乖乖使用 ffprobe 查看文件的 streams 和 packets 信息吧。

使用 ffprobe -show_streams -i quliulang.mp3 可以查看更详细的流信息

ffprobe -i quliulang.mp3

【FFmpeg小点记】AV_DISPOSITION_ATTACHED_PIC_json


可以看到,一个 *.mp3 文件也可以有 Video Stream 。是的,还可以看到它的 codec type 是 png 。

3 再查看 packets
ffprobe -show_packets -of json -i quliulang.mp3 > packets.json

【FFmpeg小点记】AV_DISPOSITION_ATTACHED_PIC_ide_02

三 分析结果

经过上述的分析,可以得到的结果是:AV_DISPOSITION_ATTACHED_PIC 是一个标志。如果一个流中含有这个标志的话,那么就是说这个流是 *.mp3 文件中的一个 Video Stream 。并且该流只有一个 AVPacket ,也就是 attached_pic 。这个 AVPacket 中所存储的内容就是这个 *.mp3 文件的封面图片。

因此,也可以很好的解释了文章开头提到的为什么 st->disposition & AV_DISPOSITION_ATTACHED_PIC 这个操作可以决定是否可以继续向缓冲区中添加 AVPacket 。这里可以回答,是因为,如果这个流中包含这个标志的话,说明这个流是 *.mp3 文件中的 Video Stream 。不是传统意义上的视频流。它只存放了封面信息,在播放或者导出时,不需要这个数据。因此我们可以使用这个标志很好的区分这个特殊的 Video Stream 。并且通过判断,屏蔽该流,不对其进行操作。