在FFmpeg中,AVPacket主要存储编码数据,例如:H264、H265、AAC等。对于视频流,它通常应该包含一个编码帧;对于音频流,则可能包含多个音频帧。编码器可能输出空AVPacket,不包含编码数据,只包含边side data,例如:在编码结束时更新一些流参数。
AVPacket结构体如下所示:
typedef struct AVPacket {
/**
* 若为空,则表示AVPacket未使用引用计数管理负载数据,否则指向存储负载数据的引用计数AVBufferRef -> AVBuffer
* 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;
/**
* 基于AVStream->time_base的pts,若文件中没有,则为AV_NOPTS_VALUE。
* pts必须大于等于dts,因为显示不能早于解码
*/
int64_t pts;
/**
* 基于AVStream->time_base的dts,若文件中没有,则为AV_NOPTS_VALUE。
*/
int64_t dts;
// 负载数据
uint8_t *data;
// 负载数据的长度
int size;
// 属于AVFormatContext中的哪个AVStream
int stream_index;
/**
* A combination of AV_PKT_FLAG values,AV_PKT_FLAG_KEY表示关键帧
*/
int flags;
/**
* Additional packet data that can be provided by the container.
* Packet can contain several types of side information.
* 携带的不同类型的side data
*/
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.
* 当前帧的持续时间,基于AVStream->time_base
*/
int64_t duration;
// byte position in stream, -1 if unknown
int64_t pos;
} AVPacket;
几个关键点:
- AVPacket的时间戳都是基于AVStream->time_base时间基准。
- dts是解码时间,pts是显示时间,pts必须大于等于dts,因为只有先解码,才能显示。
- AVPacket->buf决定了负载数据的管理方式,若为空,则表示AVPacket未使用引用计数管理负载数据,AVPacket->data就是负载数据;否则,则使用引用计数管理负载数据,AVPacket->buf引用AVBufferRef,AVBufferRef引用AVBuffer,AVBuffer存储了负载数据,关于引用计数下面 详细介绍。
side_data和side_data_elems
AVPacket->side_data是AVPacket携带的side数据数组