• AVFrame相关api内存管理


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

    1. AVFrame frame
    2. ....伪代码设置frame相关参数...
    3. 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();
    

    给其结构体成员设置值

    1. frame->width = 1920;
    2. frame->height = 1080;
    3. frame->format = AV_PIX_FMT_YUV420P;

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

    1. //alloc inner memory
    2. av_frame_get_buffer(frame, 32);

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

    1. AVFrame* pcm = av_frame_alloc();
    2. pcm->format = outSampleFmt;//位深 16/32位
    3. pcm->channels = channels;
    4. pcm->channel_layout = av_get_default_channel_layout(channels);
    5. pcm->nb_samples = nbSample;//样本数
    6. 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都分配了内存空间,且都未用视频数据填充。

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

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

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

    使用举例:

    1. avpicture_fill((AVPicture *)frame, (const uint8_t *)ptr,
    2. (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填充数据,并未分配新的空间。

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

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

  • 相关阅读:
    数字信号处理及python实现(一)
    Korzh EasyQuery .Net for ASP.Net 7.2.X Crack
    8.7 迁移学习域适应
    前端面试的话术集锦第 19 篇博文——高频考点(HTTP/2 及 HTTP/3)
    使用ComposeDesktop开发一款桌面端多功能APK工具
    AUTOSAR基础篇之StbM
    vue项目查看vue版本-- 踩坑
    利用华为ENSP模拟器分析和配置中小型企业网络的综合实验(上)
    四种类型自编码器AutoEncoder理解及代码实现
    javascript的动态作用域和静态作用域
  • 原文地址:https://blog.csdn.net/m0_60259116/article/details/126252690