FFmpeg5.0源码阅读之AVClass和AVOption

这篇具有很好参考价值的文章主要介绍了FFmpeg5.0源码阅读之AVClass和AVOption。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  摘要:本文通过阅读FFmpeg源码来理解FFmpeg中AVOption的实现原理和具体的使用方式。
  关键字:AVClss,AVOption,AVOptionRange
  版本:FFmpeg5.0

1 AVOption结构

  AVOption是FFmpeg中设置参数的一个基本抽象结构。因为FFmpeg是一个支持多种封装解封装器,编解码器的框架,而不同的外部库需要的参数各不相同,因此利用AVOption来封装一个基本的key-value结构来获取和设置对应模块的参数。AVOption本身就是一个key-value项,可以理解为C++中map中的项pair,而其中name就是keydefault_val就是value。而在实际使用中所有的参数是存储在AVClass中的AVOption数组中,而需要设置参数的模块会在Context结构体开头设置一个AVClass的指针来表示当前模块的参数,FFmpeg通过搜索该数组来获取和设置对应模块的参数。另外,并不是所有的参数都会存储在AVOption中,有些参数对应的Context本身就有对应的成员,因此AVOption只需要指定该成员相对应该Context首部地址的偏移即可进行设置和读取,也就是说通过AVOption设置和直接用Context->param = value的形式是一致的。

typedef struct AVOption {
    const char *name;           //参数名称
    const char *help;           //简短的帮助信息,因为是char因此无法支持中文等语言
    int offset;                 //选项相对于结构体首部的偏移量
    enum AVOptionType type;     //选项的类型
    union {
        int64_t i64;
        double dbl;
        const char *str;
        AVRational q;
    } default_val;              //选项的默认值
    double min;                 //选项可允许的最小值
    double max;                 //选项可允许的最大值
    int flags;                  //标志符
    const char *unit;           //当前选项所属的逻辑单元,可以为NULL
} AVOption;
  • default_value:当前选项的值是一个64bit的union,这基本能够表示所有的数值参数和字符串参数;

  • type:当前选项的类型,如下面的AVOptionType的定义,不仅仅输数据类型也涵盖了一些FFmpeg中用到的选项类型;

    enum AVOptionType{
      AV_OPT_TYPE_FLAGS,
      AV_OPT_TYPE_INT,
      AV_OPT_TYPE_INT64,
      AV_OPT_TYPE_DOUBLE,
      AV_OPT_TYPE_FLOAT,
      AV_OPT_TYPE_STRING,
      AV_OPT_TYPE_RATIONAL,
      AV_OPT_TYPE_BINARY,  ///< offset must point to a pointer immediately followed by an int for the length
      AV_OPT_TYPE_DICT,
      AV_OPT_TYPE_UINT64,
      AV_OPT_TYPE_CONST,
      AV_OPT_TYPE_IMAGE_SIZE, ///< offset must point to two consecutive integers
      AV_OPT_TYPE_PIXEL_FMT,
      AV_OPT_TYPE_SAMPLE_FMT,
      AV_OPT_TYPE_VIDEO_RATE, ///< offset must point to AVRational
      AV_OPT_TYPE_DURATION,
      AV_OPT_TYPE_COLOR,
      AV_OPT_TYPE_CHANNEL_LAYOUT,
      AV_OPT_TYPE_BOOL,
    };
    
  • offset:如上面描述,这个offset是相对于包含AVClass的Context的首地址的偏移;

  • min,max:选项取值范围,需要注意的是这里声明的是double;

  • flagsflag描述当前选项的用处,如下定义;

    #define AV_OPT_FLAG_ENCODING_PARAM  1   ///< a generic parameter which can be set by the user for muxing or encoding
    #define AV_OPT_FLAG_DECODING_PARAM  2   ///< a generic parameter which can be set by the user for demuxing or decoding
    #define AV_OPT_FLAG_AUDIO_PARAM     8
    #define AV_OPT_FLAG_VIDEO_PARAM     16
    #define AV_OPT_FLAG_SUBTITLE_PARAM  32
    //The option is intended for exporting values to the caller.
    #define AV_OPT_FLAG_EXPORT          64
    //The option may not be set through the AVOptions API, only read. This flag only makes sense when AV_OPT_FLAG_EXPORT is also set.
    #define AV_OPT_FLAG_READONLY        128
    #define AV_OPT_FLAG_BSF_PARAM       (1<<8) ///< a generic parameter which can be set by the user for bit stream filtering
    #define AV_OPT_FLAG_RUNTIME_PARAM   (1<<15) ///< a generic parameter which can be set by the user at runtime
    #define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering
    #define AV_OPT_FLAG_DEPRECATED      (1<<17) ///< set if option is deprecated, users should refer to AVOption.help text for more information
    #define AV_OPT_FLAG_CHILD_CONSTS    (1<<18) ///< set if option constants can also reside in child objects
    

