AVPacket 简介
AVPacket
是 FFmpeg 中的一个核心结构体,用于存储音频或视频数据的压缩数据包。它是 FFmpeg 的 libavcodec
模块的一部分,主要用于在解码和编码过程中传递数据。
1. AVPacket 的作用
-
存储压缩数据:
AVPacket
用于存储从输入文件或设备中读取的压缩数据(如 H.264 视频帧或 AAC 音频帧)。- 它包含了数据的指针、大小、时间戳等信息。
-
传递数据:
- 在解码过程中,
AVPacket
用于将压缩数据传递给解码器。 - 在编码过程中,
AVPacket
用于从编码器获取压缩数据。
- 在解码过程中,
-
时间戳管理:
AVPacket
包含pts
(显示时间戳)和dts
(解码时间戳),用于同步音视频。
-
内存管理:
AVPacket
的数据可以引用外部缓冲区,也可以由 FFmpeg 内部分配和管理。
2. AVPacket 的关键字段
以下是 AVPacket
的一些关键字段及其作用:
字段名 | 类型 | 作用 |
---|---|---|
data | uint8_t* | 指向数据缓冲区的指针,存储压缩的音频或视频数据。 |
size | int | 数据缓冲区的大小(以字节为单位)。 |
pts | int64_t | 显示时间戳(Presentation Timestamp),表示数据包的显示时间。 |
dts | int64_t | 解码时间戳(Decoding Timestamp),表示数据包的解码时间。 |
stream_index | int | 数据包所属的流的索引(如音频流或视频流)。 |
flags | int | 数据包的标志位(如关键帧标志)。 |
duration | int | 数据包的持续时间(以时间基为单位)。 |
pos | int64_t | 数据包在输入文件中的字节位置(如果可用)。 |
3. AVPacket 的常用函数
3.1 创建和释放 AVPacket
-
av_packet_alloc
:- 分配一个新的
AVPacket
。 - 示例:
AVPacket *packet = av_packet_alloc(); if (!packet) { printf("Failed to allocate AVPacket\n"); return -1; }
- 分配一个新的
-
av_packet_free
:- 释放
AVPacket
及其数据。 - 示例:
av_packet_free(&packet);
- 释放
3.2 初始化和重置 AVPacket
-
av_init_packet
:- 初始化一个
AVPacket
,将其字段设置为默认值。 - 示例:
AVPacket packet; av_init_packet(&packet);
- 初始化一个
-
av_packet_unref
:- 释放
AVPacket
的数据,但不释放AVPacket
本身。 - 示例:
av_packet_unref(&packet);
- 释放
3.3 数据管理
-
av_packet_ref
:- 创建一个新的
AVPacket
,引用现有数据。 - 示例:
AVPacket *new_packet = av_packet_alloc(); av_packet_ref(new_packet, packet);
- 创建一个新的
-
av_packet_move_ref
:- 将一个
AVPacket
的引用移动到另一个AVPacket
。 - 示例:
av_packet_move_ref(new_packet, packet);
- 将一个
4. 使用场景
4.1 解码音视频
在解码过程中,AVPacket
用于从输入文件或设备中读取压缩数据,并将其传递给解码器。
示例:
AVPacket packet;
while (av_read_frame(formatContext, &packet) >= 0) {
if (packet.stream_index == videoStreamIndex) {
avcodec_send_packet(codecContext, &packet);
}
av_packet_unref(&packet);
}
4.2 编码音视频
在编码过程中,AVPacket
用于从编码器中获取压缩数据,并将其写入输出文件。
示例:
AVPacket packet;
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;
while (avcodec_receive_packet(codecContext, &packet) == 0) {
av_write_frame(formatContext, &packet);
av_packet_unref(&packet);
}
5. 注意事项
-
内存管理:
- 使用
av_packet_alloc
分配的AVPacket
,需要使用av_packet_free
释放。 - 使用
av_packet_unref
释放数据,但不释放AVPacket
本身。
- 使用
-
时间戳管理:
- 确保正确设置
pts
和dts
,以避免音视频同步问题。
- 确保正确设置
-
多流处理:
- 使用
stream_index
字段区分数据包属于哪个流(如音频流或视频流)。
- 使用
-
数据引用:
- 使用
av_packet_ref
和av_packet_move_ref
时,注意数据的引用计数。
- 使用
6. 相关资源
- FFmpeg 官方文档 - AVPacket
- FFmpeg 示例代码 - 解码和编码
7. 总结
-
AVPacket
的作用:- 存储音频或视频的压缩数据包。
- 在解码和编码过程中传递数据。
-
常用函数:
- 创建和释放:
av_packet_alloc
、av_packet_free
。 - 初始化和重置:
av_init_packet
、av_packet_unref
。 - 数据管理:
av_packet_ref
、av_packet_move_ref
。
- 创建和释放:
-
使用场景:
- 解码:从输入源读取数据包并传递给解码器。
- 编码:从编码器获取数据包并写入输出文件。