mirror of
https://github.com/cnotch/ipchub.git
synced 2025-09-26 19:41:18 +08:00
add uitls
This commit is contained in:
169
utils/bits/reader.go
Normal file
169
utils/bits/reader.go
Normal 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
164
utils/bits/reader_test.go
Normal 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
37
utils/h264or5.go
Normal 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)
|
||||
}
|
Reference in New Issue
Block a user