03FFMPEG的AVOutputFormat结构体分析

03FFMPEG的AVOutputFormat结构体分析

概述:
该结构体位于libavformat库中的avformat.h中。

1 AVOutputFormat输出封装结构体分析
与AVInputFormat类似。

/*
 * 该结构体保存着输出文件指明码流数据用到封装格式。例如flv,mkv。 可认为是存放输出文件的头部相关属性信息。例如flv的头部。位于封装上下文结构体AVFormatContext的内部。
 * 
 * 注意:该结构体只有在复用时才有效,由avformat_alloc_output_context2(&m_outputContext, nullptr, "flv", outUrl.c_str())打开时确定对应的封装格式(例如flv)进行初始化赋值。
 * 解复用时该结构体无效。
*/
typedef struct AVOutputFormat {
    const char *name;//封装格式名称
    /**
     * 格式的描述性名称,这意味着比名称name更易于人类阅读。你应该使用NULL_IF_CONFIG_SMALL()宏来定义它。即与上面的name是一样的意思。
     */
    const char *long_name;
    const char *mime_type;
    const char *extensions; /**< 逗号分隔的文件扩展名 */
    /* output support */
    enum AVCodecID audio_codec;    /**< default audio codec */
    enum AVCodecID video_codec;    /**< default video codec */
    enum AVCodecID subtitle_codec; /**< default subtitle(字幕) codec */
    /**
     * flags可以使用的标记宏: AVFMT_NOFILE, AVFMT_NEEDNUMBER,
     * AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS,
     * AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH,
     * AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE
     */
    int flags;

    /**
     * 支持的codec_id-codec_tag的组对列表(pair),按“更好的选择优先”排序。数组都由AV_CODEC_ID_NONE终止。
     */
    const struct AVCodecTag * const *codec_tag;


    const AVClass *priv_class; ///< AVClass for the private context

    /*****************************************************************
     * 这一行以下的字段都不是公共API的一部分。它们可能不会被libavformat之外的使用,并且可以被随意更改和删除。
     * 新的公共字段应该在正上方添加。
     *****************************************************************
     */
     
    /**
     * ff_const59定义不是公共API的一部分,它将在没有进一步警告的情况下被删除。
     */
#if FF_API_AVIOFORMAT
#define ff_const59
#else
#define ff_const59 const
#endif
#if FF_API_NEXT
    ff_const59 struct AVOutputFormat *next;
#endif

    /**
     * 私有数据的大小,以便在wrapper包装器中进行分配。
     */
    int priv_data_size;

    int (*write_header)(struct AVFormatContext *);
    /**
     * 写一个包。
     * 如果AVFMT_ALLOW_FLUSH设置在flags中,pkt可以为NULL,以便刷新muxer复用器中缓冲的数据。
     * 在刷新时,如果还有更多数据需要刷新,则返回0;如果所有数据都已刷新,且没有更多缓冲数据,则返回1。
     */
    int (*write_packet)(struct AVFormatContext *, AVPacket *pkt);
    int (*write_trailer)(struct AVFormatContext *);
    
    /**
     * 一个格式具体指定的函数对于交错分包时。
     * 如果未设置,数据包将被dts交叉放置。
     */
    int (*interleave_packet)(struct AVFormatContext *, AVPacket *out,
                             AVPacket *in, int flush);
    /**
     * 测试给定的编解码器是否可以存储在这个容器中。
     * 
     * 返回1证明给定的编解码器id可以被存储,0代表不支持,负数表示未知。
     * MKTAG('A', 'P', 'I', 'C')如果只支持AV_DISPOSITION_ATTACHED_PIC编解码器。(笔者这里也不是很懂,不需要理会)
     */
    int (*query_codec)(enum AVCodecID id, int std_compliance);

    void (*get_output_timestamp)(struct AVFormatContext *s, int stream,
                                 int64_t *dts, int64_t *wall);
    /**
     * 允许从应用程序发送消息到设备。
     */
    int (*control_message)(struct AVFormatContext *s, int type,
                           void *data, size_t data_size);

    /**
     * 写一个未编码的AVFrame。
     *
     * 详细可查看av_write_uncoded_frame()函数。
     * 
     * library标准库将在之后释放*frame,但是muxer复用器可以通过将指针设置为NULL来阻止它。
     */
    int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index,
                               AVFrame **frame, unsigned flags);
    /**
     * 返回设备列表和它的属性。
     * 更多详细可查看avdevice_list_devices()函数。
     */
    int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
    /**
     * 初始化创建设备功能子模块。
     * 更多详细可查看avdevice_capabilities_create()函数。
     */
    int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
    /**
     * 释放设备能力子模块。
     * 更多详细可查看avdevice_capabilities_free()函数。
     */
    int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
    enum AVCodecID data_codec; /**< default data codec */
    /**
     * 初始化格式。可以在这里分配数据,并设置任何需要在数据包发送之前设置的AVFormatContext或AVStream参数。
     * 此方法不能写入输出。
     *
     * Return 0 if streams were fully configured, 1 if not, negative AVERROR on failure
     * 如果完全配置好流,返回0;如果没有,返回1;失败时返回负的AVERROR错误号。
     *
     * 这里所做的任何分配必须在deinit()中释放。
     */
    int (*init)(struct AVFormatContext *);
    /**
     * Deinitialize(解初始化即释放)格式。 如果存在,则在销毁muxer复用器时调用该函数,而不管头文件是否已经被写入。
     *
     * 如果正在写一个trailer ,它会在write_trailer()之后调用。
     *
     * 如果init()也失败了,就会调用它。
     */
    void (*deinit)(struct AVFormatContext *);
    /**
     *设置任何必要的位流过滤,并提取全局标头所需的任何额外数据。
     * Return 0 if more packets from this stream must be checked; 1 if not.
     * 如果必须检查流中更多的数据包则返回0;否则返回1。
     */
    int (*check_bitstream)(struct AVFormatContext *, const AVPacket *pkt);
} AVOutputFormat;

2 AVOutputFormat中重要的成员
同理,AVOutputFormat和AVInputFormat非常相似,里面只是存放要输出文件的相关属性。例如flv,mkv封装格式名称。其它均为avformat内部处理封装格式的API,即priv_class以下的字段。

typedef struct AVOutputFormat{
	const char *name;//输出时的封装格式名
	const char *long_name;//同上,但是更人性化
	const char *extensions;//输出封装格式的扩展名
	/*......*/
}AVOutputFormat;

3 总结AVOutputFormat输出封装格式结构体
1)由avformat_alloc_output_context2(&m_outputContext, nullptr, “flv”, outUrl.c_str())打开时确定对应的封装格式(例如flv)进行开辟内存并初始化赋值,只有在复用时才有效,解复用无效。
注:有效是指输出时的AVFormatContext->AVOutputFormat有效,而输入时是指另一个AVFormatContext->AVInputFormat有效。第一个AVFormatContext和第二个AVFormatContext是不同的,一个是输出时的封装上下文,一个是输入时的解封装上下文。

2)存放输出文件的相关封装属性和其它处理封装格式的API,且这些API只在avformat内部有效(所以非公共的API我们不需要理解,我们大概喵一眼即可。
)。

这个结构体非常简单,我们只需要知道总结的那两点,即它如何初始化赋值和它的作用即可。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值