AVFrame相关api内存管理

简介: AVFrame相关api内存管理

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

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);


释放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;
}



相关文章
|
6月前
|
存储 算法 关系型数据库
实时计算 Flink版产品使用合集之在Flink Stream API中,可以在任务启动时初始化一些静态的参数并将其存储在内存中吗
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
127 4
|
Unix 程序员 Linux
【OSTEP】动态内存开辟 | 内存API常见错误 | UNIX: brk/sbrk 系统调用 | mmap创建匿名映射区域 | mmap创建以文件为基础的映射区域
【OSTEP】动态内存开辟 | 内存API常见错误 | UNIX: brk/sbrk 系统调用 | mmap创建匿名映射区域 | mmap创建以文件为基础的映射区域
265 0
|
2月前
|
监控 Java 大数据
【Java内存管理新突破】JDK 22:细粒度内存管理API,精准控制每一块内存!
【9月更文挑战第9天】虽然目前JDK 22的确切内容尚未公布,但我们可以根据Java语言的发展趋势和社区的需求,预测细粒度内存管理API可能成为未来Java内存管理领域的新突破。这套API将为开发者提供前所未有的内存控制能力,助力Java应用在更多领域发挥更大作用。我们期待JDK 22的发布,期待Java语言在内存管理领域的持续创新和发展。
|
编解码 API
AVPacket相关api内存管理
AVPacket相关api内存管理
87 0
AVPacket相关api内存管理
AVFrame内存管理api
AVFrame内存管理api
81 0
|
缓存 安全 Unix
C/C++使用Windows的API实现共享内存以及同步
C/C++使用Windows的API实现共享内存以及同步
1523 0
|
弹性计算 API Python
云服务器配置选购指南——指定vCPU、内存的查询可用资源API实践
阿里云ECS机型众多,规格族及规格繁多。对于选购资源,我们主要关心云服务器的配置、带宽资源及地域节点信息。本文针对配置选购,教你怎么查询指定vCPU、内存的资源规格,重点介绍API查询指定vCpu及内存的可用的规格资源。
3345 0
|
SQL API Windows
Windows AWE API 内存分配和普通内存分配的不同点
以下观点可能和实际情况有点不符合,因为本人没有阅读过微软的内部文档,也找不到其他资料 只能根据现有的资料,推测,希望懂的人或者牛人能够指点。指出其中的问题,欢迎拍砖 普通内存分配方式:   图的左边,是普通内存分配方式。
480 0
|
存储 API 索引
11、Windows API 内存管理(1)
一、相关概念 1、内存主要储存程序运行时所需的机器代码、数据等内容。     内存的最小存储单元是字节,内存中的每一个字节都有一个地址。在32位系统上,使用32位的数来表示内存地址,因此一共可以表示232 (4294967296-4G)个字节。
827 0

热门文章

最新文章

下一篇
无影云桌面