How to Use AVBufferRef in FFmpeg C API
FFmpeg utilizes AVBufferRef as the core of its
reference-counting mechanism to manage heap memory safely and
efficiently across audio and video processing pipelines. This article
explains how AVBufferRef works, detailing how to allocate
reference-counted buffers, duplicate references without copying data,
handle copy-on-write semantics, and properly release references to
prevent memory leaks.
Understanding AVBuffer and AVBufferRef
Memory management in FFmpeg distinguishes between the underlying data and the reference pointing to it:
AVBuffer: An opaque structure holding the actual allocated memory, its size, the current reference count, and a free callback. You generally do not interact withAVBufferdirectly.AVBufferRef: A lightweight wrapper structure that references anAVBuffer. It exposes a pointer to the memory (data) and the buffersize. MultipleAVBufferRefinstances can point to the same underlyingAVBuffer.
When an AVBuffer's reference count drops to zero, FFmpeg
executes the associated cleanup function and frees the memory
automatically.
Allocating a Reference-Counted Buffer
To allocate a new buffer, use av_buffer_alloc(). This
creates the underlying AVBuffer and returns a pointer to an
AVBufferRef with an initial reference count of 1.
#include <libavutil/buffer.h>
size_t size = 1024;
AVBufferRef *buf = av_buffer_alloc(size);
if (!buf) {
// Handle allocation failure
}
// Access data and size
memset(buf->data, 0, buf->size);If you need to manage custom memory or bind external buffers, use
av_buffer_create() to supply a custom deallocator
callback:
void custom_free(void *opaque, uint8_t *data) {
free(data);
}
uint8_t *external_memory = malloc(size);
AVBufferRef *buf = av_buffer_create(external_memory, size, custom_free, NULL, 0);Duplicating References
To share memory between different structures (such as
AVFrame or AVPacket) without duplicating the
payload, create a new reference using av_buffer_ref().
AVBufferRef *buf_copy = av_buffer_ref(buf);
if (!buf_copy) {
// Handle error (allocation of descriptor failed)
}
// Both `buf` and `buf_copy` point to the same data.
// The internal reference count is now 2.Releasing References
To drop a reference, use av_buffer_unref(). This
function decrements the internal reference count and sets the target
pointer to NULL. When the reference count reaches zero, the
underlying memory is freed.
av_buffer_unref(&buf);
// `buf` is now NULL. The underlying data remains allocated because `buf_copy` still exists.
av_buffer_unref(&buf_copy);
// `buf_copy` is now NULL. The reference count hits 0; the data is freed.Always pass the address of the AVBufferRef pointer
(&buf) to ensure dangling pointers are cleared.
Modifying Shared Buffers (Copy-on-Write)
If multiple references point to the same buffer, modifying the
contents directly can lead to unintended side effects. FFmpeg provides
copy-on-write functionality through av_buffer_is_writable()
and av_buffer_make_writable().
av_buffer_is_writable(buf)returns1if the reference count is strictly1, meaning the buffer is safe to modify without affecting other references.av_buffer_make_writable(&buf)checks if the buffer is writable. If the reference count is greater than 1, it allocates a new buffer, copies the data over, decrements the reference on the original buffer, and replaces your pointer with the new, exclusive copy.
// Ensure buf can be safely written to
int ret = av_buffer_make_writable(&buf);
if (ret < 0) {
// Allocation failure during copy
}
// Safe to modify buf->data
buf->data[0] = 0xFF;Integration with AVFrame and AVPacket
Higher-level structures like AVFrame and
AVPacket rely on AVBufferRef:
AVPacketstores its compressed data reference inpacket->buf.AVFramestores uncompressed plane references in an array:frame->buf[0],frame->buf[1], etc.
When cloning frames or packets via functions like
av_frame_ref() or av_packet_ref(), FFmpeg
internally calls av_buffer_ref() on these pointers,
avoiding expensive memory copies. Calling av_frame_unref()
or av_packet_unref() releases the respective references
automatically.