视频编码的流程:
流程中各个函数的含义:
1. av_register_all()
功能:
初始化所有组件,该函数在所有基于ffmpeg的应用程序中几乎都是第一个被调用的。只有调用了该函数,才能使用复用器,编码器等。
该接口内部的调用为:
(1).avcodec_register_all(),该接口内部执行步骤:
- 注册硬件加速器:REGISTER_HWACCEL()
- 注册音视频编码器:REGISTER_ENCODER()
- 注册音视频解码器:REGISTER_DECODER()
- 打包注册:REGISTER_ENCDEC()
- 注册解析器:REGISTER_PARSER()
(2).执行复用器和解复用器的注册:
- 注册复用器:REGISTER_MUXER()
- 注册解复用器:REGISTER_DEMUXER()
- 既有解复用器又有复用器: REGISTER_MUXDEMUX(X,x));
2. avformat_alloc_output_context2()
功能
avformat_alloc_output_context2()函数可以初始化一个用于输出的AVFormatContext结构体。它的声明位于libavformat\avformat.h。
函数声明
/**
* Allocate an AVFormatContext for an output format.
* avformat_free_context() can be used to free the context and
* everything allocated by the framework within it.
*
* @param *ctx is set to the created format context, or to NULL in
* case of failure
* @param oformat format to use for allocating the context, if NULL
* format_name and filename are used instead
* @param format_name the name of output format to use for allocating the
* context, if NULL filename is used instead
* @param filename the name of the filename to use for allocating the
* context, may be NULL
* @return >= 0 in case of success, a negative AVERROR code in case of
* failure
*/
int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat,
const char *format_name, const char *filename);
参数说明
ctx:函数调用成功之后创建的AVFormatContext结构体。
oformat:指定AVFormatContext中的AVOutputFormat,用于确定输出格式。如果指定为NULL,可以设定后两个参数(format_name或者filename)由FFmpeg猜测输出格式。
PS:使用该参数需要自己手动获取AVOutputFormat,相对于使用后两个参数来说要麻烦一些。
format_name:指定输出格式的名称。根据格式名称,FFmpeg会推测输出格式。输出格式可以是“flv”,“mkv”等等。
返回值
函数执行成功的话,其返回值大于等于0。
调用关系
avformat_alloc_output_context2()的流程如要包含以下2步:
调用avformat_alloc_context()初始化一个默认的AVFormatContext。
如果指定了输入的AVOutputFormat,则直接将输入的AVOutputFormat赋值给AVOutputFormat的oformat。如果没有指定输入的AVOutputFormat,就需要根据文件格式名称或者文件名推测输出的AVOutputFormat。无论是通过文件格式名称还是文件名推测输出格式,都会调用一个函数av_guess_format()。
3. avio_open()
- 功能
该函数用于打开FFmpeg的输入输出文件。avio_open2()的声明位于libavformat\avio.h文件中。 - 声明
/**
* Create and initialize a AVIOContext for accessing the
* resource indicated by url.
* @note When the resource indicated by url has been opened in
* read+write mode, the AVIOContext can be used only for writing.
*
* @param s Used to return the pointer to the created AVIOContext.
* In case of failure the pointed to value is set to NULL.
* @param url resource to access
* @param flags flags which control how the resource indicated by url
* is to be opened
* @return >= 0 in case of success, a negative value corresponding to an
* AVERROR code in case of failure
*/
int avio_open(AVIOContext **s, const char *url, int flags);
参数含义
s:函数调用成功之后创建的AVIOContext结构体。
url:输入输出协议的地址(文件也是一种“广义”的协议,对于文件来说就是文件的路径)。
flags:打开地址的方式。可以选择只读,只写,或者读写。取值如下。 AVIO_FLAG_READ:只读。 AVIO_FLAG_WRITE:只写。 AVIO_FLAG_READ_WRITE:读写。
有一个和avio_open()“长得很像”的函数avio_open2(),应该是avio_open()的后期版本。avio_open()比avio_open2()少了最后2个参数。而它前面几个参数的含义和avio_open2()是一样的。从源代码中可以看出,avio_open()内部调用了avio_open2(),并且把avio_open2()的后2个参数设置成了NULL,因此它的功能实际上和avio_open2()是一样的。avio_open()源代码如下所示。
4. avformat_new_stream()
- 功能
avformat_new_stream 在 AVFormatContext 中创建 Stream 通道。 - 声明
/**
* Add a new stream to a media file.
*
* When demuxing, it is called by the demuxer in read_header(). If the
* flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also
* be called in read_packet().
*
* When muxing, should be called by the user before avformat_write_header().
*
* User is required to call avcodec_close() and avformat_free_context() to
* clean up the allocation by avformat_new_stream().
*
* @param s media file handle
* @param c If non-NULL, the AVCodecContext corresponding to the new stream
* will be initialized to use this codec. This is needed for e.g. codec-specific
* defaults to be set, so codec should be provided if it is known.
*
* @return newly created stream or NULL on error.
*/
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);
5. avcodec_find_encoder()
- 功能
avcodec_find_encoder()用于查找FFmpeg的编码器 - 定义
/**
* avcodec_find_encoder()的声明位于libavcodec\avcodec.h
* Find a registered encoder with a matching codec ID.
*
* @param id AVCodecID of the requested encoder
* @return An encoder if one was found, NULL otherwise.
*/
AVCodec *avcodec_find_encoder(enum AVCodecID id);
- 参数
函数的参数是一个编码器的ID,返回查找到的编码器(没有找到就返回NULL)。 - 函数调用关系图
6. avcodec_open2()
- 功能
该函数用于初始化一个视音频编解码器的AVCodecContext。avcodec_open2()的声明位于libavcodec\avcodec.h。 - 声明
/**
* Initialize the AVCodecContext to use the given AVCodec. Prior to using this
* function the context has to be allocated with avcodec_alloc_context3().
*
* The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),
* avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for
* retrieving a codec.
*
* @warning This function is not thread safe!
*
* @note Always call this function before using decoding routines (such as
* @ref avcodec_receive_frame()).
*
* @code
* avcodec_register_all();
* av_dict_set(&opts, "b", "2.5M", 0);
* codec = avcodec_find_decoder(AV_CODEC_ID_H264);
* if (!codec)
* exit(1);
*
* context = avcodec_alloc_context3(codec);
*
* if (avcodec_open2(context, codec, opts) < 0)
* exit(1);
* @endcode
*
* @param avctx The context to initialize.
* @param codec The codec to open this context for. If a non-NULL codec has been
* previously passed to avcodec_alloc_context3() or
* for this context, then this parameter MUST be either NULL or
* equal to the previously passed codec.
* @param options A dictionary filled with AVCodecContext and codec-private options.
* On return this object will be filled with options that were not found.
*
* @return zero on success, a negative value on error
* @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(),
* av_dict_set(), av_opt_find().
*/
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
- 参数
avctx:需要初始化的AVCodecContext。
codec:输入的AVCodec
options:一些选项。例如使用libx264编码的时候,“preset”,“tune”等都可以通过该参数设置。 - 调用关系
梳理一下avcodec_open2()所做的工作,如下所列:
(1)为各种结构体分配内存(通过各种av_malloc()实现)。
(2)将输入的AVDictionary形式的选项设置到AVCodecContext。
(3)其他一些零零碎碎的检查,比如说检查编解码器是否处于“实验”阶段。
(4)如果是编码器,检查输入参数是否符合编码器的要求
(5)调用AVCodec的init()初始化具体的解码器。
7. avformat_write_header()
功能
avformat_write_header()用于写视频文件头。
需要注意的是,尽管这3个函数功能是配套的,但是它们的前缀却不一样,写文件头Header的函数前缀是“avformat_”,其他两个函数前缀是“av_”。
声明
/**
* Allocate the stream private data and write the stream header to
* an output media file.
*
* @param s Media file handle, must be allocated with avformat_alloc_context().
* Its oformat field must be set to the desired output format;
* Its pb field must be set to an already opened AVIOContext.
* @param options An AVDictionary filled with AVFormatContext and muxer-private options.
* On return this parameter will be destroyed and replaced with a dict containing
* options that were not found. May be NULL.
*
* @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec had not already been fully initialized in avformat_init,
* AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec had already been fully initialized in avformat_init,
* negative AVERROR on failure.
*
* @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output.
*/
函数正常执行后返回值等于0。
av_warn_unused_result
int avformat_write_header(AVFormatContext *s, AVDictionary **options);
参数的含义:
s:用于输出的AVFormatContext。
options:额外的选项,目前没有深入研究过,一般为NULL。
8. av_write_frame()
- 功能
用于输出一帧视音频数据,它的声明位于libavformat\avformat.h。 - 声明
/**
* Write a packet to an output media file.
*
* This function passes the packet directly to the muxer, without any buffering
* or reordering. The caller is responsible for correctly interleaving the
* packets if the format requires it. Callers that want libavformat to handle
* the interleaving should call av_interleaved_write_frame() instead of this
* function.
*
* @param s media file handle
* @param pkt The packet containing the data to be written. Note that unlike
* av_interleaved_write_frame(), this function does not take
* ownership of the packet passed to it (though some muxers may make
* an internal reference to the input packet).
* <br>
* This parameter can be NULL (at any time, not just at the end), in
* order to immediately flush data buffered within the muxer, for
* muxers that buffer up data internally before writing it to the
* output.
* <br>
* Packet's @ref AVPacket.stream_index "stream_index" field must be
* set to the index of the corresponding stream in @ref
* AVFormatContext.streams "s->streams".
* <br>
* The timestamps (@ref AVPacket.pts "pts", @ref AVPacket.dts "dts")
* must be set to correct values in the stream's timebase (unless the
* output format is flagged with the AVFMT_NOTIMESTAMPS flag, then
* they can be set to AV_NOPTS_VALUE).
* The dts for subsequent packets passed to this function must be strictly
* increasing when compared in their respective timebases (unless the
* output format is flagged with the AVFMT_TS_NONSTRICT, then they
* merely have to be nondecreasing). @ref AVPacket.duration
* "duration") should also be set if known.
* @return < 0 on error, = 0 if OK, 1 if flushed and there is no more data to flush
*
* @see av_interleaved_write_frame()
*/
int av_write_frame(AVFormatContext *s, AVPacket *pkt);
参数的含义:
s:用于输出的AVFormatContext。
pkt:等待输出的AVPacket。
函数正常执行后返回值等于0。
从源代码可以看出,av_write_frame()主要完成了以下几步工作:
(1)调用check_packet()做一些简单的检测
(2)调用compute_pkt_fields2()设置AVPacket的一些属性值
(3)调用write_packet()写入数据
9. av_write_trailer()
- 功能
用于输出文件尾,它的声明位于libavformat\avformat.h。
它只需要指定一个参数,即用于输出的AVFormatContext。
函数正常执行后返回值等于0。 - 声明
/**
* Write the stream trailer to an output media file and free the
* file private data.
*
* May only be called after a successful call to avformat_write_header.
*
* @param s media file handle
* @return 0 if OK, AVERROR_xxx on error
*/
int av_write_trailer(AVFormatContext *s);
从源代码可以看出av_write_trailer()主要完成了以下两步工作:
(1)循环调用interleave_packet()以及write_packet(),将还未输出的AVPacket输出出来。
(2)调用AVOutputFormat的write_trailer(),输出文件尾。
AVOutputFormat的write_trailer()是一个函数指针,指向特定的AVOutputFormat中的实现函数。
原文链接:FFmpeg--视频编码的流程_ffmepg format_name_WaitFoF的博客-CSDN博客
★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。
见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