其他分享
首页 > 其他分享> > ffmpeg之-AVPacket解析(四)

ffmpeg之-AVPacket解析(四)

作者:互联网

前言

AVPacket是ffmpeg常用的结构体,位于libavcodec/avcodec.h中,它用于表示一帧压缩的视频或者多帧压缩的音频,使用了引用计数机制来管理内存

AVPacket结构体分析

如下为源码中关于AVPacket的描述(基于ffmpeg版本为4.2),已去掉注释部分

typedef struct AVPacket {
    AVBufferRef *buf;
    int64_t pts;
    int64_t dts;
    uint8_t *data;
    int   size;
    int   stream_index;
    int   flags;
    AVPacketSideData *side_data;
    int side_data_elems;
    int64_t duration;
    int64_t pos;                            ///< byte position in stream, -1 if unknown
    
#if FF_API_CONVERGENCE_DURATION
    attribute_deprecated
    int64_t convergence_duration;
#endif
} AVPacket;

如果用引用计数机制,那么AVPacket分配内存时是为buf分配的内存,然后将data指向这块内存的地址

AVPacket内存管理方式
这里主要是data的内存管理,手动管理和引用计数方式管理:

AVPacket常用相关函数

AVPacket是否可写:buf不为空,并且对应的flags非AV_BUFFER_FLAG_READONLY

首先判断是否可写,不可写则重新创建buf,并将data指向内存拷贝到buf中,将引用计数设置为1

tips:AVPacket对象如果由av_packet_free()等函数释放了,则不能调用此函数了,会奔溃

AVPacket基本使用示例

包括采用引用计数管理内存的使用方式和非引用计数管理内存的使用方式
1、AVPacket的使用方式一

//  ====== 正确的使用方式 一 ====== //
// 在堆内存创建AVPacket对象,初始化为默认值,data,buf,side_data等都为NULL,它内部会调用av_init_packet()方法
AVPacket *allocpkt = av_packet_alloc();

// 为buf分配内存,并且将data指向该内存,并且将引用计数设置为1
av_new_packet(allocpkt, 200);
// 引用计数减少1;如果引用计数为0,data内存将在此函数中释放,并且data和buf字段都置为NULL
..........
这里是伪代码。。。。举编码时的例子
内部会自动为allocpkt的buf分配内存,然后将编码后的数据存储到buf中并设置引用计数为1
avcodec_receive_packet(codecctx,allocpkt)
// 应用接受到编码后的allocpkt,处理完allocpkt的buf中数据
process(allocpkt->data)
// 调用一次,将引用计数-1;释放buf指向内存
av_packet_unref(allocpkt);
这里是伪代码。。。。。。
..........
// 由av_packet_alloc()创建的AVPacket最后还必须要用av_packet_free()来释放,调用此函数后allocpkt将置为NULL;
// 内部会调用一次av_packet_unref()
av_packet_free(&allocpkt);
//  ====== 正确的使用方式 一 ====== //

2、AVPacket的使用方式二

//  ====== 正确的使用方式 二 ====== //
// 栈内存创建AVPacket对象,按栈内存方式初始化AVPacket的值(所有的值)
AVPacket initpkt;
// 初始化AVPacket的值为默认值,data,buf,side_data等都为NULL
av_init_packet(&initpkt);
// 分配data内存,并将引用计数设置为1
av_new_packet(&initpkt, 100);
// 引用计数减少1;如果引用计数为0,data内存将在此函数中释放,并且data和buf字段都置为NULL
av_packet_unref(&initpkt);
// 由于AVPacket是创建在栈内,所以函数调用结束后,该对象占用内存会自动释放
//  ====== 正确的使用方式 二 ====== //

3、AVPacket的使用方式三

//  ====== 正确的使用方式 三 ====== //
AVPacket pkt;
av_init_packet(&initpkt);
pkt.data = (uint8_t*)av_malloc(300);
pkt.size = 200;

..........
这里是伪代码。。。。举解码时的例子
avcodec_send_packet(codecctx,&initpkt)
解码器不会对initpkt做任何处理
..........

// 解码器解码完成后,必须的手动释放内存
av_freep(pkt.data);
//  ====== 正确的使用方式 三 ====== //


from:https://www.jianshu.com/p/b0627f8ac018

 

标签:AVPacket,ffmpeg,data,packet,内存,av,解析,buf
来源: https://www.cnblogs.com/lidabo/p/15038736.html