【Meta EnCodec源码分析】BitPacker功能介绍

news2024/9/25 13:04:31

二进制流

首先介绍一下二进制流。

假如有下4个数值

[  47, 19,  38,  53 ]

首先每个数字对应的二进制分别如下

十进制数值二进制数值
470x0010 1111
190x0001 0011
380x0010 0110
530x0011 0101

我们需要将这些数字保存到一个二进制文件中。 注:这里不考虑BigEndian还是LittleEndian。
那么这个文件中,按照输入的顺序,即 [ 47, 19, 38, 53 ]来说,文件应该是这样的,


(53)  0x0011 0101        (38)   0x0010 0110         (19)  0x0001 0011       (47) 0x0010 1111

一共4个byte。

压缩字节流

如果你发现,其实每个数值的前2位都是0,如果去掉这两位,剩下有效的数据是24bit,就是3个byte。
这样就剩下了一个byte。

BitPacker是用于做这种节省工作的,它将数值按指定的bit位数存入一个二进制流中。


BitPacker源码实现

class BitPacker:
    """Simple bit packer to handle ints with a non standard width, e.g. 10 bits.
    Note that for some bandwidth (1.5, 3), the codebook representation
    will not cover an integer number of bytes.

    Args:
        bits (int): number of bits per value that will be pushed.
        fo (IO[bytes]): file-object to push the bytes to.
    """
    def __init__(self, bits: int, fo: tp.IO[bytes]):
        self._current_value = 0
        self._current_bits = 0
        self.bits = bits
        self.fo = fo

    def push(self, value: int):
        """Push a new value to the stream. This will immediately
        write as many uint8 as possible to the underlying file-object."""
        self._current_value += (value << self._current_bits)
        self._current_bits += self.bits
        while self._current_bits >= 8:
            lower_8bits = self._current_value & 0xff
            self._current_bits -= 8
            self._current_value >>= 8
            self.fo.write(bytes([lower_8bits]))

    def flush(self):
        """Flushes the remaining partial uint8, call this at the end
        of the stream to encode."""
        if self._current_bits:
            self.fo.write(bytes([self._current_value]))
            self._current_value = 0
            self._current_bits = 0
        self.fo.flush()

以及对应的解包类

class BitUnpacker:
    """BitUnpacker does the opposite of `BitPacker`.

    Args:
        bits (int): number of bits of the values to decode.
        fo (IO[bytes]): file-object to push the bytes to.
        """
    def __init__(self, bits: int, fo: tp.IO[bytes]):
        self.bits = bits
        self.fo = fo
        self._mask = (1 << bits) - 1
        self._current_value = 0
        self._current_bits = 0

    def pull(self) -> tp.Optional[int]:
        """
        Pull a single value from the stream, potentially reading some
        extra bytes from the underlying file-object.
        Returns `None` when reaching the end of the stream.
        """
        while self._current_bits < self.bits:
            buf = self.fo.read(1)
            if not buf:
                return None
            character = buf[0]
            self._current_value += character << self._current_bits
            self._current_bits += 8

        out = self._current_value & self._mask
        self._current_value >>= self.bits
        self._current_bits -= self.bits
        return out

使用BitPacker

下面是测试样例,

if __name__ == '__main__':
        length: int = 4
        bits: int = 6
        tokens: tp.List[int] = [ 47, 19,  38,  53 ]
        rebuilt: tp.List[int] = []
        buf = io.BytesIO()
        packer = BitPacker(bits, buf)
        for token in tokens:
            packer.push(token)
        packer.flush()
        buf.seek(0)
        unpacker = BitUnpacker(bits, buf)
        while True:
            value = unpacker.pull()
            if value is None:
                break
            rebuilt.append(value)
        assert len(rebuilt) >= len(tokens), (len(rebuilt), len(tokens))
        # The flushing mechanism might lead to "ghost" values at the end of the stream.
        assert len(rebuilt) <= len(tokens) + 8 // bits, (len(rebuilt), len(tokens), bits)
        for idx, (a, b) in enumerate(zip(tokens, rebuilt)):
            assert a == b, (idx, a, b)

如何工作的?

1. 打包

第一个字符输入 (47) 0x0010 1111,

下图画了两个byte的bit位置,当第一个数 (47) 0x0010 1111push进来,因为不足一个byte长度,所以不做特殊处理。

在这里插入图片描述

第二个字符输入(19) 0x0001 0011,

输入第二个字符0x0001 0011,直观上需要把它放到上一个数字的左边;
那么实际上就是将它向左移动6个bit, 即 0x0001 0011 <<6, 如下图