2 AVClass结构

  由于设置AVOption都是通过AVClass进行的,因此有必要了解下AVClass的结构。AVClass是FFmpeg中描述一个Context的抽象,FFmpeg中的Context的第一个成员就是一个AVClass的指针来描述当前Context的基本信息和相关的参数,设置参数也是通过这个指针进行的。比如AVFormatContext

typedef struct AVFormatContext {
    //A class for logging and @ref avoptions. Set by avformat_alloc_context(). Exports (de)muxer private options if they exist.
    const AVClass *av_class;
    //省略大部分代码
}AVFormatContext;
typedef struct AVClass {
    const char* class_name;                            //AVClass所属类的名称
    const char* (*item_name)(void* ctx);               //获取AVClass所属类名称的函数指针,有些实现会直接返回AVClass->class_name
    const struct AVOption *option;                     //当前类的参数,没有就置为NULL
    int version;                                       //当前字段创建的版本,可用于版本控制,This is used to allow fields to be added without requiring major version bumps everywhere.
    int log_level_offset_offset;                       //AVClass所属结构体中log_level_offset相对于其首地址的偏移,0表示没有该成员
    int parent_log_context_offset;                     //当前Context中存储parent context的偏移量
    void* (*child_next)(void *obj, void *prev);        //AVOptions中下一个可用的参数
    AVClassCategory category;                          //当前类的类别
    AVClassCategory (*get_category)(void* ctx);        //获取当前Context类别的函数指针      
    //查询对应选项的范围,虽然定义了但是FFmpeg源码中好像没有API用到
    int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags);
    /**
     * Iterate over the AVClasses corresponding to potential AVOptions-enabled children.
     * @param iter pointer to opaque iteration state. The caller must initialize *iter to NULL before the first call.
     * @return AVClass for the next AVOptions-enabled child or NULL if there are no more such children.
     * @note The difference between child_next and this is that child_next iterates over _already existing_ objects, while child_class_iterate iterates over _all possible_ children.
    const struct AVClass* (*child_class_iterate)(void **iter);
} AVClass;

  AVClassCategory定义如下:

typedef enum {
    AV_CLASS_CATEGORY_NA = 0,
    AV_CLASS_CATEGORY_INPUT,
    AV_CLASS_CATEGORY_OUTPUT,
    AV_CLASS_CATEGORY_MUXER,
    AV_CLASS_CATEGORY_DEMUXER,
    AV_CLASS_CATEGORY_ENCODER,
    AV_CLASS_CATEGORY_DECODER,
    AV_CLASS_CATEGORY_FILTER,
    AV_CLASS_CATEGORY_BITSTREAM_FILTER,
    AV_CLASS_CATEGORY_SWSCALER,
    AV_CLASS_CATEGORY_SWRESAMPLER,
    AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40,
    AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,
    AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT,
    AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT,
    AV_CLASS_CATEGORY_DEVICE_OUTPUT,
    AV_CLASS_CATEGORY_DEVICE_INPUT,
    AV_CLASS_CATEGORY_NB  ///< not part of ABI/API
}AVClassCategory;

  FFmpeg源码在libavutil/tests/opt.c中有示例程序TestContext,下面只截取其中一部分。从下面可以看到TestContext第一个成员便是AVClass的指针,然后下面定义了所有选项的数组并将该数组传递给AVClassoption成员。而其中选项不同类型初始化方式也不同有些是直接写值,有些是通过偏移写TestContext的成员变量的值:

typedef struct TestContext {
    const AVClass *class;
    int num;
    int flags;
    AVRational rational;
    enum AVPixelFormat pix_fmt;
    char *escape;
} TestContext;

#define OFFSET(x) offsetof(TestContext, x)

#define TEST_FLAG_COOL 01
#define TEST_FLAG_LAME 02
#define TEST_FLAG_MU   04

static const AVOption test_options[]= {
    {"num",        "set num",            OFFSET(num),            AV_OPT_TYPE_INT,            { .i64 = 0 },                      0,       100, 1 },
    {"rational",   "set rational",       OFFSET(rational),       AV_OPT_TYPE_RATIONAL,       { .dbl = 1 },                      0,        10, 1 },
    {"escape",     "set escape str",     OFFSET(escape),         AV_OPT_TYPE_STRING,         { .str = "\\=," },          CHAR_MIN,  CHAR_MAX, 1 },
    {"flags",      "set flags",          OFFSET(flags),          AV_OPT_TYPE_FLAGS,          { .i64 = 1 },                      0,   INT_MAX, 1, "flags" },
    {"cool",       "set cool flag",      0,                      AV_OPT_TYPE_CONST,          { .i64 = TEST_FLAG_COOL },   INT_MIN,   INT_MAX, 1, "flags" },
    {"pix_fmt",    "set pixfmt",         OFFSET(pix_fmt),        AV_OPT_TYPE_PIXEL_FMT,      { .i64 = AV_PIX_FMT_0BGR },       -1,   INT_MAX, 1 },
};

static const char *test_get_name(void *ctx)
{
    return "test";
}

static const AVClass test_class = {
    .class_name = "TestContext",
    .item_name  = test_get_name,
    .option     = test_options,
};

3 AVOptionRange及相关的API

AVOption结构

typedef struct AVOptionRange {
    const char *str;						//字符串描述
    double value_min, value_max;			//对于字符串表示最大最小长度。对于尺寸,这表示多组件情况下的最小/最大像素数或宽度/高度。
    double component_min, component_max;	//对于字符串,这表示字符的 unicode 范围,0-127 限制为 ASCII。
    int is_range;							//是不是一个范围,0的话就是一个单纯的数值
} AVOptionRange;

//List of AVOptionRange structs.
typedef struct AVOptionRanges {
    AVOptionRange **range;					//二维数组,数组中元素的数目为nb_ranges * nb_components
    int nb_ranges;
    int nb_components;						//每个component有nb_ranges个AVOptionRange
} AVOptionRanges;

  下面是FFmpeg代码中给出的示例:

 /* AV_OPT_TYPE_IMAGE_SIZE:
  * component index 0: range of pixel count (width * height).
  * component index 1: range of width.
  * component index 2: range of height.
  */
