Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cleaning up after av_frame_get_buffer

Tags:

c++

ffmpeg

libav

There are two aspects of my question. I'm using libav, ffmpeg, 3.1.


First, how do you appropriately dispose of a frame whose buffer has been allocated with av_frame_get_buffer? E.g.:

AVFrame *frame = av_frame_alloc();
frame->width = ...;
frame->height = ...;
frame->format = ...;
av_frame_get_buffer(frame, ...);

Do any buffers have to be freed manually, beyond the call to av_frame_free(frame)? The documentation doesn't mention anything special, but in my experience the ffmpeg documentation often leaves out important details, or at least hides them in places far away from the obvious spots. I took a look at the code for av_frame_free and av_frame_unref but it branched out quite a bit and I couldn't quite determine if it covered everything.


Second, if something beyond av_frame_free needs to be done, then is there any catch-all way to clean up a frame if you don't know how its data has been allocated? For example, assuming someBuffer is already allocated with the appropriate size:

AVFrame *frame2 = av_frame_alloc();
frame2->width = ...;
frame2->height = ...;
frame2->format = ...;
av_image_fill_arrays(frame2->data, frame2->linesize, someBuffer, 
                     frame2->format, frame2->width, frame2->height, 1);

Is there a way to free both frame and frame2 in the above examples using the exact same code? That is frame and its data should be freed, and frame2 should be freed, but not someBuffer, since libav did not allocate it.

like image 916
Jason C Avatar asked Nov 03 '16 22:11

Jason C


1 Answers

To answer your first question - you don't need to do anything special to free buffers unless you are doing something funky (which you shouldn't). Image data is owned by AVBuffer which includes a reference counter; there are some references to that AVBuffer in a form of AVBufferRef. You can deal with AVBufferRef instances using relevant API - see libavutil/buffer.h for a description. AVFrame can hold references for the data it is pointing to, and generally you don't need to touch them as API will take care of that. You can use av_frame_get_buffer to allocate new buffers for the frame; you can use av_frame_unref or av_frame_free to "clean up" the frame or clean up and release it (which might not free image data because it is used by some other AVFrame or by an encoder); most if not all of other frame-related API is buffer-aware as well. Just make sure not to copy AVBufferRef pointers directly as that will circumvent reference counting - use av_buffer_ref instead.

To answer your second question - av_frame_free will do exactly that. It will release any AVBufferRefs attached to AVFrame and then it will free AVFrame itself. It will not touch anything that wasn't referenced by a buffer.

like image 60
Andrey Turkin Avatar answered Oct 23 '22 23:10

Andrey Turkin