FFmpeg:AVPacket结构体分析

15 篇文章 16 订阅
12 篇文章 7 订阅

AVPacket

文档地址:传送门

在AVPacket结构体的说明部分:有这么一段描述,足够说明它的作用和重要性。

该结构存储压缩数据。 它通常由解复用器导出,然后作为输入传递给解码器,或作为编码器的输出接收,然后传递给复用器。

对于视频而言,它通常应包含一个压缩帧。 对于音频,它可能包含几个压缩帧。 允许编码器输出空包,没有压缩数据,只包含不重要的附加信息数据。例如在编码结束时更新一些流参数。

AVPacket是FFmpeg中为数不多的结构之一,其大小是公共ABI的一部分。 因此,它可以在栈上分配,并且不会添加新的字段,除非libavcodec和libavformat有大的改动。

虽然前面引用部分已经说了AVPacket的作用时机,但这里还是单独强调和总结一下:

  • 解码时:媒体源数据解封装(解复用)后,解码前。
  • 编码时:YUV数据编码后,封装前。

AVPacket主要保存一些媒体流的基本信息,例如PTS、DTS时间。最重要的当然就是媒体数据的buffer地址了。

比较重要的有:

  • pts:控制显示的pts时间
  • dts:控制解码的dts时间
  • *data:媒体数据buffer的指针
  • duration:AVStream-> time_base单位中此数据包的持续时间,如果未知则为0。 在演示顺序中等于next_pts - this_pts。

初始化与清理

AVPacket* avPacket = av_packet_alloc(); // 初始化
av_packet_unref(avPacket); // 清理

没什么稀奇,都是调用特定的函数来处理。这里需要提一下,虽然在第一小节提到,AVPacket是可以在栈内存上分配,也就是这样:AVPacket avPacket,但如非必要,我还是不建议这么做,毕竟有现成的API,就别给自己挖坑了。

还有一个函数:

int av_packet_ref (AVPacket *dst, const AVPacket *src)

它的作用是:

设置对给定数据包描述的数据的新引用。

如果src的data指针不为空,则将指针地址作为dst中data指针的值。 否则在dst中分配一个新缓冲区并将数据从src复制到其中。

所有其他字段都是从src复制的。

这个函数和av_packet_unref函数的作用刚好相反。我们详细了解一下这背后的故事:

我们在一开始有提到AVPacket保存了数据buffer的地址,所以,它实际上并没有包含数据内存本身,只是在它的字段中,用了一个uint8_t *data;来保存数据buffer的地址。

av_packet_ref函数的作用,就是从已有的AVPacket中复制一份出来。关于data部分,如果src的数据是引用计数的,直接把地址拷贝一份,然后把对应buffer的引用计数+1。如果不是,需要新分配一份保存数据的内存空间,并把src中的数据拷贝过来。

av_packet_unref函数,则会看buffer的引用计数器,如果不为0就-1,为零的话则会清楚掉buffer,AVPacket的其它数据也会回到初始状态。

结构定义及成员解读

typedef struct AVPacket {
    AVBufferRef *buf; // data的buffer引用指针计数结构体
    int64_t pts; // 控制显示的pts时间
    int64_t dts; // 控制解码的dts时间
    uint8_t *data; // 媒体数据buffer的指针
    int   size; // 数据大小
    int   stream_index; // 流index
    int   flags; // AV_PKT_FLAG值的组合
    AVPacketSideData *side_data; // 容器可以提供的附加数据包数据。 数据包可以包含几种类型的辅助信息。
		// AVStream-> time_base单位中此数据包的持续时间,如果未知则为0。 在演示顺序中等于next_pts  -  this_pts。
    int64_t duration;
    int64_t pos; // 流中的字节位置,如果未知则为-1
} AVPacket;

来扩展一下用来计数的结构体:

typedef struct AVBufferRef {
    AVBuffer *buffer;
    // 当且仅当这是对缓冲区的唯一引用时才被认为是可写的,在这种情况下av_buffer_is_writable()返回1。
    uint8_t *data;
    int      size; // 数据大小(以字节为单位)
} AVBufferRef;

这个结构体,保存了对数据缓冲区的引用。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值