音视频开发基础(七)理解FFMpeg重要结构体及常用成员

AVStream

1.简介

AVStream在FFmpeg使用过程中关于编解码至关重要的结构体之一,是对流(Stream)的封装和抽象,描述了视频、音频等流的编码格式等基本流信息。此外也是音频、视频、字母数据流的重要载体。

2.源码解读
typedef struct AVStream {
        int index;    /**< 在AVFormatContext中的stream索引 */
        /**
         * 特定格式的stream id。
         * 解码: 由libavformat设定
         * 编码: 如果未设置,则由用户通过libavformat设置
         */
        int id;
#if FF_API_LAVF_AVCTX
    /**
     * @deprecated use the codecpar struct instead
     * 不推荐使用该字段
     */
    attribute_deprecated
    //在老版本中此处为struct AVFrac pts;
    AVCodecContext *codec;
#endif
	/**
         * 这是表示帧时间戳的基本时间单位(以秒为单位)。
         *
         * 解码: libavformat设置
         * 编码: 可以在avformat_write_header()之前由调用者设置,以向混流器提供关于所需单位时间的
         * 提示。在avformat_write_header()中,混流器将用实际用于写入文件的时间戳(根据格式可能与
         * 用户提供的时间戳相关或不相关)的单位时间覆盖该字段。
         */
        AVRational time_base;
    
        /**
         * 解码: 流显示序列中的第一帧pts时间,基于流时间(in stream time base.)。
         * 只有当你百分百确定该值就是真实的第一帧的pts时间,才可以设置它
         * 该值可能未定义(AV_NOPTS_VALUE).
         * @note The ASF header does NOT contain a correct start_time the ASF
         * 分流器禁止设置该值。
         */
        int64_t start_time;
    
        /**
         * 解码: 流时长,基于流时间(in stream time base.)
         *      如果一个源文件指定了比特率,而未指定流时长,该值将由比特率和文件大小估算。
         *
         * 编码: May be set by the caller before 用户可以在avformat_write_header()调用前设
         * 置,提示混流器估算时长
         */
        int64_t duration;
    
        int64_t nb_frames;                 ///< 表示该流的已知帧数,或者为0
    
        int disposition; /**< AV_DISPOSITION_* 推荐比特字段 */
    
        enum AVDiscard discard; ///< 选择那些数据包可以被丢掉而不用被分流器分流。
    
        /**
         * 采样率(如果未知,该值为0)
         * - 编码: 用户设置.
         * - 解码: libavformat设置.
         */
        AVRational sample_aspect_ratio;
    
        AVDictionary *metadata;//原数据信息
    
        /**
         * 平均帧率
         *
         * - 分流: 在创建流时或者才函数avformat_find_stream_info()函数中可能被设置。
         * - 混流: 可能在avformat_write_header()函数调用前被设置
         */
        AVRational avg_frame_rate;
    
        /**
         * 对于设置有AV_DISPOSITION_ATTACHED_PIC标志的流, 该数据包会包含该附加图片(专辑图片什么的)
         *
         * 解码: libavformat设置, 不能被用户修改。
         * 编码: 不使用
         */
        AVPacket attached_pic;
         /**
     * An array of side data that applies to the whole stream (i.e. the
     * container does not allow it to change between packets).
     *
     * There may be no overlap between the side data in this array and side data
     * in the packets. I.e. a given side data is either exported by the muxer
     * (demuxing) / set by the caller (muxing) in this array, then it never
     * appears in the packets, or the side data is exported / sent through
     * the packets (always in the first packet where the value becomes known or
     * changes), then it does not appear in this array.
     *
     * - demuxing: Set by libavformat when the stream is created.
     * - muxing: May be set by the caller before avformat_write_header().
     *
     * Freed by libavformat in avformat_free_context().
     *
     * @see av_format_inject_global_side_data()
     */
    AVPacketSideData *side_data;
    /**
     * The number of elements in the AVStream.side_data array.
     */
    int            nb_side_data;

    /**
     * Flags for the user to detect events happening on the stream. Flags must
     * be cleared by the user once the event has been handled.
     * A combination of AVSTREAM_EVENT_FLAG_*.
     */
    int event_flags;
#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata.

    /**
     * Real base framerate of the stream.
     * This is the lowest framerate with which all timestamps can be
     * represented accurately (it is the least common multiple of all
     * framerates in the stream). Note, this value is just a guess!
     * For example, if the time base is 1/90000 and all frames have either
     * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1.
     */
    AVRational r_frame_rate;

#if FF_API_LAVF_FFSERVER
    /**
     * String containing pairs of key and values describing recommended encoder configuration.
     * Pairs are separated by ','.
     * Keys are separated from values by '='.
     *
     * @deprecated unused
     */
    attribute_deprecated
    char *recommended_encoder_configuration;
#endif

    /**
     * Codec parameters associated with this stream. Allocated and freed by
     * libavformat in avformat_new_stream() and avformat_free_context()
     * respectively.
     *
     * - demuxing: filled by libavformat on stream creation or in
     *             avformat_find_stream_info()
     * - muxing: filled by the caller before avformat_write_header()
     */
    AVCodecParameters *codecpar;

    /*****************************************************************
     * All fields below this line are not part of the public API. They
     * may not be used outside of libavformat and can be changed and
     * removed at will.
     * Internal note: be aware that physically removing these fields
     * will break ABI. Replace removed fields with dummy fields, and
     * add new fields to AVStreamInternal.
     *****************************************************************
     */

#define MAX_STD_TIMEBASES (30*12+30+3+6)
    /**
     * Stream information used internally by avformat_find_stream_info()
     */
    struct {
        int64_t last_dts;
        int64_t duration_gcd;
        int duration_count;
        int64_t rfps_duration_sum;
        double (*duration_error)[2][MAX_STD_TIMEBASES];
        int64_t codec_info_duration;
        int64_t codec_info_duration_fields;
        int frame_delay_evidence;

        /**
         * 0  -> decoder has not been searched for yet.
         * >0 -> decoder found
         * <0 -> decoder with codec_id == -found_decoder has not been found
         */
        int found_decoder;

        int64_t last_duration;

        /**
         * Those are used for average framerate estimation.
         */
        int64_t fps_first_dts;
        int     fps_first_dts_idx;
        int64_t fps_last_dts;
        int     fps_last_dts_idx;

    } *info;

    int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */

    // Timestamp generation support:
    /**
     * Timestamp corresponding to the last dts sync point.
     *
     * Initialized when AVCodecParserContext.dts_sync_point >= 0 and
     * a DTS is received from the underlying container. Otherwise set to
     * AV_NOPTS_VALUE by default.
     */
    int64_t first_dts;
    int64_t cur_dts;
    int64_t last_IP_pts;
    int last_IP_duration;

    /**
     * Number of packets to buffer for codec probing
     */
    int probe_packets;

    /**
     * Number of frames that have been demuxed during avformat_find_stream_info()
     */
    int codec_info_nb_frames;

    /* av_read_frame() support */
    enum AVStreamParseType need_parsing;
    struct AVCodecParserContext *parser;

    /**
     * last packet in packet_buffer for this stream when muxing.
     */
    struct AVPacketList *last_in_packet_buffer;
    AVProbeData probe_data;
#define MAX_REORDER_DELAY 16
    int64_t pts_buffer[MAX_REORDER_DELAY+1];

    AVIndexEntry *index_entries; /**< Only used if the format does not
                                    support seeking natively. */
    int nb_index_entries;
    unsigned int index_entries_allocated_size;

    /**
     * Stream Identifier
     * This is the MPEG-TS stream identifier +1
     * 0 means unknown
     */
    int stream_identifier;

    /**
     * Details of the MPEG-TS program which created this stream.
     */
    int program_num;
    int pmt_version;
    int pmt_stream_idx;

    int64_t interleaver_chunk_size;
    int64_t interleaver_chunk_duration;

    /**
     * stream probing state
     * -1   -> probing finished
     *  0   -> no probing requested
     * rest -> perform probing with request_probe being the minimum score to accept.
     * NOT PART OF PUBLIC API
     */
    int request_probe;
    /**
     * Indicates that everything up to the next keyframe
     * should be discarded.
     */
    int skip_to_keyframe;

    /**
     * Number of samples to skip at the start of the frame decoded from the next packet.
     */
    int skip_samples;

    /**
     * If not 0, the number of samples that should be skipped from the start of
     * the stream (the samples are removed from packets with pts==0, which also
     * assumes negative timestamps do not happen).
     * Intended for use with formats such as mp3 with ad-hoc gapless audio
     * support.
     */
    int64_t start_skip_samples;

    /**
     * If not 0, the first audio sample that should be discarded from the stream.
     * This is broken by design (needs global sample count), but can't be
     * avoided for broken by design formats such as mp3 with ad-hoc gapless
     * audio support.
     */
    int64_t first_discard_sample;

    /**
     * The sample after last sample that is intended to be discarded after
     * first_discard_sample. Works on frame boundaries only. Used to prevent
     * early EOF if the gapless info is broken (considered concatenated mp3s).
     */
    int64_t last_discard_sample;

    /**
     * Number of internally decoded frames, used internally in libavformat, do not access
     * its lifetime differs from info which is why it is not in that structure.
     */
    int nb_decoded_frames;

    /**
     * Timestamp offset added to timestamps before muxing
     * NOT PART OF PUBLIC API
     */
    int64_t mux_ts_offset;

    /**
     * Internal data to check for wrapping of the time stamp
     */
    int64_t pts_wrap_reference;

    /**
     * Options for behavior, when a wrap is detected.
     *
     * Defined by AV_PTS_WRAP_ values.
     *
     * If correction is enabled, there are two possibilities:
     * If the first time stamp is near the wrap point, the wrap offset
     * will be subtracted, which will create negative time stamps.
     * Otherwise the offset will be added.
     */
    int pts_wrap_behavior;

    /**
     * Internal data to prevent doing update_initial_durations() twice
     */
    int update_initial_durations_done;

    /**
     * Internal data to generate dts from pts
     */
    int64_t pts_reorder_error[MAX_REORDER_DELAY+1];
    uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];

    /**
     * Internal data to analyze DTS and detect faulty mpeg streams
     */
    int64_t last_dts_for_order_check;
    uint8_t dts_ordered;
    uint8_t dts_misordered;

    /**
     * Internal data to inject global side data
     */
    int inject_global_side_data;

    /**
     * display aspect ratio (0 if unknown)
     * - encoding: unused
     * - decoding: Set by libavformat to calculate sample_aspect_ratio internally
     */
    AVRational display_aspect_ratio;

    /**
     * An opaque field for libavformat internal usage.
     * Must not be accessed in any way by callers.
     */
    AVStreamInternal *internal;
} AVStream;

常用字段以及使用

AVCodecParameters * codecpar :用于记录编码后的流信息,即通道中存储的流的编码信息。

AVRational time_base :AVStream通道的时间基,时间基是个相当重要的概念。(可参考之后的关于ffmpeg时间的文章)

  1. 创建AVStream :
    AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);
    avformat_new_stream之后便在 AVFormatContext 里增加了 AVStream 通道(相关的index已经被设置了)。之后,我们就可以自行设置 AVStream 的一些参数信息。例如 : codec_id , format ,bit_rate ,width , height … …

你可能感兴趣的:(音视频开发学习)