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做了一次解除引用,而外部调用并不知晓本次操作,从而导致可能的内存误释放,进而引起程序崩溃。
两个接口使用的代码示例:
- AVFrame *AllocFrame(enum AVPixelFormat format, int width, int height)
- {
- AVFrame *frame = av_frame_alloc();
- if (!frame) return NULL;
- frame->format = format;
- frame->width = width;
- frame->height = height;
- frame->pts = 0;
- int ret = av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, (enum AVPixelFormat)frame->format, 1);
- if (ret < 0)
- {
- av_frame_free(&frame);
- return NULL;
- }
- return frame;
- }
https://blog.csdn.net/Blaze_bxh/article/details/80010857
- AVFrame *AllocFrame(enum AVPixelFormat pix_fmt, int width, int height) {
- AVFrame *frame;
- int ret;
- frame = av_frame_alloc();
- if (!frame) return NULL;
- frame->format = pix_fmt;
- frame->width = width;
- frame->height = height;
- ret = av_frame_get_buffer(frame, 32);
- if (ret < 0) {
- av_frame_free(&frame);
- return NULL;
- }
- return frame;
- }