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我们不需要理解,我们大概喵一眼即可。
)。
这个结构体非常简单,我们只需要知道总结的那两点,即它如何初始化赋值和它的作用即可。