int range_index, component_index;
AVOptionRanges *ranges;
AVOptionRange *range[3]; //may require more than 3 in the future.
av_opt_query_ranges(&ranges, obj, key, AV_OPT_MULTI_COMPONENT_RANGE);
for (range_index = 0; range_index < ranges->nb_ranges; range_index++) {
    for (component_index = 0; component_index < ranges->nb_components; component_index++)
        range[component_index] = ranges->range[ranges->nb_ranges * component_index + range_index];
    //do something with range here.
}
av_opt_freep_ranges(&ranges);

相关API描述

  • int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags):获取对应的key的取值范围,实现中只有一个AVOptionRange项:
    ranges->nb_ranges = 1;
    ranges->nb_components = 1;
    range->is_range = 1;
  • int av_opt_query_ranges(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags):具体实现调用的是obj中的query_ranges,如果未定义则使用默认的av_opt_query_ranges_default
  • void av_opt_freep_ranges(AVOptionRanges **ranges):释放AVOptionRanges
  • **

4 AVOption相关API

  AVOption相关API的第一个参数都需要是一个结构体指针,该结构的第一个成员必须是AVClass的指针。文章来源地址https://www.toymoban.com/news/detail-401961.html

  • const AVOption *av_opt_next(const void *obj, const AVOption *prev):返回相对于prev的下一个AVOption。实现比较简单既然有了prevAVOption存储在数组中那么prev自增即可,只是多了一些边界检查;
    • obj:第一个成员为AVClass指针的结构体;
    • prev:需要寻找选项的上一个选项,如果为NULL则返回第一个;
    • 返回值:prev下一个选项;
const AVOption *av_opt_next(const void *obj, const AVOption *last){
    const AVClass *class;
    if (!obj)
        return NULL;
    class = *(const AVClass**)obj;
    if (!last && class && class->option && class->option[0].name)
        return class->option;
    if (last && last[1].name)
        return ++last;
    return NULL;
}
  • void *av_opt_child_next(void *obj, void *prev):使用AVClass中的child_next返回下一个可用的参数选型;