在这里插入图片描述
此时长度已经大于一个byte,所以可以将低位byte打包起来,即 0x1110 1111,剩下数据如图

在这里插入图片描述

第三个字符输入(38) 0x0010 0110 ,

在这里插入图片描述

此时长度大于一个byte,所以可以将低位byte打包起来,即 0x0110 0100,剩下输入如图

![在这里插入图片描述](https://img-blog.csdnimg.cn/6aace43f6d4b49c6a3771beef6670f8c.png在这里插入图片描述

第四个字符输入(53) 0x0011 0101 ,

同样,按照上面的逻辑,打包最低位byte, 0x11010110
![在这里插入图片描述](https://img-blog.csdnimg.cn/2e3765656c95485a92d983ea26810962.png

注意事项

压入的数值一定要大于或者等于BitPacker中指定的bit长度,否则将会被数值截断。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/187142.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Centos使用lanproxy,搭建一个属于自己的内网穿透服务器(附转发失败解决方法),小白向

目录 前言 准备工作 搭建与使用 1. 安装git工具 2. 安装java环境 3. 安装maven工具 4. 搭建Lanproxy 5. 启动内网穿透服务 6. 设置开机自启 转发失败解决方法 前言 最近白嫖了7个月阿里云的服务器&#xff0c;顺带研究了一下&#xff0c;发现有挺多有趣又好玩的东西…

Acwing---1096. 地牢大师

地牢大师1.题目2.基本思想3.代码实现1.题目 你现在被困在一个三维地牢中&#xff0c;需要找到最快脱离的出路&#xff01; 地牢由若干个单位立方体组成&#xff0c;其中部分不含岩石障碍可以直接通过&#xff0c;部分包含岩石障碍无法通过。 向北&#xff0c;向南&#xff0…

Redis基于docker跨服务器的一主两从三哨兵集群模式搭建

文章目录1 整体拓扑图2 redis与哨兵配置文件2.1 主节点配置文件2.1.1 主节点redis.conf配置文件2.1.2 主节点哨兵配置文件2.2 从节点配置文件2.1.1 从节点redis.conf配置文件2.1.2 从节点哨兵配置文件3 docke-compose编排文件4 启动并测试查看哨兵日志查看集群状态测试集群是否…

Spring源码分析 (Spring启动过程之容器对象的创建) (十五)

点进去 1.this() 2.注册配置类 3.refresh() Spring会将所有交由Spring管理的类&#xff0c;扫描其class文件&#xff0c;将其解析成BeanDefinition&#xff0c;在BeanDefinition中会描述类的信息&#xff0c;例如:这个类是否是单例的&#xff0c;Bean的类型&#xff0c;是否是懒…

导向滤波算法——OpenGL实现

导向滤波 一、介绍 导向滤波又称引导滤波&#xff0c;通过一张引导图片反映边缘、物体等信息&#xff0c;对输入图像进行滤波处理&#xff0c;使输出图像的内容由输入图像决定&#xff0c;但纹理与引导图片相似。 导向滤波的原理是局部线性模型&#xff0c;在保持双边滤波的优…

【学习笔记】多线程

1、线程基础 1.1 创建线程的几种方式 继承Thread 类&#xff0c;覆盖run方法实现Runable接口。实现run方法。然后 通过Thread类构造方法获取Thread对象。实现Callable接口。实现call方法。 call方法可以抛出异常。也可以有返回值。 run与start 调用run方法任然是主线程在执行。…

这个 Python 游戏库,打开就能玩一天

会 Python 的小伙伴&#xff0c;选择用 Python 让“大风车”吱呦呦地转&#xff01;还有的小伙伴&#xff0c;选择用 Turtle 库绘制童年的卡通人物 我们其实还可以选择用 Python 开发小游戏&#xff0c;回忆童年的美好时光。 “凹凸版”吃豆子 这次并非用pygame制作的&#…

MyBatis超详细学习笔记(黑马)

目录 一、MyBatis快速入门 &#xff08;一&#xff09;打开MyBatis中文官网 &#xff08;二&#xff09;在工程中&#xff08;pom.xml&#xff09;导入MyBatis依赖 &#xff08;三&#xff09;编写MyBatis核心配置文件——替换连接信息&#xff0c;解决硬编码问题 &#x…

关于加强网络舆情监测的几点建议,TOOM强化舆情监控有方法

网络舆情监测是一项旨在通过监测网络上的舆情信息&#xff0c;了解社会舆论和网络话语状况&#xff0c;分析舆情动态&#xff0c;预测舆情走向&#xff0c;并进行舆情管控的工作。主要通过计算机技术和信息科学手段对网络信息进行收集、整理、分析和报告&#xff0c;以便于管理…

Golang - 操作Redis

Golang - 操作Redis go-redis是Golang语言连接、操作Redis服务的客户端&#xff0c;几乎包含了对Redis的所有操作&#xff0c;具体如下&#xff1a; 简单易用 兼容多种Redis部署架构,可用于Redis服务器、Redis群集、Redis Sentinel&#xff0c;甚至Redis服务器环go-redis 支持…

配置TF-A源码

配置TF-A源码 1.对tf-a源码进行解压 $> tar xfz tf-a-stm32mp-2.2.r2-r0.tar.gz 2.打补丁 进入/home/ubuntu/FSMP1A/tf-a-stm32mp-2.2.r2-r0/tf-a-stm32mp-2.2.r2目录 执行 for p in ls -1 ../*.patch; do patch -p1 < $p; done 3.配置工具链 1)进入/home/ubuntu/FS…

05 CSS-CSS语法【尚硅谷JavaWeb教程】

05 CSS-CSS语法【尚硅谷JavaWeb教程】 JAVAWEB的学习笔记 学习视频来自&#xff1a;https://www.bilibili.com/video/BV1AS4y177xJ/?vd_source75dce036dc8244310435eaf03de4e330 为什么需要CSS 传统的园区网络采用设备和链路冗余来保证高可靠性&#xff0c;但其链路利用率低、…

Task7:动态函数

目录注意一 Filter函数二 Subtotal函数注意 filter&#xff0c;目前只有office365支持 一 Filter函数 作用&#xff1a;需要根据指定的条件&#xff0c;将符合条件的所有记录从数据源表格式查找过来之前方法&#xff1a; 用高级筛选&#xff08;缺点&#xff1a;在查询下一个…

SAP ADM100-Unit4 数据库工作原理:中央数据库管理与DBA Cockpit

概览 本节介绍DBA Cockpit,介绍SAP环境下数据库管理和监控的要点。 使用DBA Cockpit计划日历去计划数据和日志信息的周期性备份。 课程目标 备份数据库内容 检查数据库备份是否成功被执行。 1、DBA Cockpit总览 为了最少的系统停机时间和更高的系统性能,必须计划定期的…

云计算|OpenStack|社区版OpenStack安装部署文档(一 --- 前期硬件准备和部署规划)

前言&#xff1a; 社区版OpenStack是比较难以安装部署的&#xff0c;本文将就安装部署做一个详细的说明。 首先&#xff0c;OpenStack社区版本众多&#xff0c;如何选择一个合适的版本是第一个要解决的问题&#xff08;这里的合适是指的OpenStack版本和操作系统的版本合适&am…

MATLAB-自动控制原理-时域分析

目录 step函数&#xff08;求阶跃响应&#xff09;: impulse函数&#xff08;求脉冲响应&#xff09;: lsim函数&#xff08;求输出&#xff09;: 1&#xff0c;求二阶系统不同阻尼比条件下的阶跃响应曲线 2&#xff0c;求二阶负反馈系统的动态性能指标 利用MATLAB可以方…

五、好友关注,feed流推送

文章目录关注和取消关注&#xff0c;共同关注Feed流推送Feed介绍Timeline推模式Feed流滚动分页滚动分页查询收邮箱官方命令文档&#xff1a;https://redis.io/commands/ 关注和取消关注&#xff0c;共同关注 需求&#xff1a; 可以对一个用户进行关注和取消关注查询和一个用…

深刻理解状态机设计需要避免的冒险;处理单元里的control和datapath;时序电路可能存在essential hazard;竞争冒险【SV】【VLSI】

深刻理解状态机设计需要避免的冒险&#xff1b;处理单元里的control和datapath&#xff1b;时序电路可能存在essential hazard&#xff1b;竞争冒险【SV】【VLSI】0. 前言&#xff1a;时序电路可能存在essential hazard1. 理解control和datapath1.1 Datapath control2. 硬件电路…

JavaScript XHR、Fetch

前后端分离的优势 ◼ 早期的网页都是通过后端渲染来完成的&#xff1a;服务器端渲染&#xff08;SSR&#xff0c;server side render&#xff09;&#xff1a; \qquad 客户端发出请求-> 服务端接收请求并返回相应HTML文档-> 页面刷新&#xff0c;客户端加载新的HTML文…

如何采用conda配置python虚拟环境

文章目录一、创建python虚拟环境二、配置刚创建的虚拟环境三、将虚拟环境配置到相应项目一、创建python虚拟环境 首先选中要配置环境的文件 如下&#xff1a; 在此处输入cmd按回车 此处我创建一个环境名为hands3dtext&#xff0c;环境版本为3.7.2的初始环境 conda create -n…