FFmpeg中的内部数据类型

  摘要:简要描述FFmpeg内部定义的数据类型和相关操作的API及其实现。   关键字:AVDictionary,

1 AVDictionary及相关API

  AVDictionary虽然名字里是有字典的单词,但是只是一个单纯的键值对数组。

typedef struct AVDictionaryEntry {
    char *key;
    char *value;
} AVDictionaryEntry;

struct AVDictionary {
    int count;
    AVDictionaryEntry *elems;
};

typedef struct AVDictionary AVDictionary;

  相关API实现:

  • int av_dict_count(const AVDictionary *m):实际上就是返回AVDictionary->count

  • AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags):从```prev``开始搜索下一个符合搜索要求的项,具体实现中是通过字符串一个一个比较实现的:

    • m,key:搜索的对象和目标key;

    • prev:开始搜索的位置;

    • flags:搜索的flag,如果设置AV_DICT_MATCH_CASE则忽略大小写。如果设置AV_DICT_IGNORE_SUFFIX则忽略已经匹配好的字符串的后缀,比如format1能够匹配上format

  • int av_dict_set(AVDictionary * *pm, const char *key, const char *value, int flags):这个api准确的描述应该是av_dict_set_or_add也就是说能找到则尝试更改,否则添加新的项:

    • flags:配置对keyvalue的内存管理,默认会复制对应的字符串,需要注意的是如果设置了类似AV_DICT_DONT_STRDUP_KEY也就是将外部申请的字符串的所有权交给了pm,内部在释放时会free的;

  • int av_dict_set_int(AVDictionary * *pm, const char *key, int64_t value, int flags):实际上就是将value转换成string然后通过av_dict_set```设置;

  • int av_dict_parse_string(AVDictionary * *pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags):根据字符串str解析键值对创建AVDictoionary

    • str:一个以key_val_sep作为键值对内的分隔符,pairs_sep作为键值对间分隔符的字符串,比如rate=1000;fmt=1;width=100

    • key_val_sep:键值对内部的分隔符,对于上面字符串即=

    • pairs_sep:键值对间的分隔符,对于上面的字符串为;

    • flags:控制生成字典的标志符;

  • void av_dict_free(AVDictionary * *pm):释放字典,是通过FFmpeg内的释放函数释放的也就是说申请的内存最好也是通过FFmpeg内部的函数进行处理不然可能出现无法对齐而释放不正确的问题;

  • int av_dict_copy(AVDictionary * *dst, const AVDictionary *src, int flags):不断av_dict_get然后av_dict_set

  • int av_dict_get_string(const AVDictionary *m, char * *buffer, const char key_val_sep, const char pairs_sep):将字典解析为字符串,和av_dict_parse_string互为逆操作;

  • int avpriv_dict_set_timestamp(AVDictionary * *dict, const char *key, int64_t timestamp):将timestamp格式化为字符串设置。

2 AVRational及相关API

  FFmpeg中由于部分浮点小数运算是高精度的,如果采用float,double来存储的话多次运算之后无法避免的会产生精度误差从而影响输出的结果。因此FFmpeg采用小数的分数形式来表示对应的小数,直到最后需要使用float,double的时候再将其转换成对应的形式能尽可能的降低精度损失。下面是FFmpeg中小数表示的定义形式:

typedef struct AVRational{
    int num; ///< Numerator
    int den; ///< Denominator
} AVRational;

  相关API操作:

  • int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max):将输入的``AVRational的分子分母限制在max,即输出的dst_num,dst_den的值都小于max,一般用来化简,如果max太小肯定有精度损失,一般用设置为INT_MAX```之类即可;

  • AVRational av_mul_q(AVRational b, AVRational c):$\frac{b_nc_n}{b_dc_d}$;

  • AVRational av_div_q(AVRational b, AVRational c):$\frac{b_nc_d}{b_dc_n}$,利用av_mul_q实现;

  • AVRational av_add_q(AVRational b, AVRational c):$\frac{b_nc_d+c_nb_d}{c_d*c_d}$;

  • AVRational av_sub_q(AVRational b, AVRational c):$\frac{b_nc_d-c_nb_d}{c_d*c_d}$;

  • AVRational av_d2q(double d, int max):将小数d转换成AVRational类型;

  • int av_nearer_q(AVRational q, AVRational q1, AVRational q2):比较qq1,q2哪个更接近;

    • 0表示差值绝对值相同;

    • -1表示更接近q2

    • 1表示更接近q1

  • int av_find_nearest_q_idx(AVRational q, const AVRational* q_list):寻找列表中更接近q的有理数的索引,判定标准为av_nearer_q(q, q_list[i], q_list[nearest_q_idx]) > 0

  • uint32_t av_q2intfloat(AVRational q):转为IEEE 32-bit float;

  • AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def):返回的值分子分母分别为输入的两个有理数分子分母的最大公约数,如果分母大于max_den则返回的是def