AVPacket 存储的是编码后的帧数据,它通常由 demuxer 输出,然后作为输入传递给 decoder,或者从 encoder 接收作为输出,然后传递给 muxer。
对于视频,它通常应该包含一个压缩帧。对于音频,它可能包含几个压缩帧。encoder 允许输出空数据包、不包含压缩数据、只包含 side data(例如,在编码结束时更新一些流参数)。
数据所有权的语义取决于 buf 字段。如果设置了该值,则动态分配 Packet 数据并无限期有效,直到对 av_packet_unref() 的调用将引用计数减少到 0。
如果没有设置 buf 字段,av_packet_ref() 将复制一个副本,而不是增加引用计数。
side data 总是由 av_malloc() 分配,由 av_packet_ref() 复制,由 av_packet_unref() 释放。
sizeof(AVPacket) 作为 public ABI 的一部分已被弃用。一旦 av_init_packet() 函数被移除,新的 Packet 将只能由 av_packet_alloc() 分配,新的字段可能会被添加到结构的末尾。
下面先学习 AVPacket,接着从 AVPacket 结构体引出 AVBufferRef 和 AVPacketSideData,最后又由 AVBufferRef 引出 AVBuffer,AVPacketSideData 引出 AVPacketSideDataType 枚举。
一、AVPacket
libavcodec/packet.h
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
#if FF_API_CONVERGENCE_DURATION
/**
* @deprecated Same as the duration field, but as int64_t. This was required
* for Matroska subtitles, whose duration values could overflow when the
* duration field was still an int.
*/
attribute_deprecated
int64_t convergence_duration;
#endif
} AVPacket;
下面是每个字段的含义。
字段 | 含义 |
---|---|
AVBufferRef * buf | 对存储 packet 数据的引用计数缓冲区的引用。 |
int64_t pts | 使用 AVStream->time_base 时间基显示的时间戳,将解包后的 packet 呈现给用户的时间。 |
int64_t dts | 使用 AVStream->time_base 时间基解包的时间戳,packet 被解包的时间。 |
uint8_t * data | packet 的实际数据 buffer。 |
int size | packet 实际数据的大小。 |
int stream_index | 流的 index。 |
int flags | AV_PKT_FLAG 值的组合。 |
AVPacketSideData * side_data | 容器可以提供的额外数据。 |
int side_data_elems | side_data 元数个数。 |
int64_t duration | 这个 packet 的持续时长以 AVStream->time_base 为单位,如果未知则为 0。 |
int64_t pos | 流中的字节位置,如果未知则为 -1。 |
以下是 AV_PKT_FLAG 可使用的组合值。
libavcodec/packet.h
#define AV_PKT_FLAG_KEY 0x0001 //关键帧
#define AV_PKT_FLAG_CORRUPT 0x0002 //损坏的数据
#define AV_PKT_FLAG_DISCARD 0x0004 //用于丢弃需要保持有效解码器状态但不需要输出的 packet,并且在解码后应该丢弃。
#define AV_PKT_FLAG_TRUSTED 0x0008 //packet 来自一个可信的来源。
#define AV_PKT_FLAG_DISPOSABLE 0x0010 //用来指示包含可以被解码器丢弃帧的 packet,即非引用帧。
二、 AVBufferRef
对数据缓冲区的引用。这个结构体的大小不是公共 ABI 的一部分,也不打算直接分配它。
libavutil/buffer.h
typedef struct AVBufferRef {
AVBuffer *buffer;
/**
* The data buffer. It is considered writable if and only if
* this is the only reference to the buffer, in which case
* av_buffer_is_writable() returns 1.
*/
uint8_t *data;
/**
* Size of data in bytes.
*/
#if FF_API_BUFFER_SIZE_T
int size;
#else
size_t size;
#endif
} AVBufferRef;
字段 | 含义 |
---|---|
AVBuffer *buffer | 一种引用计数缓冲区类型。它是不透明的,意味着要通过引用(AVBufferRef)使用。 |
uint8_t *data | 数据缓冲区。当且仅当这是对缓冲区的唯一引用时,才认为它是可写的,在这种情况下,av_buffer_is_writable() 返回 1。 |
size_t / int size | 以字节为单位的 data 大小。 |
三、AVBuffer
一种引用计数缓冲区类型。定义在 libavutil/buffer_internal.h 中。它是不透明的,意味着要通过引用(AVBufferRef)使用。
libavutil/buffer_internal.h
struct AVBuffer {
uint8_t *data; /**< data described by this buffer */
buffer_size_t size; /**< size of data in bytes */
/**
* number of existing AVBufferRef instances referring to this buffer
*/
atomic_uint refcount;
/**
* a callback for freeing the data
*/
void (*free)(void *opaque, uint8_t *data);
/**
* an opaque pointer, to be used by the freeing callback
*/
void *opaque;
/**
* A combination of AV_BUFFER_FLAG_*
*/
int flags;
/**
* A combination of BUFFER_FLAG_*
*/
int flags_internal;
};
字段 | 含义 |
---|---|
uint8_t *data | 由该缓冲区描述的数据。 |
buffer_size_t size | 以字节为单位的数据大小。 |
atomic_uint refcount | 引用此缓冲区的现有 AVBufferRef 实例的数目。 |
void (*free)(void *opaque, uint8_t *data) | 用于释放数据的回调。 |
void *opaque | 一个不透明的指针,由释放回调函数使用。 |
int flags | AV_BUFFER_FLAG_* 的组合。 |
int flags_internal | BUFFER_FLAG_* 的组合。 |
AVBuffer 是一个用于引用计数数据缓冲区的 API。
在这个 API 中有两个核心对象 AVBuffer 和 AVBufferRef。AVBuffer 表示数据缓冲区本身;它是不透明的,不能被调用者直接访问,只能通过 AVBufferRef 访问。然而,调用者可能会比较两个 AVBuffer 指针来检查两个不同的引用是否描述了同一个数据缓冲区。AVBufferRef 表示对 AVBuffer 的单个引用,它是可以被调用者直接操作的对象。
有两个函数可以用一个引用来创建新的 AVBuffer —— av_buffer_alloc() 用于分配一个新的缓冲区,av_buffer_create() 用于在 AVBuffer 中包装一个现有数组。从现有引用中,可以使用 av_buffer_ref() 创建其他引用。使用 av_buffer_unref() 释放一个引用(一旦释放了所有的引用,就会自动释放数据)。
这个 API 和 FFmpeg 的其余部分的约定是,如果只存在一个对缓冲区的引用(而且它没有被标记为只读),则认为缓冲区是可写的。提供了 av_buffer_is_writable() 函数来检查这是否为真,并且 av_buffer_make_writable() 将在必要时自动创建一个新的可写缓冲区。
当然,没有什么可以阻止调用代码违反这个约定,但是,只有当所有现有的引用都在它的控制之下时,这才是安全的。
引用和取消引用缓冲区是线程安全的,因此可以由多个线程同时使用,而不需要任何额外的锁。
对同一个缓冲区的两个不同的引用可以指向缓冲区的不同部分(例如,它们的 AVBufferRef.data 数据将不相等)。
四、AVPacketSideData
容器可以提供的额外 Packet 数据。Packet 可以包含几种类型的 side 信息。
libavcodec/packet.h
typedef struct AVPacketSideData {
uint8_t *data;
#if FF_API_BUFFER_SIZE_T
int size;
#else
size_t size;
#endif
enum AVPacketSideDataType type;
} AVPacketSideData;
字段 | 含义 |
---|---|
uint8_t *data | 数据缓存区。 |
int / size_t size | 以字节为单位的数据缓存区大小。 |
enum AVPacketSideDataType type | Packet side data 类型。 |
AVPacketSideDataType 枚举定义了各种 side data 类型。
libavcodec/packet.h
/**
* @defgroup lavc_packet AVPacket
*
* Types and functions for working with AVPacket.
* @{
*/
enum AVPacketSideDataType {
/**
* An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE
* bytes worth of palette. This side data signals that a new palette is
* present.
*/
AV_PKT_DATA_PALETTE,
/**
* The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format
* that the extradata buffer was changed and the receiving side should
* act upon it appropriately. The new extradata is embedded in the side
* data buffer and should be immediately used for processing the current
* frame or packet.
*/
AV_PKT_DATA_NEW_EXTRADATA,
/**
* An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows:
* @code
* u32le param_flags
* if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT)
* s32le channel_count
* if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT)
* u64le channel_layout
* if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE)
* s32le sample_rate
* if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS)
* s32le width
* s32le height
* @endcode
*/
AV_PKT_DATA_PARAM_CHANGE,
/**
* An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of
* structures with info about macroblocks relevant to splitting the
* packet into smaller packets on macroblock edges (e.g. as for RFC 2190).
* That is, it does not necessarily contain info about all macroblocks,
* as long as the distance between macroblocks in the info is smaller
* than the target payload size.
* Each MB info structure is 12 bytes, and is laid out as follows:
* @code
* u32le bit offset from the start of the packet
* u8 current quantizer at the start of the macroblock
* u8 GOB number
* u16le macroblock address within the GOB
* u8 horizontal MV predictor
* u8 vertical MV predictor
* u8 horizontal MV predictor for block number 3
* u8 vertical MV predictor for block number 3
* @endcode
*/
AV_PKT_DATA_H263_MB_INFO,
/**
* This side data should be associated with an audio stream and contains
* ReplayGain information in form of the AVReplayGain struct.
*/
AV_PKT_DATA_REPLAYGAIN,
/**
* This side data contains a 3x3 transformation matrix describing an affine
* transformation that needs to be applied to the decoded video frames for
* correct presentation.
*
* See libavutil/display.h for a detailed description of the data.
*/
AV_PKT_DATA_DISPLAYMATRIX,
/**
* This side data should be associated with a video stream and contains
* Stereoscopic 3D information in form of the AVStereo3D struct.
*/
AV_PKT_DATA_STEREO3D,
/**
* This side data should be associated with an audio stream and corresponds
* to enum AVAudioServiceType.
*/
AV_PKT_DATA_AUDIO_SERVICE_TYPE,
/**
* This side data contains quality related information from the encoder.
* @code
* u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad).
* u8 picture type
* u8 error count
* u16 reserved
* u64le[error count] sum of squared differences between encoder in and output
* @endcode
*/
AV_PKT_DATA_QUALITY_STATS,
/**
* This side data contains an integer value representing the stream index
* of a "fallback" track. A fallback track indicates an alternate
* track to use when the current track can not be decoded for some reason.
* e.g. no decoder available for codec.
*/
AV_PKT_DATA_FALLBACK_TRACK,
/**
* This side data corresponds to the AVCPBProperties struct.
*/
AV_PKT_DATA_CPB_PROPERTIES,
/**
* Recommmends skipping the specified number of samples
* @code
* u32le number of samples to skip from start of this packet
* u32le number of samples to skip from end of this packet
* u8 reason for start skip
* u8 reason for end skip (0=padding silence, 1=convergence)
* @endcode
*/
AV_PKT_DATA_SKIP_SAMPLES,
/**
* An AV_PKT_DATA_JP_DUALMONO side data packet indicates that
* the packet may contain "dual mono" audio specific to Japanese DTV
* and if it is true, recommends only the selected channel to be used.
* @code
* u8 selected channels (0=mail/left, 1=sub/right, 2=both)
* @endcode
*/
AV_PKT_DATA_JP_DUALMONO,
/**
* A list of zero terminated key/value strings. There is no end marker for
* the list, so it is required to rely on the side data size to stop.
*/
AV_PKT_DATA_STRINGS_METADATA,
/**
* Subtitle event position
* @code
* u32le x1
* u32le y1
* u32le x2
* u32le y2
* @endcode
*/
AV_PKT_DATA_SUBTITLE_POSITION,
/**
* Data found in BlockAdditional element of matroska container. There is
* no end marker for the data, so it is required to rely on the side data
* size to recognize the end. 8 byte id (as found in BlockAddId) followed
* by data.
*/
AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
/**
* The optional first identifier line of a WebVTT cue.
*/
AV_PKT_DATA_WEBVTT_IDENTIFIER,
/**
* The optional settings (rendering instructions) that immediately
* follow the timestamp specifier of a WebVTT cue.
*/
AV_PKT_DATA_WEBVTT_SETTINGS,
/**
* A list of zero terminated key/value strings. There is no end marker for
* the list, so it is required to rely on the side data size to stop. This
* side data includes updated metadata which appeared in the stream.
*/
AV_PKT_DATA_METADATA_UPDATE,
/**
* MPEGTS stream ID as uint8_t, this is required to pass the stream ID
* information from the demuxer to the corresponding muxer.
*/
AV_PKT_DATA_MPEGTS_STREAM_ID,
/**
* Mastering display metadata (based on SMPTE-2086:2014). This metadata
* should be associated with a video stream and contains data in the form
* of the AVMasteringDisplayMetadata struct.
*/
AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
/**
* This side data should be associated with a video stream and corresponds
* to the AVSphericalMapping structure.
*/
AV_PKT_DATA_SPHERICAL,
/**
* Content light level (based on CTA-861.3). This metadata should be
* associated with a video stream and contains data in the form of the
* AVContentLightMetadata struct.
*/
AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
/**
* ATSC A53 Part 4 Closed Captions. This metadata should be associated with
* a video stream. A53 CC bitstream is stored as uint8_t in AVPacketSideData.data.
* The number of bytes of CC data is AVPacketSideData.size.
*/
AV_PKT_DATA_A53_CC,
/**
* This side data is encryption initialization data.
* The format is not part of ABI, use av_encryption_init_info_* methods to
* access.
*/
AV_PKT_DATA_ENCRYPTION_INIT_INFO,
/**
* This side data contains encryption info for how to decrypt the packet.
* The format is not part of ABI, use av_encryption_info_* methods to access.
*/
AV_PKT_DATA_ENCRYPTION_INFO,
/**
* Active Format Description data consisting of a single byte as specified
* in ETSI TS 101 154 using AVActiveFormatDescription enum.
*/
AV_PKT_DATA_AFD,
/**
* Producer Reference Time data corresponding to the AVProducerReferenceTime struct,
* usually exported by some encoders (on demand through the prft flag set in the
* AVCodecContext export_side_data field).
*/
AV_PKT_DATA_PRFT,
/**
* ICC profile data consisting of an opaque octet buffer following the
* format described by ISO 15076-1.
*/
AV_PKT_DATA_ICC_PROFILE,
/**
* DOVI configuration
* ref:
* dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2.1.2, section 2.2
* dolby-vision-bitstreams-in-mpeg-2-transport-stream-multiplex-v1.2, section 3.3
* Tags are stored in struct AVDOVIDecoderConfigurationRecord.
*/
AV_PKT_DATA_DOVI_CONF,
/**
* Timecode which conforms to SMPTE ST 12-1:2014. The data is an array of 4 uint32_t
* where the first uint32_t describes how many (1-3) of the other timecodes are used.
* The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum()
* function in libavutil/timecode.h.
*/
AV_PKT_DATA_S12M_TIMECODE,
/**
* The number of side data types.
* This is not part of the public API/ABI in the sense that it may
* change when new side data types are added.
* This must stay the last enum value.
* If its value becomes huge, some code using it
* needs to be updated as it assumes it to be smaller than other limits.
*/
AV_PKT_DATA_NB
};
类型 | 含义 |
---|---|
AV_PKT_DATA_PALETTE | 调色板,数据大小由 AVPALETTE_SIZE 决定。 |
AV_PKT_DATA_NEW_EXTRADATA | 用于通知编解码器或格式 extradata 缓冲区已更改,并且接收方应对此采取适当措施。新的 extradata 被嵌入到 side data 缓冲区中,并且应该被立即用于处理当前 frame 或 packet。 |
AV_PKT_DATA_PARAM_CHANGE | 参数改变,布局受 AVSideDataParamChangeFlags 类型影响而不同。 |
AV_PKT_DATA_H263_MB_INFO | 包含了许多关于宏块信息的结构,这些信息与在宏块边缘将 packet 分割成更小的 packet 有关。 |
AV_PKT_DATA_REPLAYGAIN | 与音频流相关联,并以 AVReplayGain 结构体的形式包含重放增益(ReplayGain)信息。 |
AV_PKT_DATA_DISPLAYMATRIX | 包含一个 3x3 的变换矩阵,它描述了一个仿射变换,需要应用到解码后的视频帧上才能正确显示。 |
AV_PKT_DATA_STEREO3D | 与视频流相关联,并包含以 AVStereo3D 结构体形式呈现的立体 3D 信息。 |
AV_PKT_DATA_AUDIO_SERVICE_TYPE | 与一个音频流相关联,并且对应枚举类型 enum AVAudioServiceType。 |
AV_PKT_DATA_QUALITY_STATS | 包含来自编码器的质量相关信息。 |
AV_PKT_DATA_FALLBACK_TRACK | 包含一个整数值,表示“回退”轨道的流索引。 |
AV_PKT_DATA_CPB_PROPERTIES | 对应于 AVCPBProperties 结构体。 |
AV_PKT_DATA_SKIP_SAMPLES | 建议跳过指定的样本数量。 |
AV_PKT_DATA_JP_DUALMONO | 表明数据包可能包含特定于日本 DTV 的“dual mono”音频,如果它是真的,建议只使用选定的 channel。 |
AV_PKT_DATA_STRINGS_METADATA | 字符串键值对列表。 |
AV_PKT_DATA_SUBTITLE_POSITION | 副标题事件的位置。 |
AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL | 在 matroska 容器的 BlockAdditional 元素中找到的数据。 |
AV_PKT_DATA_WEBVTT_IDENTIFIER | WebVTT cue 的可选第一标识符行。 |
AV_PKT_DATA_WEBVTT_SETTINGS | WebVTT cue 的时间戳说明符之后的可选设置(呈现说明)。 |
AV_PKT_DATA_METADATA_UPDATE | 字符串键值对列表。包括出现在流中的更新元数据。 |
AV_PKT_DATA_MPEGTS_STREAM_ID | uint8_t 类型的 MPEGTS 流 ID,这需要从 demuxer 传递流 ID 信息到相应的 muxer。 |
AV_PKT_DATA_MASTERING_DISPLAY_METADATA | Mastering 显示元数据(基于SMPTE-2086:2014),该元数据应该与视频流相关联,并以 AVMasteringDisplayMetadata 结构体的形式存放数据。 |
AV_PKT_DATA_SPHERICAL | 与视频流相关联,并对应于 AVSphericalMapping 结构体。 |
AV_PKT_DATA_CONTENT_LIGHT_LEVEL | Content light 等级(基于CTA-861.3)。该元数据应该与视频流相关联,并以 AVContentLightMetadata 结构体的形式存放数据。 |
AV_PKT_DATA_A53_CC | ATSC A53 第 4 部分 Closed Captions(隐藏式字幕?)。 |
AV_PKT_DATA_ENCRYPTION_INIT_INFO | 加密初始化数据。 |
AV_PKT_DATA_ENCRYPTION_INFO | 包含如何解密 packet 的加密信息。 |
AV_PKT_DATA_AFD | Active Format Description 数据。描述在 ETSI TS 101 154 中使用 AVActiveFormatDescription 枚举指定的由单个字节组成的数据。 |
AV_PKT_DATA_PRFT | 生产者引用时间数据对应于 AVProducerReferenceTime 结构体,通常由一些编码器导出(通过在 AVCodecContext export_side_data 字段中设置 prft 标记)。 |
AV_PKT_DATA_ICC_PROFILE | 由 ISO 15076-1 描述的格式不透明的八位字节缓冲区组成的 ICC 配置文件数据。 |
AV_PKT_DATA_DOVI_CONF | DOVI 配置。 |
AV_PKT_DATA_S12M_TIMECODE | 符合 SMPTE ST 12-1:2014 的 Timecode。 |
AV_PKT_DATA_NB | side data 类型的数量。 |
参考资料: