diff --git a/codec/h265parser/parser.go b/codec/h265parser/parser.go index a70f5e5..746525b 100644 --- a/codec/h265parser/parser.go +++ b/codec/h265parser/parser.go @@ -531,7 +531,7 @@ type AVCDecoderConfRecord struct { var ErrDecconfInvalid = fmt.Errorf("h265parser: AVCDecoderConfRecord invalid") func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) { - if len(b) < 7 { + if len(b) < 30 { err = ErrDecconfInvalid return } @@ -539,22 +539,23 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) { 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++ { + + vpscount := int(b[25] & 0x1f) + n += 26 + for i := 0; i < vpscount; i++ { if len(b) < n+2 { err = ErrDecconfInvalid return } - spslen := int(pio.U16BE(b[n:])) + vpslen := int(pio.U16BE(b[n:])) n += 2 - if len(b) < n+spslen { + if len(b) < n+vpslen { err = ErrDecconfInvalid return } - self.SPS = append(self.SPS, b[n:n+spslen]) - n += spslen + self.VPS = append(self.VPS, b[n:n+vpslen]) + n += vpslen } if len(b) < n+1 { @@ -562,42 +563,48 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) { return } - ppscount := int(b[n]) + n++ n++ - for i := 0; i < ppscount; i++ { + spscount := int(b[n]) + n++ + + for i := 0; i < spscount; i++ { if len(b) < n+2 { err = ErrDecconfInvalid return } - ppslen := int(pio.U16BE(b[n:])) + spslen := int(pio.U16BE(b[n:])) n += 2 - if len(b) < n+ppslen { + if len(b) < n+spslen { err = ErrDecconfInvalid return } - self.PPS = append(self.PPS, b[n:n+ppslen]) - n += ppslen + self.SPS = append(self.SPS, b[n:n+spslen]) + n += spslen } - vpscount := int(b[n]) + n++ n++ - for i := 0; i < vpscount; i++ { + ppscount := int(b[n]) + n++ + + for i := 0; i < ppscount; i++ { if len(b) < n+2 { err = ErrDecconfInvalid return } - vpslen := int(pio.U16BE(b[n:])) + ppslen := int(pio.U16BE(b[n:])) n += 2 - if len(b) < n+vpslen { + if len(b) < n+ppslen { err = ErrDecconfInvalid return } - self.VPS = append(self.VPS, b[n:n+vpslen]) - n += vpslen + self.PPS = append(self.PPS, b[n:n+ppslen]) + n += ppslen } return } diff --git a/format/flv/flv.go b/format/flv/flv.go index 0cc5da7..ea23264 100644 --- a/format/flv/flv.go +++ b/format/flv/flv.go @@ -11,6 +11,7 @@ import ( "github.com/deepch/vdk/codec/aacparser" "github.com/deepch/vdk/codec/fake" "github.com/deepch/vdk/codec/h264parser" + "github.com/deepch/vdk/codec/h265parser" "github.com/deepch/vdk/format/flv/flvio" "github.com/deepch/vdk/utils/bits/pio" ) @@ -28,6 +29,8 @@ func NewMetadataByStreams(streams []av.CodecData) (metadata flvio.AMFMap, err er switch typ { case av.H264: metadata["videocodecid"] = flvio.VIDEO_H264 + case av.H265: + metadata["videocodecid"] = flvio.VIDEO_H265 default: err = fmt.Errorf("flv: metadata: unsupported video codecType=%v", stream.Type()) @@ -87,10 +90,12 @@ func (self *Prober) PushTag(tag flvio.Tag, timestamp int32) (err error) { switch tag.AVCPacketType { case flvio.AVC_SEQHDR: if !self.GotVideo { - var stream h264parser.CodecData + var stream av.CodecData if stream, err = h264parser.NewCodecDataFromAVCDecoderConfRecord(tag.Data); err != nil { - err = fmt.Errorf("flv: h264 seqhdr invalid") - return + if stream, err = h265parser.NewCodecDataFromAVCDecoderConfRecord(tag.Data); err != nil { + err = fmt.Errorf("flv: h264 seqhdr invalid") + return + } } self.VideoStreamIdx = len(self.Streams) self.Streams = append(self.Streams, stream) @@ -222,7 +227,17 @@ func CodecDataToTag(stream av.CodecData) (_tag flvio.Tag, ok bool, err error) { } ok = true _tag = tag - + case av.H265: + h264 := stream.(h264parser.CodecData) + tag := flvio.Tag{ + Type: flvio.TAG_VIDEO, + AVCPacketType: flvio.AVC_SEQHDR, + CodecID: flvio.VIDEO_H265, + Data: h264.AVCDecoderConfRecordBytes(), + FrameType: flvio.FRAME_KEY, + } + ok = true + _tag = tag case av.NELLYMOSER: case av.SPEEX: @@ -272,7 +287,19 @@ func PacketToTag(pkt av.Packet, stream av.CodecData) (tag flvio.Tag, timestamp i } else { tag.FrameType = flvio.FRAME_INTER } - + case av.H265: + tag = flvio.Tag{ + Type: flvio.TAG_VIDEO, + AVCPacketType: flvio.AVC_NALU, + CodecID: flvio.VIDEO_H265, + Data: pkt.Data, + CompositionTime: flvio.TimeToTs(pkt.CompositionTime), + } + if pkt.IsKeyFrame { + tag.FrameType = flvio.FRAME_KEY + } else { + tag.FrameType = flvio.FRAME_INTER + } case av.AAC: tag = flvio.Tag{ Type: flvio.TAG_AUDIO, @@ -336,7 +363,7 @@ func NewMuxer(w io.Writer) *Muxer { return NewMuxerWriteFlusher(bufio.NewWriterSize(w, pio.RecommendBufioSize)) } -var CodecTypes = []av.CodecType{av.H264, av.AAC, av.SPEEX} +var CodecTypes = []av.CodecType{av.H264, av.AAC, av.SPEEX, av.H265} func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) { var flags uint8 diff --git a/format/flv/flvio/flvio.go b/format/flv/flvio/flvio.go index fd72626..7770005 100644 --- a/format/flv/flvio/flvio.go +++ b/format/flv/flvio/flvio.go @@ -59,6 +59,7 @@ const ( FRAME_INTER = 2 VIDEO_H264 = 7 + VIDEO_H265 = 12 ) type Tag struct {