FFmpeg:浅谈 AVBuffer 和 AVBufferRef 结构体

FFmpeg 借助 struct AVBufferstruct AVBufferRef 以及相关 API 实现了引用计数功能。

结构体定义

struct AVBuffer 目前共包含七个成员变量,从功能上可以划分为三部分:

  • 数据部分
    • uint8_t *datasize_t size:指向一段长度为 size 的内存。
    • void *opaque:一个指针,指向一个用户自定义类型的对象,也可为空,FFmpeg 不关心。
    • void (*free)(void *opaque, uint8_t *data):函数指针,用于释放 dataopaque
  • 计数部分:
    • atomic_uint refcount:引用计数,配合 AVBufferRef 使用,记录有多少个 AVBufferRef 对象引用了自己。
  • 辅助部分:
    • int flagsint flags_internal:一些用于描述自身状态的标志变量。

完整定义如下:

struct AVBuffer {
    uint8_t *data; /**< data described by this buffer */
    size_t size; /**< size of data in bytes */

    /**
     *  number of existing AVBufferRef instances referring to this buffer
     */
    atomic_uint refcount;

    /**
     * a callback for freeing the data
     */
    void (*free)(void *opaque, uint8_t *data);

    /**
     * an opaque pointer, to be used by the freeing callback
     */
    void *opaque;

    /**
     * A combination of AV_BUFFER_FLAG_*
     */
    int flags;

    /**
     * A combination of BUFFER_FLAG_*
     */
    int flags_internal;
};

struct AVBufferRef 更为简单,仅包含三个变量:

  • AVBuffer *buffer:引用的 AVBuffer 对象。
  • uint8_t *datasize_t size:指向一段长度为 size 的内存。其值与 buffer->databuffer->size 相同。
typedef struct AVBufferRef {
    AVBuffer *buffer;

    /**
     * The data buffer. It is considered writable if and only if
     * this is the only reference to the buffer, in which case
     * av_buffer_is_writable() returns 1.
     */
    uint8_t *data;
    /**
     * Size of data in bytes.
     */
    size_t   size;
} AVBufferRef;

相关函数

创建新的 AVBufferRef 对象

av_buffer_alloc / av_buffer_allocz

创建一个新的 struct AVbufferRef 对象。

/**
 * Allocate an AVBuffer of the given size using av_malloc().
 *
 * @return an AVBufferRef of given size or NULL when out of memory
 */
AVBufferRef *av_buffer_alloc(size_t size);

/**
 * Same as av_buffer_alloc(), except the returned buffer will be initialized
 * to zero.
 */
AVBufferRef *av_buffer_allocz(size_t size);

av_buffer_alloc 会调用三次 av_malloc

  • 分配一段长度为 size 的内存,供用户使用。
  • 分配一段长度为 sizeof(AVBuffer) 的内存,存储 AVBuffer 对象。
  • 分配一段长度为 sizeof(AVBufferRef) 的内存,存储 AVBufferRef 对象。

av_buffer_alloczav_buffer_alloc 类似,只是会将长度为 size 的内存全部值为 0

此时三部分内存的状态如下图:

av_buffer_create

新创建一个 AVBufferRef 对象,并使其维护一段用户分配的内存。

/**
 * Create an AVBuffer from an existing array.
 *
 * If this function is successful, data is owned by the AVBuffer. The caller may
 * only access data through the returned AVBufferRef and references derived from
 * it.
 * If this function fails, data is left untouched.
 * @param data   data array
 * @param size   size of data in bytes
 * @param free   a callback for freeing this buffer's data
 * @param opaque parameter to be got for processing or passed to free
 * @param flags  a combination of AV_BUFFER_FLAG_*
 *
 * @return an AVBufferRef referring to data on success, NULL on failure.
 */
AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
                              void (*free)(void *opaque, uint8_t *data),
                              void *opaque, int flags);

维护引用

av_buffer_ref

