diff --git a/codec/h265parser/parser.go b/codec/h265parser/parser.go index b33f28b..79dbc6f 100644 --- a/codec/h265parser/parser.go +++ b/codec/h265parser/parser.go @@ -2,6 +2,7 @@ package h265parser import ( "bytes" + "errors" "fmt" "github.com/deepch/vdk/av" @@ -9,6 +10,32 @@ import ( "github.com/deepch/vdk/utils/bits/pio" ) +type SPSInfo struct { + ProfileIdc uint + LevelIdc uint + MbWidth uint + MbHeight uint + CropLeft uint + CropRight uint + CropTop uint + CropBottom uint + Width uint + Height uint + numTemporalLayers uint + temporalIdNested uint + chromaFormat uint + PicWidthInLumaSamples uint + PicHeightInLumaSamples uint + bitDepthLumaMinus8 uint + bitDepthChromaMinus8 uint + generalProfileSpace uint + generalTierFlag uint + generalProfileIDC uint + generalProfileCompatibilityFlags uint32 + generalConstraintIndicatorFlags uint64 + generalLevelIDC uint +} + const ( NAL_UNIT_CODED_SLICE_TRAIL_N = 0 NAL_UNIT_CODED_SLICE_TRAIL_R = 1 @@ -83,6 +110,11 @@ const ( MAX_SPS_COUNT = 32 ) +var ( + ErrorH265IncorectUnitSize = errors.New("Invorect Unit Size") + ErrorH265IncorectUnitType = errors.New("Incorect Unit Type") +) + func IsDataNALU(b []byte) bool { typ := b[0] & 0x1f return typ >= 1 && typ <= 5 @@ -128,7 +160,6 @@ func SplitNALUs(b []byte) (nalus [][]byte, typ int) { return nalus, NALU_AVCC } } - // is Annex B if val3 == 1 || val4 == 1 { _val3 := val3 _val4 := val4 @@ -175,212 +206,216 @@ func SplitNALUs(b []byte) (nalus [][]byte, typ int) { return [][]byte{b}, NALU_RAW } -type SPSInfo struct { - ProfileIdc uint - LevelIdc uint - - MbWidth uint - MbHeight uint - - CropLeft uint - CropRight uint - CropTop uint - CropBottom uint - - Width uint - Height uint -} - -func ParseSPS(data []byte) (self SPSInfo, err error) { - r := &bits.GolombBitReader{R: bytes.NewReader(data)} - - if _, err = r.ReadBits(8); err != nil { +func ParseSPS(sps []byte) (ctx SPSInfo, err error) { + if len(sps) < 2 { + err = ErrorH265IncorectUnitSize return } - - if self.ProfileIdc, err = r.ReadBits(8); err != nil { + rbsp := nal2rbsp(sps[2:]) + br := &bits.GolombBitReader{R: bytes.NewReader(rbsp)} + if _, err = br.ReadBits(4); err != nil { return } - - // constraint_set0_flag-constraint_set6_flag,reserved_zero_2bits - if _, err = r.ReadBits(8); err != nil { + spsMaxSubLayersMinus1, err := br.ReadBits(3) + if err != nil { return } - // level_idc - if self.LevelIdc, err = r.ReadBits(8); err != nil { + if spsMaxSubLayersMinus1+1 > ctx.numTemporalLayers { + ctx.numTemporalLayers = spsMaxSubLayersMinus1 + 1 + } + if ctx.temporalIdNested, err = br.ReadBit(); err != nil { return } - - // seq_parameter_set_id - if _, err = r.ReadExponentialGolombCode(); err != nil { + if err = parsePTL(br, &ctx, spsMaxSubLayersMinus1); err != nil { return } - - if self.ProfileIdc == 100 || self.ProfileIdc == 110 || - self.ProfileIdc == 122 || self.ProfileIdc == 244 || - self.ProfileIdc == 44 || self.ProfileIdc == 83 || - self.ProfileIdc == 86 || self.ProfileIdc == 118 { - - var chroma_format_idc uint - if chroma_format_idc, err = r.ReadExponentialGolombCode(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { + return + } + var cf uint + if cf, err = br.ReadExponentialGolombCode(); err != nil { + return + } + ctx.chromaFormat = uint(cf) + if ctx.chromaFormat == 3 { + if _, err = br.ReadBit(); err != nil { return } - - if chroma_format_idc == 3 { - // residual_colour_transform_flag - if _, err = r.ReadBit(); err != nil { - return - } - } - - // bit_depth_luma_minus8 - if _, err = r.ReadExponentialGolombCode(); err != nil { + } + if ctx.PicWidthInLumaSamples, err = br.ReadExponentialGolombCode(); err != nil { + return + } + ctx.Width = uint(ctx.PicWidthInLumaSamples) + if ctx.PicHeightInLumaSamples, err = br.ReadExponentialGolombCode(); err != nil { + return + } + ctx.Height = uint(ctx.PicHeightInLumaSamples) + conformanceWindowFlag, err := br.ReadBit() + if err != nil { + return + } + if conformanceWindowFlag != 0 { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - // bit_depth_chroma_minus8 - if _, err = r.ReadExponentialGolombCode(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - // qpprime_y_zero_transform_bypass_flag - if _, err = r.ReadBit(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - - var seq_scaling_matrix_present_flag uint - if seq_scaling_matrix_present_flag, err = r.ReadBit(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - - if seq_scaling_matrix_present_flag != 0 { - for i := 0; i < 8; i++ { - var seq_scaling_list_present_flag uint - if seq_scaling_list_present_flag, err = r.ReadBit(); err != nil { - return - } - if seq_scaling_list_present_flag != 0 { - var sizeOfScalingList uint - if i < 6 { - sizeOfScalingList = 16 - } else { - sizeOfScalingList = 64 - } - lastScale := uint(8) - nextScale := uint(8) - for j := uint(0); j < sizeOfScalingList; j++ { - if nextScale != 0 { - var delta_scale uint - if delta_scale, err = r.ReadSE(); err != nil { - return - } - nextScale = (lastScale + delta_scale + 256) % 256 - } - if nextScale != 0 { - lastScale = nextScale - } - } - } - } - } } - // log2_max_frame_num_minus4 - if _, err = r.ReadExponentialGolombCode(); err != nil { + var bdlm8 uint + if bdlm8, err = br.ReadExponentialGolombCode(); err != nil { + return + } + ctx.bitDepthChromaMinus8 = uint(bdlm8) + var bdcm8 uint + if bdcm8, err = br.ReadExponentialGolombCode(); err != nil { return } + ctx.bitDepthChromaMinus8 = uint(bdcm8) - var pic_order_cnt_type uint - if pic_order_cnt_type, err = r.ReadExponentialGolombCode(); err != nil { + _, err = br.ReadExponentialGolombCode() + if err != nil { return } - if pic_order_cnt_type == 0 { - // log2_max_pic_order_cnt_lsb_minus4 - if _, err = r.ReadExponentialGolombCode(); err != nil { - return - } - } else if pic_order_cnt_type == 1 { - // delta_pic_order_always_zero_flag - if _, err = r.ReadBit(); err != nil { - return - } - // offset_for_non_ref_pic - if _, err = r.ReadSE(); err != nil { + spsSubLayerOrderingInfoPresentFlag, err := br.ReadBit() + if err != nil { + return + } + var i uint + if spsSubLayerOrderingInfoPresentFlag != 0 { + i = 0 + } else { + i = spsMaxSubLayersMinus1 + } + for ; i <= spsMaxSubLayersMinus1; i++ { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - // offset_for_top_to_bottom_field - if _, err = r.ReadSE(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - var num_ref_frames_in_pic_order_cnt_cycle uint - if num_ref_frames_in_pic_order_cnt_cycle, err = r.ReadExponentialGolombCode(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - for i := uint(0); i < num_ref_frames_in_pic_order_cnt_cycle; i++ { - if _, err = r.ReadSE(); err != nil { - return - } - } } - // max_num_ref_frames - if _, err = r.ReadExponentialGolombCode(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - - // gaps_in_frame_num_value_allowed_flag - if _, err = r.ReadBit(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - - if self.MbWidth, err = r.ReadExponentialGolombCode(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - self.MbWidth++ - - if self.MbHeight, err = r.ReadExponentialGolombCode(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - self.MbHeight++ - - var frame_mbs_only_flag uint - if frame_mbs_only_flag, err = r.ReadBit(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } - if frame_mbs_only_flag == 0 { - // mb_adaptive_frame_field_flag - if _, err = r.ReadBit(); err != nil { - return - } - } - - // direct_8x8_inference_flag - if _, err = r.ReadBit(); err != nil { + if _, err = br.ReadExponentialGolombCode(); err != nil { return } + return +} - var frame_cropping_flag uint - if frame_cropping_flag, err = r.ReadBit(); err != nil { - return +func parsePTL(br *bits.GolombBitReader, ctx *SPSInfo, maxSubLayersMinus1 uint) error { + var err error + var ptl SPSInfo + if ptl.generalProfileSpace, err = br.ReadBits(2); err != nil { + return err } - if frame_cropping_flag != 0 { - if self.CropLeft, err = r.ReadExponentialGolombCode(); err != nil { - return + if ptl.generalTierFlag, err = br.ReadBit(); err != nil { + return err + } + if ptl.generalProfileIDC, err = br.ReadBits(5); err != nil { + return err + } + if ptl.generalProfileCompatibilityFlags, err = br.ReadBits32(32); err != nil { + return err + } + if ptl.generalConstraintIndicatorFlags, err = br.ReadBits64(48); err != nil { + return err + } + if ptl.generalLevelIDC, err = br.ReadBits(8); err != nil { + return err + } + updatePTL(ctx, &ptl) + if maxSubLayersMinus1 == 0 { + return nil + } + subLayerProfilePresentFlag := make([]uint, maxSubLayersMinus1) + subLayerLevelPresentFlag := make([]uint, maxSubLayersMinus1) + for i := uint(0); i < maxSubLayersMinus1; i++ { + if subLayerProfilePresentFlag[i], err = br.ReadBit(); err != nil { + return err } - if self.CropRight, err = r.ReadExponentialGolombCode(); err != nil { - return + if subLayerLevelPresentFlag[i], err = br.ReadBit(); err != nil { + return err } - if self.CropTop, err = r.ReadExponentialGolombCode(); err != nil { - return + } + if maxSubLayersMinus1 > 0 { + for i := maxSubLayersMinus1; i < 8; i++ { + if _, err = br.ReadBits(2); err != nil { + return err + } } - if self.CropBottom, err = r.ReadExponentialGolombCode(); err != nil { - return + } + for i := uint(0); i < maxSubLayersMinus1; i++ { + if subLayerProfilePresentFlag[i] != 0 { + if _, err = br.ReadBits32(32); err != nil { + return err + } + if _, err = br.ReadBits32(32); err != nil { + return err + } + if _, err = br.ReadBits32(24); err != nil { + return err + } + } + + if subLayerLevelPresentFlag[i] != 0 { + if _, err = br.ReadBits(8); err != nil { + return err + } } } + return nil +} - self.Width = (self.MbWidth * 16) - self.CropLeft*2 - self.CropRight*2 - self.Height = ((2 - frame_mbs_only_flag) * self.MbHeight * 16) - self.CropTop*2 - self.CropBottom*2 +func updatePTL(ctx, ptl *SPSInfo) { + ctx.generalProfileSpace = ptl.generalProfileSpace - return + if ptl.generalTierFlag > ctx.generalTierFlag { + ctx.generalLevelIDC = ptl.generalLevelIDC + + ctx.generalTierFlag = ptl.generalTierFlag + } else { + if ptl.generalLevelIDC > ctx.generalLevelIDC { + ctx.generalLevelIDC = ptl.generalLevelIDC + } + } + + if ptl.generalProfileIDC > ctx.generalProfileIDC { + ctx.generalProfileIDC = ptl.generalProfileIDC + } + + ctx.generalProfileCompatibilityFlags &= ptl.generalProfileCompatibilityFlags + + ctx.generalConstraintIndicatorFlags &= ptl.generalConstraintIndicatorFlags +} + +func nal2rbsp(nal []byte) []byte { + return bytes.Replace(nal, []byte{0x0, 0x0, 0x3}, []byte{0x0, 0x0}, -1) } type CodecData struct { @@ -443,23 +478,20 @@ func NewCodecDataFromAVCDecoderConfRecord(record []byte) (self CodecData, err er func NewCodecDataFromVPSAndSPSAndPPS(vps, sps, pps []byte) (self CodecData, err error) { recordinfo := AVCDecoderConfRecord{} - recordinfo.AVCProfileIndication = sps[1] - recordinfo.ProfileCompatibility = sps[2] - recordinfo.AVCLevelIndication = sps[3] + recordinfo.AVCProfileIndication = sps[3] + recordinfo.ProfileCompatibility = sps[4] + recordinfo.AVCLevelIndication = sps[5] recordinfo.SPS = [][]byte{sps} recordinfo.PPS = [][]byte{pps} recordinfo.VPS = [][]byte{vps} recordinfo.LengthSizeMinusOne = 3 - - buf := make([]byte, recordinfo.Len()) - recordinfo.Marshal(buf) - - self.RecordInfo = recordinfo - self.Record = buf - if self.SPSInfo, err = ParseSPS(sps); err != nil { return } + buf := make([]byte, recordinfo.Len()) + recordinfo.Marshal(buf, self.SPSInfo) + self.RecordInfo = recordinfo + self.Record = buf return } @@ -480,14 +512,12 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) { err = ErrDecconfInvalid return } - self.AVCProfileIndication = b[1] self.ProfileCompatibility = b[2] self.AVCLevelIndication = b[3] self.LengthSizeMinusOne = b[4] & 0x03 spscount := int(b[5] & 0x1f) n += 6 - for i := 0; i < spscount; i++ { if len(b) < n+2 { err = ErrDecconfInvalid @@ -550,55 +580,63 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) { } func (self AVCDecoderConfRecord) Len() (n int) { - n = 7 + n = 23 for _, sps := range self.SPS { - n += 2 + len(sps) + n += 5 + len(sps) } for _, pps := range self.PPS { - n += 2 + len(pps) + n += 5 + len(pps) } for _, vps := range self.VPS { - n += 2 + len(vps) + n += 5 + len(vps) } return } -func (self AVCDecoderConfRecord) Marshal(b []byte) (n int) { +func (self AVCDecoderConfRecord) Marshal(b []byte, si SPSInfo) (n int) { b[0] = 1 b[1] = self.AVCProfileIndication b[2] = self.ProfileCompatibility b[3] = self.AVCLevelIndication - b[4] = self.LengthSizeMinusOne | 0xfc - b[5] = uint8(len(self.SPS)) | 0xe0 - n += 6 - + b[21] = 3 + b[22] = 3 + n += 23 + b[n] = (self.VPS[0][0] >> 1) & 0x3f + n++ + b[n] = byte(len(self.VPS) >> 8) + n++ + b[n] = byte(len(self.VPS)) + n++ + for _, vps := range self.VPS { + pio.PutU16BE(b[n:], uint16(len(vps))) + n += 2 + copy(b[n:], vps) + n += len(vps) + } + b[n] = (self.SPS[0][0] >> 1) & 0x3f + n++ + b[n] = byte(len(self.SPS) >> 8) + n++ + b[n] = byte(len(self.SPS)) + n++ for _, sps := range self.SPS { pio.PutU16BE(b[n:], uint16(len(sps))) n += 2 copy(b[n:], sps) n += len(sps) } - - b[n] = uint8(len(self.PPS)) + b[n] = (self.PPS[0][0] >> 1) & 0x3f + n++ + b[n] = byte(len(self.PPS) >> 8) + n++ + b[n] = byte(len(self.PPS)) n++ - for _, pps := range self.PPS { pio.PutU16BE(b[n:], uint16(len(pps))) n += 2 copy(b[n:], pps) n += len(pps) } - - b[n] = uint8(len(self.VPS)) - n++ - - for _, vps := range self.VPS { - pio.PutU16BE(b[n:], uint16(len(vps))) - n += 2 - copy(b[n:], vps) - n += len(vps) - } - return } @@ -623,17 +661,13 @@ const ( ) func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) { - if len(packet) <= 1 { err = fmt.Errorf("h265parser: packet too short to parse slice header") return } - nal_unit_type := packet[0] & 0x1f switch nal_unit_type { case 1, 2, 5, 19: - // slice_layer_without_partitioning_rbsp - // slice_data_partition_a_layer_rbsp default: err = fmt.Errorf("h265parser: nal_unit_type=%d has no slice header", nal_unit_type) @@ -641,13 +675,9 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) { } r := &bits.GolombBitReader{R: bytes.NewReader(packet[1:])} - - // first_mb_in_slice if _, err = r.ReadExponentialGolombCode(); err != nil { return } - - // slice_type var u uint if u, err = r.ReadExponentialGolombCode(); err != nil { return @@ -664,6 +694,5 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) { err = fmt.Errorf("h265parser: slice_type=%d invalid", u) return } - return } diff --git a/format/mp4f/muxer.go b/format/mp4f/muxer.go index 2cd1d1c..bb1c04d 100644 --- a/format/mp4f/muxer.go +++ b/format/mp4f/muxer.go @@ -181,6 +181,7 @@ func (self *Stream) fillTrackAtom() (err error) { } else if self.Type() == av.H265 { codec := self.CodecData.(h265parser.CodecData) width, height := codec.Width(), codec.Height() + self.sample.SampleDesc.HV1Desc = &mp4io.HV1Desc{ DataRefIdx: 1, HorizontalResolution: 72, @@ -192,6 +193,7 @@ func (self *Stream) fillTrackAtom() (err error) { ColorTableId: -1, Conf: &mp4io.HV1Conf{Data: codec.AVCDecoderConfRecordBytes()}, } + self.trackAtom.Media.Handler = &mp4io.HandlerRefer{ SubType: [4]byte{'v', 'i', 'd', 'e'}, Name: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'G', 'G', 0, 0, 0}, @@ -200,6 +202,7 @@ func (self *Stream) fillTrackAtom() (err error) { Flags: 0x000001, } self.codecString = fmt.Sprintf("hvc1.%02X%02X%02X", codec.RecordInfo.AVCProfileIndication, codec.RecordInfo.ProfileCompatibility, codec.RecordInfo.AVCLevelIndication) + } else if self.Type() == av.AAC { codec := self.CodecData.(aacparser.CodecData) self.sample.SampleDesc.MP4ADesc = &mp4io.MP4ADesc{ @@ -354,6 +357,7 @@ func (element *Stream) writePacketV3(pkt av.Packet, rawdur time.Duration, maxFra } func (element *Stream) writePacketV2(pkt av.Packet, rawdur time.Duration, maxFrames int) (bool, []byte, error) { + //pkt.Data = pkt.Data[4:] trackID := pkt.Idx + 1 if element.sampleIndex == 0 { element.moof.Header = &mp4fio.MovieFragHeader{Seqnum: uint32(element.muxer.fragmentIndex + 1)} diff --git a/format/rtspv2/client.go b/format/rtspv2/client.go index f59863d..3f37ea3 100644 --- a/format/rtspv2/client.go +++ b/format/rtspv2/client.go @@ -142,26 +142,33 @@ func Dial(options RTSPClientOptions) (*RTSPClient, error) { return nil, err } if i2.AVType == VIDEO { - if i2.Type == av.H264 && len(i2.SpropParameterSets) > 1 { - if codecData, err := h264parser.NewCodecDataFromSPSAndPPS(i2.SpropParameterSets[0], i2.SpropParameterSets[1]); err == nil { - client.sps = i2.SpropParameterSets[0] - client.pps = i2.SpropParameterSets[1] - client.CodecData = append(client.CodecData, codecData) - client.videoIDX = int8(len(client.CodecData) - 1) - client.videoCodec = av.H264 + if i2.Type == av.H264 { + if len(i2.SpropParameterSets) > 1 { + if codecData, err := h264parser.NewCodecDataFromSPSAndPPS(i2.SpropParameterSets[0], i2.SpropParameterSets[1]); err == nil { + client.sps = i2.SpropParameterSets[0] + client.pps = i2.SpropParameterSets[1] + client.CodecData = append(client.CodecData, codecData) + } + } else { + client.CodecData = append(client.CodecData, h264parser.CodecData{}) } - } else if i2.Type == av.H265 && len(i2.SpropVPS) > 1 && len(i2.SpropSPS) > 1 && len(i2.SpropPPS) > 1 { - if codecData, err := h265parser.NewCodecDataFromVPSAndSPSAndPPS(i2.SpropVPS, i2.SpropSPS, i2.SpropPPS); err == nil { - client.vps = i2.SpropVPS - client.sps = i2.SpropSPS - client.pps = i2.SpropPPS - client.CodecData = append(client.CodecData, codecData) - client.videoIDX = int8(len(client.CodecData) - 1) - client.videoCodec = av.H265 + client.videoCodec = av.H264 + } else if i2.Type == av.H265 { + if len(i2.SpropVPS) > 1 && len(i2.SpropSPS) > 1 && len(i2.SpropPPS) > 1 { + if codecData, err := h265parser.NewCodecDataFromVPSAndSPSAndPPS(i2.SpropVPS, i2.SpropSPS, i2.SpropPPS); err == nil { + client.vps = i2.SpropVPS + client.sps = i2.SpropSPS + client.pps = i2.SpropPPS + client.CodecData = append(client.CodecData, codecData) + } + } else { + client.CodecData = append(client.CodecData, h265parser.CodecData{}) } + client.videoCodec = av.H265 } else { client.Println("SDP Video Codec Type Not Supported", i2.Type) } + client.videoIDX = int8(len(client.CodecData) - 1) client.videoID = ch } if i2.AVType == AUDIO { @@ -552,7 +559,7 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { Data: append(binSize(len(nal)), nal...), CompositionTime: time.Duration(1) * time.Millisecond, Idx: client.videoIDX, - IsKeyFrame: naluType == h265parser.NAL_UNIT_CODED_SLICE_IDR_W_RADL, + IsKeyFrame: false, Duration: time.Duration(float32(timestamp-client.PreVideoTS)/90) * time.Millisecond, Time: time.Duration(timestamp/90) * time.Millisecond, }) @@ -564,22 +571,19 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { client.CodecUpdatePPS(nal) case h265parser.NAL_UNIT_UNSPECIFIED_49: se := nal[2] >> 6 - naluType = nal[2] & 0x3f + naluType := nal[2] & 0x3f if se == 2 { client.BufferRtpPacket.Truncate(0) client.BufferRtpPacket.Reset() - client.BufferRtpPacket.Write([]byte{0, 0, 0, 0, (nal[0] & 0x81) | (naluType << 1), nal[1]}) + client.BufferRtpPacket.Write([]byte{(nal[0] & 0x81) | (naluType << 1), nal[1]}) r := make([]byte, 2) r[1] = nal[1] r[0] = (nal[0] & 0x81) | (naluType << 1) client.BufferRtpPacket.Write(nal[3:]) } else if se == 1 { client.BufferRtpPacket.Write(nal[3:]) - binary.BigEndian.PutUint32(client.BufferRtpPacket.Bytes()[:4], uint32(client.BufferRtpPacket.Len())-4) - buf := make([]byte, client.BufferRtpPacket.Len()) - copy(buf, client.BufferRtpPacket.Bytes()) retmap = append(retmap, &av.Packet{ - Data: append(binSize(len(nal)), nal...), + Data: append(binSize(client.BufferRtpPacket.Len()), client.BufferRtpPacket.Bytes()...), CompositionTime: time.Duration(1) * time.Millisecond, Idx: client.videoIDX, IsKeyFrame: naluType == h265parser.NAL_UNIT_CODED_SLICE_IDR_W_RADL, @@ -590,8 +594,9 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { client.BufferRtpPacket.Write(nal[3:]) } default: - //log.Println("???", naluType) + client.Println("Unsupported Nal", naluType) } + } else if client.videoCodec == av.H264 { naluType := nal[0] & 0x1f switch { diff --git a/format/webrtcv3/adapter.go b/format/webrtcv3/adapter.go index 5a0ed30..dd3e17d 100644 --- a/format/webrtcv3/adapter.go +++ b/format/webrtcv3/adapter.go @@ -195,6 +195,9 @@ func (element *Muxer) WritePacket(pkt av.Packet) (err error) { } if tmp, ok := element.streams[pkt.Idx]; ok { element.StreamACK.Reset(10 * time.Second) + if len(pkt.Data) < 5 { + return nil + } switch tmp.codec.Type() { case av.H264: codec := tmp.codec.(h264parser.CodecData) diff --git a/go.mod b/go.mod index a5626fb..7ad6719 100644 --- a/go.mod +++ b/go.mod @@ -5,4 +5,5 @@ go 1.14 require ( github.com/pion/webrtc/v2 v2.2.23 // indirect github.com/pion/webrtc/v3 v3.0.1 // indirect + github.com/q191201771/lal v0.19.1 // indirect ) diff --git a/go.sum b/go.sum index 77483bb..790aca2 100644 --- a/go.sum +++ b/go.sum @@ -100,6 +100,10 @@ github.com/pion/webrtc/v3 v3.0.1/go.mod h1:ePzv8r2tzj95nJuPsns/7OiS5M8RiGSULdxzI github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/q191201771/lal v0.19.1 h1:Fxh33T+9y7Dp958/SFalzpWlt18LEYYT2z8UZdzhokQ= +github.com/q191201771/lal v0.19.1/go.mod h1:HUvNYsaXA7ZwGStxtpnxpH0lN5qzd350glLmdigDg0A= +github.com/q191201771/naza v0.17.0 h1:ZuETbHDX8srxxxL4AiDW+HTwEHnbfJvS40R8PUNStpQ= +github.com/q191201771/naza v0.17.0/go.mod h1:5LeGupZZFtYP1g/S203n9vXoUNVdlRnPIfM6rExjqt0= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/utils/bits/golomb_reader.go b/utils/bits/golomb_reader.go index da57cb2..b40978b 100644 --- a/utils/bits/golomb_reader.go +++ b/utils/bits/golomb_reader.go @@ -33,6 +33,30 @@ func (self *GolombBitReader) ReadBits(n int) (res uint, err error) { return } +func (self *GolombBitReader) ReadBits32(n uint) (r uint32, err error) { + var t uint + for i := uint(0); i < n; i++ { + t, err = self.ReadBit() + if err != nil { + return + } + r = (r << 1) | uint32(t) + } + return +} + +func (self *GolombBitReader) ReadBits64(n uint) (r uint64, err error) { + var t uint + for i := uint(0); i < n; i++ { + t, err = self.ReadBit() + if err != nil { + return + } + r = (r << 1) | uint64(t) + } + return +} + func (self *GolombBitReader) ReadExponentialGolombCode() (res uint, err error) { i := 0 for {