void *av_opt_child_next(void *obj, void *prev){
    const AVClass *c = *(AVClass **)obj;
    if (c->child_next)
        return c->child_next(obj, prev);
    return NULL;
}
  • const AVClass *av_opt_child_class_iterate(const AVClass *parent, void * *iter):搜寻子类的AVClass,c中没有子类的概念,这里的子类由AVClasschild_class_iterate定义,具体实现也是调用的child_class_iterate取搜索的;
    • iter:存储搜索标志位的地址;
  • const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, int opt_flags, int search_flags, void * *target_obj):在obj中搜索目标参数:
    • 搜索成功的条件:(string(o->name) == string(name)) && ((o->flags & opt_flags) == opt_flags) && ((!unit && o->type != AV_OPT_TYPE_CONST) || (unit && o->type == AV_OPT_TYPE_CONST && o->unit && string(o->unit) == string(unit))))
    • obj:应该是一个第一个成员指针为AVClass的结构体;
    • name:希望搜索的参数的名称;
    • unit:搜索的参数所属的逻辑单元;
    • opt_flags:期望搜索的参数的标志位;
    • search_flags:搜索的目标的标志位,如果设置了AV_OPT_SEARCH_CHILDREN则搜索的是由child_class_iterate定义的子类;
    • target_obj:搜索的目标,如果未设置AV_OPT_SEARCH_CHILDREN则为NULL或者输入的obj,否则为对应的子类的指针或者NULL(是否为NULL根据search_flags是否设置了AV_OPT_SEARCH_FAKE_OBJ而定);
    • const AVOption *av_opt_find(void *obj, const char *name, const char *unit, int opt_flags, int search_flags):调用av_opt_find2实现,只不过无法搜索子类的选项;
const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, int opt_flags, int search_flags, void **target_obj){
	//下面是简化的代码
    c= *(AVClass**)obj;
    if (search_flags & AV_OPT_SEARCH_CHILDREN) {
        if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) {
            void *iter = NULL;
            const AVClass *child;
            while (child = av_opt_child_class_iterate(c, &iter))
                if (o = av_opt_find2(&child, name, unit, opt_flags, search_flags, NULL))
                    return o;
        } else {
            void *child = NULL;
            while (child = av_opt_child_next(obj, child))
                if (o = av_opt_find2(child, name, unit, opt_flags, search_flags, target_obj))
                    return o;
        }
    }

    while (o = av_opt_next(obj, o)) {
		if(符合条件 && target_obj)
                if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ))
                    *target_obj = obj;
                else
                    *target_obj = NULL;
            }
            return o;
        }
    }
    return NULL;
}
  • av_opt_set(void *obj, const char *name, const char *val, int search_flags):在obj中搜索name选项并设置对应的参数,如果对应的参数是只读参数或者搜索失败会返回错误;
    • obj:第一个成员为AVClass的结构体指针;
    • name:希望设置参数的选项的key;
    • val:key对应的值,以字符串的形式存储,具体的参数类型内部会根据AVOption的类型来进行转换;
    • search_flags:搜索目标选项的标志位,内部搜索通过av_opt_find2实现;
