ABitReader简介


前言

      在前一篇介绍了Extractor的整个框架以及关键的AnohterPacketSource之后, 我们来介绍一下Extractor中用来读取文件二进制bit数据的类. 她的芳名为: ABitReader(哈哈, 还真是顾名思义呀~).


1. 从"头"开始

      按照惯例, 我们首先来看一下这个类的头文件声明. 文件路径为: /frameworks/av/include/media/stagefright/fundation/ABitReader.h(我会在关键方法后加上本菜鸟自己的理解)

28class ABitReader {
29public:
30    ABitReader(const uint8_t *data, size_t size);
31    virtual ~ABitReader();
32
33    // Tries to get |n| bits. If not successful, returns |fallback|. Otherwise, returns result.
34    // Reading 0 bits will always succeed and return 0.
35    uint32_t getBitsWithFallback(size_t n, uint32_t fallback);
36
37    // Tries to get |n| bits. If not successful, returns false. Otherwise, stores result in |out|
38    // and returns true. Use !overRead() to determine if this call was successful. Reading 0 bits
39    // will always succeed and write 0 in |out|.
40    bool getBitsGraceful(size_t n, uint32_t *out);
41
42    // Gets |n| bits and returns result. ABORTS if unsuccessful. Reading 0 bits will always
43    // succeed.
44    uint32_t getBits(size_t n);
45
46    // Tries to skip |n| bits. Returns true iff successful. Skipping 0 bits will always succeed.
47    bool skipBits(size_t n);
48
49    // "Puts" |n| bits with the value |x| back virtually into the bit stream. The put-back bits
50    // are not actually written into the data, but are tracked in a separate buffer that can
51    // store at most 32 bits. This is a no-op if the stream has already been over-read.
52    void putBits(uint32_t x, size_t n);
53    //返回当前一共读了多少个bit
54    size_t numBitsLeft() const;
55    //返回本次读取bit时, 起始Byte的指针
56    const uint8_t *data() const;
57
58    // Returns true iff the stream was over-read (e.g. any getBits operation has been unsuccessful
59    // due to overread (and not trying to read >32 bits).)
60    bool overRead() const { return mOverRead; }
61
62protected:
63    const uint8_t *mData; //要开始读取的位置的指针
64    size_t mSize; //要读取的Byte数
65
66    uint32_t mReservoir;  // left-aligned bits
67    size_t mNumBitsLeft; //本次读取工作剩余bit数(多少bit是剩下的)
68    bool mOverRead; //标识是否读取bit越界
69    //这是个基本的函数,名字叫:"填充蓄水池". 作用是检查mOverRead, 如果没有OverReader, mNumBitsLedt记录读取了多少bit(8的倍数)
70    virtual bool fillReservoir();
71
72    DISALLOW_EVIL_CONSTRUCTORS(ABitReader);
73};
74
75class NALBitReader : public ABitReader {
76public:
77    NALBitReader(const uint8_t *data, size_t size);
78
79    bool atLeastNumBitsLeft(size_t n) const;
80
81private:
82    int32_t mNumZeros;
83
84    virtual bool fillReservoir();
85
86    DISALLOW_EVIL_CONSTRUCTORS(NALBitReader);
87};

2. 追寻本"源"

      这个头文件还是非常友好的说, 关键的方法都加了注释, 小弟只是在没有注释的地方, 加了点自己的理解.
      其实, 常用方法只有getBits或者是skipBits. 让我们一起来看下.

2.1. getBits

54 uint32_t ABitReader::getBits(size_t n) {
55    uint32_t ret;
56    CHECK(getBitsGraceful(n, &ret));
57    return ret;
58 }

      我们可以看到, 直接简单的调用了getBitGraceful, 然后将拿到的result放入ret中. 哈哈, 接下来看看是如何get bit Graceful(优雅的).

2.2 getBitsGraceful

66bool ABitReader::getBitsGraceful(size_t n, uint32_t *out) {
67    if (n > 32) {
68        return false;
69    }
70
71    uint32_t result = 0;
72    while (n > 0) {
73        if (mNumBitsLeft == 0) {
74            if (!fillReservoir()) {
75                return false;
76            }
77        }
78
79        size_t m = n;
80        if (m > mNumBitsLeft) {
81            m = mNumBitsLeft;
82        }
83
84        result = (result << m) | (mReservoir >> (32 - m));
85        mReservoir <<= m;
86        mNumBitsLeft -= m;
87
88        n -= m;
89    }
90
91    *out = result;
92    return true;
93}

67 - 69: 如果有人要搞事情, 一次性读取bit数超过了32, 那还是无情的返回false吧;

71 - 89: 开始循环读取bit位. 大家一定发现了一个有趣的方法fillReservoir(), 顾名思义, 他是一个容量最大为32bit的容器. 我们来看看他的实现.

34 bool ABitReader::fillReservoir() {
35    if (mSize == 0) {
36        mOverRead = true;
37        return false;
38    }
39
40    mReservoir = 0;
41    size_t i;
42    for (i = 0; mSize > 0 && i < 4; ++i) {
43        mReservoir = (mReservoir << 8) | *mData;
44
45        ++mData;
46        --mSize;
47    }
48
49    mNumBitsLeft = 8 * i;
50    mReservoir <<= 32 - mNumBitsLeft;
51    return true;
52}

35- 37: 如果读到mSize都没有了, 那就直接返回false吧;
42- 47: 逐个Byte(8bit去读mData指向的内容), 放入mReservoir;
49 - 50: 更新mNumBitsLeft, mReservoir;
之后就是更新下各私有变量的值, 以便下次读取之用.

91 - 92 把结果放入out, 返回读取成功true.

2.2. skipBits

95 bool ABitReader::skipBits(size_t n) {
96    uint32_t dummy;
97    while (n > 32) {
98        if (!getBitsGraceful(32, &dummy)) {
99            return false;
100        }
101        n -= 32;
102    }
103
104    if (n > 0) {
105        return getBitsGraceful(n, &dummy);
106    }
107    return true;
108}

96: 造一个假的接收数据的变量dummy;
97 - 108: 优雅的去使用getBitsGraceful去读取bit位, 反正读取出来的放在dummy中, 我们不用管. 这样就达到了我们skip n bit的目的.(有点意思)


小结

      这是Extractor中读取bit位做判断的基础. 核心方法是getBitsGracefulfillReservoir. 我们搞清楚他的实现, 对于以后自己写Extractror还是很有帮助的, (更何况, 他的命名规则和逻辑处理方法也比较有意思_).

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,559评论 18 139
  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,102评论 0 13
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,531评论 18 399
  • “如果中国每个人都给我1块钱,我就发了“ 我们好像都做过这样的白日梦,然后旁别总会有人敲醒你”人家凭什么给你1块钱...
    文无用阅读 244评论 2 2
  • 昨晚带妹妹出去和朋友们聚餐,回家晚了点,她洗漱完已经9点半都过了。吃睡前奶时,我都迷迷糊糊好像睡着了,她反而越来越...
    添想阅读 179评论 0 1