ffmpeg源码学习结构体及配套函数的总结归纳

    我是一个比较笨的人,记忆力比较差的,可能学习到一定程度就觉得需要记录下来,这样怎能让我自己的学习完成由点到面的升华,所以我把ffmpeg源码学习中比较重要的部分记录下来,因为源码都是C/C++语言的需要有这些基础的人才能读懂源码。实事求是的说这种定制化开源源码的学习一定要从源码中提供的例子入手,从例子中先学习知识点,然后自己再通过上手编写,这样循序渐进才能得到提升。网络上这样的总结相对少很多,那么我将ffmpeg中API常用结构体以及跟和它配套使用的函数总结下来。先来张火锅图片吧,之后都是一些总结,等这些结构体和配套的函数都烂熟于心我们编写代码的时候就得心应手不少!

图片发自简书App


源码下载链接http://ffmpeg.org/,本总结的学习是基于ffmpeg-4.2,这是目前为止最新版。

下载之后使用visual stud code工具打开学习,建议从example开始学习!

1.AVPacket

    This structure stores compressed data. It is typically exported by demuxers and then passed as input to decoders, or received as output from encoders and then passed to muxers.

    For video, it should typically contain one compressed frame. For audio it may contain several compressed frames.      Encoders are allowed to output empty packets, with no compressed data, containing only side data (e.g. to update some stream parameters at the end of encoding). AVPacket is one of the few structs in FFmpeg, whose size is a part of public ABI.

    Thus it may be allocated on stack and no new fields can be added to it without libavcodec and libavformat major bump. The semantics of data ownership depends on the buf field.If it is set, the packet data is dynamically allocated and is valid indefinitely until a call to av_packet_unref() reduces the reference count to 0.

    If the buf field is not set av_packet_ref() would make a copy instead of increasing the reference count.The side data is always allocated with av_malloc(), copied by av_packet_ref() and freed by av_packet_unref().

@see av_packet_ref

@see av_packet_unref

与其对应的函数是

1.1 av_packet_alloc()

    Allocate an AVPacket and set its fields to default values.

    The resulting struct must be freed using av_packet_free(). @return An AVPacket filled with default values or NULL on failure.

@note this only allocates the AVPacket itself, not the data buffers. Those must be allocated through other means such as av_new_packet.

@see av_new_packet

1.2 av_packet_free()

    Free the packet, if the packet is reference counted, it will be unreferenced first. @param pkt packet to be freed. The pointer will be set to NULL.

@note passing NULL is a no-op.

2 AVCodec

    编解码器的结构体,包括了各种变量和函数指针,官方没有给出这个结构体的英文描述,但官方给出了大部分过成员变量的描述和解释

2.1 avcodec_find_decoder()

    Find a registered decoder with a matching codec ID.

@param id AVCodecID of the requested decoder @return A decoder if one was found, NULL otherwise.

3 AVCodecContext

    main external API structure.New fields can be added to the end with minor version bumps.

Removal, reordering and changes to existing fields require a major version bump. You can use AVOptions (av_opt* / av_set/get*()) to access these fields from user applications.

The name string for AVOptions options matches the associated command line parameter name and can be found in libavcodec/options_table.h

The AVOption/command line parameter names differ in some cases from the C structure field names for historic reasons or brevity.

sizeof(AVCodecContext) must not be used outside libav*.

3.1 avcodec_alloc_context3()

    Allocate an AVCodecContext and set its fields to default values. The resulting struct should be freed with avcodec_free_context().

@param codec if non-NULL, allocate private data and initialize defaults for the given codec. It is illegal to then call avcodec_open2() with a different codec.If NULL, then the codec-specific defaults won't be initialized,which may result in suboptimal default settings (this is important mainly for encoders, e.g. libx264).

@return An AVCodecContext filled with default values or NULL on failure.

3.2 avcodec_open2()

      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()).

4 AVFrame

    This structure describes decoded (raw) audio or video data.AVFrame must be allocated using av_frame_alloc().

Note that this only allocates the AVFrame itself, the buffers for the data must be managed through other means (see below). AVFrame must be freed with av_frame_free(). AVFrame is typically allocated once and then reused multiple times to hold different data (e.g. a single AVFrame to hold frames received from a decoder). In such a case, av_frame_unref() will free any references held by the frame and reset it to its original clean state before it is reused again.

The data described by an AVFrame is usually reference counted through the AVBuffer API. The underlying buffer references are stored in AVFrame.buf / AVFrame.extended_buf.

An AVFrame is considered to be reference counted if at least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case, every single data plane must be contained in one of the buffers in AVFrame.buf or AVFrame.extended_buf. There may be a single buffer for all the data, or one separate buffer for each plane, or anything in between. sizeof(AVFrame) is not a part of the public ABI, so new fields may be added to the end with a minor bump.

