欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【FFMPEG】AVFrame中buffer分配的两种方式

程序员文章站 2022-07-01 23:25:09
...

AVFrame在使用ffmpeg进行编解码过程中,是最基本的数据结构。

在某些场景下,需要对AVFrame的数据区域进行提前分配,有两种方法,需要根据自己的需求来使用。

(1)

 * This function will fill AVFrame.data and AVFrame.buf arrays and, if
 * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf.

 * For planar formats, one buffer will be allocated for each plane.

int av_frame_get_buffer(AVFrame *frame, int align);

使用该接口分配到的数据空间,是可复用的,即内部有引用计数(reference),本次对frame data使用完成,可以解除引用,av_frame_unref(AVFrame *frame),调用后,引用计数减1,如果引用计数变为0,则释放data空间。

当然,也可以添加引用,接口:av_frame_ref(AVFrame *dst, const AVFrame *src)。

(2)

 * 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]).

int av_image_alloc(uint8_t *pointers[4], int linesizes[4], int w, int h, enum AVPixelFormat pix_fmt, int align);

如上接口,和(1)不同在于,(1)只要输入frame指针即可,而本接口看不到frame的数据结构,相比(1),分配的级别更低,看注释中“The allocated image buffer has to be freed by using  av_freep(&pointers[0])”,即,这种分配方式,不能用(2)中的解除引用来进行隐形释放了,需要自行调用释放才行。

注意使用过程中的坑:使用(1)进行分配后,调用ffmpeg某底层接口,结果,该接口对输入的frame做了一次解除引用,而外部调用并不知晓本次操作,从而导致可能的内存误释放,进而引起程序崩溃。

两个接口使用的代码示例:

  1. AVFrame *AllocFrame(enum AVPixelFormat format, int width, int height)
  2. {
  3. AVFrame *frame = av_frame_alloc();
  4. if (!frame) return NULL;
  5. frame->format = format;
  6. frame->width = width;
  7. frame->height = height;
  8. frame->pts = 0;
  9. int ret = av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, (enum AVPixelFormat)frame->format, 1);
  10. if (ret < 0)
  11. {
  12. av_frame_free(&frame);
  13. return NULL;
  14. }
  15. return frame;
  16. }
  1. AVFrame *AllocFrame(enum AVPixelFormat pix_fmt, int width, int height) {
  2.   AVFrame *frame;
  3.   int ret;
  4.   frame = av_frame_alloc();
  5.   if (!frame) return NULL;
  6.   frame->format = pix_fmt;
  7.   frame->width = width;
  8.   frame->height = height;
  9.   ret = av_frame_get_buffer(frame, 32);
  10.   if (ret < 0) {    
  11.   av_frame_free(&frame);   
  12.   return NULL;
  13.   }
  14.   return frame;
  15. }
https://blog.csdn.net/Blaze_bxh/article/details/80010857
相关标签: ffmpeg