FFmpeg结构体分析:AVFormatContext连接FFmpeg的桥梁

AVFormatContext对开发者开放,是连接开发者与FFmpeg内部的桥梁。结构体内部包含有AVInputFormat、AVOutputFormat、AVCodec、AVStream、AVDictionary 、AVClass等。支持设置自定义IO、监听网络中断状态、设置options、直播秒开调优等。

AVFormatContext结构体的源码位于libavformat/avformat.h,具体代码如下:

在这里插入代码片typedef struct AVFormatContext {
    // 用于打印日志和设置选项的类
    const AVClass *av_class;
 
    // 输入容器格式
    ff_const59 struct AVInputFormat *iformat;
 
    // 输出容器格式
    ff_const59 struct AVOutputFormat *oformat;
 
    // 私有数据
    void *priv_data;
 
    /**
     * I/O 上下文
     *
     * - demuxing: avformat_open_input()之前设置
     * - muxing: avformat_write_header()之前设置
     */
    AVIOContext *pb;
 
    // 关于stream属性的Flags
    int ctx_flags;
 
    // 码流的数量
    unsigned int nb_streams;
 
    // 码流数组
    AVStream **streams;
 
    // 输入或输出的URL
    char *url;
 
    // 第一帧的开始时间
    int64_t start_time;
 
    // 码流的时长
    int64_t duration;
 
    // 码流的码率,单位为bit/s
    int64_t bit_rate;
 
    unsigned int packet_size;
    int max_delay;
 
    int flags;
#define AVFMT_FLAG_GENPTS       0x0001 ///< Generate missing pts
#define AVFMT_FLAG_IGNIDX       0x0002 ///< Ignore index.
#define AVFMT_FLAG_NONBLOCK     0x0004 ///< Do not block when reading packets from input.
#define AVFMT_FLAG_IGNDTS       0x0008 ///< Ignore DTS on frames
#define AVFMT_FLAG_NOFILLIN     0x0010 ///< Do not infer any values from other values
#define AVFMT_FLAG_NOPARSE      0x0020 ///< Do not use AVParsers
#define AVFMT_FLAG_NOBUFFER     0x0040 ///< Do not buffer frames when possible
#define AVFMT_FLAG_CUSTOM_IO    0x0080 ///< The caller has supplied a custom AVIOContext
#define AVFMT_FLAG_DISCARD_CORRUPT  0x0100 ///< Discard frames marked corrupted
#define AVFMT_FLAG_FLUSH_PACKETS    0x0200 ///< Flush the AVIOContext every packet.
#define AVFMT_FLAG_BITEXACT         0x0400
#if FF_API_LAVF_MP4A_LATM
#define AVFMT_FLAG_MP4A_LATM    0x8000 ///< Deprecated, does nothing.
#endif
#define AVFMT_FLAG_SORT_DTS    0x10000 ///< try to interleave outputted packets by dts 
#if FF_API_LAVF_PRIV_OPT
#define AVFMT_FLAG_PRIV_OPT    0x20000 ///< Enable use of private options by delaying codec open (deprecated, will do nothing once av_demuxer_open() is removed)
#endif
#if FF_API_LAVF_KEEPSIDE_FLAG
#define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Deprecated, does nothing.
#endif
#define AVFMT_FLAG_FAST_SEEK   0x80000 ///< Enable fast, but inaccurate seeks for some formats
#define AVFMT_FLAG_SHORTEST   0x100000 ///< Stop muxing when the shortest stream stops.
#define AVFMT_FLAG_AUTO_BSF   0x200000 ///< Add bitstream filters as requested by the muxer
 
    // 从输入流探测数据包的大小
    int64_t probesize;
 
    // 最大的分析时长,单位为AV_TIME_BASE
    int64_t max_analyze_duration;
 
    const uint8_t *key;
    int keylen;
 
    unsigned int nb_programs;
    AVProgram **programs;
 
    enum AVCodecID video_codec_id;
 
    enum AVCodecID audio_codec_id;
 
    enum AVCodecID subtitle_codec_id;
 
    unsigned int max_index_size;
 
    unsigned int max_picture_buffer;
 
    unsigned int nb_chapters;
    AVChapter **chapters;
 
    // 文件元数据媒体信息
    AVDictionary *metadata;
 
    int64_t start_time_realtime;
 
    int fps_probe_size;
 
    int error_recognition;
 
    // 自定义的I/O层中断回调
    AVIOInterruptCB interrupt_callback;
 
    int debug;
  
    int64_t max_interleave_delta;
 
    int strict_std_compliance;
 
    int event_flags;
 
    int max_ts_probe;
 
    // 避免负数的时间戳
    int avoid_negative_ts;
#define AVFMT_AVOID_NEG_TS_AUTO             -1 ///< Enabled when required by target format
#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative
#define AVFMT_AVOID_NEG_TS_MAKE_ZERO         2 ///< Shift timestamps so that they start at 0
 
    int ts_id;
 
    int audio_preload;
 
    int max_chunk_duration;
 
    int max_chunk_size;
 
    int use_wallclock_as_timestamps;
 
    int avio_flags;
 
    enum AVDurationEstimationMethod duration_estimation_method;
 
    int64_t skip_initial_bytes;
 
    unsigned int correct_ts_overflow;
 
    // 强制seek到任意帧,包括非关键帧位置
    int seek2any;
 
    int flush_packets;
 
    // 格式探测分数
    int probe_score;
 
    int format_probesize;
 
    // codec的白名单
    char *codec_whitelist;
 
    // format的白名单
    char *format_whitelist;
 
    AVFormatInternal *internal;
 
    int io_repositioned;
    // 视频codec
    AVCodec *video_codec;
    // 音频codec
    AVCodec *audio_codec;
    // 字幕codec
    AVCodec *subtitle_codec;
    // 数据codec
    AVCodec *data_codec;
 
    int metadata_header_padding;
 
    // 用户数据
    void *opaque;
 
    av_format_control_message control_message_cb;
 
    int64_t output_ts_offset;
 
    uint8_t *dump_separator;
 
    enum AVCodecID data_codec_id;
 
    // 协议白名单
    char *protocol_whitelist;
 
    // 打开新IO流的回调
    int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url,
                   int flags, AVDictionary **options);
 
    // 关闭IO流的回调
    void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);
 
    // 协议黑名单
    char *protocol_blacklist;
 
    int max_streams;
 
    int skip_estimate_duration_from_pts;
 
    int max_probe_packets;
} AVFormatContext;

