注意:如果用栈的方式分配内存

AVFrame frame
....伪代码设置frame相关参数...
avcodec_receive_frame(decodec_ctx, &frame)

则会发生段错误,目前还没发现有AVPacket的api av_init_packet类似的函数来初始化AVFrame,并且如果存储视频的话1080i50,1s中就6M左右,而一个进程Linux分配的栈内存总共才8M,推荐使用堆方式如下:

构建AVFrame变量的api,其中av_frame_alloc显示申请结构体空间,然后对结构体变量进行初始化,设置默认值(后附源码)。

分配结构体空间

AVFrame* frame = av_frame_alloc();

给其结构体成员设置值

frame->width = 1920;
frame->height = 1080;
frame->format = AV_PIX_FMT_YUV420P;

//参数二传0即可,表示根据目前cpu类型自动选择对齐的字节数,音频里是0,视频必须是按32位补齐,这里是给结构体内部指向视频数据的指针分配空间,根据前面设置的三个参数分配合理的空间大小(只需配置这三个即可获得一帧视频大小)。

//alloc inner memory
av_frame_get_buffer(frame, 32);

对于音频来说需要设置位深,采样数和通道数,因为一帧音频的大小:(format/8) x channels x nb_samples。

AVFrame* pcm = av_frame_alloc();
pcm->format = outSampleFmt;//位深 16/32位
pcm->channels = channels;
pcm->channel_layout = av_get_default_channel_layout(channels);
pcm->nb_samples = nbSample;//样本数
ret = av_frame_get_buffer(pcm, 0);
 av_frame_unref(praw_frame);

本文福利, C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs)↓↓↓↓↓↓见下面↓↓文章底部点击领取↓↓

释放praw_frame空间,并重置它的各个参数,不建议每次avcodec_receive_frame后调用av_frame_unref,因为AVFrame中存储的视频或音频大小固定,每次释放后,再次调用avcodec_receive_frame,还需要为praw_frame分配内存。

另一篇文章,从编解码接口来看AVPacket和AVFrame的内存分配释放问题,avcodec_send_frame和avcodec_receive_packet

只处理视频的api:

(1)此api前两个参数都是输出参数,用来把给指针pointers申请指定格式的空间,它和av_frame_get_buffer都分配了内存空间,且都未用视频数据填充。

/*** Allocate an image with size w and h and pixel format pix_fmt, and* fill pointers and linesizes accordingly.* The allocated image buffer has to be freed by using* av_freep(&pointers[0]).** @param align the value to use for buffer size alignment* @return the size in bytes required for the image buffer, a negative* error code in case of failure*/
int av_image_alloc(uint8_t *pointers[4], int linesizes[4],
int w, int h, enum AVPixelFormat pix_fmt, int align);

(2)当你获得一个指针ptr,这个ptr中存储着一帧视频数据,想把他放到AVFrame中可以使用以下api。

/*** @deprecated use av_image_fill_arrays() instead.*/
attribute_deprecated
int avpicture_fill(AVPicture *picture, const uint8_t *ptr,enum AVPixelFormat pix_fmt, int width, int height);

使用举例:

avpicture_fill((AVPicture *)frame, (const uint8_t *)ptr,(enum AVPixelFormat)frame->format, in_width, in_height);

可以看出AVFrame类型的frame需要用AVPicture强制转换。

注意它并没有给frame->data分配内存空间,而是将frame->data与ptr指针关联起来,frame中的视频数据,是ptr所指向的内存中的视频数据,因此是浅拷贝。

(3)这个是上面api的升级版,使用场景相同。笔者为ffmpeg4.3,上面标注是弃用版,但不影响使用,也不会报提示。在源码中avpicture_fill()内部就是调用av_image_fill_arrays实现的,因此它也是浅拷贝,并没有给dst_data分配内存空间。

以下两个个api均是给存储视频的AVFrame填充数据,并未分配新的空间。

/*** Setup the data pointers and linesizes based on the specified image* parameters and the provided array.** The fields of the given image are filled in by using the src* address which points to the image data buffer. Depending on the* specified pixel format, one or multiple image data pointers and* line sizes will be set.  If a planar format is specified, several* pointers will be set pointing to the different picture planes and* the line sizes of the different planes will be stored in the* lines_sizes array. Call with src == NULL to get the required* size for the src buffer.** To allocate the buffer and fill in the dst_data and dst_linesize in* one call, use av_image_alloc().** @param dst_data      data pointers to be filled in* @param dst_linesize  linesizes for the image in dst_data to be filled in* @param src           buffer which will contain or contains the actual image data, can be NULL* @param pix_fmt       the pixel format of the image* @param width         the width of the image in pixels* @param height        the height of the image in pixels* @param align         the value used in src for linesize alignment* @return the size in bytes required for src, a negative error code* in case of failure*/
int av_image_fill_arrays(uint8_t *dst_data[4],
int dst_linesize[4],const uint8_t *src,
enum AVPixelFormat pix_fmt, int width, int height, int align);
AVFrame *av_frame_alloc(void)
{//申请一块AVFrame大小的内存AVFrame *frame = av_mallocz(sizeof(*frame));if (!frame)return NULL;frame->extended_data = NULL;//设置默认的值get_frame_defaults(frame);return frame;
}

