当前位置: 首页 > article >正文

FFmpeg源码:av_base64_decode函数分析

一、引言

Base64(基底64)是一种基于64个可打印字符来表示二进制数据的表示方法。由于log2 64=6,所以每6个比特为一个单元,对应某个可打印字符。3个字节相当于24个比特,对应于4个Base64单元,即3个字节可由4个可打印字符来表示。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。一些如uuencode的其他编码方法,和之后BinHex的版本使用不同的64字符集来代表6个二进制数字,但是不被称为Base64。

Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据,包括MIME的电子邮件及XML的一些复杂数据。

Base64编码具有以下特点:1.编码后的数据长度总是比原始数据长约 1/3;2.编码后的数据可以包含 A-Z、a-z、0-9 和两个额外字符的任意组合;3.Base64 编码是一种可逆的编码方式,可以通过解码还原原始数据。

FFmpeg源码中,通过av_base64_decode函数对Base64编码的字符串进行解码。

二、av_base64_decode函数的声明

av_base64_decode函数声明在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的头文件libavutil/base64.h中:

/**
 * Decode a base64-encoded string.
 *
 * @param out      buffer for decoded data
 * @param in       null-terminated input string
 * @param out_size size in bytes of the out buffer, must be at
 *                 least 3/4 of the length of in, that is AV_BASE64_DECODE_SIZE(strlen(in))
 * @return         number of bytes written, or a negative value in case of
 *                 invalid input
 */
int av_base64_decode(uint8_t *out, const char *in, int out_size);

该函数的作用是:对Base64编码的字符串进行解码。

形参out:输出型参数,存放以Base64解码后的数据的缓冲区。

形参in:输入型参数,存放以Base64编码后的数据的缓冲区。

形参out_size:输入型参数,形参out指向的缓冲区的大小,单位为字节。

返回值:解码成功,返回写入的字节数,即解码后数据占用空间的大小;解码失败,返回一个负数。

三、av_base64_decode函数的定义

av_base64_decode函数定义在源文件libavutil/base64.c中:

int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
{
    uint8_t *dst = out;
    uint8_t *end;
    // no sign extension
    const uint8_t *in = in_str;
    unsigned bits = 0xff;
    unsigned v;

    if (!out)
        goto validity_check;

    end = out + out_size;
    while (end - dst > 3) {
        BASE64_DEC_STEP(0);
        BASE64_DEC_STEP(1);
        BASE64_DEC_STEP(2);
        BASE64_DEC_STEP(3);
        // Using AV_WB32 directly confuses compiler
        v = av_be2ne32(v << 8);
        AV_WN32(dst, v);
        dst += 3;
        in += 4;
    }
    if (end - dst) {
        BASE64_DEC_STEP(0);
        BASE64_DEC_STEP(1);
        BASE64_DEC_STEP(2);
        BASE64_DEC_STEP(3);
        *dst++ = v >> 16;
        if (end - dst)
            *dst++ = v >> 8;
        if (end - dst)
            *dst++ = v;
        in += 4;
    }
validity_check:
    while (1) {
        BASE64_DEC_STEP(0);
        in++;
        BASE64_DEC_STEP(0);
        in++;
        BASE64_DEC_STEP(0);
        in++;
        BASE64_DEC_STEP(0);
        in++;
    }

out3:
    if (end - dst)
        *dst++ = v >> 10;
    v <<= 2;
out2:
    if (end - dst)
        *dst++ = v >> 4;
out1:
out0:
    return bits & 1 ? AVERROR_INVALIDDATA : out ? dst - out : 0;
}

四、参考

《维基百科——Base64》

Base64 编码/解码 | 菜鸟工具


http://www.kler.cn/a/526178.html

相关文章:

  • SAP SD学习笔记27 - 请求计划(开票计划)之1 - 定期请求
  • 【go语言】gorm 快速入门
  • sem_init的概念和使用案例
  • 本地部署deepseek模型步骤
  • openeuler 22.03 lts sp4 使用 cri-o 和 静态 pod 的方式部署 k8s-v1.32.0 高可用集群
  • 【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.20 极值追踪:高效获取数据特征的秘诀
  • Python练习(2)
  • 超级强大的压缩和解压工具,免费解压
  • Autosar-Os是怎么运行的?(时间保护)
  • C语言自定义数据类型详解(二)——结构体类型(下)
  • 基于STM32的轮式移动机器人教学
  • olloama下载deepseek-r1大模型本地部署
  • BypassWAF--基本概念
  • Cocoa和Cocoa Touch是什么语言写成的?什么是Cocoa?编程语言中什么是框架?为什么苹果公司Cocoa类库有不少NS前缀?Swift编程语言?
  • [EAI-026] DeepSeek-VL2 技术报告解读
  • 蓝桥云客 三羊献瑞
  • 4.装饰模式(Decorator)
  • Day07:缓存-数据淘汰策略
  • Springboot如何使用面向切面编程AOP?
  • 【Linux系统】进程间通信:实现命名管道通信
  • Linux:基础IO(一.C语言文件接口与系统调用、默认打开的文件流、详解文件描述符与dup2系统调用)
  • vector有用的自己不太熟悉的函数
  • 设计转换Apache Hive的HQL语句为Snowflake SQL语句的Python程序方法
  • 【Qt】各种常用的按钮(button)
  • 深入理解Linux内核的虚拟地址到物理地址转换机制及缓存优化
  • 6.工厂模式(Factory Method)