int av_opt_set(void *obj, const char *name, const char *val, int search_flags){
    int ret = 0;
    void *dst, *target_obj;
    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
	//然后将val根据类型转换成对应的值设置进o
}
  • void av_opt_free(void *obj):释放所有的AVOption,只有AV_OPT_TYPE_STRING|AV_OPT_TYPE_BINARY|AV_OPT_TYPE_DICT三中类型需要释放;
  • int av_opt_copy(void *dst, const void *src):拷贝一份;
  • 其他设置参数的API,下面这些API基本都是设置对应的类型的具体实现,和av_opt_set的实现类似,先搜索再设置,只不过有些需要通过偏移量写入到obj的成员变量里,具体的作用从API的名称也能看出来不再赘述:
    • av_opt_set_defaults(void *s):设置s中所有的AVOption值为默认值,s的以一个指针应该为AVClass
    • av_opt_set_defaults2(void *s, int mask, int flags):仅仅设置(opt->flags & mask) == flags的选项的默认值,av_opt_set_defaults也是调用av_opt_set_defaults2实现的;
    • av_set_options_string(void *ctx, const char *opts, const char *key_val_sep, const char *pairs_sep):设置一系列参数;
      • ctx:第一个成员为AVClass的结构体指针;
      • opts:多个键值对,键值对之间以paris_seq为分隔符,键值对内以key_val_sep为分隔符,比如width=30;height=40;bitrate=3000
      • key_val_sep:分隔key-val的字符串,比如key=value中分隔符为=
      • pairs_sep:分隔一对键值对的字符串,比如key1=val1;key2=val2中分隔符为;
    • int av_opt_set_from_string(void *ctx, const char *opts, const char *const *shorthand, const char *key_val_sep, const char *pairs_sep):基本参数和定义和av_set_options_string类似,不同的是多了一个shorthand参数:
      • shorthand:多个字符串的数组,如果opts中的前几个键值对未解析出key,则会使用shorthand中的值作为key。比如opts="5:hello:size=pal",shorthand={ "num", "string", NULL };则设置的结果是num=5,string=hello
    • int av_opt_set_dict(void *obj, struct AVDictionary * *options):遍历options内的值然后将值一一设置进obj;
    • int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags):类似av_opt_set_dictsearch_flags作用于av_opt_set
    • int av_opt_set_int (void *obj, const char *name, int64_t val, int search_flags)
    • int av_opt_set_double (void *obj, const char *name, double val, int search_flags)
    • int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags)
    • int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags)
    • int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags)
    • int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags)
    • int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags)
    • int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags)
    • int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags)
    • int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags)
  • int av_opt_get (void *obj, const char *name, int search_flags, uint8_t * *out_val):获取的实现就是通过avav_opt_find2搜索然后再将数据转成字符串传出;
  • 其他获取的API:
    • int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name):获取某个flag是否设置,具体实现就是先搜索然后通过av_opt_get_int获取值;
      • obj:第一个成员为AVClass的结构体指针;
      • field_name:对应flag所属的标签;
      • flag_name:具体的flag的key;
    • int av_opt_get_key_value(const char * *ropts, const char *key_val_sep, const char *pairs_sep, unsigned flags, char * *rkey, char * *rval):从给定的字符串键值对中解析出第一个键值对并返回;
    • int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val)
    • int av_opt_get_double (void *obj, const char *name, int search_flags, double *out_val)
    • int av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val)
    • int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out)
    • int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt)
    • int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt)
    • int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val)
    • int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout)
    • int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary * *out_val)
    • void *av_opt_ptr(const AVClass *class, void *obj, const char *name):返回AVClass所属Context中对应成员的地址,比如返回AVCodecContext->width的地址;
    • int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags):通过name搜索然后通过av_opt_is_set_to_default获取;
    • int av_opt_serialize(void *obj, int opt_flags, int flags, char * *buffer, const char key_val_sep, const char pairs_sep):将obj中的选项序列化为一个字符串,字符串中键值对间的间隔为pairs_sep,键值对内的间隔为key_val_sep
  • 其他API:
    • av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags):通过av_log将当前context支持的选项输出,默认输出到控制台,可以通过FFmpeg内的av_log_callback重定向输出:
      • obj:是AVClass所属类的指针比如AVFormatContext
      • av_log_obj:一般情况置空,可以传入对应的Context的指针来显示更丰富的内容;
      • req_flagsrej_flags**:用来过滤需要显示的内容,req_flags是显示需要显示的,rej_flags是不显示对应的内容。
    • 下面几个API在头文件中有定义但是看不到实现,从注释看和av_opt_set类似,只不过会将结果写会最后一个指针来校验是否写正确:
      • int av_opt_eval_flags (void *obj, const AVOption *o, const char *val, int *flags_out)
      • av_opt_eval_int (void *obj, const AVOption *o, const char *val, int *int_out)
      • int av_opt_eval_int64 (void *obj, const AVOption *o, const char *val, int64_t *int64_out)
      • int av_opt_eval_float (void *obj, const AVOption *o, const char *val, float *float_out)
      • int av_opt_eval_double(void *obj, const AVOption *o, const char *val, double *double_out)
      • int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational *q_out)