AVBufferRef *av_buffer_ref(const AVBufferRef *buf); 仅会调用一次 av_malloc

  • 分配一段长度为 size 的内存,供用户使用。
  • 分配一段长度为 sizeof(AVBuffer) 的内存,存储 AVBuffer 对象。
  • 分配一段长度为 sizeof(AVBufferRef) 的内存,存储 AVBufferRef 对象。

新的 AVBufferRef 对象和 buf 共享一个 AVBuffer 对象。

该函数会使 buf->buffer->refcount 的值加一。

/**
 * Create a new reference to an AVBuffer.
 *
 * @return a new AVBufferRef referring to the same AVBuffer as buf or NULL on
 * failure.
 */
AVBufferRef *av_buffer_ref(const AVBufferRef *buf);

av_buffer_unref

av_buffer_unrefav_buffer_ref 相反。

void av_buffer_unref(AVBufferRef **buf); 做两件事:

  • 释放内存:调用 av_free 释放 AVBufferRef 对象自身占用的内存。
  • 维护引用:将引用计数减一,如果减一后其值为 0,则调用 buffer->free,然后将 buffer 的内存释放。
/**
 * Free a given reference and automatically free the buffer if there are no more
 * references to it.
 *
 * @param buf the reference to be freed. The pointer is set to NULL on return.
 */
void av_buffer_unref(AVBufferRef **buf);

是否可写

av_buffer_is_writable

当且仅当 buf->buffer->refcount1buf->buffer->flag 为设置 AV_BUFFER_FLAG_READONLY

/**
 * @return 1 if the caller may write to the data referred to by buf (which is
 * true if and only if buf is the only reference to the underlying AVBuffer).
 * Return 0 otherwise.
 * A positive answer is valid until av_buffer_ref() is called on buf.
 */
int av_buffer_is_writable(const AVBufferRef *buf);

av_buffer_make_writable

借助 av_buffer_make_writable 函数,可将 AVBufferRef 值为可写状态。

如果传入的 AVBufferRef 不可写,则会新分配一段内存,并进行数据拷贝。换言之,此时已与不可写的 AVBuffer 对象解除引用啦。

/**
 * Create a writable reference from a given buffer reference, avoiding data copy
 * if possible.
 *
 * @param buf buffer reference to make writable. On success, buf is either left
 *            untouched, or it is unreferenced and a new writable AVBufferRef is
 *            written in its place. On failure, buf is left untouched.
 * @return 0 on success, a negative AVERROR on failure.
 */
int av_buffer_make_writable(AVBufferRef **buf);

其他

av_buffer_realloc

重新分配指定长度的内存。

/**
 * Reallocate a given buffer.
 *
 * @param buf  a buffer reference to reallocate. On success, buf will be
 *             unreferenced and a new reference with the required size will be
 *             written in its place. On failure buf will be left untouched. *buf
 *             may be NULL, then a new buffer is allocated.
 * @param size required new buffer size.
 * @return 0 on success, a negative AVERROR on failure.
 *
 * @note the buffer is actually reallocated with av_realloc() only if it was
 * initially allocated through av_buffer_realloc(NULL) and there is only one
 * reference to it (i.e. the one passed to this function). In all other cases
 * a new buffer is allocated and the data is copied.
 */
int av_buffer_realloc(AVBufferRef **buf, size_t size);

av_buffer_replace

改变引用。

/**
 * Ensure dst refers to the same data as src.
 *
 * When *dst is already equivalent to src, do nothing. Otherwise unreference dst
 * and replace it with a new reference to src.
 *
 * @param dst Pointer to either a valid buffer reference or NULL. On success,
 *            this will point to a buffer reference equivalent to src. On
 *            failure, dst will be left untouched.
 * @param src A buffer reference to replace dst with. May be NULL, then this
 *            function is equivalent to av_buffer_unref(dst).
 * @return 0 on success
 *         AVERROR(ENOMEM) on memory allocation failure.
 */
int av_buffer_replace(AVBufferRef **dst, const AVBufferRef *src);
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值