1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.media.samplevideoencoder;
18 
19 public class ParsableBitArray {
20     public byte[] data;
21     private int byteOffset;
22     private int bitOffset;
23     private int byteLimit;
24 
ParsableBitArray(byte[] dataArray)25     public ParsableBitArray(byte[] dataArray) {
26         this(dataArray, dataArray.length);
27     }
28 
ParsableBitArray(byte[] dataArray, int limit)29     public ParsableBitArray(byte[] dataArray, int limit) {
30         this.data = dataArray;
31         byteLimit = limit;
32     }
33 
reset(byte[] data, int offset, int limit)34     public void reset(byte[] data, int offset, int limit) {
35         this.data = data;
36         byteOffset = offset;
37         bitOffset = 0;
38         byteLimit = limit;
39     }
40 
skipBit()41     public void skipBit() {
42         if (++bitOffset == 8) {
43             bitOffset = 0;
44             byteOffset++;
45         }
46     }
47 
skipBits(int numBits)48     public void skipBits(int numBits) {
49         int numBytes = numBits / 8;
50         byteOffset += numBytes;
51         bitOffset += numBits - (numBytes * 8);
52         if (bitOffset > 7) {
53             byteOffset++;
54             bitOffset -= 8;
55         }
56     }
57 
readBit()58     public boolean readBit() {
59         boolean returnValue = (data[byteOffset] & (0x80 >> bitOffset)) != 0;
60         skipBit();
61         return returnValue;
62     }
63 
readBits(int numBits)64     public int readBits(int numBits) {
65         if (numBits == 0) {
66             return 0;
67         }
68         int returnValue = 0;
69         bitOffset += numBits;
70         while (bitOffset > 8) {
71             bitOffset -= 8;
72             returnValue |= (data[byteOffset++] & 0xFF) << bitOffset;
73         }
74         returnValue |= (data[byteOffset] & 0xFF) >> (8 - bitOffset);
75         returnValue &= 0xFFFFFFFF >>> (32 - numBits);
76         if (bitOffset == 8) {
77             bitOffset = 0;
78             byteOffset++;
79         }
80         return returnValue;
81     }
82 
canReadUEV()83     public boolean canReadUEV() {
84         int initialByteOffset = byteOffset;
85         int initialBitOffset = bitOffset;
86         int leadingZeros = 0;
87         while (byteOffset < byteLimit && !readBit()) {
88             leadingZeros++;
89         }
90         boolean hitLimit = byteOffset == byteLimit;
91         byteOffset = initialByteOffset;
92         bitOffset = initialBitOffset;
93         return !hitLimit && canReadBits(leadingZeros * 2 + 1);
94     }
95 
readUEV()96     public int readUEV() {
97         int leadingZeros = 0;
98         while (!readBit()) {
99             leadingZeros++;
100         }
101         return (1 << leadingZeros) - 1 + (leadingZeros > 0 ? readBits(leadingZeros) : 0);
102     }
103 
canReadBits(int numBits)104     public boolean canReadBits(int numBits) {
105         int oldByteOffset = byteOffset;
106         int numBytes = numBits / 8;
107         int newByteOffset = byteOffset + numBytes;
108         int newBitOffset = bitOffset + numBits - (numBytes * 8);
109         if (newBitOffset > 7) {
110             newByteOffset++;
111             newBitOffset -= 8;
112         }
113         for (int i = oldByteOffset + 1; i <= newByteOffset && newByteOffset < byteLimit; i++) {
114             if (shouldSkipByte(i)) {
115                 // Skip the byte and check three bytes ahead.
116                 newByteOffset++;
117                 i += 2;
118             }
119         }
120         return newByteOffset < byteLimit || (newByteOffset == byteLimit && newBitOffset == 0);
121     }
122 
shouldSkipByte(int offset)123     private boolean shouldSkipByte(int offset) {
124         return (2 <= offset && offset < byteLimit && data[offset] == (byte) 0x03 &&
125                 data[offset - 2] == (byte) 0x00 && data[offset - 1] == (byte) 0x00);
126     }
127 
128 }
129