前言
在前一篇介绍了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位做判断的基础. 核心方法是getBitsGraceful
和fillReservoir
. 我们搞清楚他的实现, 对于以后自己写Extractror还是很有帮助的, (更何况, 他的命名规则和逻辑处理方法也比较有意思_).