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

  • 相关阅读:
    windows中echo的用法
    通过phpMyAdmin写入MySQL,获取webshell
    底部小鱼特效
    kali Linux的简单介绍
    Kali安装gmpy2
    利用kali生成字典的三种方式
    利用kali嗅探HTTP网页用户账户密码
    永恒之蓝(ms017-010)漏洞利用
    如何使用最新Microsoft Edge打开Flash页面
    结对第二次作业
  • 原文地址:https://www.cnblogs.com/faithlocus/p/15636169.html
Copyright © 2011-2022 走看看