目录
引子
AVPacket是ffmpeg基础且非常重要的数据结构,AVPacket存储着压缩数据(视频帧或者音频帧)及相关的描述信息,通常作为解封装器的输出,解码器的输入,是解封装和解码之间的桥梁。典型场景:比如播放一个本地mp4文件,通常的流程是解封装器解析mp4文件,输出一个一个的AVPacket,再根据AVPacket中存储的是视频还是音频(只能是一种视频或音频)送给对应的解码器解码。
翻译一下官方注释:
定义来自ffmpeg5.1,libavcodec\packet.h
AVPacket存储着压缩数据。典型使用场景:AVPacket被解封装器输出并作为解码器的输入,或作为编码器的输出传递给封装器做输入。
对于视频,一个AVPacket通常包含一个视频帧。对于音频,一个AVPacket通常包含几个完整的音频帧。编码器可能会输出空的AVPacket(指的是数据buf为空,但side data不为空,比如side data包含一些码流参数作为编码结束的标志)。
AVPacket包含的数据取决于成员变量buf(关于AVBufferRef的介绍请看前一篇文章:ffmpeg-AVBuffer、AVBufferRef、引用计数机制_小葫芦写代码的博客-CSDN博客)。如果成员变量buf被使用(就是不为NULL,该AVPacket包含的数据是存储在buf指向的AVBufferRef里),该AVPacket指向的数据一直有效直至其引用计数为0。如果buf没被使用(=NULL),该AVPacket包含的数据是成员变量data,当调用av_packet_ref时,会把原数据拷贝到成员变量data指向的地址。
/**
* This structure stores compressed data. It is typically exported by demuxers
* and then passed as input to decoders, or received as output from encoders and
* then passed to muxers.
*
* For video, it should typically contain one compressed frame. For audio it may
* contain several compressed frames. Encoders are allowed to output empty
* packets, with no compressed data, containing only side data
* (e.g. to update some stream parameters at the end of encoding).
*
* The semantics of data ownership depends on the buf field.
* If it is set, the packet data is dynamically allocated and is
* valid indefinitely until a call to av_packet_unref() reduces the
* reference count to 0.
*
* If the buf field is not set av_packet_ref() would make a copy instead
* of increasing the reference count.
*
* The side data is always allocated with av_malloc(), copied by
* av_packet_ref() and freed by av_packet_unref().
*
* sizeof(AVPacket) being a part of the public ABI is deprecated. once
* av_init_packet() is removed, new packets will only be able to be allocated
* with av_packet_alloc(), and new fields may be added to the end of the struct
* with a minor bump.
*
* @see av_packet_alloc
* @see av_packet_ref
* @see av_packet_unref
*/
typedef struct AVPacket {
/**
* A reference to the reference-counted buffer where the packet data is
* stored.
* May be NULL, then the packet data is not reference-counted.
*/
AVBufferRef *buf;
/**
* Presentation timestamp in AVStream->time_base units; the time at which
* the decompressed packet will be presented to the user.
* Can be AV_NOPTS_VALUE if it is not stored in the file.
* pts MUST be larger or equal to dts as presentation cannot happen before
* decompression, unless one wants to view hex dumps. Some formats misuse
* the terms dts and pts/cts to mean something different. Such timestamps
* must be converted to true pts/dts before they are stored in AVPacket.
*/
int64_t pts;
/**
* Decompression timestamp in AVStream->time_base units; the time at which
* the packet is decompressed.
* Can be AV_NOPTS_VALUE if it is not stored in the file.
*/
int64_t dts;
uint8_t *data;
int size;
int stream_index;
/**
* A combination of AV_PKT_FLAG values
*/
int flags;
/**
* Additional packet data that can be provided by the container.
* Packet can contain several types of side information.
*/
AVPacketSideData *side_data;
int side_data_elems;
/**
* Duration of this packet in AVStream->time_base units, 0 if unknown.
* Equals next_pts - this_pts in presentation order.
*/
int64_t duration;
int64_t pos; ///< byte position in stream, -1 if unknown
/**
* for some private data of the user
*/
void *opaque;
/**
* AVBufferRef for free use by the API user. FFmpeg will never check the
* contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when
* the packet is unreferenced. av_packet_copy_props() calls create a new
* reference with av_buffer_ref() for the target packet's opaque_ref field.
*
* This is unrelated to the opaque field, although it serves a similar
* purpose.
*/
AVBufferRef *opaque_ref;
/**
* Time base of the packet's timestamps.
* In the future, this field may be set on packets output by encoders or
* demuxers, but its value will be by default ignored on input to decoders
* or muxers.
*/
AVRational time_base;
} AVPacket;
成员变量:
AVBufferRef *buf
在上方官方注释已经解释过。
pts
显示时间戳,单位是AVStream->time_base,比如AVStream->time_base=0.001秒,pts=40,则packet要在0.001*40=0.04秒显示。用来描述该packet的显示时间,默认值是AV_NOPTS_VALUE(如果文件没有描述这个pts,会在av_init_packet中置为AV_NOPTS_VALUE)。pts必须大于等于dts,因为显示不可能在解码之前。
dts
解码时间戳,参考pts,描述该packet解码的时间。默认值AV_NOPTS_VALUE
data
参考AVBufferRef *buf的介绍和av_packet_ref的定义,如果该AVPacket指向的数据不使用引用计数,就使用data指针指向数据。
size
成员变量data使用时对应的data size。
stream_index
流id,可以通过id来区分是视频流、音频流、字幕流。
flag
描述该packet的属性,比如该packet的内容损坏/需要放弃等。
side_data
容器提供的用来描述该packet的辅助信息。
side_data_elems
side_data的数量。
duration
该packet的播放持续时间,和pts/dts的单位一样。比如duration=40,AVStream->time_base=0.001秒,则该packet的duration=40*0.001=0.04秒。通常duration=下一个packet的pts - 当前packet的pts。
pos
该packet在stream中的位置,单位byte
opaque
用户使用的私有数据。
opaque_ref
和上面的opaque成员没什么关系。看注释也没看明白,但是从ffmpeg源码里面看好像也没用到。
time_base
该packet使用的时间基。