前言:
本文介绍FFMPEG的AVPacket相关内容:
1. AVPacket在FFMPEG中用来保存Demux分离出来的压缩的ES流信息。
2. AVBufferRef表示AVBuffer的引用,和AVBuffer的关系是多个AVBufferRef对一个AVBuffer。
3. AVBuffer 实现引用计数,其参数refcount表示正在使用这个AVBuffer的AVBufferRef个数。
使用AVPacket时,通过调用av_buffer_alloc获得表示AVBufferRef的buf和AVBuffer,数据操作可在获得buf后读写pkt->data结构体实现,本文FFMPEG使用版本ffmpeg-4.2.2。
AVPacket,AVBufferRef,AVBuffer关系总结
关系图

引用层次关系可以简述为:AVPacket ->AVBufferRef->AVBuffer->refcount
总结


API解读
AVPacket *av_packet_alloc(void)
{
AVPacket *pkt = av_mallocz(sizeof(AVPacket));
if (!pkt)
return pkt;
/*
*1. 释放side_data,side_data类似extradata,比如保存ADTS的采样率,声道等信息。
在FFMPEG中用AVPacketSideDataType这个枚举类型来描述,Android的MetaData就是一种side_data。
封装在MP4,FLV,MKV中的H264,H265的SPS,PPS信息也存在于extradata中,push给解码器的时候,需要事先把这些Header加上。
此处av_freep(&pkt->side_data)时,用free或者_aligned_free函数释放了0地址。
GCC手册中描述,free的参数可以是0,也就是说free 0地址多次是可以的,什么动作也不会发生。但如果free的参数非calloc,malloc,realloc,则结果未定义。
*2. 如果AVBufferRef存在,则消灭他。
*3. 给AVPacket的成员赋初值
*/
av_packet_unref(pkt);
return pkt;
}
/* 带了size参数意味着可以生成AVBufferRef和AVBuffer */
int av_new_packet(AVPacket *pkt, int size)
{
AVBufferRef *buf = NULL;
/*
* 1. AVBufferRef为空时,流程同av_buffer_alloc,先创建data空间,再创建AVBuffer,最后创建AVBufferRef并返回。此时设置BUFFER_FLAG_REALLOCATABLE标记。
* 2. AVBufferRef不空时,调用av_buffer_realloc:
a.AVBuffer的flag不带有BUFFER_FLAG_REALLOCATABLE标记,或不能写(READONLY或者引用计数不是1),或者data指向与AVBufferRef不一致,则重新分配AVBufferRef并释放之前的AVBufferRef。
b.否则不用重新分配AVBufferRef,直接av_realloc(buf->buffer->data, size)。
*/
int ret = packet_alloc(&buf, size);
if (ret < 0)
return ret;
av_init_packet(pkt);
pkt->buf = buf;
pkt->data = buf->data;
pkt->size = size;
return 0;
}
/* 两个packet共享AVBuffer,但side data不共享 */
int av_packet_ref(AVPacket *dst, const AVPacket *src)
{
int ret;
/* 复制src的内容到dst,整这一出是为了深拷贝。
* 把src中side data全部拷贝到dst中去,而不是仅仅传个指针到dst。

本文详细介绍了FFmpeg中的AVPacket、AVBufferRef和AVBuffer之间的关系,包括数据操作、引用计数管理、内存分配与释放等,重点展示了如何使用这些数据结构进行流媒体数据处理。
最低0.47元/天 解锁文章
577





