FFmpeg AVPacket 剖析以及使用

文章目录函数说明
知识准备
:存储压缩数据(视频对应H.264等码流数据,音频对应AAC/MP3等码流数据),简单来说就是携带一个NAL视频单元,或者多个NAL音频单元 。保存一个NAL单元的解码前数据,该结构本身不直接包含数据,其有一个指向数据域的指针 。传递给函数的结构体data中的数据前面是00 00 00 01开头,说明是NALU格式的数据
重要结构体成员分析
AVBufferRef *buf; //当前AVPacket中压缩数据的引用计数,以及保存压缩数据的指针地址(压缩数据申请的空间在这里)uint8_t *data;//保存压缩数据的指针地址(data同时指向了buf中的data)intsize;//压缩数据的长度intstream_index;//视频还是音频的索引
实战(构建包含一个NAL单元(长度为nLen)的)
AVPacket pkt1, *packet= &pkt1;//nLen压缩数据长度av_new_packet(packet, nLen); //已经为packet->buf申请内存,而data和buf指向同一片内存memcpy(packet->data, data, nLen);packet->size = nLen;packet->stream_index = 0;
然后就可以将加入链表等待解码出一帧数据,或者调用2进行解码,解码之后,可以调用或者 释放资源
释疑
1)为什么不直接对->data申请内存,然后进行数据的拷贝?按结构体中定义说明 只是数据的引用计数,可以为NULL,代表没有任何的引用
所以上面的代码修改(不推荐):
av_init_packet(packet);//初始化结构体,尤其是AVBufferRef *buf,避免packet->data = http://www.kingceram.com/post/(uint8_t *)malloc(sizeof(uint8_t)* nByte);memcpy(packet->data, data, nLen);packet->size = nLen;packet->stream_index = 0;
注意:();//初始化结构体,尤其是 *buf,避免在解码的时候,访问到非法的指针地址 。
不推荐原因:无法使用或者 进行资源的释放,必须手动释放掉->data申请的内存,因为这两个函数释放资源针对的都是结构体中的buf,而不是data
void av_free_packet(AVPacket *pkt){if (pkt) {if (pkt->buf)av_buffer_unref(&pkt->buf);pkt->data= http://www.kingceram.com/post/NULL;pkt->size= 0;av_packet_free_side_data(pkt);}}void av_packet_unref(AVPacket *pkt){av_packet_free_side_data(pkt);av_buffer_unref(&pkt->buf);av_init_packet(pkt);pkt->data = http://www.kingceram.com/post/NULL;pkt->size = 0;}
2)为什么 里面中的data跟外层的data指针是一样的,但是size长度不一样
根据
int av_new_packet(AVPacket *pkt, int size){AVBufferRef *buf = NULL;int ret = packet_alloc(&buf, size);if (ret < 0)return ret;av_init_packet(pkt);pkt->buf= buf;pkt->data= http://www.kingceram.com/post/buf->data;pkt->size= size;return 0;}
可以得知两个data指针指向的是同一块内存,但是在申请内存的时候,进行了字节的对齐
多申请个字节的数据作为结尾的填充
函数说明
初始化和释放相关的函数
void ( * pkt)
void(**pkt)
* (void )
| void(** pkt )
void av_packet_free(AVPacket **pkt){if (!pkt || !*pkt)return;av_packet_unref(*pkt);av_freep(pkt);}
*(const*src);
int ( *dst, const*src);
data
int data( *dst, const*src);
void av_init_packet(AVPacket *pkt){pkt->pts= AV_NOPTS_VALUE;pkt->dts= AV_NOPTS_VALUE;pkt->pos= -1;pkt->duration= 0;#if FF_API_CONVERGENCE_DURATIONFF_DISABLE_DEPRECATION_WARNINGSpkt->convergence_duration = 0;FF_ENABLE_DEPRECATION_WARNINGS#endifpkt->flags= 0;pkt->stream_index= 0;pkt->buf= NULL;pkt->side_data= http://www.kingceram.com/post/NULL;pkt->side_data_elems= 0;}//AV_INPUT_BUFFER_PADDING_SIZE是为了进行数据的对齐,方便数据的访问static int packet_alloc(AVBufferRef **buf, int size){int ret;if (size