FFmpeg源码:av_packet_move_ref、av_packet_make_refcounted函数分析

发布于:2024-08-11 ⋅ 阅读:(190) ⋅ 点赞:(0)

一、av_packet_move_ref函数

(一)av_packet_move_ref函数的声明

av_packet_move_ref函数声明在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的头文件libavcodec/packet.h中:

/**
 * Move every field in src to dst and reset src.
 *
 * @see av_packet_unref
 *
 * @param src Source packet, will be reset
 * @param dst Destination packet
 */
void av_packet_move_ref(AVPacket *dst, AVPacket *src);

该函数作用是:将形参src指向的AVPacket对象(以下简称原对象)浅拷贝到形参dst指向的AVPacket对象(以下简称目标对象)中,然后给原对象的成员变量pts、dts、pos、time_base赋默认值。执行该函数后,只对目标对象赋值原对象的成员变量的值,并不复制原对象的动态分配内存(src->buf、src->data、src->side_data指向的缓冲区)等外部资源,这也就意味着当原对象修改自己指向的外部资源时,可能会影响到目标对象。

(二)av_packet_move_ref函数的定义

av_packet_move_ref函数定义在源文件libavcodec/avpacket.c中:

void av_packet_move_ref(AVPacket *dst, AVPacket *src)
{
    *dst = *src;
    get_packet_defaults(src);
}

可以看到FFmpeg用自己的方式实现了C++中的浅拷贝。

二、av_packet_make_refcounted函数

(一)av_packet_make_refcounted函数的声明

av_packet_make_refcounted函数声明在头文件libavcodec/packet.h中:

/**
 * Ensure the data described by a given packet is reference counted.
 *
 * @note This function does not ensure that the reference will be writable.
 *       Use av_packet_make_writable instead for that purpose.
 *
 * @see av_packet_ref
 * @see av_packet_make_writable
 *
 * @param pkt packet whose data should be made reference counted.
 *
 * @return 0 on success, a negative AVERROR on error. On failure, the
 *         packet is unchanged.
 */
int av_packet_make_refcounted(AVPacket *pkt);

该函数作用是:确保给定数据包(pkt指向的对象)描述的数据是引用计数的。

1.如果pkt->buf不为空,表示给定数据包描述的数据已经是引用计数了。该函数返回0,不执行也不需要执行其它操作。

2.如果pkt->buf为空,给给pkt->buf和pkt->buf->buffer分配内存,给pkt->buf->data重新分配大小为(pkt->size + AV_INPUT_BUFFER_PADDING_SIZE)个字节内存。然后把pkt->data中的数据拷贝pkt->size个字节到pkt->buf->data中。执行上述操作(情况“2”的操作)后,pkt->buf->buffer->refcount的值会是1,所以可以保证数据已经是引用计数了。

返回值:返回0表示成功,返回一个负数表示失败。

(二)av_packet_make_refcounted函数的定义

av_packet_make_refcounted函数定义在源文件libavcodec/avpacket.c中:

int av_packet_make_refcounted(AVPacket *pkt)
{
    int ret;

    if (pkt->buf)
        return 0;

    ret = packet_alloc(&pkt->buf, pkt->size);
    if (ret < 0)
        return ret;
    av_assert1(!pkt->size || pkt->data);
    if (pkt->size)
        memcpy(pkt->buf->data, pkt->data, pkt->size);

    pkt->data = pkt->buf->data;

    return 0;
}

当pkt->buf为空时,av_packet_make_refcounted函数内部会执行packet_alloc函数,而packet_alloc函数内部会执行av_buffer_realloc函数,av_buffer_realloc函数内部又会执行av_buffer_create函数,从《FFmpeg源码:buffer_create、av_buffer_create、av_buffer_default_free、av_buffer_alloc、av_buffer_allocz函数分析》中可以知道,av_buffer_create函数会让refcount的值被初始化为1,所以可以保证数据是引用计数的。


网站公告

今日签到

点亮在社区的每一天
去签到