ffmpeg之struct AVDictionary分析

从代码分析,dict功能实际就是一个查找器,将对象数据字符串"AAAA"映射到标识字符串"BBBB",通过字符串"BBBB"查找到对应映射的字符串"AAAA";
代码设计上比较简单,差不多就是简单的遍历数组。

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

int av_dict_count(const AVDictionary *m)
{
    return m ? m->count : 0;
}

AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
                               const AVDictionaryEntry *prev, int flags)
{
    unsigned int i, j;

    if (!m)
        return NULL;

    //计算prev对象在字典中的索引
    if (prev)
        //指定prev, prev对象地址减去首地址 + 1为prev在m->elems中的索引
        i = prev - m->elems + 1;
    else
        //未指定prev,从0开始索引
        i = 0;

    for (; i < m->count; i++) {
        const char *s = m->elems[i].key;
        if (flags & AV_DICT_MATCH_CASE)
            //区分大小写
            for (j = 0; s[j] == key[j] && key[j]; j++)
                ;
        else
            //不区分大小写
            for (j = 0; av_toupper(s[j]) == av_toupper(key[j]) && key[j]; j++)
                ;
        if (key[j])//说明匹配不成功
            continue;
        //如果不忽略后缀,则表示匹配不成功,反之
        if (s[j] && !(flags & AV_DICT_IGNORE_SUFFIX))
            continue;
        //返回索引到的对象
        return &m->elems[i];
    }
    //索引不成功,返回失败
    return NULL;
}

int av_dict_set(AVDictionary **pm, const char *key, const char *value,
                int flags)
{
    AVDictionary *m = *pm;
    AVDictionaryEntry *tag = NULL;
    char *oldval = NULL, *copy_key = NULL, *copy_value = NULL;

    if (!(flags & AV_DICT_MULTIKEY)) {
        //如果不允许相同键值被存储,则将键值读出来,后续处理
        tag = av_dict_get(m, key, NULL, flags);
    }
    if (flags & AV_DICT_DONT_STRDUP_KEY)
        //如果设置接管键值则
        copy_key = (void *)key;
    else
        //否则
        copy_key = av_strdup(key);
    if (flags & AV_DICT_DONT_STRDUP_VAL)
        //如果设置接管信息,则
        copy_value = (void *)value;
    else if (copy_key)
        copy_value = av_strdup(value);
    if (!m)
        //字典句柄不存在,申请新空间组织
        m = *pm = av_mallocz(sizeof(*m));
    if (!m || (key && !copy_key) || (value && !copy_value))
        goto err_out;

    if (tag) {
        //设置了相同键值,但不允许,所以需要处理一下
        if (flags & AV_DICT_DONT_OVERWRITE) {
            //不允许重写已经存在的键值,返回失败,并释放相关的内存空间
            av_free(copy_key);
            av_free(copy_value);
            return 0;
        }
        //是否设置追加
        if (flags & AV_DICT_APPEND)
            //设置允许追加,先保存旧值
            oldval = tag->value;
        else
            //设置不允许追加,释放旧值
            av_free(tag->value);
        //释放旧键值
        av_free(tag->key);
        //将最后一个对象拷贝到tag上
        *tag = m->elems[--m->count];
    } else if (copy_value) {
        //设置了新键值,需要对键值对象进行存储空间申请
        //(动态数组 ==>  
        //      在m->elems指针的基础上,新增内存空间,
        //      有连续空间则连续申请,无连续空间则重新申请整个
        //      需要空间,再把数据拷贝过去,最后释放非连续的原先内存)
        AVDictionaryEntry *tmp = av_realloc_array(m->elems,
                                                  m->count + 1, sizeof(*m->elems));
        if (!tmp)
            goto err_out;
        m->elems = tmp;
    }
    if (copy_value) {
        //有新对象添加,将新键值/数据存储到字典最后一个对象
        m->elems[m->count].key = copy_key;
        m->elems[m->count].value = copy_value;
        if (oldval && flags & AV_DICT_APPEND) {
            //将两个数据内容合并
            size_t len = strlen(oldval) + strlen(copy_value) + 1;
            char *newval = av_mallocz(len);
            if (!newval)
                goto err_out;
            av_strlcat(newval, oldval, len);
            av_freep(&oldval);
            av_strlcat(newval, copy_value, len);
            m->elems[m->count].value = newval;
            av_freep(&copy_value);
        }
        m->count++;
    } else {
        av_freep(&copy_key);
    }
    if (!m->count) {
        //内部没有对象,销毁整个字典
        av_freep(&m->elems);
        av_freep(pm);
    }

    return 0;

err_out:
    if (m && !m->count) {
        av_freep(&m->elems);
        av_freep(pm);
    }
    av_free(copy_key);
    av_free(copy_value);
    return AVERROR(ENOMEM);
}

int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value,
                int flags)
{
    char valuestr[22];
    snprintf(valuestr, sizeof(valuestr), "%"PRId64, value);
    //设置需要拷贝value值
    flags &= ~AV_DICT_DONT_STRDUP_VAL;
    return av_dict_set(pm, key, valuestr, flags);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值