FFmpeg源码分析: AVStream码流

在AVCodecContext结构体存储有AVStream数组,包含所有视频流、音频流、字幕流的信息。每个码流包含有时间基、时长、索引数组、编解码器参数、dts、元数据。其中,索引数组用于保存每帧数据包offset、size、timestamp、flag,用于seek定位某个时间戳对应的帧。

AVStream结构体如下:

typedef struct AVStream {
	// 数组索引
    int index;
    // stream id
    int id;
    // 私有数据
    void *priv_data;
    // 时间基
    AVRational time_base;
    // 开始时间
    int64_t start_time;
    // 码流时长
    int64_t duration;
    // 帧数
    int64_t nb_frames;
    int disposition; /**< AV_DISPOSITION_* bit field */
    // 选择丢弃哪些packets
    enum AVDiscard discard;
    // 宽高比
    AVRational sample_aspect_ratio;
    // 码流的元数据信息
    AVDictionary *metadata;
    // 平均帧率
    AVRational avg_frame_rate;
    // 封面信息
    AVPacket attached_pic;
    // 附加数据
    AVPacketSideData *side_data;
    int            nb_side_data;

    int event_flags;

    AVRational r_frame_rate;
    // 编解码器参数
    AVCodecParameters *codecpar;

    int pts_wrap_bits;

    int64_t first_dts;
    int64_t cur_dts;
    int64_t last_IP_pts;
    int last_IP_duration;

    int probe_packets;

    int codec_info_nb_frames;

    /* av_read_frame() support */
    enum AVStreamParseType need_parsing;
    struct AVCodecParserContext *parser;
    // 索引数组
    AVIndexEntry *index_entries;
	// 索引数组长度
    int nb_index_entries;
    unsigned int index_entries_allocated_size;

    int stream_identifier;

    AVStreamInternal *internal;
} AVStream;

我们来看下ffprobe打印的码流信息,该mp4文件有5个码流,属于双音轨双字幕。第一个是video,编码器为h264,帧率为23.98fps,分辨率为720x306,像素格式为yuv420p;第二个是audio,编码器为aac,采样率为44100,立体声,语言为印地语;第三个也是audio,参数与第二个相同,除了语言是英语;第四个是subtitle,语言为英语,编码器为mov_text;第五个也是subtitle,参数与第四个相同。具体的码流信息如下:

 

 接下来是调试的实时数据,stream数组信息:

 然后是AVCodecContext的编解码器参数,包括codec_type(媒体类型)、codec_id、bit_rate、profile、level、width、height、sample_rate、channels等。具体参数如下:

 另外,AVStream内部有nb_index_entries(索引数组长度)、index_entries(索引数组)。而索引数组包括:offset、size、timestamp、flags、min_distance。在seek操作时,根据给定时间戳二分查找timestamp数组,seek有三种模式:previous、next、nearest,一般使用previous前向查找。具体信息如下:

 最后,要讨论的是time_base时间基。FFmpeg中的时间戳是用time_base作为单位,位于rational.h的AVRational结构体定义如下:

typedef struct AVRational{
    int num; ///< Numerator
    int den; ///< Denominator
} AVRational;

换算为真实时间,需要使用num分子与den分母相除,公式如下:

static inline double av_q2d(AVRational a){
    return a.num / (double) a.den;
}

猜你喜欢

转载自blog.csdn.net/u011686167/article/details/121528354