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的能力。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FFmpeg是一个开源的音视频处理库,而OpenCV是一个开源的计算机视觉库。它们可以通过交叉编译的方式进行整合,以实现音视频处理和计算机视觉的功能。 下面是一种常见的方法来将FFmpeg和OpenCV进行交叉编译: 1. 配置交叉编译环境:首先,你需要配置好交叉编译环境,包括交叉编译工具链和相关的库文件。这些工具链和库文件需要根据你的目标平台来选择和配置。 2. 下载和编译FFmpeg:从FFmpeg官方网站下载最新的源代码,并解压到本地。然后,在终端中进入FFmpeg源代码目录,执行以下命令进行交叉编译: ``` ./configure --prefix=<安装路径> --enable-shared --disable-static --cross-prefix=<交叉编译工具链前缀> --target-os=<目标操作系统> --arch=<目标架构> --extra-cflags="-I<交叉编译工具链头文件路径>" --extra-ldflags="-L<交叉编译工具链库文件路径>" make make install ``` 这些命令将会配置、编译和安装FFmpeg库到指定的安装路径。 3. 下载和编译OpenCV:从OpenCV官方网站下载最新的源代码,并解压到本地。然后,在终端中进入OpenCV源代码目录,执行以下命令进行交叉编译: ``` mkdir build cd build cmake -DCMAKE_TOOLCHAIN_FILE=<交叉编译工具链文件> -DCMAKE_INSTALL_PREFIX=<安装路径> .. make make install ``` 这些命令将会配置、编译和安装OpenCV库到指定的安装路径。 4. 链接FFmpeg和OpenCV:在你的项目中,你可以使用FFmpeg和OpenCV的头文件和库文件来进行开发。在编译时,需要指定FFmpeg和OpenCV的头文件路径和库文件路径,并链接对应的库文件。 以上是一种常见的方法来将FFmpeg和OpenCV进行交叉编译。具体的配置和编译过程可能会因为不同的平台和工具链而有所差异,请根据你的实际情况进行相应的调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值