本文福利, C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs)↓↓↓↓↓↓见下面↓↓文章底部点击领取↓↓

AVFrame相关api内存管理相关推荐

  1. copy与mutableCopy的内存管理剖析

    title: copy与mutableCopy的内存管理剖析 date: 2016-04-24 16:50:04 tags: copy copy与mutableCopy相关的内存管理 不知道为什么一说 ...

  2. linux堆内存管理

    堆内存的使用在linux开发过程中非常普遍,我们有必要了解相关的内存管理方便我们对内存问题的理解和定位. 堆内存结构层次 linux的堆内存管理分为三个层次,分别为分配区area.堆heap和内存块c ...

  3. LiteOS内存管理

    1.内存管理简介 内存管理模块管理系统的内存资源,它是操作系统的核心模块之一. 主要包括内存的初始化.分配以及释放. 在系统运行过程中,内存管理模块通过对内存的申请/释放操作,来管理用户和OS对内存的 ...

  4. malloc内存管理总结

    内存管理 内存管理主要包含两个层面的内容: 1.操作系统内核相关的内存管理:物理内存层 2.库函数层:主要是堆内存,即malloc实现层 如果用户还有需要会在用户层再做一次内存管理机制,例如SGI S ...

  5. Unity AssetBundle内存管理相关问题

    AssetBundle机制相关资料收集 最近网友通过网站搜索Unity3D在手机及其他平台下占用内存太大. 这里写下关于Unity3D对于内存的管理与优化. Unity3D 里有两种动态加载机制:一个 ...

  6. Linux kernel内存管理之OOM相关参数

    一.OOM概念 OOM是Out Of Memory(内存溢出)的缩写,虽然linux kernel的内存管理有很多机制(从cache中回收.swap out等)可以满足用户空间的各种虚拟内存需求,但是 ...

  7. linux netstat Netstat是在内核中访问网络连接状态及其相关信息的程序,它能提供TCP连接,TCP和UDP监听,进程内存管理的相关报告。

    在Internet RFC标准中,Netstat的定义是: Netstat是在内核中访问网络连接状态及其相关信息的程序,它能提供TCP连接,TCP和UDP监听,进程内存管理的相关报告. Netstat ...

  8. Linux内存管理之slab 2:slab API

    Linux内存管理之slab 2:slab API 0. 前沿/须知: 1. kmem_cache_create 1.1 kmem_cache_create (仅分配一个kmem_cache实例)未分 ...

  9. linux-glibc内存管理小结2(内存相关系统调用的实现)

    在上一节ptmalloc源码分析中我们提到dlmalloc向系统申请内存的方式有两种, 对应Linux系统下分别是sbrk()与mmap()系统调用. 本节我们就来看下brk()/sbrk()与mma ...

最新文章

  1. pwm调制 matlab仿真,PWM脉冲调制直流电机的simulink仿真
  2. Visual Studio 2015上安装Entity Framework Power Tools
  3. 提升领导力 六商是基础
  4. SDUT - 2604 Thrall’s Dream(tarjan+拓扑)
  5. 计算机基本网络测试命令实验报告,实验三 基本网络测试工具的使用
  6. gRPC in ASP.NET Core 3.x -- Protocol Buffer, Go语言的例子(上)
  7. [C++STL]C++实现stack容器适配器
  8. 怀念一下过去的人和事
  9. CDateTimeUI类源码分析
  10. Jmeter 2.6下载安装
  11. 动态规划经典问题:背包问题
  12. python实现mysql的读写分离及负载均衡
  13. 蚂蚁金服招聘-高级数据技术工程师、大数据研发工程师/专家
  14. 软件测试高频面试题真实分享/网上银行转账是怎么测的,设计一下测试用例。
  15. Ubuntu安装OpenCV
  16. 小说APP源码的图片加载方式,懒加载和预加载的实现
  17. 2022搜狐校园 情感分析 × 推荐排序 算法大赛
  18. 沙箱-简单实现支付宝网页支付功能
  19. 三维动画在计算机上的应用,计算机图技术在三维动画中的应用.doc
  20. 网站地图怎么做?dedecms网站地图制作方法

热门文章

  1. Mysql数据库管理工具简介
  2. Flink系列文档-(YY05)-Flink编程API-多流算子
  3. UUID 通用唯一识别码(Universally Unique Identifier)介绍
  4. linux添加五笔输入法,Linux学习笔记(三)Centos 安装五笔输入法
  5. 统计学习方法 学习笔记(1)统计学习方法及监督学习理论
  6. 关于统计学的一些思考(一)
  7. jenkins中使用脚本来节省资源空间和使用shell提取文件名或目录名的方法
  8. discuz帖子最后编辑时间如何取消显示
  9. 【编程不良人】快速入门Spring学习笔记08---事务属性、Spring整合Structs2框架(SM)、Spring整合Mybatis+Struts2(SSM)、Spring注解、SSM注解式开发
  10. 基于光栅波导结构的 R ARMR 系统的 建模