-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbitstream.go
108 lines (90 loc) · 2.05 KB
/
bitstream.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package jpegsl
import (
"bytes"
"fmt"
"log"
)
type Bitstream struct {
dataStream *bytes.Reader
bytePosition int
byteBuffer uint16
}
func NewBitstream(data []byte) *Bitstream {
var bs = new(Bitstream)
bs.dataStream = bytes.NewReader(data)
bs.bytePosition = 0
bs.byteBuffer = 0
return bs
}
func (bs *Bitstream) bit() int {
if bs.bytePosition == 0 {
newByte := read1Byte(bs.dataStream)
if newByte == 0xff {
bs.dataStream.ReadByte()
}
bs.byteBuffer = bs.byteBuffer<<8 | uint16(newByte)
bs.bytePosition = 8
}
bs.bytePosition -= 1
return int((bs.byteBuffer >> bs.bytePosition) & 1)
}
func (bs *Bitstream) tryByte() int {
if bs.bytePosition < 8 {
newByte := read1Byte(bs.dataStream)
if newByte == 0xff {
bs.dataStream.ReadByte()
}
bs.byteBuffer = bs.byteBuffer<<8 | uint16(newByte)
bs.bytePosition += 8
}
return int((bs.byteBuffer >> (bs.bytePosition - 8)) & 0xFF)
}
func (bs *Bitstream) advance(n int) {
bs.bytePosition -= n
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func read1Byte(reader *bytes.Reader) byte {
b, err := reader.ReadByte()
if err != nil {
log.Panic(err)
}
return b
}
func read2Bytes(reader *bytes.Reader) uint16 {
b0, err := reader.ReadByte()
if err != nil {
log.Panic(err)
}
b1, err := reader.ReadByte()
if err != nil {
log.Panic(err)
}
return uint16(b0)<<8 | uint16(b1)
}
func (bs *Bitstream) bits(length int) int {
nextLength := min(bs.bytePosition, length)
length -= nextLength
bs.bytePosition -= nextLength
if nextLength < 0 || bs.bytePosition < 0 {
fmt.Print(nextLength, " ", length, " ", bs.bytePosition)
}
currentBits := int(bs.byteBuffer>>bs.bytePosition) & int((1<<nextLength)-1)
for length > 0 {
newByte := read1Byte(bs.dataStream)
bs.byteBuffer = bs.byteBuffer<<8 | uint16(newByte)
if newByte == 0xff {
bs.dataStream.ReadByte()
}
nextLength = min(8, length)
length -= nextLength
bs.bytePosition = 8 - nextLength
currentBits <<= nextLength
currentBits |= int(bs.byteBuffer>>bs.bytePosition) & int((1<<nextLength)-1)
}
return int(currentBits)
}