1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

GB28181: Enable regression test for gb28181. v5.0.122

1. Build regression test tool for gb28181.
2. Run regression test for gb28181.
3. Format go code and eliminate logs.
4. Change base docker to ubuntu20.

PICK 7750bdae10
This commit is contained in:
winlin 2022-12-31 17:15:07 +08:00
parent bc381a0242
commit 3f7c4a7ff4
32 changed files with 3882 additions and 9727 deletions

View file

@ -12,25 +12,25 @@ import "errors"
type AAC_PROFILE int
const (
MAIN AAC_PROFILE = iota
LC
SSR
MAIN AAC_PROFILE = iota
LC
SSR
)
type AAC_SAMPLING_FREQUENCY int
const (
AAC_SAMPLE_96000 AAC_SAMPLING_FREQUENCY = iota
AAC_SAMPLE_88200
AAC_SAMPLE_64000
AAC_SAMPLE_48000
AAC_SAMPLE_44100
AAC_SAMPLE_32000
AAC_SAMPLE_24000
AAC_SAMPLE_22050
AAC_SAMPLE_16000
AAC_SAMPLE_11025
AAC_SAMPLE_8000
AAC_SAMPLE_96000 AAC_SAMPLING_FREQUENCY = iota
AAC_SAMPLE_88200
AAC_SAMPLE_64000
AAC_SAMPLE_48000
AAC_SAMPLE_44100
AAC_SAMPLE_32000
AAC_SAMPLE_24000
AAC_SAMPLE_22050
AAC_SAMPLE_16000
AAC_SAMPLE_11025
AAC_SAMPLE_8000
)
var AAC_Sampling_Idx [11]int = [11]int{96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000}
@ -73,15 +73,15 @@ var AAC_Sampling_Idx [11]int = [11]int{96000, 88200, 64000, 48000, 44100, 32000,
// }
type ADTS_Fix_Header struct {
ID uint8
Layer uint8
Protection_absent uint8
Profile uint8
Sampling_frequency_index uint8
Private_bit uint8
Channel_configuration uint8
Originalorcopy uint8
Home uint8
ID uint8
Layer uint8
Protection_absent uint8
Profile uint8
Sampling_frequency_index uint8
Private_bit uint8
Channel_configuration uint8
Originalorcopy uint8
Home uint8
}
// adts_variable_header() {
@ -93,91 +93,91 @@ type ADTS_Fix_Header struct {
// }
type ADTS_Variable_Header struct {
Copyright_identification_bit uint8
copyright_identification_start uint8
Frame_length uint16
Adts_buffer_fullness uint16
Number_of_raw_data_blocks_in_frame uint8
Copyright_identification_bit uint8
copyright_identification_start uint8
Frame_length uint16
Adts_buffer_fullness uint16
Number_of_raw_data_blocks_in_frame uint8
}
type ADTS_Frame_Header struct {
Fix_Header ADTS_Fix_Header
Variable_Header ADTS_Variable_Header
Fix_Header ADTS_Fix_Header
Variable_Header ADTS_Variable_Header
}
func NewAdtsFrameHeader() *ADTS_Frame_Header {
return &ADTS_Frame_Header{
Fix_Header: ADTS_Fix_Header{
ID: 0,
Layer: 0,
Protection_absent: 1,
Profile: uint8(MAIN),
Sampling_frequency_index: uint8(AAC_SAMPLE_44100),
Private_bit: 0,
Channel_configuration: 0,
Originalorcopy: 0,
Home: 0,
},
return &ADTS_Frame_Header{
Fix_Header: ADTS_Fix_Header{
ID: 0,
Layer: 0,
Protection_absent: 1,
Profile: uint8(MAIN),
Sampling_frequency_index: uint8(AAC_SAMPLE_44100),
Private_bit: 0,
Channel_configuration: 0,
Originalorcopy: 0,
Home: 0,
},
Variable_Header: ADTS_Variable_Header{
copyright_identification_start: 0,
Copyright_identification_bit: 0,
Frame_length: 0,
Adts_buffer_fullness: 0,
Number_of_raw_data_blocks_in_frame: 0,
},
}
Variable_Header: ADTS_Variable_Header{
copyright_identification_start: 0,
Copyright_identification_bit: 0,
Frame_length: 0,
Adts_buffer_fullness: 0,
Number_of_raw_data_blocks_in_frame: 0,
},
}
}
func (frame *ADTS_Frame_Header) Decode(aac []byte) error {
_ = aac[6]
frame.Fix_Header.ID = aac[1] >> 3
frame.Fix_Header.Layer = aac[1] >> 1 & 0x03
frame.Fix_Header.Protection_absent = aac[1] & 0x01
frame.Fix_Header.Profile = aac[2] >> 6 & 0x03
frame.Fix_Header.Sampling_frequency_index = aac[2] >> 2 & 0x0F
frame.Fix_Header.Private_bit = aac[2] >> 1 & 0x01
frame.Fix_Header.Channel_configuration = (aac[2] & 0x01 << 2) | (aac[3] >> 6)
frame.Fix_Header.Originalorcopy = aac[3] >> 5 & 0x01
frame.Fix_Header.Home = aac[3] >> 4 & 0x01
frame.Variable_Header.Copyright_identification_bit = aac[3] >> 3 & 0x01
frame.Variable_Header.copyright_identification_start = aac[3] >> 2 & 0x01
frame.Variable_Header.Frame_length = (uint16(aac[3]&0x03) << 11) | (uint16(aac[4]) << 3) | (uint16(aac[5]>>5) & 0x07)
frame.Variable_Header.Adts_buffer_fullness = (uint16(aac[5]&0x1F) << 6) | uint16(aac[6]>>2)
frame.Variable_Header.Number_of_raw_data_blocks_in_frame = aac[6] & 0x03
return nil
_ = aac[6]
frame.Fix_Header.ID = aac[1] >> 3
frame.Fix_Header.Layer = aac[1] >> 1 & 0x03
frame.Fix_Header.Protection_absent = aac[1] & 0x01
frame.Fix_Header.Profile = aac[2] >> 6 & 0x03
frame.Fix_Header.Sampling_frequency_index = aac[2] >> 2 & 0x0F
frame.Fix_Header.Private_bit = aac[2] >> 1 & 0x01
frame.Fix_Header.Channel_configuration = (aac[2] & 0x01 << 2) | (aac[3] >> 6)
frame.Fix_Header.Originalorcopy = aac[3] >> 5 & 0x01
frame.Fix_Header.Home = aac[3] >> 4 & 0x01
frame.Variable_Header.Copyright_identification_bit = aac[3] >> 3 & 0x01
frame.Variable_Header.copyright_identification_start = aac[3] >> 2 & 0x01
frame.Variable_Header.Frame_length = (uint16(aac[3]&0x03) << 11) | (uint16(aac[4]) << 3) | (uint16(aac[5]>>5) & 0x07)
frame.Variable_Header.Adts_buffer_fullness = (uint16(aac[5]&0x1F) << 6) | uint16(aac[6]>>2)
frame.Variable_Header.Number_of_raw_data_blocks_in_frame = aac[6] & 0x03
return nil
}
func (frame *ADTS_Frame_Header) Encode() []byte {
var hdr []byte
if frame.Fix_Header.Protection_absent == 1 {
hdr = make([]byte, 7)
} else {
hdr = make([]byte, 9)
}
hdr[0] = 0xFF
hdr[1] = 0xF0
hdr[1] = hdr[1] | (frame.Fix_Header.ID << 3) | (frame.Fix_Header.Layer << 1) | frame.Fix_Header.Protection_absent
hdr[2] = frame.Fix_Header.Profile<<6 | frame.Fix_Header.Sampling_frequency_index<<2 | frame.Fix_Header.Private_bit<<1 | frame.Fix_Header.Channel_configuration>>2
hdr[3] = frame.Fix_Header.Channel_configuration<<6 | frame.Fix_Header.Originalorcopy<<5 | frame.Fix_Header.Home<<4
hdr[3] = hdr[3] | frame.Variable_Header.copyright_identification_start<<3 | frame.Variable_Header.Copyright_identification_bit<<2 | byte(frame.Variable_Header.Frame_length<<11)
hdr[4] = byte(frame.Variable_Header.Frame_length >> 3)
hdr[5] = byte((frame.Variable_Header.Frame_length&0x07)<<5) | byte(frame.Variable_Header.Adts_buffer_fullness>>3)
hdr[6] = byte(frame.Variable_Header.Adts_buffer_fullness&0x3F<<2) | frame.Variable_Header.Number_of_raw_data_blocks_in_frame
return hdr
var hdr []byte
if frame.Fix_Header.Protection_absent == 1 {
hdr = make([]byte, 7)
} else {
hdr = make([]byte, 9)
}
hdr[0] = 0xFF
hdr[1] = 0xF0
hdr[1] = hdr[1] | (frame.Fix_Header.ID << 3) | (frame.Fix_Header.Layer << 1) | frame.Fix_Header.Protection_absent
hdr[2] = frame.Fix_Header.Profile<<6 | frame.Fix_Header.Sampling_frequency_index<<2 | frame.Fix_Header.Private_bit<<1 | frame.Fix_Header.Channel_configuration>>2
hdr[3] = frame.Fix_Header.Channel_configuration<<6 | frame.Fix_Header.Originalorcopy<<5 | frame.Fix_Header.Home<<4
hdr[3] = hdr[3] | frame.Variable_Header.copyright_identification_start<<3 | frame.Variable_Header.Copyright_identification_bit<<2 | byte(frame.Variable_Header.Frame_length<<11)
hdr[4] = byte(frame.Variable_Header.Frame_length >> 3)
hdr[5] = byte((frame.Variable_Header.Frame_length&0x07)<<5) | byte(frame.Variable_Header.Adts_buffer_fullness>>3)
hdr[6] = byte(frame.Variable_Header.Adts_buffer_fullness&0x3F<<2) | frame.Variable_Header.Number_of_raw_data_blocks_in_frame
return hdr
}
func SampleToAACSampleIndex(sampling int) int {
for i, v := range AAC_Sampling_Idx {
if v == sampling {
return i
}
}
panic("not Found AAC Sample Index")
for i, v := range AAC_Sampling_Idx {
if v == sampling {
return i
}
}
panic("not Found AAC Sample Index")
}
func AACSampleIdxToSample(idx int) int {
return AAC_Sampling_Idx[idx]
return AAC_Sampling_Idx[idx]
}
// +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@ -185,71 +185,71 @@ func AACSampleIdxToSample(idx int) int {
// +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
type AudioSpecificConfiguration struct {
Audio_object_type uint8
Sample_freq_index uint8
Channel_configuration uint8
GA_framelength_flag uint8
GA_depends_on_core_coder uint8
GA_extension_flag uint8
Audio_object_type uint8
Sample_freq_index uint8
Channel_configuration uint8
GA_framelength_flag uint8
GA_depends_on_core_coder uint8
GA_extension_flag uint8
}
func NewAudioSpecificConfiguration() *AudioSpecificConfiguration {
return &AudioSpecificConfiguration{
Audio_object_type: 0,
Sample_freq_index: 0,
Channel_configuration: 0,
GA_framelength_flag: 0,
GA_depends_on_core_coder: 0,
GA_extension_flag: 0,
}
return &AudioSpecificConfiguration{
Audio_object_type: 0,
Sample_freq_index: 0,
Channel_configuration: 0,
GA_framelength_flag: 0,
GA_depends_on_core_coder: 0,
GA_extension_flag: 0,
}
}
func (asc *AudioSpecificConfiguration) Encode() []byte {
buf := make([]byte, 2)
buf[0] = (asc.Audio_object_type & 0x1f << 3) | (asc.Sample_freq_index & 0x0F >> 1)
buf[1] = (asc.Sample_freq_index & 0x0F << 7) | (asc.Channel_configuration & 0x0F << 3) | (asc.GA_framelength_flag & 0x01 << 2) | (asc.GA_depends_on_core_coder & 0x01 << 1) | (asc.GA_extension_flag & 0x01)
return buf
buf := make([]byte, 2)
buf[0] = (asc.Audio_object_type & 0x1f << 3) | (asc.Sample_freq_index & 0x0F >> 1)
buf[1] = (asc.Sample_freq_index & 0x0F << 7) | (asc.Channel_configuration & 0x0F << 3) | (asc.GA_framelength_flag & 0x01 << 2) | (asc.GA_depends_on_core_coder & 0x01 << 1) | (asc.GA_extension_flag & 0x01)
return buf
}
func (asc *AudioSpecificConfiguration) Decode(buf []byte) error {
if len(buf) < 2 {
return errors.New("len of buf < 2 ")
}
if len(buf) < 2 {
return errors.New("len of buf < 2 ")
}
asc.Audio_object_type = buf[0] >> 3
asc.Sample_freq_index = (buf[0] & 0x07 << 1) | (buf[1] >> 7)
asc.Channel_configuration = buf[1] >> 3 & 0x0F
asc.GA_framelength_flag = buf[1] >> 2 & 0x01
asc.GA_depends_on_core_coder = buf[1] >> 1 & 0x01
asc.GA_extension_flag = buf[1] & 0x01
return nil
asc.Audio_object_type = buf[0] >> 3
asc.Sample_freq_index = (buf[0] & 0x07 << 1) | (buf[1] >> 7)
asc.Channel_configuration = buf[1] >> 3 & 0x0F
asc.GA_framelength_flag = buf[1] >> 2 & 0x01
asc.GA_depends_on_core_coder = buf[1] >> 1 & 0x01
asc.GA_extension_flag = buf[1] & 0x01
return nil
}
func ConvertADTSToASC(frame []byte) ([]byte, error) {
if len(frame) < 7 {
return nil, errors.New("len of frame < 7")
}
if len(frame) < 7 {
return nil, errors.New("len of frame < 7")
}
adts := NewAdtsFrameHeader()
adts.Decode(frame)
asc := NewAudioSpecificConfiguration()
asc.Audio_object_type = adts.Fix_Header.Profile + 1
asc.Channel_configuration = adts.Fix_Header.Channel_configuration
asc.Sample_freq_index = adts.Fix_Header.Sampling_frequency_index
return asc.Encode(), nil
adts := NewAdtsFrameHeader()
adts.Decode(frame)
asc := NewAudioSpecificConfiguration()
asc.Audio_object_type = adts.Fix_Header.Profile + 1
asc.Channel_configuration = adts.Fix_Header.Channel_configuration
asc.Sample_freq_index = adts.Fix_Header.Sampling_frequency_index
return asc.Encode(), nil
}
func ConvertASCToADTS(asc []byte, aacbytes int) []byte {
aac_asc := NewAudioSpecificConfiguration()
aac_asc.Decode(asc)
aac_adts := NewAdtsFrameHeader()
aac_adts.Fix_Header.Profile = aac_asc.Audio_object_type - 1
aac_adts.Fix_Header.Channel_configuration = aac_asc.Channel_configuration
aac_adts.Fix_Header.Sampling_frequency_index = aac_asc.Sample_freq_index
aac_adts.Fix_Header.Protection_absent = 1
aac_adts.Variable_Header.Adts_buffer_fullness = 0x3F
aac_adts.Variable_Header.Frame_length = uint16(aacbytes)
return aac_adts.Encode()
aac_asc := NewAudioSpecificConfiguration()
aac_asc.Decode(asc)
aac_adts := NewAdtsFrameHeader()
aac_adts.Fix_Header.Profile = aac_asc.Audio_object_type - 1
aac_adts.Fix_Header.Channel_configuration = aac_asc.Channel_configuration
aac_adts.Fix_Header.Sampling_frequency_index = aac_asc.Sample_freq_index
aac_adts.Fix_Header.Protection_absent = 1
aac_adts.Variable_Header.Adts_buffer_fullness = 0x3F
aac_adts.Variable_Header.Frame_length = uint16(aacbytes)
return aac_adts.Encode()
}

View file

@ -1,358 +1,358 @@
package codec
import (
"encoding/binary"
"encoding/binary"
)
var BitMask [8]byte = [8]byte{0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}
type BitStream struct {
bits []byte
bytesOffset int
bitsOffset int
bitsmark int
bytemark int
bits []byte
bytesOffset int
bitsOffset int
bitsmark int
bytemark int
}
func NewBitStream(buf []byte) *BitStream {
return &BitStream{
bits: buf,
bytesOffset: 0,
bitsOffset: 0,
bitsmark: 0,
bytemark: 0,
}
return &BitStream{
bits: buf,
bytesOffset: 0,
bitsOffset: 0,
bitsmark: 0,
bytemark: 0,
}
}
func (bs *BitStream) Uint8(n int) uint8 {
return uint8(bs.GetBits(n))
return uint8(bs.GetBits(n))
}
func (bs *BitStream) Uint16(n int) uint16 {
return uint16(bs.GetBits(n))
return uint16(bs.GetBits(n))
}
func (bs *BitStream) Uint32(n int) uint32 {
return uint32(bs.GetBits(n))
return uint32(bs.GetBits(n))
}
func (bs *BitStream) GetBytes(n int) []byte {
if bs.bytesOffset+n > len(bs.bits) {
panic("OUT OF RANGE")
}
if bs.bitsOffset != 0 {
panic("invaild operation")
}
data := make([]byte, n)
copy(data, bs.bits[bs.bytesOffset:bs.bytesOffset+n])
bs.bytesOffset += n
return data
if bs.bytesOffset+n > len(bs.bits) {
panic("OUT OF RANGE")
}
if bs.bitsOffset != 0 {
panic("invaild operation")
}
data := make([]byte, n)
copy(data, bs.bits[bs.bytesOffset:bs.bytesOffset+n])
bs.bytesOffset += n
return data
}
//n <= 64
func (bs *BitStream) GetBits(n int) uint64 {
if bs.bytesOffset >= len(bs.bits) {
panic("OUT OF RANGE")
}
var ret uint64 = 0
if 8-bs.bitsOffset >= n {
ret = uint64((bs.bits[bs.bytesOffset] >> (8 - bs.bitsOffset - n)) & BitMask[n-1])
bs.bitsOffset += n
if bs.bitsOffset == 8 {
bs.bytesOffset++
bs.bitsOffset = 0
}
} else {
ret = uint64(bs.bits[bs.bytesOffset] & BitMask[8-bs.bitsOffset-1])
bs.bytesOffset++
n -= 8 - bs.bitsOffset
bs.bitsOffset = 0
for n > 0 {
if bs.bytesOffset >= len(bs.bits) {
panic("OUT OF RANGE")
}
if n >= 8 {
ret = ret<<8 | uint64(bs.bits[bs.bytesOffset])
bs.bytesOffset++
n -= 8
} else {
ret = (ret << n) | uint64((bs.bits[bs.bytesOffset]>>(8-n))&BitMask[n-1])
bs.bitsOffset = n
break
}
}
}
return ret
if bs.bytesOffset >= len(bs.bits) {
panic("OUT OF RANGE")
}
var ret uint64 = 0
if 8-bs.bitsOffset >= n {
ret = uint64((bs.bits[bs.bytesOffset] >> (8 - bs.bitsOffset - n)) & BitMask[n-1])
bs.bitsOffset += n
if bs.bitsOffset == 8 {
bs.bytesOffset++
bs.bitsOffset = 0
}
} else {
ret = uint64(bs.bits[bs.bytesOffset] & BitMask[8-bs.bitsOffset-1])
bs.bytesOffset++
n -= 8 - bs.bitsOffset
bs.bitsOffset = 0
for n > 0 {
if bs.bytesOffset >= len(bs.bits) {
panic("OUT OF RANGE")
}
if n >= 8 {
ret = ret<<8 | uint64(bs.bits[bs.bytesOffset])
bs.bytesOffset++
n -= 8
} else {
ret = (ret << n) | uint64((bs.bits[bs.bytesOffset]>>(8-n))&BitMask[n-1])
bs.bitsOffset = n
break
}
}
}
return ret
}
func (bs *BitStream) GetBit() uint8 {
if bs.bytesOffset >= len(bs.bits) {
panic("OUT OF RANGE")
}
ret := bs.bits[bs.bytesOffset] >> (7 - bs.bitsOffset) & 0x01
bs.bitsOffset++
if bs.bitsOffset >= 8 {
bs.bytesOffset++
bs.bitsOffset = 0
}
return ret
if bs.bytesOffset >= len(bs.bits) {
panic("OUT OF RANGE")
}
ret := bs.bits[bs.bytesOffset] >> (7 - bs.bitsOffset) & 0x01
bs.bitsOffset++
if bs.bitsOffset >= 8 {
bs.bytesOffset++
bs.bitsOffset = 0
}
return ret
}
func (bs *BitStream) SkipBits(n int) {
bytecount := n / 8
bitscount := n % 8
bs.bytesOffset += bytecount
if bs.bitsOffset+bitscount < 8 {
bs.bitsOffset += bitscount
} else {
bs.bytesOffset += 1
bs.bitsOffset += bitscount - 8
}
bytecount := n / 8
bitscount := n % 8
bs.bytesOffset += bytecount
if bs.bitsOffset+bitscount < 8 {
bs.bitsOffset += bitscount
} else {
bs.bytesOffset += 1
bs.bitsOffset += bitscount - 8
}
}
func (bs *BitStream) Markdot() {
bs.bitsmark = bs.bitsOffset
bs.bytemark = bs.bytesOffset
bs.bitsmark = bs.bitsOffset
bs.bytemark = bs.bytesOffset
}
func (bs *BitStream) DistanceFromMarkDot() int {
bytecount := bs.bytesOffset - bs.bytemark - 1
bitscount := bs.bitsOffset + (8 - bs.bitsmark)
return bytecount*8 + bitscount
bytecount := bs.bytesOffset - bs.bytemark - 1
bitscount := bs.bitsOffset + (8 - bs.bitsmark)
return bytecount*8 + bitscount
}
func (bs *BitStream) RemainBytes() int {
if bs.bitsOffset > 0 {
return len(bs.bits) - bs.bytesOffset - 1
} else {
return len(bs.bits) - bs.bytesOffset
}
if bs.bitsOffset > 0 {
return len(bs.bits) - bs.bytesOffset - 1
} else {
return len(bs.bits) - bs.bytesOffset
}
}
func (bs *BitStream) RemainBits() int {
if bs.bitsOffset > 0 {
return bs.RemainBytes()*8 + 8 - bs.bitsOffset
} else {
return bs.RemainBytes() * 8
}
if bs.bitsOffset > 0 {
return bs.RemainBytes()*8 + 8 - bs.bitsOffset
} else {
return bs.RemainBytes() * 8
}
}
func (bs *BitStream) Bits() []byte {
return bs.bits
return bs.bits
}
func (bs *BitStream) RemainData() []byte {
return bs.bits[bs.bytesOffset:]
return bs.bits[bs.bytesOffset:]
}
//无符号哥伦布熵编码
func (bs *BitStream) ReadUE() uint64 {
leadingZeroBits := 0
for bs.GetBit() == 0 {
leadingZeroBits++
}
if leadingZeroBits == 0 {
return 0
}
info := bs.GetBits(leadingZeroBits)
return uint64(1)<<leadingZeroBits - 1 + info
leadingZeroBits := 0
for bs.GetBit() == 0 {
leadingZeroBits++
}
if leadingZeroBits == 0 {
return 0
}
info := bs.GetBits(leadingZeroBits)
return uint64(1)<<leadingZeroBits - 1 + info
}
//有符号哥伦布熵编码
func (bs *BitStream) ReadSE() int64 {
v := bs.ReadUE()
if v%2 == 0 {
return -1 * int64(v/2)
} else {
return int64(v+1) / 2
}
v := bs.ReadUE()
if v%2 == 0 {
return -1 * int64(v/2)
} else {
return int64(v+1) / 2
}
}
func (bs *BitStream) ByteOffset() int {
return bs.bytesOffset
return bs.bytesOffset
}
func (bs *BitStream) UnRead(n int) {
if n-bs.bitsOffset <= 0 {
bs.bitsOffset -= n
} else {
least := n - bs.bitsOffset
for least >= 8 {
bs.bytesOffset--
least -= 8
}
if least > 0 {
bs.bytesOffset--
bs.bitsOffset = 8 - least
}
}
if n-bs.bitsOffset <= 0 {
bs.bitsOffset -= n
} else {
least := n - bs.bitsOffset
for least >= 8 {
bs.bytesOffset--
least -= 8
}
if least > 0 {
bs.bytesOffset--
bs.bitsOffset = 8 - least
}
}
}
func (bs *BitStream) NextBits(n int) uint64 {
r := bs.GetBits(n)
bs.UnRead(n)
return r
r := bs.GetBits(n)
bs.UnRead(n)
return r
}
func (bs *BitStream) EOS() bool {
return bs.bytesOffset == len(bs.bits) && bs.bitsOffset == 0
return bs.bytesOffset == len(bs.bits) && bs.bitsOffset == 0
}
type BitStreamWriter struct {
bits []byte
byteoffset int
bitsoffset int
bitsmark int
bytemark int
bits []byte
byteoffset int
bitsoffset int
bitsmark int
bytemark int
}
func NewBitStreamWriter(n int) *BitStreamWriter {
return &BitStreamWriter{
bits: make([]byte, n),
byteoffset: 0,
bitsoffset: 0,
bitsmark: 0,
bytemark: 0,
}
return &BitStreamWriter{
bits: make([]byte, n),
byteoffset: 0,
bitsoffset: 0,
bitsmark: 0,
bytemark: 0,
}
}
func (bsw *BitStreamWriter) expandSpace(n int) {
if (len(bsw.bits)-bsw.byteoffset-1)*8+8-bsw.bitsoffset < n {
newlen := 0
if len(bsw.bits)*8 < n {
newlen = len(bsw.bits) + n/8 + 1
} else {
newlen = len(bsw.bits) * 2
}
tmp := make([]byte, newlen)
copy(tmp, bsw.bits)
bsw.bits = tmp
}
if (len(bsw.bits)-bsw.byteoffset-1)*8+8-bsw.bitsoffset < n {
newlen := 0
if len(bsw.bits)*8 < n {
newlen = len(bsw.bits) + n/8 + 1
} else {
newlen = len(bsw.bits) * 2
}
tmp := make([]byte, newlen)
copy(tmp, bsw.bits)
bsw.bits = tmp
}
}
func (bsw *BitStreamWriter) ByteOffset() int {
return bsw.byteoffset
return bsw.byteoffset
}
func (bsw *BitStreamWriter) BitOffset() int {
return bsw.bitsoffset
return bsw.bitsoffset
}
func (bsw *BitStreamWriter) Markdot() {
bsw.bitsmark = bsw.bitsoffset
bsw.bytemark = bsw.byteoffset
bsw.bitsmark = bsw.bitsoffset
bsw.bytemark = bsw.byteoffset
}
func (bsw *BitStreamWriter) DistanceFromMarkDot() int {
bytecount := bsw.byteoffset - bsw.bytemark - 1
bitscount := bsw.bitsoffset + (8 - bsw.bitsmark)
return bytecount*8 + bitscount
bytecount := bsw.byteoffset - bsw.bytemark - 1
bitscount := bsw.bitsoffset + (8 - bsw.bitsmark)
return bytecount*8 + bitscount
}
func (bsw *BitStreamWriter) PutByte(v byte) {
bsw.expandSpace(8)
if bsw.bitsoffset == 0 {
bsw.bits[bsw.byteoffset] = v
bsw.byteoffset++
} else {
bsw.bits[bsw.byteoffset] |= v >> byte(bsw.bitsoffset)
bsw.byteoffset++
bsw.bits[bsw.byteoffset] = v & BitMask[bsw.bitsoffset-1]
}
bsw.expandSpace(8)
if bsw.bitsoffset == 0 {
bsw.bits[bsw.byteoffset] = v
bsw.byteoffset++
} else {
bsw.bits[bsw.byteoffset] |= v >> byte(bsw.bitsoffset)
bsw.byteoffset++
bsw.bits[bsw.byteoffset] = v & BitMask[bsw.bitsoffset-1]
}
}
func (bsw *BitStreamWriter) PutBytes(v []byte) {
if bsw.bitsoffset != 0 {
panic("bsw.bitsoffset > 0")
}
bsw.expandSpace(8 * len(v))
copy(bsw.bits[bsw.byteoffset:], v)
bsw.byteoffset += len(v)
if bsw.bitsoffset != 0 {
panic("bsw.bitsoffset > 0")
}
bsw.expandSpace(8 * len(v))
copy(bsw.bits[bsw.byteoffset:], v)
bsw.byteoffset += len(v)
}
func (bsw *BitStreamWriter) PutRepetValue(v byte, n int) {
if bsw.bitsoffset != 0 {
panic("bsw.bitsoffset > 0")
}
bsw.expandSpace(8 * n)
for i := 0; i < n; i++ {
bsw.bits[bsw.byteoffset] = v
bsw.byteoffset++
}
if bsw.bitsoffset != 0 {
panic("bsw.bitsoffset > 0")
}
bsw.expandSpace(8 * n)
for i := 0; i < n; i++ {
bsw.bits[bsw.byteoffset] = v
bsw.byteoffset++
}
}
func (bsw *BitStreamWriter) PutUint8(v uint8, n int) {
bsw.PutUint64(uint64(v), n)
bsw.PutUint64(uint64(v), n)
}
func (bsw *BitStreamWriter) PutUint16(v uint16, n int) {
bsw.PutUint64(uint64(v), n)
bsw.PutUint64(uint64(v), n)
}
func (bsw *BitStreamWriter) PutUint32(v uint32, n int) {
bsw.PutUint64(uint64(v), n)
bsw.PutUint64(uint64(v), n)
}
func (bsw *BitStreamWriter) PutUint64(v uint64, n int) {
bsw.expandSpace(n)
if 8-bsw.bitsoffset >= n {
bsw.bits[bsw.byteoffset] |= uint8(v) & BitMask[n-1] << (8 - bsw.bitsoffset - n)
bsw.bitsoffset += n
if bsw.bitsoffset == 8 {
bsw.bitsoffset = 0
bsw.byteoffset++
}
} else {
bsw.bits[bsw.byteoffset] |= uint8(v>>(n-int(8-bsw.bitsoffset))) & BitMask[8-bsw.bitsoffset-1]
bsw.byteoffset++
n -= 8 - bsw.bitsoffset
for n-8 >= 0 {
bsw.bits[bsw.byteoffset] = uint8(v>>(n-8)) & 0xFF
bsw.byteoffset++
n -= 8
}
bsw.bitsoffset = n
if n > 0 {
bsw.bits[bsw.byteoffset] |= (uint8(v) & BitMask[n-1]) << (8 - n)
}
}
bsw.expandSpace(n)
if 8-bsw.bitsoffset >= n {
bsw.bits[bsw.byteoffset] |= uint8(v) & BitMask[n-1] << (8 - bsw.bitsoffset - n)
bsw.bitsoffset += n
if bsw.bitsoffset == 8 {
bsw.bitsoffset = 0
bsw.byteoffset++
}
} else {
bsw.bits[bsw.byteoffset] |= uint8(v>>(n-int(8-bsw.bitsoffset))) & BitMask[8-bsw.bitsoffset-1]
bsw.byteoffset++
n -= 8 - bsw.bitsoffset
for n-8 >= 0 {
bsw.bits[bsw.byteoffset] = uint8(v>>(n-8)) & 0xFF
bsw.byteoffset++
n -= 8
}
bsw.bitsoffset = n
if n > 0 {
bsw.bits[bsw.byteoffset] |= (uint8(v) & BitMask[n-1]) << (8 - n)
}
}
}
func (bsw *BitStreamWriter) SetByte(v byte, where int) {
bsw.bits[where] = v
bsw.bits[where] = v
}
func (bsw *BitStreamWriter) SetUint16(v uint16, where int) {
binary.BigEndian.PutUint16(bsw.bits[where:where+2], v)
binary.BigEndian.PutUint16(bsw.bits[where:where+2], v)
}
func (bsw *BitStreamWriter) Bits() []byte {
if bsw.byteoffset == len(bsw.bits) {
return bsw.bits
}
if bsw.bitsoffset > 0 {
return bsw.bits[0 : bsw.byteoffset+1]
} else {
return bsw.bits[0:bsw.byteoffset]
}
if bsw.byteoffset == len(bsw.bits) {
return bsw.bits
}
if bsw.bitsoffset > 0 {
return bsw.bits[0 : bsw.byteoffset+1]
} else {
return bsw.bits[0:bsw.byteoffset]
}
}
//用v 填充剩余字节
func (bsw *BitStreamWriter) FillRemainData(v byte) {
for i := bsw.byteoffset; i < len(bsw.bits); i++ {
bsw.bits[i] = v
}
bsw.byteoffset = len(bsw.bits)
bsw.bitsoffset = 0
for i := bsw.byteoffset; i < len(bsw.bits); i++ {
bsw.bits[i] = v
}
bsw.byteoffset = len(bsw.bits)
bsw.bitsoffset = 0
}
func (bsw *BitStreamWriter) Reset() {
for i := 0; i < len(bsw.bits); i++ {
bsw.bits[i] = 0
}
bsw.bitsmark = 0
bsw.bytemark = 0
bsw.bitsoffset = 0
bsw.byteoffset = 0
for i := 0; i < len(bsw.bits); i++ {
bsw.bits[i] = 0
}
bsw.bitsmark = 0
bsw.bytemark = 0
bsw.bitsoffset = 0
bsw.byteoffset = 0
}

View file

@ -3,62 +3,62 @@ package codec
type CodecID int
const (
CODECID_VIDEO_H264 CodecID = iota
CODECID_VIDEO_H265
CODECID_VIDEO_VP8
CODECID_VIDEO_H264 CodecID = iota
CODECID_VIDEO_H265
CODECID_VIDEO_VP8
CODECID_AUDIO_AAC CodecID = iota + 98
CODECID_AUDIO_G711A
CODECID_AUDIO_G711U
CODECID_AUDIO_OPUS
CODECID_AUDIO_AAC CodecID = iota + 98
CODECID_AUDIO_G711A
CODECID_AUDIO_G711U
CODECID_AUDIO_OPUS
CODECID_UNRECOGNIZED = 999
CODECID_UNRECOGNIZED = 999
)
type H264_NAL_TYPE int
const (
H264_NAL_RESERVED H264_NAL_TYPE = iota
H264_NAL_P_SLICE
H264_NAL_SLICE_A
H264_NAL_SLICE_B
H264_NAL_SLICE_C
H264_NAL_I_SLICE
H264_NAL_SEI
H264_NAL_SPS
H264_NAL_PPS
H264_NAL_AUD
H264_NAL_RESERVED H264_NAL_TYPE = iota
H264_NAL_P_SLICE
H264_NAL_SLICE_A
H264_NAL_SLICE_B
H264_NAL_SLICE_C
H264_NAL_I_SLICE
H264_NAL_SEI
H264_NAL_SPS
H264_NAL_PPS
H264_NAL_AUD
)
type H265_NAL_TYPE int
const (
H265_NAL_Slice_TRAIL_N H265_NAL_TYPE = iota
H265_NAL_LICE_TRAIL_R
H265_NAL_SLICE_TSA_N
H265_NAL_SLICE_TSA_R
H265_NAL_SLICE_STSA_N
H265_NAL_SLICE_STSA_R
H265_NAL_SLICE_RADL_N
H265_NAL_SLICE_RADL_R
H265_NAL_SLICE_RASL_N
H265_NAL_SLICE_RASL_R
H265_NAL_Slice_TRAIL_N H265_NAL_TYPE = iota
H265_NAL_LICE_TRAIL_R
H265_NAL_SLICE_TSA_N
H265_NAL_SLICE_TSA_R
H265_NAL_SLICE_STSA_N
H265_NAL_SLICE_STSA_R
H265_NAL_SLICE_RADL_N
H265_NAL_SLICE_RADL_R
H265_NAL_SLICE_RASL_N
H265_NAL_SLICE_RASL_R
//IDR
H265_NAL_SLICE_BLA_W_LP H265_NAL_TYPE = iota + 6
H265_NAL_SLICE_BLA_W_RADL
H265_NAL_SLICE_BLA_N_LP
H265_NAL_SLICE_IDR_W_RADL
H265_NAL_SLICE_IDR_N_LP
H265_NAL_SLICE_CRA
//IDR
H265_NAL_SLICE_BLA_W_LP H265_NAL_TYPE = iota + 6
H265_NAL_SLICE_BLA_W_RADL
H265_NAL_SLICE_BLA_N_LP
H265_NAL_SLICE_IDR_W_RADL
H265_NAL_SLICE_IDR_N_LP
H265_NAL_SLICE_CRA
//vps pps sps
H265_NAL_VPS H265_NAL_TYPE = iota + 16
H265_NAL_SPS
H265_NAL_PPS
H265_NAL_AUD
//vps pps sps
H265_NAL_VPS H265_NAL_TYPE = iota + 16
H265_NAL_SPS
H265_NAL_PPS
H265_NAL_AUD
//SEI
H265_NAL_SEI H265_NAL_TYPE = iota + 19
H265_NAL_SEI_SUFFIX
//SEI
H265_NAL_SEI H265_NAL_TYPE = iota + 19
H265_NAL_SEI_SUFFIX
)

View file

@ -9,241 +9,241 @@ import "encoding/binary"
// }
type H264NaluHdr struct {
Forbidden_zero_bit uint8
Nal_ref_idc uint8
Nal_unit_type uint8
Forbidden_zero_bit uint8
Nal_ref_idc uint8
Nal_unit_type uint8
}
func (hdr *H264NaluHdr) Decode(bs *BitStream) {
hdr.Forbidden_zero_bit = bs.GetBit()
hdr.Nal_ref_idc = bs.Uint8(2)
hdr.Nal_unit_type = bs.Uint8(5)
hdr.Forbidden_zero_bit = bs.GetBit()
hdr.Nal_ref_idc = bs.Uint8(2)
hdr.Nal_unit_type = bs.Uint8(5)
}
type SliceHeader struct {
First_mb_in_slice uint64
Slice_type uint64
Pic_parameter_set_id uint64
Frame_num uint64
First_mb_in_slice uint64
Slice_type uint64
Pic_parameter_set_id uint64
Frame_num uint64
}
//调用方根据sps中的log2_max_frame_num_minus4的值来解析Frame_num
func (sh *SliceHeader) Decode(bs *BitStream) {
sh.First_mb_in_slice = bs.ReadUE()
sh.Slice_type = bs.ReadUE()
sh.Pic_parameter_set_id = bs.ReadUE()
sh.First_mb_in_slice = bs.ReadUE()
sh.Slice_type = bs.ReadUE()
sh.Pic_parameter_set_id = bs.ReadUE()
}
type SPS struct {
Profile_idc uint8
Constraint_set0_flag uint8
Constraint_set1_flag uint8
Constraint_set2_flag uint8
Constraint_set3_flag uint8
Constraint_set4_flag uint8
Constraint_set5_flag uint8
Reserved_zero_2bits uint8
Level_idc uint8
Seq_parameter_set_id uint64
Chroma_format_idc uint64
Separate_colour_plane_flag uint8
Bit_depth_luma_minus8 uint64
Bit_depth_chroma_minus8 uint64
Log2_max_frame_num_minus4 uint64
Pic_order_cnt_type uint64
Max_num_ref_frames uint64
Gaps_in_frame_num_value_allowed_flag uint8
Pic_width_in_mbs_minus1 uint64
Pic_height_in_map_units_minus1 uint64
Frame_mbs_only_flag uint8
Direct_8x8_inference_flag uint8
Frame_cropping_flag uint8
Frame_crop_left_offset uint64
Frame_crop_right_offset uint64
Frame_crop_top_offset uint64
Frame_crop_bottom_offset uint64
Vui_parameters_present_flag uint8
Profile_idc uint8
Constraint_set0_flag uint8
Constraint_set1_flag uint8
Constraint_set2_flag uint8
Constraint_set3_flag uint8
Constraint_set4_flag uint8
Constraint_set5_flag uint8
Reserved_zero_2bits uint8
Level_idc uint8
Seq_parameter_set_id uint64
Chroma_format_idc uint64
Separate_colour_plane_flag uint8
Bit_depth_luma_minus8 uint64
Bit_depth_chroma_minus8 uint64
Log2_max_frame_num_minus4 uint64
Pic_order_cnt_type uint64
Max_num_ref_frames uint64
Gaps_in_frame_num_value_allowed_flag uint8
Pic_width_in_mbs_minus1 uint64
Pic_height_in_map_units_minus1 uint64
Frame_mbs_only_flag uint8
Direct_8x8_inference_flag uint8
Frame_cropping_flag uint8
Frame_crop_left_offset uint64
Frame_crop_right_offset uint64
Frame_crop_top_offset uint64
Frame_crop_bottom_offset uint64
Vui_parameters_present_flag uint8
}
func (sps *SPS) Decode(bs *BitStream) {
sps.Profile_idc = bs.Uint8(8)
sps.Constraint_set0_flag = bs.GetBit()
sps.Constraint_set1_flag = bs.GetBit()
sps.Constraint_set2_flag = bs.GetBit()
sps.Constraint_set3_flag = bs.GetBit()
sps.Constraint_set4_flag = bs.GetBit()
sps.Constraint_set5_flag = bs.GetBit()
sps.Reserved_zero_2bits = bs.Uint8(2)
sps.Level_idc = bs.Uint8(8)
sps.Seq_parameter_set_id = bs.ReadUE()
if sps.Profile_idc == 100 || sps.Profile_idc == 110 ||
sps.Profile_idc == 122 || sps.Profile_idc == 244 ||
sps.Profile_idc == 44 || sps.Profile_idc == 83 ||
sps.Profile_idc == 86 || sps.Profile_idc == 118 || sps.Profile_idc == 128 {
sps.Chroma_format_idc = bs.ReadUE()
if sps.Chroma_format_idc == 3 {
sps.Separate_colour_plane_flag = bs.Uint8(1) //separate_colour_plane_flag
}
sps.Bit_depth_luma_minus8 = bs.ReadUE() //bit_depth_luma_minus8
sps.Bit_depth_chroma_minus8 = bs.ReadUE() //bit_depth_chroma_minus8
bs.SkipBits(1) //qpprime_y_zero_transform_bypass_flag
seq_scaling_matrix_present_flag := bs.GetBit()
if seq_scaling_matrix_present_flag == 1 {
//seq_scaling_list_present_flag[i]
if sps.Chroma_format_idc == 3 {
bs.SkipBits(12)
} else {
bs.SkipBits(8)
}
}
}
sps.Log2_max_frame_num_minus4 = bs.ReadUE()
sps.Pic_order_cnt_type = bs.ReadUE()
if sps.Pic_order_cnt_type == 0 {
bs.ReadUE() // log2_max_pic_order_cnt_lsb_minus4
} else if sps.Pic_order_cnt_type == 1 {
bs.SkipBits(1) //delta_pic_order_always_zero_flag
bs.ReadSE() //offset_for_non_ref_pic
bs.ReadSE() //offset_for_top_to_bottom_field
num_ref_frames_in_pic_order_cnt_cycle := bs.ReadUE()
for i := 0; i < int(num_ref_frames_in_pic_order_cnt_cycle); i++ {
bs.ReadSE() //offset_for_ref_frame
}
}
sps.Max_num_ref_frames = bs.ReadUE()
sps.Gaps_in_frame_num_value_allowed_flag = bs.GetBit()
sps.Pic_width_in_mbs_minus1 = bs.ReadUE()
sps.Pic_height_in_map_units_minus1 = bs.ReadUE()
sps.Frame_mbs_only_flag = bs.GetBit()
if sps.Frame_mbs_only_flag == 0 {
bs.SkipBits(1) // mb_adaptive_frame_field_flag
}
sps.Direct_8x8_inference_flag = bs.GetBit()
sps.Frame_cropping_flag = bs.GetBit()
if sps.Frame_cropping_flag == 1 {
sps.Frame_crop_left_offset = bs.ReadUE() //frame_crop_left_offset
sps.Frame_crop_right_offset = bs.ReadUE() //frame_crop_right_offset
sps.Frame_crop_top_offset = bs.ReadUE() //frame_crop_top_offset
sps.Frame_crop_bottom_offset = bs.ReadUE() //frame_crop_bottom_offset
}
sps.Vui_parameters_present_flag = bs.GetBit()
sps.Profile_idc = bs.Uint8(8)
sps.Constraint_set0_flag = bs.GetBit()
sps.Constraint_set1_flag = bs.GetBit()
sps.Constraint_set2_flag = bs.GetBit()
sps.Constraint_set3_flag = bs.GetBit()
sps.Constraint_set4_flag = bs.GetBit()
sps.Constraint_set5_flag = bs.GetBit()
sps.Reserved_zero_2bits = bs.Uint8(2)
sps.Level_idc = bs.Uint8(8)
sps.Seq_parameter_set_id = bs.ReadUE()
if sps.Profile_idc == 100 || sps.Profile_idc == 110 ||
sps.Profile_idc == 122 || sps.Profile_idc == 244 ||
sps.Profile_idc == 44 || sps.Profile_idc == 83 ||
sps.Profile_idc == 86 || sps.Profile_idc == 118 || sps.Profile_idc == 128 {
sps.Chroma_format_idc = bs.ReadUE()
if sps.Chroma_format_idc == 3 {
sps.Separate_colour_plane_flag = bs.Uint8(1) //separate_colour_plane_flag
}
sps.Bit_depth_luma_minus8 = bs.ReadUE() //bit_depth_luma_minus8
sps.Bit_depth_chroma_minus8 = bs.ReadUE() //bit_depth_chroma_minus8
bs.SkipBits(1) //qpprime_y_zero_transform_bypass_flag
seq_scaling_matrix_present_flag := bs.GetBit()
if seq_scaling_matrix_present_flag == 1 {
//seq_scaling_list_present_flag[i]
if sps.Chroma_format_idc == 3 {
bs.SkipBits(12)
} else {
bs.SkipBits(8)
}
}
}
sps.Log2_max_frame_num_minus4 = bs.ReadUE()
sps.Pic_order_cnt_type = bs.ReadUE()
if sps.Pic_order_cnt_type == 0 {
bs.ReadUE() // log2_max_pic_order_cnt_lsb_minus4
} else if sps.Pic_order_cnt_type == 1 {
bs.SkipBits(1) //delta_pic_order_always_zero_flag
bs.ReadSE() //offset_for_non_ref_pic
bs.ReadSE() //offset_for_top_to_bottom_field
num_ref_frames_in_pic_order_cnt_cycle := bs.ReadUE()
for i := 0; i < int(num_ref_frames_in_pic_order_cnt_cycle); i++ {
bs.ReadSE() //offset_for_ref_frame
}
}
sps.Max_num_ref_frames = bs.ReadUE()
sps.Gaps_in_frame_num_value_allowed_flag = bs.GetBit()
sps.Pic_width_in_mbs_minus1 = bs.ReadUE()
sps.Pic_height_in_map_units_minus1 = bs.ReadUE()
sps.Frame_mbs_only_flag = bs.GetBit()
if sps.Frame_mbs_only_flag == 0 {
bs.SkipBits(1) // mb_adaptive_frame_field_flag
}
sps.Direct_8x8_inference_flag = bs.GetBit()
sps.Frame_cropping_flag = bs.GetBit()
if sps.Frame_cropping_flag == 1 {
sps.Frame_crop_left_offset = bs.ReadUE() //frame_crop_left_offset
sps.Frame_crop_right_offset = bs.ReadUE() //frame_crop_right_offset
sps.Frame_crop_top_offset = bs.ReadUE() //frame_crop_top_offset
sps.Frame_crop_bottom_offset = bs.ReadUE() //frame_crop_bottom_offset
}
sps.Vui_parameters_present_flag = bs.GetBit()
}
type PPS struct {
Pic_parameter_set_id uint64
Seq_parameter_set_id uint64
Entropy_coding_mode_flag uint8
Bottom_field_pic_order_in_frame_present_flag uint8
Num_slice_groups_minus1 uint64
Pic_parameter_set_id uint64
Seq_parameter_set_id uint64
Entropy_coding_mode_flag uint8
Bottom_field_pic_order_in_frame_present_flag uint8
Num_slice_groups_minus1 uint64
}
func (pps *PPS) Decode(bs *BitStream) {
pps.Pic_parameter_set_id = bs.ReadUE()
pps.Seq_parameter_set_id = bs.ReadUE()
pps.Entropy_coding_mode_flag = bs.GetBit()
pps.Bottom_field_pic_order_in_frame_present_flag = bs.GetBit()
pps.Num_slice_groups_minus1 = bs.ReadUE()
pps.Pic_parameter_set_id = bs.ReadUE()
pps.Seq_parameter_set_id = bs.ReadUE()
pps.Entropy_coding_mode_flag = bs.GetBit()
pps.Bottom_field_pic_order_in_frame_present_flag = bs.GetBit()
pps.Num_slice_groups_minus1 = bs.ReadUE()
}
type SEIReaderWriter interface {
Read(size uint16, bs *BitStream)
Write(bsw *BitStreamWriter)
Read(size uint16, bs *BitStream)
Write(bsw *BitStreamWriter)
}
type UserDataUnregistered struct {
UUID []byte
UserData []byte
UUID []byte
UserData []byte
}
func (udu *UserDataUnregistered) Read(size uint16, bs *BitStream) {
udu.UUID = bs.GetBytes(16)
udu.UserData = bs.GetBytes(int(size - 16))
udu.UUID = bs.GetBytes(16)
udu.UserData = bs.GetBytes(int(size - 16))
}
func (udu *UserDataUnregistered) Write(bsw *BitStreamWriter) {
bsw.PutBytes(udu.UUID)
bsw.PutBytes(udu.UserData)
bsw.PutBytes(udu.UUID)
bsw.PutBytes(udu.UserData)
}
type SEI struct {
PayloadType uint16
PayloadSize uint16
Sei_payload SEIReaderWriter
PayloadType uint16
PayloadSize uint16
Sei_payload SEIReaderWriter
}
func (sei *SEI) Decode(bs *BitStream) {
for bs.NextBits(8) == 0xFF {
sei.PayloadType += 255
}
sei.PayloadType += uint16(bs.Uint8(8))
for bs.NextBits(8) == 0xFF {
sei.PayloadSize += 255
}
sei.PayloadSize += uint16(bs.Uint8(8))
if sei.PayloadType == 5 {
sei.Sei_payload = new(UserDataUnregistered)
sei.Sei_payload.Read(sei.PayloadSize, bs)
}
for bs.NextBits(8) == 0xFF {
sei.PayloadType += 255
}
sei.PayloadType += uint16(bs.Uint8(8))
for bs.NextBits(8) == 0xFF {
sei.PayloadSize += 255
}
sei.PayloadSize += uint16(bs.Uint8(8))
if sei.PayloadType == 5 {
sei.Sei_payload = new(UserDataUnregistered)
sei.Sei_payload.Read(sei.PayloadSize, bs)
}
}
func (sei *SEI) Encode(bsw *BitStreamWriter) []byte {
payloadType := sei.PayloadType
payloadSize := sei.PayloadSize
for payloadType >= 0xFF {
bsw.PutByte(0xFF)
payloadType -= 255
}
bsw.PutByte(uint8(payloadType))
for payloadSize >= 0xFF {
bsw.PutByte(0xFF)
payloadSize -= 255
}
bsw.PutByte(uint8(payloadSize))
sei.Sei_payload.Write(bsw)
return bsw.Bits()
payloadType := sei.PayloadType
payloadSize := sei.PayloadSize
for payloadType >= 0xFF {
bsw.PutByte(0xFF)
payloadType -= 255
}
bsw.PutByte(uint8(payloadType))
for payloadSize >= 0xFF {
bsw.PutByte(0xFF)
payloadSize -= 255
}
bsw.PutByte(uint8(payloadSize))
sei.Sei_payload.Write(bsw)
return bsw.Bits()
}
func GetSPSIdWithStartCode(sps []byte) uint64 {
start, sc := FindStartCode(sps, 0)
return GetSPSId(sps[start+int(sc):])
start, sc := FindStartCode(sps, 0)
return GetSPSId(sps[start+int(sc):])
}
func GetSPSId(sps []byte) uint64 {
sps = sps[1:]
bs := NewBitStream(sps)
bs.SkipBits(24)
return bs.ReadUE()
sps = sps[1:]
bs := NewBitStream(sps)
bs.SkipBits(24)
return bs.ReadUE()
}
func GetPPSIdWithStartCode(pps []byte) uint64 {
start, sc := FindStartCode(pps, 0)
return GetPPSId(pps[start+int(sc):])
start, sc := FindStartCode(pps, 0)
return GetPPSId(pps[start+int(sc):])
}
func GetPPSId(pps []byte) uint64 {
pps = pps[1:]
bs := NewBitStream(pps)
return bs.ReadUE()
pps = pps[1:]
bs := NewBitStream(pps)
return bs.ReadUE()
}
//https://stackoverflow.com/questions/12018535/get-the-width-height-of-the-video-from-h-264-nalu
//int Width = ((pic_width_in_mbs_minus1 +1)*16) - frame_crop_right_offset *2 - frame_crop_left_offset *2;
//int Height = ((2 - frame_mbs_only_flag)* (pic_height_in_map_units_minus1 +1) * 16) - (frame_crop_bottom_offset* 2) - (frame_crop_top_offset* 2);
func GetH264Resolution(sps []byte) (width uint32, height uint32) {
start, sc := FindStartCode(sps, 0)
bs := NewBitStream(sps[start+int(sc)+1:])
var s SPS
s.Decode(bs)
start, sc := FindStartCode(sps, 0)
bs := NewBitStream(sps[start+int(sc)+1:])
var s SPS
s.Decode(bs)
widthInSample := (uint32(s.Pic_width_in_mbs_minus1) + 1) * 16
widthCrop := uint32(s.Frame_crop_left_offset)*2 - uint32(s.Frame_crop_right_offset)*2
width = widthInSample - widthCrop
widthInSample := (uint32(s.Pic_width_in_mbs_minus1) + 1) * 16
widthCrop := uint32(s.Frame_crop_left_offset)*2 - uint32(s.Frame_crop_right_offset)*2
width = widthInSample - widthCrop
heightInSample := ((2 - uint32(s.Frame_mbs_only_flag)) * (uint32(s.Pic_height_in_map_units_minus1) + 1) * 16)
heightCrop := uint32(s.Frame_crop_bottom_offset)*2 - uint32(s.Frame_crop_top_offset)*2
height = heightInSample - heightCrop
heightInSample := ((2 - uint32(s.Frame_mbs_only_flag)) * (uint32(s.Pic_height_in_map_units_minus1) + 1) * 16)
heightCrop := uint32(s.Frame_crop_bottom_offset)*2 - uint32(s.Frame_crop_top_offset)*2
height = heightInSample - heightCrop
return
return
}
// aligned(8) class AVCDecoderConfigurationRecord {
@ -302,95 +302,95 @@ func GetH264Resolution(sps []byte) (width uint32, height uint32) {
// variable PPS NALU data
func CreateH264AVCCExtradata(spss [][]byte, ppss [][]byte) []byte {
extradata := make([]byte, 6, 256)
for i, sps := range spss {
start, sc := FindStartCode(sps, 0)
spss[i] = sps[start+int(sc):]
}
extradata := make([]byte, 6, 256)
for i, sps := range spss {
start, sc := FindStartCode(sps, 0)
spss[i] = sps[start+int(sc):]
}
for i, pps := range ppss {
start, sc := FindStartCode(pps, 0)
ppss[i] = pps[start+int(sc):]
}
for i, pps := range ppss {
start, sc := FindStartCode(pps, 0)
ppss[i] = pps[start+int(sc):]
}
extradata[0] = 0x01
extradata[1] = spss[0][1]
extradata[2] = spss[0][2]
extradata[3] = spss[0][3]
extradata[4] = 0xFF
extradata[5] = 0xE0 | uint8(len(spss))
for _, sps := range spss {
spssize := make([]byte, 2)
binary.BigEndian.PutUint16(spssize, uint16(len(sps)))
extradata = append(extradata, spssize...)
extradata = append(extradata, sps...)
}
extradata = append(extradata, uint8(len(ppss)))
for _, pps := range ppss {
ppssize := make([]byte, 2)
binary.BigEndian.PutUint16(ppssize, uint16(len(pps)))
extradata = append(extradata, ppssize...)
extradata = append(extradata, pps...)
}
var h264sps SPS
h264sps.Decode(NewBitStream(spss[0][1:]))
if h264sps.Profile_idc == 100 ||
h264sps.Profile_idc == 110 ||
h264sps.Profile_idc == 122 ||
h264sps.Profile_idc == 144 {
tmp := make([]byte, 4)
tmp[0] = 0xFC | uint8(h264sps.Chroma_format_idc&0x03)
tmp[1] = 0xF8 | uint8(h264sps.Bit_depth_luma_minus8&0x07)
tmp[2] = 0xF8 | uint8(h264sps.Bit_depth_chroma_minus8&0x07)
tmp[3] = 0
extradata = append(extradata, tmp...)
}
extradata[0] = 0x01
extradata[1] = spss[0][1]
extradata[2] = spss[0][2]
extradata[3] = spss[0][3]
extradata[4] = 0xFF
extradata[5] = 0xE0 | uint8(len(spss))
for _, sps := range spss {
spssize := make([]byte, 2)
binary.BigEndian.PutUint16(spssize, uint16(len(sps)))
extradata = append(extradata, spssize...)
extradata = append(extradata, sps...)
}
extradata = append(extradata, uint8(len(ppss)))
for _, pps := range ppss {
ppssize := make([]byte, 2)
binary.BigEndian.PutUint16(ppssize, uint16(len(pps)))
extradata = append(extradata, ppssize...)
extradata = append(extradata, pps...)
}
var h264sps SPS
h264sps.Decode(NewBitStream(spss[0][1:]))
if h264sps.Profile_idc == 100 ||
h264sps.Profile_idc == 110 ||
h264sps.Profile_idc == 122 ||
h264sps.Profile_idc == 144 {
tmp := make([]byte, 4)
tmp[0] = 0xFC | uint8(h264sps.Chroma_format_idc&0x03)
tmp[1] = 0xF8 | uint8(h264sps.Bit_depth_luma_minus8&0x07)
tmp[2] = 0xF8 | uint8(h264sps.Bit_depth_chroma_minus8&0x07)
tmp[3] = 0
extradata = append(extradata, tmp...)
}
return extradata
return extradata
}
func CovertExtradata(extraData []byte) ([][]byte, [][]byte) {
spsnum := extraData[5] & 0x1F
spss := make([][]byte, spsnum)
offset := 6
for i := 0; i < int(spsnum); i++ {
spssize := binary.BigEndian.Uint16(extraData[offset:])
sps := make([]byte, spssize+4)
copy(sps, []byte{0x00, 0x00, 0x00, 0x01})
copy(sps[4:], extraData[offset+2:offset+2+int(spssize)])
offset += 2 + int(spssize)
spss[i] = sps
}
ppsnum := extraData[offset]
ppss := make([][]byte, ppsnum)
offset++
for i := 0; i < int(ppsnum); i++ {
ppssize := binary.BigEndian.Uint16(extraData[offset:])
pps := make([]byte, ppssize+4)
copy(pps, []byte{0x00, 0x00, 0x00, 0x01})
copy(pps[4:], extraData[offset+2:offset+2+int(ppssize)])
offset += 2 + int(ppssize)
ppss[i] = pps
}
return spss, ppss
spsnum := extraData[5] & 0x1F
spss := make([][]byte, spsnum)
offset := 6
for i := 0; i < int(spsnum); i++ {
spssize := binary.BigEndian.Uint16(extraData[offset:])
sps := make([]byte, spssize+4)
copy(sps, []byte{0x00, 0x00, 0x00, 0x01})
copy(sps[4:], extraData[offset+2:offset+2+int(spssize)])
offset += 2 + int(spssize)
spss[i] = sps
}
ppsnum := extraData[offset]
ppss := make([][]byte, ppsnum)
offset++
for i := 0; i < int(ppsnum); i++ {
ppssize := binary.BigEndian.Uint16(extraData[offset:])
pps := make([]byte, ppssize+4)
copy(pps, []byte{0x00, 0x00, 0x00, 0x01})
copy(pps[4:], extraData[offset+2:offset+2+int(ppssize)])
offset += 2 + int(ppssize)
ppss[i] = pps
}
return spss, ppss
}
func ConvertAnnexBToAVCC(annexb []byte) []byte {
start, sc := FindStartCode(annexb, 0)
if sc == START_CODE_4 {
binary.BigEndian.PutUint32(annexb[start:], uint32(len(annexb)-4))
return annexb
} else {
avcc := make([]byte, 1+len(annexb))
binary.BigEndian.PutUint32(avcc, uint32(len(annexb)-3))
copy(avcc[4:], annexb[start+3:])
return avcc
}
start, sc := FindStartCode(annexb, 0)
if sc == START_CODE_4 {
binary.BigEndian.PutUint32(annexb[start:], uint32(len(annexb)-4))
return annexb
} else {
avcc := make([]byte, 1+len(annexb))
binary.BigEndian.PutUint32(avcc, uint32(len(annexb)-3))
copy(avcc[4:], annexb[start+3:])
return avcc
}
}
func CovertAVCCToAnnexB(avcc []byte) {
avcc[0] = 0x00
avcc[1] = 0x00
avcc[2] = 0x00
avcc[3] = 0x01
avcc[0] = 0x00
avcc[1] = 0x00
avcc[2] = 0x00
avcc[3] = 0x01
}

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
package codec
import (
"encoding/binary"
"errors"
"encoding/binary"
"errors"
)
// rfc6716 https://datatracker.ietf.org/doc/html/rfc6716
@ -157,169 +157,169 @@ import (
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
var (
/// 10ms,20ms,40ms,60ms, samplerate 48000
// sample num per millisecond
// 48000 / 1000ms * 10 = 480 ...
SLKOpusSampleSize [4]int = [4]int{480, 960, 1920, 2880}
HybridOpusSampleSize [4]int = [4]int{480, 960}
CELTOpusSampleSize [4]int = [4]int{120, 210, 480, 960}
/// 10ms,20ms,40ms,60ms, samplerate 48000
// sample num per millisecond
// 48000 / 1000ms * 10 = 480 ...
SLKOpusSampleSize [4]int = [4]int{480, 960, 1920, 2880}
HybridOpusSampleSize [4]int = [4]int{480, 960}
CELTOpusSampleSize [4]int = [4]int{120, 210, 480, 960}
)
func OpusPacketDuration(packet []byte) uint64 {
config := int(packet[0] >> 3)
code := packet[0] & 0x03
frameCount := 0
var duration uint64
if code == 0 {
frameCount = 1
} else if code == 1 || code == 2 {
frameCount = 2
} else if code == 3 {
frameCount = int(packet[1] & 0x1F)
} else {
panic("code must <= 3")
}
config := int(packet[0] >> 3)
code := packet[0] & 0x03
frameCount := 0
var duration uint64
if code == 0 {
frameCount = 1
} else if code == 1 || code == 2 {
frameCount = 2
} else if code == 3 {
frameCount = int(packet[1] & 0x1F)
} else {
panic("code must <= 3")
}
switch {
case config >= 0 && config < 12:
duration = uint64(frameCount * SLKOpusSampleSize[config%4])
case config >= 12 && config < 16:
duration = uint64(frameCount * HybridOpusSampleSize[config%2])
case config >= 16 && config < 32:
duration = uint64(frameCount * CELTOpusSampleSize[config%4])
default:
panic("unkown opus config")
}
switch {
case config >= 0 && config < 12:
duration = uint64(frameCount * SLKOpusSampleSize[config%4])
case config >= 12 && config < 16:
duration = uint64(frameCount * HybridOpusSampleSize[config%2])
case config >= 16 && config < 32:
duration = uint64(frameCount * CELTOpusSampleSize[config%4])
default:
panic("unkown opus config")
}
return duration
return duration
}
//ffmpeg opus.h OpusPacket
type OpusPacket struct {
Code int
Config int
Stereo int
Vbr int
FrameCount int
FrameLen []uint16
Frame []byte
Duration uint64
Code int
Config int
Stereo int
Vbr int
FrameCount int
FrameLen []uint16
Frame []byte
Duration uint64
}
func DecodeOpusPacket(packet []byte) *OpusPacket {
pkt := &OpusPacket{}
pkt.Code = int(packet[0] & 0x03)
pkt.Stereo = int((packet[0] >> 2) & 0x01)
pkt.Config = int(packet[0] >> 3)
pkt := &OpusPacket{}
pkt.Code = int(packet[0] & 0x03)
pkt.Stereo = int((packet[0] >> 2) & 0x01)
pkt.Config = int(packet[0] >> 3)
switch pkt.Code {
case 0:
pkt.FrameCount = 1
pkt.FrameLen = make([]uint16, 1)
pkt.FrameLen[0] = uint16(len(packet) - 1)
pkt.Frame = packet[1:]
case 1:
pkt.FrameCount = 2
pkt.FrameLen = make([]uint16, 1)
pkt.FrameLen[0] = uint16(len(packet)-1) / 2
pkt.Frame = packet[1:]
case 2:
pkt.FrameCount = 2
hdr := 1
N1 := int(packet[1])
if N1 >= 252 {
N1 = N1 + int(packet[2]*4)
hdr = 2
}
pkt.FrameLen = make([]uint16, 2)
pkt.FrameLen[0] = uint16(N1)
pkt.FrameLen[1] = uint16(len(packet)-hdr) - uint16(N1)
case 3:
hdr := 2
pkt.Vbr = int(packet[1] >> 7)
padding := packet[1] >> 6
pkt.FrameCount = int(packet[1] & 0x1F)
paddingLen := 0
if padding == 1 {
for packet[hdr] == 255 {
paddingLen += 254
hdr++
}
paddingLen += int(packet[hdr])
}
switch pkt.Code {
case 0:
pkt.FrameCount = 1
pkt.FrameLen = make([]uint16, 1)
pkt.FrameLen[0] = uint16(len(packet) - 1)
pkt.Frame = packet[1:]
case 1:
pkt.FrameCount = 2
pkt.FrameLen = make([]uint16, 1)
pkt.FrameLen[0] = uint16(len(packet)-1) / 2
pkt.Frame = packet[1:]
case 2:
pkt.FrameCount = 2
hdr := 1
N1 := int(packet[1])
if N1 >= 252 {
N1 = N1 + int(packet[2]*4)
hdr = 2
}
pkt.FrameLen = make([]uint16, 2)
pkt.FrameLen[0] = uint16(N1)
pkt.FrameLen[1] = uint16(len(packet)-hdr) - uint16(N1)
case 3:
hdr := 2
pkt.Vbr = int(packet[1] >> 7)
padding := packet[1] >> 6
pkt.FrameCount = int(packet[1] & 0x1F)
paddingLen := 0
if padding == 1 {
for packet[hdr] == 255 {
paddingLen += 254
hdr++
}
paddingLen += int(packet[hdr])
}
if pkt.Vbr == 0 {
pkt.FrameLen = make([]uint16, 1)
pkt.FrameLen[0] = uint16(len(packet)-hdr-paddingLen) / uint16(pkt.FrameCount)
pkt.Frame = packet[hdr : hdr+int(pkt.FrameLen[0]*uint16(pkt.FrameCount))]
} else {
n := 0
for i := 0; i < int(pkt.FrameCount)-1; i++ {
N1 := int(packet[hdr])
hdr += 1
if N1 >= 252 {
N1 = N1 + int(packet[hdr]*4)
hdr += 1
}
n += N1
pkt.FrameLen = append(pkt.FrameLen, uint16(N1))
}
lastFrameLen := len(packet) - hdr - paddingLen - n
pkt.FrameLen = append(pkt.FrameLen, uint16(lastFrameLen))
pkt.Frame = packet[hdr : hdr+n+lastFrameLen]
}
default:
panic("Error C must <= 3")
}
OpusPacketDuration(packet)
return pkt
if pkt.Vbr == 0 {
pkt.FrameLen = make([]uint16, 1)
pkt.FrameLen[0] = uint16(len(packet)-hdr-paddingLen) / uint16(pkt.FrameCount)
pkt.Frame = packet[hdr : hdr+int(pkt.FrameLen[0]*uint16(pkt.FrameCount))]
} else {
n := 0
for i := 0; i < int(pkt.FrameCount)-1; i++ {
N1 := int(packet[hdr])
hdr += 1
if N1 >= 252 {
N1 = N1 + int(packet[hdr]*4)
hdr += 1
}
n += N1
pkt.FrameLen = append(pkt.FrameLen, uint16(N1))
}
lastFrameLen := len(packet) - hdr - paddingLen - n
pkt.FrameLen = append(pkt.FrameLen, uint16(lastFrameLen))
pkt.Frame = packet[hdr : hdr+n+lastFrameLen]
}
default:
panic("Error C must <= 3")
}
OpusPacketDuration(packet)
return pkt
}
const (
LEFT_CHANNEL = 0
RIGHT_CHANNEL = 1
LEFT_CHANNEL = 0
RIGHT_CHANNEL = 1
)
var (
vorbisChanLayoutOffset [8][8]byte = [8][8]byte{
{0},
{0, 1},
{0, 2, 1},
{0, 1, 2, 3},
{0, 2, 1, 3, 4},
{0, 2, 1, 5, 3, 4},
{0, 2, 1, 6, 5, 3, 4},
{0, 2, 1, 7, 5, 6, 3, 4},
}
vorbisChanLayoutOffset [8][8]byte = [8][8]byte{
{0},
{0, 1},
{0, 2, 1},
{0, 1, 2, 3},
{0, 2, 1, 3, 4},
{0, 2, 1, 5, 3, 4},
{0, 2, 1, 6, 5, 3, 4},
{0, 2, 1, 7, 5, 6, 3, 4},
}
)
type ChannelOrder func(channels int, idx int) int
func defalutOrder(channels int, idx int) int {
return idx
return idx
}
func vorbisOrder(channels int, idx int) int {
return int(vorbisChanLayoutOffset[channels-1][idx])
return int(vorbisChanLayoutOffset[channels-1][idx])
}
type ChannelMap struct {
StreamIdx int
ChannelIdx int
Silence bool
Copy bool
CopyFrom int
StreamIdx int
ChannelIdx int
Silence bool
Copy bool
CopyFrom int
}
type OpusContext struct {
Preskip int
SampleRate int
ChannelCount int
StreamCount int
StereoStreamCount int
OutputGain uint16
MapType uint8
ChannelMaps []ChannelMap
Preskip int
SampleRate int
ChannelCount int
StreamCount int
StereoStreamCount int
OutputGain uint16
MapType uint8
ChannelMaps []ChannelMap
}
// opus ID Head
@ -348,83 +348,83 @@ type OpusContext struct {
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
func (ctx *OpusContext) ParseExtranData(extraData []byte) error {
if string(extraData[0:8]) != "OpusHead" {
return errors.New("magic signature must equal OpusHead")
}
if string(extraData[0:8]) != "OpusHead" {
return errors.New("magic signature must equal OpusHead")
}
_ = extraData[8] // version
ctx.ChannelCount = int(extraData[9])
ctx.Preskip = int(binary.LittleEndian.Uint16(extraData[10:]))
ctx.SampleRate = int(binary.LittleEndian.Uint32(extraData[12:]))
ctx.OutputGain = binary.LittleEndian.Uint16(extraData[16:])
ctx.MapType = extraData[18]
var channel []byte
var order ChannelOrder
if ctx.MapType == 0 {
ctx.StreamCount = 1
ctx.StereoStreamCount = ctx.ChannelCount - 1
channel = []byte{0, 1}
order = defalutOrder
} else if ctx.MapType == 1 || ctx.MapType == 2 || ctx.MapType == 255 {
ctx.StreamCount = int(extraData[19])
ctx.StereoStreamCount = int(extraData[20])
if ctx.MapType == 1 {
channel = extraData[21 : 21+ctx.ChannelCount]
order = vorbisOrder
}
} else {
return errors.New("unsupport map type 255")
}
_ = extraData[8] // version
ctx.ChannelCount = int(extraData[9])
ctx.Preskip = int(binary.LittleEndian.Uint16(extraData[10:]))
ctx.SampleRate = int(binary.LittleEndian.Uint32(extraData[12:]))
ctx.OutputGain = binary.LittleEndian.Uint16(extraData[16:])
ctx.MapType = extraData[18]
var channel []byte
var order ChannelOrder
if ctx.MapType == 0 {
ctx.StreamCount = 1
ctx.StereoStreamCount = ctx.ChannelCount - 1
channel = []byte{0, 1}
order = defalutOrder
} else if ctx.MapType == 1 || ctx.MapType == 2 || ctx.MapType == 255 {
ctx.StreamCount = int(extraData[19])
ctx.StereoStreamCount = int(extraData[20])
if ctx.MapType == 1 {
channel = extraData[21 : 21+ctx.ChannelCount]
order = vorbisOrder
}
} else {
return errors.New("unsupport map type 255")
}
for i := 0; i < ctx.ChannelCount; i++ {
cm := ChannelMap{}
index := channel[order(ctx.ChannelCount, i)]
if index == 255 {
cm.Silence = true
continue
} else if index > byte(ctx.StereoStreamCount)+byte(ctx.StreamCount) {
return errors.New("index must < (streamcount + stereo streamcount)")
}
for i := 0; i < ctx.ChannelCount; i++ {
cm := ChannelMap{}
index := channel[order(ctx.ChannelCount, i)]
if index == 255 {
cm.Silence = true
continue
} else if index > byte(ctx.StereoStreamCount)+byte(ctx.StreamCount) {
return errors.New("index must < (streamcount + stereo streamcount)")
}
for j := 0; j < i; j++ {
if channel[order(ctx.ChannelCount, i)] == index {
cm.Copy = true
cm.CopyFrom = j
break
}
}
for j := 0; j < i; j++ {
if channel[order(ctx.ChannelCount, i)] == index {
cm.Copy = true
cm.CopyFrom = j
break
}
}
if int(index) < 2*ctx.StereoStreamCount {
cm.StreamIdx = int(index) / 2
if index&1 == 0 {
cm.ChannelIdx = LEFT_CHANNEL
} else {
cm.ChannelIdx = RIGHT_CHANNEL
}
} else {
cm.StreamIdx = int(index) - ctx.StereoStreamCount
cm.ChannelIdx = 0
}
ctx.ChannelMaps = append(ctx.ChannelMaps, cm)
}
if int(index) < 2*ctx.StereoStreamCount {
cm.StreamIdx = int(index) / 2
if index&1 == 0 {
cm.ChannelIdx = LEFT_CHANNEL
} else {
cm.ChannelIdx = RIGHT_CHANNEL
}
} else {
cm.StreamIdx = int(index) - ctx.StereoStreamCount
cm.ChannelIdx = 0
}
ctx.ChannelMaps = append(ctx.ChannelMaps, cm)
}
return nil
return nil
}
func (ctx *OpusContext) WriteOpusExtraData() []byte {
extraData := make([]byte, 19)
copy(extraData, string("OpusHead"))
extraData[8] = 0x01
extraData[9] = byte(ctx.ChannelCount)
binary.LittleEndian.PutUint16(extraData[10:], uint16(ctx.Preskip))
binary.LittleEndian.PutUint32(extraData[12:], uint32(ctx.SampleRate))
return extraData
extraData := make([]byte, 19)
copy(extraData, string("OpusHead"))
extraData[8] = 0x01
extraData[9] = byte(ctx.ChannelCount)
binary.LittleEndian.PutUint16(extraData[10:], uint16(ctx.Preskip))
binary.LittleEndian.PutUint32(extraData[12:], uint32(ctx.SampleRate))
return extraData
}
func WriteDefaultOpusExtraData() []byte {
return []byte{
'O', 'p', 'u', 's', 'H', 'e', 'a', 'd',
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}
return []byte{
'O', 'p', 'u', 's', 'H', 'e', 'a', 'd',
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}
}

View file

@ -5,253 +5,253 @@ import "fmt"
type START_CODE_TYPE int
const (
START_CODE_3 START_CODE_TYPE = 3
START_CODE_4 = 4
START_CODE_3 START_CODE_TYPE = 3
START_CODE_4 = 4
)
func FindStartCode(nalu []byte, offset int) (int, START_CODE_TYPE) {
for i := offset; i < len(nalu)-4; i++ {
if nalu[i] == 0x00 && nalu[i+1] == 0x00 {
if nalu[i+2] == 0x01 {
return i, START_CODE_3
} else if nalu[i+2] == 0x00 && nalu[i+3] == 0x01 {
return i, START_CODE_4
}
}
}
return -1, START_CODE_3
for i := offset; i < len(nalu)-4; i++ {
if nalu[i] == 0x00 && nalu[i+1] == 0x00 {
if nalu[i+2] == 0x01 {
return i, START_CODE_3
} else if nalu[i+2] == 0x00 && nalu[i+3] == 0x01 {
return i, START_CODE_4
}
}
}
return -1, START_CODE_3
}
func FindSyncword(aac []byte, offset int) int {
for i := offset; i < len(aac); i++ {
if aac[i] == 0xFF && aac[i+1]&0xF0 == 0xF0 {
return i
}
}
return -1
for i := offset; i < len(aac); i++ {
if aac[i] == 0xFF && aac[i+1]&0xF0 == 0xF0 {
return i
}
}
return -1
}
func SplitFrame(frames []byte, onFrame func(nalu []byte) bool) {
beg, sc := FindStartCode(frames, 0)
for beg >= 0 {
end, sc2 := FindStartCode(frames, beg+int(sc))
if end == -1 {
if onFrame != nil {
onFrame(frames[beg+int(sc):])
}
break
}
if onFrame != nil && onFrame(frames[beg+int(sc):end]) == false {
break
}
beg = end
sc = sc2
}
beg, sc := FindStartCode(frames, 0)
for beg >= 0 {
end, sc2 := FindStartCode(frames, beg+int(sc))
if end == -1 {
if onFrame != nil {
onFrame(frames[beg+int(sc):])
}
break
}
if onFrame != nil && onFrame(frames[beg+int(sc):end]) == false {
break
}
beg = end
sc = sc2
}
}
func SplitFrameWithStartCode(frames []byte, onFrame func(nalu []byte) bool) {
beg, sc := FindStartCode(frames, 0)
for beg >= 0 {
end, sc2 := FindStartCode(frames, beg+int(sc))
if end == -1 {
if onFrame != nil {
onFrame(frames[beg:])
}
break
}
if onFrame != nil && onFrame(frames[beg:end]) == false {
break
}
beg = end
sc = sc2
}
beg, sc := FindStartCode(frames, 0)
for beg >= 0 {
end, sc2 := FindStartCode(frames, beg+int(sc))
if end == -1 {
if onFrame != nil {
onFrame(frames[beg:])
}
break
}
if onFrame != nil && onFrame(frames[beg:end]) == false {
break
}
beg = end
sc = sc2
}
}
func SplitAACFrame(frames []byte, onFrame func(aac []byte)) {
var adts ADTS_Frame_Header
start := FindSyncword(frames, 0)
for start >= 0 {
adts.Decode(frames[start:])
onFrame(frames[start : start+int(adts.Variable_Header.Frame_length)])
start = FindSyncword(frames, start+int(adts.Variable_Header.Frame_length))
}
var adts ADTS_Frame_Header
start := FindSyncword(frames, 0)
for start >= 0 {
adts.Decode(frames[start:])
onFrame(frames[start : start+int(adts.Variable_Header.Frame_length)])
start = FindSyncword(frames, start+int(adts.Variable_Header.Frame_length))
}
}
func H264NaluType(h264 []byte) H264_NAL_TYPE {
loc, sc := FindStartCode(h264, 0)
return H264_NAL_TYPE(h264[loc+int(sc)] & 0x1F)
loc, sc := FindStartCode(h264, 0)
return H264_NAL_TYPE(h264[loc+int(sc)] & 0x1F)
}
func H264NaluTypeWithoutStartCode(h264 []byte) H264_NAL_TYPE {
return H264_NAL_TYPE(h264[0] & 0x1F)
return H264_NAL_TYPE(h264[0] & 0x1F)
}
func H265NaluType(h265 []byte) H265_NAL_TYPE {
loc, sc := FindStartCode(h265, 0)
return H265_NAL_TYPE((h265[loc+int(sc)] >> 1) & 0x3F)
loc, sc := FindStartCode(h265, 0)
return H265_NAL_TYPE((h265[loc+int(sc)] >> 1) & 0x3F)
}
func H265NaluTypeWithoutStartCode(h265 []byte) H265_NAL_TYPE {
return H265_NAL_TYPE((h265[0] >> 1) & 0x3F)
return H265_NAL_TYPE((h265[0] >> 1) & 0x3F)
}
func GetH264FirstMbInSlice(nalu []byte) uint64 {
start, sc := FindStartCode(nalu, 0)
bs := NewBitStream(nalu[start+int(sc)+1:])
sliceHdr := &SliceHeader{}
sliceHdr.Decode(bs)
return sliceHdr.First_mb_in_slice
start, sc := FindStartCode(nalu, 0)
bs := NewBitStream(nalu[start+int(sc)+1:])
sliceHdr := &SliceHeader{}
sliceHdr.Decode(bs)
return sliceHdr.First_mb_in_slice
}
func GetH265FirstMbInSlice(nalu []byte) uint64 {
start, sc := FindStartCode(nalu, 0)
bs := NewBitStream(nalu[start+int(sc)+2:])
sliceHdr := &SliceHeader{}
sliceHdr.Decode(bs)
return sliceHdr.First_mb_in_slice
start, sc := FindStartCode(nalu, 0)
bs := NewBitStream(nalu[start+int(sc)+2:])
sliceHdr := &SliceHeader{}
sliceHdr.Decode(bs)
return sliceHdr.First_mb_in_slice
}
func IsH264IDRFrame(h264 []byte) bool {
ret := false
onnalu := func(nalu []byte) bool {
nal_type := H264NaluTypeWithoutStartCode(nalu)
if nal_type < 5 {
return false
} else if nal_type == 5 {
ret = true
return false
} else {
return true
}
}
SplitFrame(h264, onnalu)
return ret
ret := false
onnalu := func(nalu []byte) bool {
nal_type := H264NaluTypeWithoutStartCode(nalu)
if nal_type < 5 {
return false
} else if nal_type == 5 {
ret = true
return false
} else {
return true
}
}
SplitFrame(h264, onnalu)
return ret
}
func IsH264VCLNaluType(nal_type H264_NAL_TYPE) bool {
if nal_type <= H264_NAL_I_SLICE && nal_type > H264_NAL_RESERVED {
return true
}
return false
if nal_type <= H264_NAL_I_SLICE && nal_type > H264_NAL_RESERVED {
return true
}
return false
}
func IsH265VCLNaluType(nal_type H265_NAL_TYPE) bool {
if (nal_type <= H265_NAL_SLICE_CRA && nal_type >= H265_NAL_SLICE_BLA_W_LP) ||
(nal_type <= H265_NAL_SLICE_RASL_R && nal_type >= H265_NAL_Slice_TRAIL_N) {
return true
}
return false
if (nal_type <= H265_NAL_SLICE_CRA && nal_type >= H265_NAL_SLICE_BLA_W_LP) ||
(nal_type <= H265_NAL_SLICE_RASL_R && nal_type >= H265_NAL_Slice_TRAIL_N) {
return true
}
return false
}
func IsH265IDRFrame(h265 []byte) bool {
ret := false
onnalu := func(nalu []byte) bool {
nal_type := H264NaluTypeWithoutStartCode(nalu)
if nal_type <= 9 && nal_type >= 0 {
return false
} else if nal_type >= 16 && nal_type <= 21 {
ret = true
return false
} else {
return true
}
}
SplitFrame(h265, onnalu)
return ret
ret := false
onnalu := func(nalu []byte) bool {
nal_type := H264NaluTypeWithoutStartCode(nalu)
if nal_type <= 9 && nal_type >= 0 {
return false
} else if nal_type >= 16 && nal_type <= 21 {
ret = true
return false
} else {
return true
}
}
SplitFrame(h265, onnalu)
return ret
}
func Max(x, y int) int {
if x > y {
return x
} else {
return y
}
if x > y {
return x
} else {
return y
}
}
func Min(x, y int) int {
if x > y {
return y
} else {
return x
}
if x > y {
return y
} else {
return x
}
}
func ShowPacketHexdump(data []byte) {
for k := 0; k < len(data); k++ {
if k%8 == 0 && k != 0 {
fmt.Printf("\n")
}
fmt.Printf("%02x ", data[k])
}
fmt.Printf("\n")
for k := 0; k < len(data); k++ {
if k%8 == 0 && k != 0 {
fmt.Printf("\n")
}
fmt.Printf("%02x ", data[k])
}
fmt.Printf("\n")
}
var crc32table [256]uint32 = [256]uint32{
0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517,
0xB24D861A, 0x0550471E, 0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B,
0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38, 0x70DB114C, 0xC7C6D048,
0x1EE09345, 0xA9FD5241, 0xACAD155F, 0x1BB0D45B, 0xC2969756, 0x758B5652,
0xC836196A, 0x7F2BD86E, 0xA60D9B63, 0x11105A67, 0x14401D79, 0xA35DDC7D,
0x7A7B9F70, 0xCD665E74, 0xE0B62398, 0x57ABE29C, 0x8E8DA191, 0x39906095,
0x3CC0278B, 0x8BDDE68F, 0x52FBA582, 0xE5E66486, 0x585B2BBE, 0xEF46EABA,
0x3660A9B7, 0x817D68B3, 0x842D2FAD, 0x3330EEA9, 0xEA16ADA4, 0x5D0B6CA0,
0x906D32D4, 0x2770F3D0, 0xFE56B0DD, 0x494B71D9, 0x4C1B36C7, 0xFB06F7C3,
0x2220B4CE, 0x953D75CA, 0x28803AF2, 0x9F9DFBF6, 0x46BBB8FB, 0xF1A679FF,
0xF4F63EE1, 0x43EBFFE5, 0x9ACDBCE8, 0x2DD07DEC, 0x77708634, 0xC06D4730,
0x194B043D, 0xAE56C539, 0xAB068227, 0x1C1B4323, 0xC53D002E, 0x7220C12A,
0xCF9D8E12, 0x78804F16, 0xA1A60C1B, 0x16BBCD1F, 0x13EB8A01, 0xA4F64B05,
0x7DD00808, 0xCACDC90C, 0x07AB9778, 0xB0B6567C, 0x69901571, 0xDE8DD475,
0xDBDD936B, 0x6CC0526F, 0xB5E61162, 0x02FBD066, 0xBF469F5E, 0x085B5E5A,
0xD17D1D57, 0x6660DC53, 0x63309B4D, 0xD42D5A49, 0x0D0B1944, 0xBA16D840,
0x97C6A5AC, 0x20DB64A8, 0xF9FD27A5, 0x4EE0E6A1, 0x4BB0A1BF, 0xFCAD60BB,
0x258B23B6, 0x9296E2B2, 0x2F2BAD8A, 0x98366C8E, 0x41102F83, 0xF60DEE87,
0xF35DA999, 0x4440689D, 0x9D662B90, 0x2A7BEA94, 0xE71DB4E0, 0x500075E4,
0x892636E9, 0x3E3BF7ED, 0x3B6BB0F3, 0x8C7671F7, 0x555032FA, 0xE24DF3FE,
0x5FF0BCC6, 0xE8ED7DC2, 0x31CB3ECF, 0x86D6FFCB, 0x8386B8D5, 0x349B79D1,
0xEDBD3ADC, 0x5AA0FBD8, 0xEEE00C69, 0x59FDCD6D, 0x80DB8E60, 0x37C64F64,
0x3296087A, 0x858BC97E, 0x5CAD8A73, 0xEBB04B77, 0x560D044F, 0xE110C54B,
0x38368646, 0x8F2B4742, 0x8A7B005C, 0x3D66C158, 0xE4408255, 0x535D4351,
0x9E3B1D25, 0x2926DC21, 0xF0009F2C, 0x471D5E28, 0x424D1936, 0xF550D832,
0x2C769B3F, 0x9B6B5A3B, 0x26D61503, 0x91CBD407, 0x48ED970A, 0xFFF0560E,
0xFAA01110, 0x4DBDD014, 0x949B9319, 0x2386521D, 0x0E562FF1, 0xB94BEEF5,
0x606DADF8, 0xD7706CFC, 0xD2202BE2, 0x653DEAE6, 0xBC1BA9EB, 0x0B0668EF,
0xB6BB27D7, 0x01A6E6D3, 0xD880A5DE, 0x6F9D64DA, 0x6ACD23C4, 0xDDD0E2C0,
0x04F6A1CD, 0xB3EB60C9, 0x7E8D3EBD, 0xC990FFB9, 0x10B6BCB4, 0xA7AB7DB0,
0xA2FB3AAE, 0x15E6FBAA, 0xCCC0B8A7, 0x7BDD79A3, 0xC660369B, 0x717DF79F,
0xA85BB492, 0x1F467596, 0x1A163288, 0xAD0BF38C, 0x742DB081, 0xC3307185,
0x99908A5D, 0x2E8D4B59, 0xF7AB0854, 0x40B6C950, 0x45E68E4E, 0xF2FB4F4A,
0x2BDD0C47, 0x9CC0CD43, 0x217D827B, 0x9660437F, 0x4F460072, 0xF85BC176,
0xFD0B8668, 0x4A16476C, 0x93300461, 0x242DC565, 0xE94B9B11, 0x5E565A15,
0x87701918, 0x306DD81C, 0x353D9F02, 0x82205E06, 0x5B061D0B, 0xEC1BDC0F,
0x51A69337, 0xE6BB5233, 0x3F9D113E, 0x8880D03A, 0x8DD09724, 0x3ACD5620,
0xE3EB152D, 0x54F6D429, 0x7926A9C5, 0xCE3B68C1, 0x171D2BCC, 0xA000EAC8,
0xA550ADD6, 0x124D6CD2, 0xCB6B2FDF, 0x7C76EEDB, 0xC1CBA1E3, 0x76D660E7,
0xAFF023EA, 0x18EDE2EE, 0x1DBDA5F0, 0xAAA064F4, 0x738627F9, 0xC49BE6FD,
0x09FDB889, 0xBEE0798D, 0x67C63A80, 0xD0DBFB84, 0xD58BBC9A, 0x62967D9E,
0xBBB03E93, 0x0CADFF97, 0xB110B0AF, 0x060D71AB, 0xDF2B32A6, 0x6836F3A2,
0x6D66B4BC, 0xDA7B75B8, 0x035D36B5, 0xB440F7B1,
0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517,
0xB24D861A, 0x0550471E, 0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B,
0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38, 0x70DB114C, 0xC7C6D048,
0x1EE09345, 0xA9FD5241, 0xACAD155F, 0x1BB0D45B, 0xC2969756, 0x758B5652,
0xC836196A, 0x7F2BD86E, 0xA60D9B63, 0x11105A67, 0x14401D79, 0xA35DDC7D,
0x7A7B9F70, 0xCD665E74, 0xE0B62398, 0x57ABE29C, 0x8E8DA191, 0x39906095,
0x3CC0278B, 0x8BDDE68F, 0x52FBA582, 0xE5E66486, 0x585B2BBE, 0xEF46EABA,
0x3660A9B7, 0x817D68B3, 0x842D2FAD, 0x3330EEA9, 0xEA16ADA4, 0x5D0B6CA0,
0x906D32D4, 0x2770F3D0, 0xFE56B0DD, 0x494B71D9, 0x4C1B36C7, 0xFB06F7C3,
0x2220B4CE, 0x953D75CA, 0x28803AF2, 0x9F9DFBF6, 0x46BBB8FB, 0xF1A679FF,
0xF4F63EE1, 0x43EBFFE5, 0x9ACDBCE8, 0x2DD07DEC, 0x77708634, 0xC06D4730,
0x194B043D, 0xAE56C539, 0xAB068227, 0x1C1B4323, 0xC53D002E, 0x7220C12A,
0xCF9D8E12, 0x78804F16, 0xA1A60C1B, 0x16BBCD1F, 0x13EB8A01, 0xA4F64B05,
0x7DD00808, 0xCACDC90C, 0x07AB9778, 0xB0B6567C, 0x69901571, 0xDE8DD475,
0xDBDD936B, 0x6CC0526F, 0xB5E61162, 0x02FBD066, 0xBF469F5E, 0x085B5E5A,
0xD17D1D57, 0x6660DC53, 0x63309B4D, 0xD42D5A49, 0x0D0B1944, 0xBA16D840,
0x97C6A5AC, 0x20DB64A8, 0xF9FD27A5, 0x4EE0E6A1, 0x4BB0A1BF, 0xFCAD60BB,
0x258B23B6, 0x9296E2B2, 0x2F2BAD8A, 0x98366C8E, 0x41102F83, 0xF60DEE87,
0xF35DA999, 0x4440689D, 0x9D662B90, 0x2A7BEA94, 0xE71DB4E0, 0x500075E4,
0x892636E9, 0x3E3BF7ED, 0x3B6BB0F3, 0x8C7671F7, 0x555032FA, 0xE24DF3FE,
0x5FF0BCC6, 0xE8ED7DC2, 0x31CB3ECF, 0x86D6FFCB, 0x8386B8D5, 0x349B79D1,
0xEDBD3ADC, 0x5AA0FBD8, 0xEEE00C69, 0x59FDCD6D, 0x80DB8E60, 0x37C64F64,
0x3296087A, 0x858BC97E, 0x5CAD8A73, 0xEBB04B77, 0x560D044F, 0xE110C54B,
0x38368646, 0x8F2B4742, 0x8A7B005C, 0x3D66C158, 0xE4408255, 0x535D4351,
0x9E3B1D25, 0x2926DC21, 0xF0009F2C, 0x471D5E28, 0x424D1936, 0xF550D832,
0x2C769B3F, 0x9B6B5A3B, 0x26D61503, 0x91CBD407, 0x48ED970A, 0xFFF0560E,
0xFAA01110, 0x4DBDD014, 0x949B9319, 0x2386521D, 0x0E562FF1, 0xB94BEEF5,
0x606DADF8, 0xD7706CFC, 0xD2202BE2, 0x653DEAE6, 0xBC1BA9EB, 0x0B0668EF,
0xB6BB27D7, 0x01A6E6D3, 0xD880A5DE, 0x6F9D64DA, 0x6ACD23C4, 0xDDD0E2C0,
0x04F6A1CD, 0xB3EB60C9, 0x7E8D3EBD, 0xC990FFB9, 0x10B6BCB4, 0xA7AB7DB0,
0xA2FB3AAE, 0x15E6FBAA, 0xCCC0B8A7, 0x7BDD79A3, 0xC660369B, 0x717DF79F,
0xA85BB492, 0x1F467596, 0x1A163288, 0xAD0BF38C, 0x742DB081, 0xC3307185,
0x99908A5D, 0x2E8D4B59, 0xF7AB0854, 0x40B6C950, 0x45E68E4E, 0xF2FB4F4A,
0x2BDD0C47, 0x9CC0CD43, 0x217D827B, 0x9660437F, 0x4F460072, 0xF85BC176,
0xFD0B8668, 0x4A16476C, 0x93300461, 0x242DC565, 0xE94B9B11, 0x5E565A15,
0x87701918, 0x306DD81C, 0x353D9F02, 0x82205E06, 0x5B061D0B, 0xEC1BDC0F,
0x51A69337, 0xE6BB5233, 0x3F9D113E, 0x8880D03A, 0x8DD09724, 0x3ACD5620,
0xE3EB152D, 0x54F6D429, 0x7926A9C5, 0xCE3B68C1, 0x171D2BCC, 0xA000EAC8,
0xA550ADD6, 0x124D6CD2, 0xCB6B2FDF, 0x7C76EEDB, 0xC1CBA1E3, 0x76D660E7,
0xAFF023EA, 0x18EDE2EE, 0x1DBDA5F0, 0xAAA064F4, 0x738627F9, 0xC49BE6FD,
0x09FDB889, 0xBEE0798D, 0x67C63A80, 0xD0DBFB84, 0xD58BBC9A, 0x62967D9E,
0xBBB03E93, 0x0CADFF97, 0xB110B0AF, 0x060D71AB, 0xDF2B32A6, 0x6836F3A2,
0x6D66B4BC, 0xDA7B75B8, 0x035D36B5, 0xB440F7B1,
}
func CalcCrc32(crc uint32, buffer []byte) uint32 {
var i int = 0
for i = 0; i < len(buffer); i++ {
crc = crc32table[(crc^uint32(buffer[i]))&0xff] ^ (crc >> 8)
}
return crc
var i int = 0
for i = 0; i < len(buffer); i++ {
crc = crc32table[(crc^uint32(buffer[i]))&0xff] ^ (crc >> 8)
}
return crc
}
func CovertRbspToSodb(rbsp []byte) []byte {
bs := NewBitStream(rbsp)
bsw := NewBitStreamWriter(len(rbsp))
for !bs.EOS() {
if bs.RemainBytes() > 3 && bs.NextBits(24) == 0x000003 {
bsw.PutByte(bs.Uint8(8))
bsw.PutByte(bs.Uint8(8))
bs.SkipBits(8)
} else {
bsw.PutByte(bs.Uint8(8))
}
}
return bsw.Bits()
bs := NewBitStream(rbsp)
bsw := NewBitStreamWriter(len(rbsp))
for !bs.EOS() {
if bs.RemainBytes() > 3 && bs.NextBits(24) == 0x000003 {
bsw.PutByte(bs.Uint8(8))
bsw.PutByte(bs.Uint8(8))
bs.SkipBits(8)
} else {
bsw.PutByte(bs.Uint8(8))
}
}
return bsw.Bits()
}

View file

@ -3,70 +3,70 @@ package codec
import "errors"
type VP8FrameTag struct {
FrameType uint32 //0: I frame , 1: P frame
Version uint32
Display uint32
FirstPartSize uint32
FrameType uint32 //0: I frame , 1: P frame
Version uint32
Display uint32
FirstPartSize uint32
}
type VP8KeyFrameHead struct {
Width int
Height int
HorizScale int
VertScale int
Width int
Height int
HorizScale int
VertScale int
}
func DecodeFrameTag(frame []byte) (*VP8FrameTag, error) {
if len(frame) < 3 {
return nil, errors.New("frame bytes < 3")
}
var tmp uint32 = (uint32(frame[2]) << 16) | (uint32(frame[1]) << 8) | uint32(frame[0])
tag := &VP8FrameTag{}
tag.FrameType = tmp & 0x01
tag.Version = (tmp >> 1) & 0x07
tag.Display = (tmp >> 4) & 0x01
tag.FirstPartSize = (tmp >> 5) & 0x7FFFF
return tag, nil
if len(frame) < 3 {
return nil, errors.New("frame bytes < 3")
}
var tmp uint32 = (uint32(frame[2]) << 16) | (uint32(frame[1]) << 8) | uint32(frame[0])
tag := &VP8FrameTag{}
tag.FrameType = tmp & 0x01
tag.Version = (tmp >> 1) & 0x07
tag.Display = (tmp >> 4) & 0x01
tag.FirstPartSize = (tmp >> 5) & 0x7FFFF
return tag, nil
}
func DecodeKeyFrameHead(frame []byte) (*VP8KeyFrameHead, error) {
if len(frame) < 7 {
return nil, errors.New("frame bytes < 3")
}
if len(frame) < 7 {
return nil, errors.New("frame bytes < 3")
}
if frame[0] != 0x9d || frame[1] != 0x01 || frame[2] != 0x2a {
return nil, errors.New("not find Start code")
}
if frame[0] != 0x9d || frame[1] != 0x01 || frame[2] != 0x2a {
return nil, errors.New("not find Start code")
}
head := &VP8KeyFrameHead{}
head.Width = int(uint16(frame[4]&0x3f)<<8 | uint16(frame[3]))
head.HorizScale = int(frame[4] >> 6)
head.Height = int(uint16(frame[6]&0x3f)<<8 | uint16(frame[5]))
head.VertScale = int(frame[6] >> 6)
return head, nil
head := &VP8KeyFrameHead{}
head.Width = int(uint16(frame[4]&0x3f)<<8 | uint16(frame[3]))
head.HorizScale = int(frame[4] >> 6)
head.Height = int(uint16(frame[6]&0x3f)<<8 | uint16(frame[5]))
head.VertScale = int(frame[6] >> 6)
return head, nil
}
func IsKeyFrame(frame []byte) bool {
tag, err := DecodeFrameTag(frame)
if err != nil {
return false
}
tag, err := DecodeFrameTag(frame)
if err != nil {
return false
}
if tag.FrameType == 0 {
return true
} else {
return false
}
if tag.FrameType == 0 {
return true
} else {
return false
}
}
func GetResloution(frame []byte) (width int, height int, err error) {
if !IsKeyFrame(frame) {
return 0, 0, errors.New("the frame is not Key frame")
}
if !IsKeyFrame(frame) {
return 0, 0, errors.New("the frame is not Key frame")
}
head, err := DecodeKeyFrameHead(frame[3:])
if err != nil {
return 0, 0, err
}
return head.Width, head.Height, nil
head, err := DecodeKeyFrameHead(frame[3:])
if err != nil {
return 0, 0, err
}
return head.Width, head.Height, nil
}