我是靠谱客的博主 勤奋猫咪,最近开发中收集的这篇文章主要介绍ffmpeg的AVBuffer和AVBufferRef,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

AVBufferRef是对AVBuffer的一层封装,主要用来保护AVBuffer,以及管理AVBuffer的引用次数,从而达到自动释放的目的。
下面是两个结构体详细信息:
AVBufferRef 的内容:

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结构体中有一个AVBuffer,这个就是它管理的buf了,它在外部还有data和size,这两个变量跟buffer内部的data和size是一样的,是用来在AVBufferRef中修改buffer的内容。

AVBuffer 的内容:

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;
};

核心函数有三个(正常情况下,视频数据在buf中是不改变的,仅仅传递):

//创建
AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
                              void (*free)(void *opaque, uint8_t *data),
                              void *opaque, int flags);
//引用,引用计数增加1                          
AVBufferRef *av_buffer_ref(const AVBufferRef *buf);
//解引用,应用技术计数减1,如果到1的时候就释放内容,跟智能指针一样
void av_buffer_unref(AVBufferRef **buf);

首先看av_buffer_create()里面有一个回调函数free,用来释放data用的

AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
                              void (*free)(void *opaque, uint8_t *data),
                              void *opaque, int flags)
{
    AVBufferRef *ret;
    //创建buf
    AVBuffer *buf = av_mallocz(sizeof(*buf));
    if (!buf)
        return NULL;

    ret = buffer_create(buf, data, size, free, opaque, flags);
    if (!ret) {
        av_free(buf);
        return NULL;
    }
    return ret;
}

static AVBufferRef *buffer_create(AVBuffer *buf, uint8_t *data, size_t size,
                                  void (*free)(void *opaque, uint8_t *data),
                                  void *opaque, int flags)
{
    AVBufferRef *ref = NULL;
    
   //简单赋值
    buf->data     = data;
    buf->size     = size;
    buf->free     = free ? free : av_buffer_default_free;
    buf->opaque   = opaque;
	//引用计数加1
    atomic_init(&buf->refcount, 1);

    buf->flags = flags;
	//创建ref,返回
    ref = av_mallocz(sizeof(*ref));
    if (!ref)
        return NULL;
//这里可以看出ref的data和size是和buf中的一样的
    ref->buffer = buf;
    ref->data   = data;
    ref->size   = size;

    return ref;
}

av_buffer_ref()获取引用

AVBufferRef *av_buffer_ref(const AVBufferRef *buf)
{
    AVBufferRef *ret = av_mallocz(sizeof(*ret));

    if (!ret)
        return NULL;
        
   //简单赋值
    *ret = *buf;

	//核心这里,引用计数加1
    atomic_fetch_add_explicit(&buf->buffer->refcount, 1, memory_order_relaxed);

    return ret;
}

av_buffer_unref()解引用

void av_buffer_unref(AVBufferRef **buf)
{
    if (!buf || !*buf)
        return;

    buffer_replace(buf, NULL);
}

static void buffer_replace(AVBufferRef **dst, AVBufferRef **src)
{
    AVBuffer *b;

    b = (*dst)->buffer;

    if (src) {
        **dst = **src;
        av_freep(src);
    } else
        av_freep(dst);//释放结构体
        
   //引用减去1,并判断是否为1,如果为1就释放data中的数据
    if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) {
        /* b->free below might already free the structure containing *b,
         * so we have to read the flag now to avoid use-after-free. */
        int free_avbuffer = !(b->flags_internal & BUFFER_FLAG_NO_FREE);
        b->free(b->opaque, b->data);
        if (free_avbuffer)
            av_free(b);
    }
}

看完代码,发现很简单,也没什么可以讲的,就是malloc和free,最关键的是recount原子变量的增加和减少,从而达到控制释放data的能力。

最后

以上就是勤奋猫咪为你收集整理的ffmpeg的AVBuffer和AVBufferRef的全部内容,希望文章能够帮你解决ffmpeg的AVBuffer和AVBufferRef所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部