ABitReader簡介


前言

??????在前一篇介紹了Extractor的整個框架以及關(guān)鍵的AnohterPacketSource之后, 我們來介紹一下Extractor中用來讀取文件二進制bit數(shù)據(jù)的類. 她的芳名為: ABitReader(哈哈, 還真是顧名思義呀~).


1. 從"頭"開始

??????按照慣例, 我們首先來看一下這個類的頭文件聲明. 文件路徑為: /frameworks/av/include/media/stagefright/fundation/ABitReader.h(我會在關(guān)鍵方法后加上本菜鳥自己的理解)

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    //返回當(dāng)前一共讀了多少個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數(shù)
65
66    uint32_t mReservoir;  // left-aligned bits
67    size_t mNumBitsLeft; //本次讀取工作剩余bit數(shù)(多少bit是剩下的)
68    bool mOverRead; //標(biāo)識是否讀取bit越界
69    //這是個基本的函數(shù),名字叫:"填充蓄水池". 作用是檢查mOverRead, 如果沒有OverReader, mNumBitsLedt記錄讀取了多少bit(8的倍數(shù))
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. 追尋本"源"

??????這個頭文件還是非常友好的說, 關(guān)鍵的方法都加了注釋, 小弟只是在沒有注釋的地方, 加了點自己的理解.
??????其實, 常用方法只有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 }

??????我們可以看到, 直接簡單的調(diào)用了getBitGraceful, 然后將拿到的result放入ret中. 哈哈, 接下來看看是如何get bit Graceful(優(yōu)雅的).

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數(shù)超過了32, 那還是無情的返回false吧;

71 - 89: 開始循環(huán)讀取bit位. 大家一定發(fā)現(xiàn)了一個有趣的方法fillReservoir(), 顧名思義, 他是一個容量最大為32bit的容器. 我們來看看他的實現(xiàn).

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指向的內(nèi)容), 放入mReservoir;
49 - 50: 更新mNumBitsLeft, mReservoir;
之后就是更新下各私有變量的值, 以便下次讀取之用.

91 - 92 把結(jié)果放入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: 造一個假的接收數(shù)據(jù)的變量dummy;
97 - 108: 優(yōu)雅的去使用getBitsGraceful去讀取bit位, 反正讀取出來的放在dummy中, 我們不用管. 這樣就達到了我們skip n bit的目的.(有點意思)


小結(jié)

??????這是Extractor中讀取bit位做判斷的基礎(chǔ). 核心方法是getBitsGracefulfillReservoir. 我們搞清楚他的實現(xiàn), 對于以后自己寫Extractror還是很有幫助的, (更何況, 他的命名規(guī)則和邏輯處理方法也比較有意思_).

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末募强,一起剝皮案震驚了整個濱河市卿泽,隨后出現(xiàn)的幾起案子秘狞,更是在濱河造成了極大的恐慌,老刑警劉巖舔稀,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件装悲,死亡現(xiàn)場離奇詭異嘁傀,居然都是意外死亡载荔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門凹炸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來戏阅,“玉大人,你說我怎么就攤上這事啤它∞瓤穑” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵变骡,是天一觀的道長离赫。 經(jīng)常有香客問我,道長塌碌,這世上最難降的妖魔是什么渊胸? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮誊爹,結(jié)果婚禮上蹬刷,老公的妹妹穿的比我還像新娘瓢捉。我一直安慰自己频丘,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布泡态。 她就那樣靜靜地躺著搂漠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪某弦。 梳的紋絲不亂的頭發(fā)上桐汤,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天而克,我揣著相機與錄音,去河邊找鬼怔毛。 笑死员萍,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拣度。 我是一名探鬼主播碎绎,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼抗果!你這毒婦竟也來了筋帖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤冤馏,失蹤者是張志新(化名)和其女友劉穎日麸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逮光,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡代箭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了涕刚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梢卸。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖副女,靈堂內(nèi)的尸體忽然破棺而出蛤高,到底是詐尸還是另有隱情,我是刑警寧澤碑幅,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布戴陡,位于F島的核電站,受9級特大地震影響沟涨,放射性物質(zhì)發(fā)生泄漏恤批。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一裹赴、第九天 我趴在偏房一處隱蔽的房頂上張望喜庞。 院中可真熱鬧,春花似錦棋返、人聲如沸延都。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晰房。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間殊者,已是汗流浹背与境。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留猖吴,地道東北人摔刁。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像海蔽,于是被迫代替她去往敵國和親簸搞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理准潭,服務(wù)發(fā)現(xiàn)趁俊,斷路器,智...
    卡卡羅2017閱讀 134,664評論 18 139
  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line)刑然,也就是一...
    悟名先生閱讀 4,149評論 0 13
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法寺擂,類相關(guān)的語法,內(nèi)部類的語法泼掠,繼承相關(guān)的語法怔软,異常的語法,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • “如果中國每個人都給我1塊錢,我就發(fā)了“ 我們好像都做過這樣的白日夢腻豌,然后旁別總會有人敲醒你”人家憑什么給你1塊錢...
    文無用閱讀 254評論 2 2
  • 昨晚帶妹妹出去和朋友們聚餐家坎,回家晚了點,她洗漱完已經(jīng)9點半都過了吝梅。吃睡前奶時虱疏,我都迷迷糊糊好像睡著了,她反而越來越...
    添想閱讀 185評論 0 1