123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- package codec
- import "encoding/binary"
- // nal_unit( NumBytesInNALunit ) {
- // forbidden_zero_bit All f(1)
- // nal_ref_idc All u(2)
- // nal_unit_type u(5)
- // }
- type H264NaluHdr struct {
- 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)
- }
- type SliceHeader struct {
- 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()
- }
- 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
- }
- 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()
- }
- 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
- }
- 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()
- }
- type SEIReaderWriter interface {
- Read(size uint16, bs *BitStream)
- Write(bsw *BitStreamWriter)
- }
- type UserDataUnregistered struct {
- UUID []byte
- UserData []byte
- }
- func (udu *UserDataUnregistered) Read(size uint16, bs *BitStream) {
- 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)
- }
- type SEI struct {
- 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)
- }
- }
- 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()
- }
- func GetSPSIdWithStartCode(sps []byte) uint64 {
- 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()
- }
- func GetPPSIdWithStartCode(pps []byte) uint64 {
- 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()
- }
- //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)
- 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
- return
- }
- // aligned(8) class AVCDecoderConfigurationRecord {
- // unsigned int(8) configurationVersion = 1;
- // unsigned int(8) AVCProfileIndication;
- // unsigned int(8) profile_compatibility;
- // unsigned int(8) AVCLevelIndication;
- // bit(6) reserved = ‘111111’b;
- // unsigned int(2) lengthSizeMinusOne;
- // bit(3) reserved = ‘111’b;
- // unsigned int(5) numOfSequenceParameterSets;
- // for (i=0; i< numOfSequenceParameterSets; i++) {
- // unsigned int(16) sequenceParameterSetLength ;
- // bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;
- // }
- // unsigned int(8) numOfPictureParameterSets;
- // for (i=0; i< numOfPictureParameterSets; i++) {
- // unsigned int(16) pictureParameterSetLength;
- // bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
- // }
- // if( profile_idc == 100 || profile_idc == 110 ||
- // profile_idc == 122 || profile_idc == 144 )
- // {
- // bit(6) reserved = ‘111111’b;
- // unsigned int(2) chroma_format;
- // bit(5) reserved = ‘11111’b;
- // unsigned int(3) bit_depth_luma_minus8;
- // bit(5) reserved = ‘11111’b;
- // unsigned int(3) bit_depth_chroma_minus8;
- // unsigned int(8) numOfSequenceParameterSetExt;
- // for (i=0; i< numOfSequenceParameterSetExt; i++) {
- // unsigned int(16) sequenceParameterSetExtLength;
- // bit(8*sequenceParameterSetExtLength) sequenceParameterSetExtNALUnit;
- // }
- // }
- // }
- // }
- // bits
- // 8 version ( always 0x01 )
- // 8 avc profile ( sps[0][1] )
- // 8 avc compatibility ( sps[0][2] )
- // 8 avc level ( sps[0][3] )
- // 6 reserved ( all bits on )
- // 2 NALULengthSizeMinusOne
- // 3 reserved ( all bits on )
- // 5 number of SPS NALUs (usually 1)
- // repeated once per SPS:
- // 16 SPS size
- // variable SPS NALU data
- // 8 number of PPS NALUs (usually 1)
- // repeated once per PPS:
- // 16 PPS size
- // 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):]
- }
- 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...)
- }
- 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
- }
- 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
- }
- }
- func CovertAVCCToAnnexB(avcc []byte) {
- avcc[0] = 0x00
- avcc[1] = 0x00
- avcc[2] = 0x00
- avcc[3] = 0x01
- }
|