zoukankan      html  css  js  c++  java
  • ffmpeg之AVPacket

    用于存储压缩编码后的相关数据信息的结构体

    结构体说明

    /**
     * This structure stores compressed data. It is typically exported by demuxers
     * and then passed as input to decoders, or received as output from encoders and
     * then passed to muxers.
     * 此结构存储的是压缩后的数据,通常由解复用器导出,然后传递给解码器,或者作为编码器的输出,然后传递给多路复用器
     * For video, it should typically contain one compressed frame. For audio it may
     * contain several compressed frames. Encoders are allowed to output empty
     * packets, with no compressed data, containing only side data
     * (e.g. to update some stream parameters at the end of encoding).
     * 对于视频压缩数据,AVPacket通常包含一帧压缩数据;对于音频,AVPacket可能包含多帧压缩数据。
     * 当没有压缩数据,仅仅包含端数据时,编码器允许输出空的AVPacket(比如编码结束后的冲刷编码器)。
     * AVPacket is one of the few structs in FFmpeg, whose size is a part of public
     * ABI. Thus it may be allocated on stack and no new fields can be added to it
     * without libavcodec and libavformat major bump.
     *
     * The semantics of data ownership depends on the buf field.
     * If it is set, the packet data is dynamically allocated and is
     * valid indefinitely until a call to av_packet_unref() reduces the
     * reference count to 0.
     *
     * If the buf field is not set av_packet_ref() would make a copy instead
     * of increasing the reference count.
     *
     * The side data is always allocated with av_malloc(), copied by
     * av_packet_ref() and freed by av_packet_unref().
     *
     * @see av_packet_ref
     * @see av_packet_unref
     */
    typedef struct AVPacket {
        /**
         * A reference to the reference-counted buffer where the packet data is
         * stored.
         * May be NULL, then the packet data is not reference-counted.
         * 真实存储数据的引用,采用引用计数机制,如果数据为NULL时,这引用计数为0
         */
        AVBufferRef *buf;
        /**
         * Presentation timestamp in AVStream->time_base units; the time at which
         * the decompressed packet will be presented to the user.
         * 向用户展示数据的事件戳(单位不是秒,而是AVStream->time_base)
         * Can be AV_NOPTS_VALUE if it is not stored in the file.
         * 如果未存储在文件中,pts = AV_NOPTS_VALUE
         * pts MUST be larger or equal to dts as presentation cannot happen before
         * decompression, unless one wants to view hex dumps. Some formats misuse
         * the terms dts and pts/cts to mean something different. Such timestamps
         * must be converted to true pts/dts before they are stored in AVPacket.
         * pts必须不小于dts,因为编码之前用户不可能显示此数据的信息。
         * 此类时间戳(单位time_base)必须转换为真正的事件戳(单位秒)才能显示
         */
        int64_t pts;
        /**
         * Decompression timestamp in AVStream->time_base units; the time at which
         * the packet is decompressed.
         * Can be AV_NOPTS_VALUE if it is not stored in the file.
         * 编码时间戳(单位AVStream->time_base)
         * 如果未存储dts,这dts = AV_NOPTS_VALUE
         */
        int64_t dts;
        uint8_t *data;        // 压缩编码的数据
        int   size;           // data的长度
        int   stream_index;   // AVStream的标识,表示属于音频还是视频流
        /**
         * A combination of AV_PKT_FLAG values
         */
        int   flags;  // AV_PKT_FLAG的集合,比如标识关键帧
        /**
         * Additional packet data that can be provided by the container.
         * Packet can contain several types of side information.
         */
        AVPacketSideData *side_data;
        int side_data_elems;
    
        /**
         * Duration of this packet in AVStream->time_base units, 0 if unknown.
         * Equals next_pts - this_pts in presentation order.
         */
        int64_t duration;
    
        int64_t pos;                            ///< byte position in stream, -1 if unknown
    
    #if FF_API_CONVERGENCE_DURATION
        /**
         * @deprecated Same as the duration field, but as int64_t. This was required
         * for Matroska subtitles, whose duration values could overflow when the
         * duration field was still an int.
         */
        attribute_deprecated
        int64_t convergence_duration;    // 不建议使用
    #endif
    } AVPacket;
    

    AV_PKT_FLAG

    #define AV_PKT_FLAG_KEY     0x0001 ///< The packet contains a keyframe
    #define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted
    /**
     * Flag is used to discard packets which are required to maintain valid
     * decoder state but are not required for output and should be dropped
     * after decoding.
     **/
    #define AV_PKT_FLAG_DISCARD   0x0004
    /**
     * The packet comes from a trusted source.
     *
     * Otherwise-unsafe constructs such as arbitrary pointers to data
     * outside the packet may be followed.
     */
    #define AV_PKT_FLAG_TRUSTED   0x0008
    /**
     * Flag is used to indicate packets that contain frames that can
     * be discarded by the decoder.  I.e. Non-reference frames.
     */
    #define AV_PKT_FLAG_DISPOSABLE 0x0010
    

    内存管理AVBufferRef

    /**
     * A reference to a data buffer.
     * 对数据buffer的引用
     * The size of this struct is not a part of the public ABI and it is not meant
     * to be allocated directly.
     */
    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.
         */
        int      size;           // 数据长度
    } AVBufferRef;
    
    /**
     * A reference counted buffer type. It is opaque and is meant to be used through
     * references (AVBufferRef).
     */
    typedef struct AVBuffer AVBuffer;
    
    struct AVBuffer {
        uint8_t *data; /**< data described by this buffer */
        int      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 BUFFER_FLAG_*
         */
        int flags;
    };
    
    /**
     * The buffer is always treated as read-only.
     */
    #define BUFFER_FLAG_READONLY      (1 << 0)
    /**
     * The buffer was av_realloc()ed, so it is reallocatable.
     */
    #define BUFFER_FLAG_REALLOCATABLE (1 << 1)
    

    AVPacket常用函数

    av_packet_alloc:分配一个packet内存空间,buffer未分配空间

    /**
     * Allocate an AVPacket and set its fields to default values.  The resulting
     * struct must be freed using av_packet_free().
     *
     * @return An AVPacket filled with default values or NULL on failure.
     *
     * @note this only allocates the AVPacket itself, not the data buffers. Those
     * must be allocated through other means such as av_new_packet.
     *
     * @see av_new_packet
     */
    AVPacket *av_packet_alloc(void)
    {
        AVPacket *pkt = av_mallocz(sizeof(AVPacket));
        if (!pkt)
            return pkt;
    
        av_packet_unref(pkt);
    
        return pkt;
    }
    

    av_packet_free:释放packet的内存空间

    /**
     * Free the packet, if the packet is reference counted, it will be
     * unreferenced first.
     *
     * @param pkt packet to be freed. The pointer will be set to NULL.
     * @note passing NULL is a no-op.
     */
    void av_packet_free(AVPacket **pkt)
    {
        if (!pkt || !*pkt)
            return;
    
        av_packet_unref(*pkt);
        av_freep(pkt);
    }
    
    

    av_new_packet:利用AVBuffRef和size分配packet。buff已经分配空间

    /**
     * Allocate the payload of a packet and initialize its fields with
     * default values.
     *
     * @param pkt packet
     * @param size wanted payload size
     * @return 0 if OK, AVERROR_xxx otherwise
     */
    int av_new_packet(AVPacket *pkt, int size)
    {
        AVBufferRef *buf = NULL;
        int ret = packet_alloc(&buf, size);
        if (ret < 0)
            return ret;
    
        av_init_packet(pkt);
        pkt->buf      = buf;
        pkt->data     = buf->data;
        pkt->size     = size;
    
        return 0;
    }
    

    av_free_packet:释放指定packet的空间,不建议使用

    /**
     * Free a packet.
     *
     * @deprecated Use av_packet_unref
     *
     * @param pkt packet to free
     */
    attribute_deprecated
    void av_free_packet(AVPacket *pkt)
    {
        if (pkt) {
            if (pkt->buf)
                av_buffer_unref(&pkt->buf);
            pkt->data            = NULL;
            pkt->size            = 0;
    
            av_packet_free_side_data(pkt);
        }
    }
    

    packet_alloc:利用buf和size为packet分配空间

    static int packet_alloc(AVBufferRef **buf, int size)
    {
        int ret;
        if (size < 0 || size >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
            return AVERROR(EINVAL);
    
        ret = av_buffer_realloc(buf, size + AV_INPUT_BUFFER_PADDING_SIZE);
        if (ret < 0)
            return ret;
    
        memset((*buf)->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
    
        return 0;
    }
    

    av_init_packet:初始化packet成员,不会为buffer分配空间

    /**
     * Initialize optional fields of a packet with default values.
     *
     * Note, this does not touch the data and size members, which have to be
     * initialized separately.
     *
     * @param pkt packet
     */
    void av_init_packet(AVPacket *pkt)
    {
        pkt->pts                  = AV_NOPTS_VALUE;
        pkt->dts                  = AV_NOPTS_VALUE;
        pkt->pos                  = -1;
        pkt->duration             = 0;
    #if FF_API_CONVERGENCE_DURATION
    FF_DISABLE_DEPRECATION_WARNINGS
        pkt->convergence_duration = 0;
    FF_ENABLE_DEPRECATION_WARNINGS
    #endif
        pkt->flags                = 0;
        pkt->stream_index         = 0;
        pkt->buf                  = NULL;
        pkt->side_data            = NULL;
        pkt->side_data_elems      = 0;
    }
    
    

    av_packet_ref:AVPacket的引用计数+1

    /**
     * Setup a new reference to the data described by a given packet
     *
     * If src is reference-counted, setup dst as a new reference to the
     * buffer in src. Otherwise allocate a new buffer in dst and copy the
     * data from src into it.
     *
     * All the other fields are copied from src.
     *
     * @see av_packet_unref
     *
     * @param dst Destination packet
     * @param src Source packet
     *
     * @return 0 on success, a negative AVERROR on error.
     */
    int av_packet_ref(AVPacket *dst, const AVPacket *src)
    {
        int ret;
    
        ret = av_packet_copy_props(dst, src);
        if (ret < 0)
            return ret;
    
        if (!src->buf) {
            ret = packet_alloc(&dst->buf, src->size);
            if (ret < 0)
                goto fail;
            av_assert1(!src->size || src->data);
            if (src->size)
                memcpy(dst->buf->data, src->data, src->size);
    
            dst->data = dst->buf->data;
        } else {
            dst->buf = av_buffer_ref(src->buf);
            if (!dst->buf) {
                ret = AVERROR(ENOMEM);
                goto fail;
            }
            dst->data = src->data;
        }
    
        dst->size = src->size;
    
        return 0;
    fail:
        av_packet_free_side_data(dst);
        return ret;
    }
    

    av_packet_unref:AVPacket的引用计数-1,为零时这释放内存

    /**
     * Wipe the packet.
     *
     * Unreference the buffer referenced by the packet and reset the
     * remaining packet fields to their default values.
     *
     * @param pkt The packet to be unreferenced.
     */
    void av_packet_unref(AVPacket *pkt)
    {
        av_packet_free_side_data(pkt);
        av_buffer_unref(&pkt->buf);
        av_init_packet(pkt);
        pkt->data = NULL;
        pkt->size = 0;
    }
    

    av_packet_move:AVPacket数据转移,引用计数不变

    /**
     * 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)
    {
        *dst = *src;
        av_init_packet(src);
        src->data = NULL;
        src->size = 0;
    }
    

    av_packet_clone:利用已有的packet克隆一份packet,新的packet引用计数为1,源packet引用计数不变

    /**
     * Create a new packet that references the same data as src.
     *
     * This is a shortcut for av_packet_alloc()+av_packet_ref().
     *
     * @return newly created AVPacket on success, NULL on error.
     *
     * @see av_packet_alloc
     * @see av_packet_ref
     */
    AVPacket *av_packet_clone(const AVPacket *src)
    {
        AVPacket *ret = av_packet_alloc();
    
        if (!ret)
            return ret;
    
        if (av_packet_ref(ret, src))
            av_packet_free(&ret);
    
        return ret;
    }
    

    av_packet_make_refcounted:创建可使用引用技术的pkt

    /**
     * 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)
    {
        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;
    }
    

    av_packet_make_writable:创建一个可写引用的pkt,避免内存的拷贝

    /**
     * Create a writable reference for the data described by a given packet,
     * avoiding data copy if possible.
     *
     * @param pkt Packet whose data should be made writable.
     *
     * @return 0 on success, a negative AVERROR on failure. On failure, the
     *         packet is unchanged.
     */
    int av_packet_make_writable(AVPacket *pkt)
    {
        AVBufferRef *buf = NULL;
        int ret;
    
        if (pkt->buf && av_buffer_is_writable(pkt->buf))
            return 0;
    
        ret = packet_alloc(&buf, pkt->size);
        if (ret < 0)
            return ret;
        av_assert1(!pkt->size || pkt->data);
        if (pkt->size)
            memcpy(buf->data, pkt->data, pkt->size);
    
        av_buffer_unref(&pkt->buf);
        pkt->buf  = buf;
        pkt->data = buf->data;
    
        return 0;
    }
    

    本文来自博客园,作者:faithlocus,转载请注明原文链接:https://www.cnblogs.com/faithlocus/p/15636169.html

  • 相关阅读:
    Entity Framework Core 2.0 新特性
    asp.net core部署时自定义监听端口,提高部署的灵活性
    asp.net core使用jexus部署在linux无法正确 获取远程ip的解决办法
    使用xshell连接服务器,数字键盘无法使用解决办法
    使用Jexus 5.8.2在Centos下部署运行Asp.net core
    【DevOps】DevOps成功的八大炫酷工具
    【Network】Calico, Flannel, Weave and Docker Overlay Network 各种网络模型之间的区别
    【Network】UDP 大包怎么发? MTU怎么设置?
    【Network】高性能 UDP 应该怎么做?
    【Network】golang 容器项目 flannel/UDP相关资料
  • 原文地址:https://www.cnblogs.com/faithlocus/p/15636169.html
Copyright © 2011-2022 走看看