Fields can be accessed through AVOptions, the name string used, matches the C structure field name for fields accessible through AVOptions.

The AVClass for AVFrame can be obtained from avcodec_get_frame_class().

4.1 av_frame_alloc()

    Allocate an AVFrame and set its fields to default values. The resulting struct must be freed using av_frame_free(). @return An AVFrame filled with default values or NULL on failure.

@note this only allocates the AVFrame itself, not the data buffers. Those must be allocated through other means, e.g. with av_frame_get_buffer() or manually.

4.2 av_frame_free()

    Free the frame and any dynamically allocated objects in it, e.g. extended_data. If the frame is reference counted, it will be unreferenced first.

@param frame frame to be freed. The pointer will be set to NULL.

5 AVCodecParserContext

    解析器内容的结构体,包括了各种变量来解释和记录frame相关的side infomation,官方没有给出这个结构体的英文描述,但官方给出了大部分过成员变量的描述和解释

5.1 av_parser_init(参数codec的ID)

    利用与参数code ID匹配的解析器注册实例化并返回一个AVCodecParserContext类型。

5.2 av_parser_parse2()

    Parse a packet.

@param s parser context.

@param avctx codec context.

@param poutbuf set to pointer to parsed buffer or NULL if not yet finished.

@param poutbuf_size set to size of parsed buffer or zero if not yet finished.

@param buf input buffer.

@param buf_size buffer size in bytes without the padding. I.e. the full buffer size is assumed to be buf_size + AV_INPUT_BUFFER_PADDING_SIZE. To signal EOF, this should be 0 (so that the last frame can be output). @param pts input presentation timestamp.

@param dts input decoding timestamp.

@param pos input byte position in stream.

@return the number of bytes of the input bitstream used.

Example: @code

while(in_len){ len = av_parser_parse2(myparser, AVCodecContext, &data, &size,in_data, in_len,pts, dts, pos);

    in_data += len;

    in_len -= len;

    if(size) decode_frame(data, size); }

@endcode

5.3 av_parser_close()

    关闭解析器,free所有和解析相关的解析内容结构体指针

5.4 int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)

    Supply raw packet data as input to a decoder. Internally, this call will copy relevant AVCodecContext fields, which can influence decoding per-packet, and apply them when the packet is actually decoded. (For example AVCodecContext.skip_frame, which might direct the decoder to drop the frame contained by the packet sent with this function.)

@warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE larger than the actual read bytes because some optimized bitstream readers read 32 or 64 bits at once and could read over the end.

@warning Do not mix this API with the legacy API (like avcodec_decode_video2()) on the same AVCodecContext. It will return unexpected results now or in future libavcodec versions.

@note The AVCodecContext MUST have been opened with

@ref avcodec_open2() before packets may be fed to the decoder.

@param avctx codec context

@param[in] avpkt The input AVPacket. Usually, this will be a single video Ownership of the packet remains with the caller, and the decoder will not write to the packet. The decoder may create a reference to the packet data (or copy it if the packet is not reference-counted). Unlike with older APIs, the packet is always fully consumed, and if it contains multiple frames (e.g. some audio codecs),will require you to call avcodec_receive_frame() multiple times afterwards before you can send a new packet. It can be NULL (or an AVPacket with data set to NULL and size set to 0); in this case, it is considered a flushpacket, which signals the end of the stream. Sending the first flush packet will return success. Subsequent ones are unnecessary and will return AVERROR_EOF. If the decoder still has frames buffered, it will return them after sending a flush packet.

@return 0 on success, otherwise negative error code: AVERROR(EAGAIN): input is not accepted in the current state - user must read output with avcodec_receive_frame() (once all output is read, the packet should be resent, and the call will not fail with EAGAIN).

AVERROR_EOF: the decoder has been flushed, and no new packets can be sent to it (also returned if more than 1 flush packet is sent)

AVERROR(EINVAL): codec not opened, it is an encoder, or requires flush AVERROR(ENOMEM): failed to add packet to internal queue, or similar other errors: legitimate decoding errors.

5.5 int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)

    Return decoded output data from a decoder.

@param avctx codec context

@param frame This will be set to a reference-counted video or audio frame (depending on the decoder type) allocated by the decoder. Note that the function will always call av_frame_unref(frame) before doing anything else.

@return 0: success, a frame was returned AVERROR(EAGAIN): output is not available in this state - user must try to send new input AVERROR_EOF: the decoder has been fully flushed, and there will be no more output frames AVERROR(EINVAL): codec not opened, or it is an encoder AVERROR_INPUT_CHANGED: current decoded frame has changed parameters with respect to first decoded frame.

