add uitls

This commit is contained in:
notch
2021-01-08 22:00:38 +08:00
parent 25877a2a81
commit c09eceaace
3 changed files with 370 additions and 0 deletions

169
utils/bits/reader.go Normal file
View File

@@ -0,0 +1,169 @@
// Copyright (c) 2019,CAOHONGJU All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package bits
const uintBitsCount = int(32 << (^uint(0) >> 63))
// Reader .
type Reader struct {
buf []byte
offset int // bit base
}
// NewReader retruns a new Reader.
func NewReader(buf []byte) *Reader {
return &Reader{
buf: buf,
}
}
// Skip skip n bits.
func (r *Reader) Skip(n int) {
if n <= 0 {
return
}
_ = r.buf[(r.offset+n-1)>>3] // bounds check hint to compiler; see golang.org/issue/14808
r.offset += n
}
// Peek peek the uint32 of n bits.
func (r *Reader) Peek(n int) uint32 {
clone := *r
return uint32(clone.readUint64(n, 32))
}
// Read read the uint32 of n bits.
func (r *Reader) Read(n int) uint32 {
return uint32(r.readUint64(n, 32))
}
// ReadBit read a bit.
func (r *Reader) ReadBit() uint8 {
_ = r.buf[(r.offset+1-1)>>3] // bounds check hint to compiler; see golang.org/issue/14808
tmp := (r.buf[r.offset>>3] >> (7 - r.offset&0x7)) & 1
r.offset++
return tmp
}
// ReadUe .
func (r *Reader) ReadUe() (res uint32) {
i := 0
for {
if bit := r.ReadBit(); !(bit == 0 && i < 32) {
break
}
i++
}
res = r.Read(i)
res += (1 << uint(i)) - 1
return
}
// ReadSe .
func (r *Reader) ReadSe() (res int32) {
ui32 := r.ReadUe()
if ui32&0x01 != 0 {
res = (int32(res) + 1) / 2
} else {
res = -int32(res) / 2
}
return
}
// ==== shortcut methods
// ReadBool read one bit bool.
func (r *Reader) ReadBool() bool { return bool(r.ReadBit() == 1) }
// ReadUint read the uint of n bits.
func (r *Reader) ReadUint(n int) uint { return uint(r.readUint64(n, uintBitsCount)) }
// ReadUint8 read the uint8 of n bits.
func (r *Reader) ReadUint8(n int) uint8 { return uint8(r.readUint64(n, 8)) }
// ReadUint16 read the uint16 of n bits.
func (r *Reader) ReadUint16(n int) uint16 { return uint16(r.readUint64(n, 16)) }
// ReadUint32 read the uint32 of n bits.
func (r *Reader) ReadUint32(n int) uint32 { return uint32(r.readUint64(n, 32)) }
// ReadUint64 read the uint64 of n bits.
func (r *Reader) ReadUint64(n int) uint64 { return r.readUint64(n, 64) }
// ReadInt read the int of n bits.
func (r *Reader) ReadInt(n int) int { return int(r.readUint64(n, uintBitsCount)) }
// ReadInt8 read the int8 of n bits.
func (r *Reader) ReadInt8(n int) int8 { return int8(r.readUint64(n, 8)) }
// ReadInt16 read the int16 of n bits.
func (r *Reader) ReadInt16(n int) int16 { return int16(r.readUint64(n, 16)) }
// ReadInt32 read the int32 of n bits.
func (r *Reader) ReadInt32(n int) int32 { return int32(r.readUint64(n, 32)) }
// ReadInt64 read the int64 of n bits.
func (r *Reader) ReadInt64(n int) int64 { return int64(r.readUint64(n, 64)) }
// ReadUe8 read the UE GolombCode of uint8.
func (r *Reader) ReadUe8() uint8 { return uint8(r.ReadUe()) }
// ReadUe16 read the UE GolombCode of uint16.
func (r *Reader) ReadUe16() uint16 { return uint16(r.ReadUe()) }
// ReadSe8 read the SE of int8.
func (r *Reader) ReadSe8() int8 { return int8(r.ReadSe()) }
// ReadSe16 read the SE of int16.
func (r *Reader) ReadSe16() int16 { return int16(r.ReadSe()) }
// Offset returns the offset of bits.
func (r *Reader) Offset() int {
return r.offset
}
// BitsLeft returns the number of left bits.
func (r *Reader) BitsLeft() int {
return len(r.buf)<<3 - r.offset
}
// BytesLeft returns the left byte slice.
func (r *Reader) BytesLeft() []byte {
return r.buf[r.offset>>3:]
}
var bitsMask = [9]byte{
0x00,
0x01, 0x03, 0x07, 0x0f,
0x1f, 0x3f, 0x7f, 0xff,
}
// readUint64 read the uint64 of n bits.
func (r *Reader) readUint64(n, max int) uint64 {
if n <= 0 || n > max {
return 0
}
_ = r.buf[(r.offset+n-1)>>3] // bounds check hint to compiler; see golang.org/issue/14808
idx := r.offset >> 3
validBits := 8 - r.offset&0x7
r.offset += n
var tmp uint64
for n >= validBits {
n -= validBits
tmp |= uint64(r.buf[idx]&bitsMask[validBits]) << n
idx++
validBits = 8
}
if n > 0 {
tmp |= uint64((r.buf[idx] >> (validBits - n)) & bitsMask[n])
}
return tmp
}