打开输入流的流程比较简单,先分配AVFormatContext,然后再打开输入流:

AVFormatContext *format_ctx = avformat_alloc_context();
int ret = avformat_open_input(&format_ctx, url, NULL, NULL);

如果要设置avoptions,使用av_dict_set()来设置参数键值对:

AVDictionary *options = NULL;
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "pixel_format", "rgb24", 0);
AVFormatContext *format_ctx = avformat_alloc_context();
int ret = avformat_open_input(&format_ctx, url, NULL, &options);

如果要监听网络中断状态,使用AVIOInterruptCB进行监听:

static int custom_interrupt_callback(void *arg) {
    ......
}
 
AVFormatContext *format_ctx = avformat_alloc_context();
format_ctx->interrupt_callback.callback = custom_interrupt_callback;
format_ctx->interrupt_callback.opaque= NULL;
int ret = avformat_open_input(&format_ctx, url, NULL, NULL);

其中AVIOInterruptCB的结构体定义如下,包含callback函数指针和opaque:

typedef struct AVIOInterruptCB {
    int (*callback)(void*);
    void *opaque;
} AVIOInterruptCB;

在使用FFmpeg拉流直播时,做直播秒开调优,可以调节probesize和max_analyze_duration。其中probesize表示探测数据包的大小,max_analyze_duration表示最大分析时长,比如这样:

probesize            = 5 * 1024 * 1024;
max_analyze_duration = 500;

如果要自定义IO读取缓冲区数据,使用AVIOContext,分配缓冲区,实现read_packet、write_packet、seek方法:

#define IO_BUFFER_SIZE (4 * 1024 * 1024)
 
uint8_t *io_buffer = av_malloc(IO_BUFFER_SIZE);
 
int read_packet(void *opaque, uint8_t *buf, int buf_size) {
  ......
}
 
int64_t seek(void *opaque, int64_t offset, int whence) {
  ......
}
 
AVIOContext *avio_ctx = avio_alloc_context(io_buffer, IO_BUFFER_SIZE, 0, &user_data, &read_packet, NULL, &seek);
AVFormatContext *format_ctx = avformat_alloc_context();
format_ctx .pb = avio_ctx;
format_ctx->flags |= AVFMT_FLAG_CUSTOM_IO;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值