Applicable when flag AV_CODEC_FLAG_DROPCHANGED is set. other negative values: legitimate decoding errors.

6 AVFormatContext

    Format I/O context. New fields can be added to the end with minor version bumps. Removal, reordering and changes to existing fields require a major version bump.

sizeof(AVFormatContext) must not be used outside libav*, use avformat_alloc_context() to create an AVFormatContext. Fields can be accessed through AVOptions (av_opt*), the name string used matches the associated command line parameter name and can be found in libavformat/options_table.h.

The AVOption/command line parameter names differ in some cases from the C structure field names for historic reasons or brevity.

6.1 AVFormatContext *avformat_alloc_context(void)

    Allocate an AVFormatContext. avformat_free_context() can be used to free the context and everything allocated by the framework within it.

6.2 void avformat_free_context(AVFormatContext *s)

    Free an AVFormatContext and all its streams.@param s context to free

6.3 int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options)

    Open an input stream and read the header. The codecs are not opened. The stream must be closed with avformat_close_input().

@param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context). May be a pointer to NULL, in which case an AVFormatContext is allocated by this function and written into ps. Note that a user-supplied AVFormatContext will be freed on failure.

@param url URL of the stream to open.

@param fmt If non-NULL, this parameter forces a specific input format. Otherwise the format is autodetected.

@param options A dictionary filled with AVFormatContext and demuxer-private options. On return this parameter will be destroyed and replaced with a dict containing options that were not found. May be NULL.

@return 0 on success, a negative AVERROR on failure.

@note If you want to use custom IO, preallocate the format context and set its pb field.

6.4 int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)

    Read packets of a media file to get stream information. This is useful for file formats with no headers such as MPEG. This function also computes the real framerate in case of MPEG-2 repeat frame mode.The logical file position is not changed by this function; examined packets may be buffered for later processing.

@param ic media file handle

@param options If non-NULL, an ic.nb_streams long array of pointers to dictionaries, where i-th member contains options for codec corresponding to i-th stream. On return each dictionary will be filled with options that were not found.

@return >=0 if OK, AVERROR_xxx on error

@note this function isn't guaranteed to open all the codecs, so options being non-empty at return is a perfectly normal behavior.

@todo Let the user decide somehow what information is needed so that we do not waste time getting stuff the user does not need.

6.5 int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, int wanted_stream_nb, int related_stream, AVCodec **decoder_ret, int flags)

    Find the "best" stream in the file. The best stream is determined according to various heuristics as the most likely to be what the user expects. If the decoder parameter is non-NULL, av_find_best_stream will find the default decoder for the stream's codec; streams for which no decoder can be found are ignored.

@param ic media file handle

@param type stream type: video, audio, subtitles, etc.

@param wanted_stream_nb user-requested stream number,or -1 for automatic selection

@param related_stream try to find a stream related (eg. in the same program) to this one, or -1 if none

@param decoder_ret if non-NULL, returns the decoder for the selected stream

@param flags flags; none are currently defined

@return the non-negative stream number in case of success, AVERROR_STREAM_NOT_FOUND if no stream with the requested type could be found, AVERROR_DECODER_NOT_FOUND if streams were found but no decoder

@note If av_find_best_stream returns successfully and decoder_ret is not NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec.

6.6 int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par)

    Fill the codec context based on the values from the supplied codec parameters. Any allocated fields in codec that have a corresponding field in par are freed and replaced with duplicates of the corresponding field in par. Fields in codec that do not have a counterpart in par are not touched.

@return >= 0 on success, a negative AVERROR code on failure.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容

  • 教程一:视频截图(Tutorial 01: Making Screencaps) 首先我们需要了解视频文件的一些基...
    90后的思维阅读 4,693评论 0 3
  • 在上一篇笔记中我们已经完成了使用SDL播放声音和视频,声音播放没有什么问题,而视频播放太快,很明显视频没有同步。在...
    762683ff5d3d阅读 1,323评论 0 1
  • 根据ffmpeg官方网站上的例子程序开始学习ffmpeg和SDL编程。 SDL是一个跨平台的多媒体开发包。适用于游...
    762683ff5d3d阅读 1,796评论 0 2
  • 也曾用脚步丈量大地的宽广,马踏四方;也曾凭借满载丝绸的马车闯出悠悠丝路,喝一声“大漠孤烟直”;也曾乘风而下,万国来...
    春耕部落阅读 2,023评论 18 113
  • 我沉浸在谭维维的独特唱腔中,被半道而来的卡农旋律带动了情绪。单曲循环第四遍,铛问我:你觉得这里面最悲伤的是哪一句?...
    娜豆阅读 317评论 0 0