164
utils/bits/reader_test.go Normal file
View File

@@ -0,0 +1,164 @@
// Copyright (c) 2019,CAOHONGJU All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package bits
import (
"testing"
"github.com/stretchr/testify/assert"
)
var bitsDatas = [][]byte{
{0x46, 0x4c, 0x56, 0x01, 0x05, 0x00, 0x00, 0x00, 0x09},
{
0x47, 0x40, 0x00, 0x10, 0x00,
0x00, 0xb0, 0x0d, 0x00, 0x01, 0xc1, 0x00, 0x00,
0x00, 0x01, 0xf0, 0x01,
0x2e, 0x70, 0x19, 0x05,
},
}
func TestBitsReader_ReadBit(t *testing.T) {
r := NewReader(bitsDatas[0])
gotRet := r.ReadBit()
wantRet := uint8(0)
assert.Equal(t, wantRet, gotRet)
gotRet = r.ReadBit()
wantRet = 1
assert.Equal(t, wantRet, gotRet)
r.Skip(3)
gotRet = r.ReadBit()
wantRet = 1
assert.Equal(t, wantRet, gotRet)
gotRet = r.ReadBit()
wantRet = 1
assert.Equal(t, wantRet, gotRet)
r.Skip(5)
gotRet = r.ReadBit()
wantRet = 1
assert.Equal(t, wantRet, gotRet)
gotRet = r.ReadBit()
wantRet = 1
assert.Equal(t, wantRet, gotRet)
gotRet = r.ReadBit()
wantRet = 0
assert.Equal(t, wantRet, gotRet)
gotRet = r.ReadUint8(8)
wantRet = 0x2b
assert.Equal(t, wantRet, gotRet)
}
func TestBitsReader_ReadUint16(t *testing.T) {
r := NewReader(bitsDatas[0])
gotRet := r.ReadUint16(16)
wantRet := uint16(0x464c)
assert.Equal(t, wantRet, gotRet)
r.Skip(4)
gotRet = r.ReadUint16(16)
wantRet = uint16(0x6010)
assert.Equal(t, wantRet, gotRet)
r.Skip(1)
gotRet = r.ReadUint16(2)
wantRet = uint16(0x2)
assert.Equal(t, wantRet, gotRet)
}
func TestBitsReader_ReadUint32(t *testing.T) {
r := NewReader(bitsDatas[1])
gotRet := r.ReadUint32(32)
wantRet := uint32(0x47400010)
assert.Equal(t, wantRet, gotRet)
r.Skip(4)
gotRet = r.ReadUint32(32)
wantRet = uint32(0x000b00d0)
assert.Equal(t, wantRet, gotRet)
r.Skip(8)
gotRet = r.ReadUint32(12)
wantRet = uint32(0x1c1)
assert.Equal(t, wantRet, gotRet)
}
func TestBitsReader_ReadUint64(t *testing.T) {
r := NewReader(bitsDatas[1])
gotRet := r.ReadUint64(36)
wantRet := uint64(0x474000100)
assert.Equal(t, wantRet, gotRet)
gotRet = r.ReadUint64(32)
wantRet = uint64(0x000b00d0)
assert.Equal(t, wantRet, gotRet)
r.Skip(8)
gotRet = r.ReadUint64(12)
wantRet = uint64(0x1c1)
assert.Equal(t, wantRet, gotRet)
}
func BenchmarkReadBit(b *testing.B) {
r := NewReader(bitsDatas[1])
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.offset = 2
ret := r.ReadBit()
_ = ret
}
}
func BenchmarkReadUint8(b *testing.B) {
r := NewReader(bitsDatas[1])
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.offset = 2
ret := r.ReadUint8(7)
_ = ret
}
}
func BenchmarkReadUint16(b *testing.B) {
r := NewReader(bitsDatas[1])
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.offset = 2
ret := r.ReadUint16(13)
_ = ret
}
}
func BenchmarkReadUint32(b *testing.B) {
r := NewReader(bitsDatas[1])
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.offset = 2
ret := r.ReadUint32(29)
_ = ret
}
}
func BenchmarkReadUint64(b *testing.B) {
r := NewReader(bitsDatas[1])
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.offset = 2
ret := r.ReadUint64(61)
_ = ret
}
}

37
utils/h264or5.go Normal file
View File

@@ -0,0 +1,37 @@
// Copyright (c) 2019,CAOHONGJU All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package utils
// RemoveH264or5EmulationBytes A general routine for making a copy of a (H.264 or H.265) NAL unit, removing 'emulation' bytes from the copy
// copy from live555
func RemoveH264or5EmulationBytes(from []byte) []byte {
to := make([]byte, len(from))
toMaxSize := len(to)
fromSize := len(from)
toSize := 0
i := 0
for i < fromSize && toSize+1 < toMaxSize {
if i+2 < fromSize && from[i] == 0 && from[i+1] == 0 && from[i+2] == 3 {
to[toSize] = 0
to[toSize+1] = 0
toSize += 2
i += 3
} else {
to[toSize] = from[i]
toSize++
i++
}
}
// 如果剩余最后一个字节,拷贝它
if i < fromSize && toSize < toMaxSize {
to[toSize] = from[i]
toSize++
i++
}
return to[:toSize]
// return bytes.Replace(from, []byte{0, 0, 3}, []byte{0, 0}, -1)
}