到了这里,关于FFmpeg5.0源码阅读之AVClass和AVOption的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FFmpeg5.0源码阅读—— av_read_frame

       摘要 :本文主要描述了FFmpeg中用于打开编解码器接口 av_read_frame 的具体调用流程,详细描述了该接口被调用时所作的具体工作。    : ffmpeg 、 av_read_frame    读者须知 :读者需要了解FFmpeg的基本使用流程,以及一些FFmpeg的基本常识,了解FFmpegIO相关的内容,

    2024年02月16日
    浏览(29)
  • FFmpeg5.0源码阅读——av_interleaved_write_frame

       摘要 :本文主要详细描述FFmpeg中封装时写packet到媒体文件的函数 av_interleaved_write_frame 的实现。    : av_interleaved_write_frame    读者须知 :读者需要熟悉ffmpeg的基本使用。    av_interleaved_write_frame 的基本调用流程图如下。   首先就是根据输入数据是否为空

    2024年02月14日
    浏览(47)
  • FFmpeg5.0源码阅读—— avcodec_send_frame && avcodec_receive_packet

       摘要 :本文主要描述了FFmpeg中用于编码的接口的具体调用流程,详细描述了该接口被调用时所作的具体工作。    : ffmpeg 、 avcodec_send_frame 、 avcodec_receive_packet    读者须知 :读者需要了解FFmpeg的基本使用流程,以及一些FFmpeg的基本常识,了解FFmpegIO相关的内

    2024年02月16日
    浏览(37)
  • 【Android音视频】MacOS上FFmpeg5.0.1编译

    1. FFmpeg官网下载链接(推荐下载release的版本): Download FFmpeg http://ffmpeg.org/download.html#releases  尽情去下载并开始编译吧 2. 下载压缩包,解压至自己想要的文件路径下即可。个人习惯用全英文路径,避免出现奇怪的问题。 3. Android Studio请预先下载好。点击AS右上角“SDK Manager”

    2024年02月02日
    浏览(40)
  • FFmpeg5.1.3编译动态库踩坑之旅(基于Linux虚拟机)

    环境准备 1.Windows安装Oracle VM VirtualBox 7.0.10,安装ubuntu-22.04.3。 坑一 :无法往虚拟机里拖放复制文件,解决办法:登录Ubuntu虚拟机时切换到xorg方式登录,参考地址:Ubuntu Desktop 22.04 无法实现拖放复制操作解决办法-CSDN博客 下载文件 下载ndk25 官网下载:ndk官网 网盘下载:andr

    2024年02月07日
    浏览(38)
  • FFMPEG源码之ffmpeg.c解析

    下面是对每个步骤的功能的详细解释: 初始化动态加载。 调用init_dynload函数,用于初始化动态加载库的相关资源,以便在需要时加载需要的库。 注册退出回调函数。 调用register_exit函数,将ffmpeg_cleanup函数注册为在程序退出时被调用的回调函数。 设置stderr的缓冲模式。 调用

    2024年02月15日
    浏览(44)
  • FFmpeg开发笔记(六)如何访问Github下载FFmpeg源码

    ​ 学习FFmpeg的时候,经常要到GitHub下载各种开源代码,比如FFmpeg的源码页面位于https://github.com/FFmpeg/FFmpeg。然而国内访问GitHub很不稳定,经常打不开该网站,比如在命令行执行下面的ping命令。 上面的ping结果如下所示,可见默认解析的DNS地址连接超时。 现在GitHub的DNS请求超时

    2024年03月17日
    浏览(59)
  • [FFmpeg] 源码编译

    git clone https://git.ffmpeg.org/ffmpeg.git git checkout -b 5.1 remotes/origin/release/5.1 ./configure --prefix=./OUT --enable-shared --disable-static make make install 默认安装路径见: /usr/local/bin /usr/local/include /usr/local/lib /usr/local/main/man1 /usr/local/main/man3 有 --prefix 参数的安装路径: [prefix]/bin [prefix]/include [prefix

    2024年02月10日
    浏览(33)
  • 源码编译FFmpeg4.3

    FreeSWITCH的mod_av模块目前(1.10.11)暂不支持FFmpeg4.4(或者更高版本),但4.3就没问题 最近试了试源码编译FFmpeg4.3,记录如下(系统centos7.9): git clone GitHub - BtbN/FFmpeg-Builds 找到4.4.sh,改成这样: GIT_BRANCH=\\\"release/4.3\\\" ./build.sh linux64 gpl 4.4 cd ffbuild/ffmpeg ./configure --enable-shared make

    2024年02月01日
    浏览(36)
  • FFmpeg源码走读之内存管理模型

    数据包管理过程中当数据转移到新的数据包时存在两种操作一种是数据包之间相互独立,当新创建一份数据包时,需要将原来的数据重新申请一个数据空间并且将数据拷贝到新的数据包中,具体过程如下图所示。这种数据包的管理优势是在于数据之间相互独立,不会存在数据

    2023年04月24日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包