美文网首页ffmpeg
FFmpeg 开源项目分析(三)AVStream解析

FFmpeg 开源项目分析(三)AVStream解析

作者: 码上就说 | 来源:发表于2020-06-02 01:19 被阅读0次

    FFmpeg 开源项目分析(一)FFmpeg/Openssl/x264编译
    FFmpeg 开源项目分析(二)AVFormatContext解析
    FFmpeg 开源项目分析(三)AVStream解析
    FFmpeg 开源项目分析(四)AVCodecParameters解析

    上一章分析了AVFormatContext,其中有两个参数

        unsigned int nb_streams;
        AVStream **streams;
    

    nb_streams是当前轨道数,就是流数量,streams是轨道的指针数组。一般而言一个视频文件会有一个视频流和一个音频流,那就是两个AVStream结构。我们看一下AVStream结构体的源码,在libavformat/avformat.h中。

    /**
     * Stream structure.
     * New fields can be added to the end with minor version bumps.
     * Removal, reordering and changes to existing fields require a major
     * version bump.
     * sizeof(AVStream) must not be used outside libav*.
     */
    typedef struct AVStream {
        int index;    /**< stream index in AVFormatContext */
        /**
         * Format-specific stream ID.
         * decoding: set by libavformat
         * encoding: set by the user, replaced by libavformat if left unset
         */
        int id;
    #if FF_API_LAVF_AVCTX
        /**
         * @deprecated use the codecpar struct instead
         */
        attribute_deprecated
        AVCodecContext *codec;
    #endif
        void *priv_data;
    
        /**
         * This is the fundamental unit of time (in seconds) in terms
         * of which frame timestamps are represented.
         *
         * decoding: set by libavformat
         * encoding: May be set by the caller before avformat_write_header() to
         *           provide a hint to the muxer about the desired timebase. In
         *           avformat_write_header(), the muxer will overwrite this field
         *           with the timebase that will actually be used for the timestamps
         *           written into the file (which may or may not be related to the
         *           user-provided one, depending on the format).
         */
        AVRational time_base;
    
        /**
         * Decoding: pts of the first frame of the stream in presentation order, in stream time base.
         * Only set this if you are absolutely 100% sure that the value you set
         * it to really is the pts of the first frame.
         * This may be undefined (AV_NOPTS_VALUE).
         * @note The ASF header does NOT contain a correct start_time the ASF
         * demuxer must NOT set this.
         */
        int64_t start_time;
    
        /**
         * Decoding: duration of the stream, in stream time base.
         * If a source file does not specify a duration, but does specify
         * a bitrate, this value will be estimated from bitrate and file size.
         *
         * Encoding: May be set by the caller before avformat_write_header() to
         * provide a hint to the muxer about the estimated duration.
         */
        int64_t duration;
    
        int64_t nb_frames;                 ///< number of frames in this stream if known or 0
    
        int disposition; /**< AV_DISPOSITION_* bit field */
    
        enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed.
    
        /**
         * sample aspect ratio (0 if unknown)
         * - encoding: Set by user.
         * - decoding: Set by libavformat.
         */
        AVRational sample_aspect_ratio;
    
        AVDictionary *metadata;
    
        /**
         * Average framerate
         *
         * - demuxing: May be set by libavformat when creating the stream or in
         *             avformat_find_stream_info().
         * - muxing: May be set by the caller before avformat_write_header().
         */
        AVRational avg_frame_rate;
    
        /**
         * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet
         * will contain the attached picture.
         *
         * decoding: set by libavformat, must not be modified by the caller.
         * encoding: unused
         */
        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;
    
    • int index:标识该视频/音频流
    • AVCodecContext *codec:指向该视频/音频流的AVCodecContext(它们是一一对应的关系)
    • AVRational time_base:时基。通过该值可以把PTS,DTS转化为真正的时间。FFMPEG其他结构体中也有这个字段,但是根据我的经验,只有AVStream中的time_base是可用的。PTS*time_base=真正的时间
    • int64_t duration:该视频/音频流长度
    • AVDictionary *metadata:元数据信息
    • AVRational avg_frame_rate:帧率(注:对视频来说,这个挺重要的)
    • AVPacket attached_pic:附带的图片。比如说一些MP3,AAC音频文件附带的专辑封面。
    • nb_frames:帧个数

    AVStream结构中的数据要靠解码才能得到了,所以是Codec工作之后才能得到的数据。AVStream中的数才是最准确的。
    例如AVFormatContext中也有width-height,但是这个width-height不一定准确,一般我们解码出AVRational display_aspect_ratio,这个里面的宽高比才是最终准确的。
    或者AVCodecContext *codec中也有宽高的数据。毕竟解出来的帧数据中的信息才最可靠。

    感谢关注公众号JeffMony,持续给你带来音视频方面的知识。

    相关文章

      网友评论

        本文标题:FFmpeg 开源项目分析(三)AVStream解析

        本文链接:https://www.haomeiwen.com/subject/opcyzhtx.html