[RTMP] client / server full support h265 video codec
This commit is contained in:
parent
b31edccea5
commit
472775f07c
@ -531,7 +531,7 @@ type AVCDecoderConfRecord struct {
|
|||||||
var ErrDecconfInvalid = fmt.Errorf("h265parser: AVCDecoderConfRecord invalid")
|
var ErrDecconfInvalid = fmt.Errorf("h265parser: AVCDecoderConfRecord invalid")
|
||||||
|
|
||||||
func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) {
|
func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) {
|
||||||
if len(b) < 7 {
|
if len(b) < 30 {
|
||||||
err = ErrDecconfInvalid
|
err = ErrDecconfInvalid
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -539,8 +539,36 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) {
|
|||||||
self.ProfileCompatibility = b[2]
|
self.ProfileCompatibility = b[2]
|
||||||
self.AVCLevelIndication = b[3]
|
self.AVCLevelIndication = b[3]
|
||||||
self.LengthSizeMinusOne = b[4] & 0x03
|
self.LengthSizeMinusOne = b[4] & 0x03
|
||||||
spscount := int(b[5] & 0x1f)
|
|
||||||
n += 6
|
vpscount := int(b[25] & 0x1f)
|
||||||
|
n += 26
|
||||||
|
for i := 0; i < vpscount; i++ {
|
||||||
|
if len(b) < n+2 {
|
||||||
|
err = ErrDecconfInvalid
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vpslen := int(pio.U16BE(b[n:]))
|
||||||
|
n += 2
|
||||||
|
|
||||||
|
if len(b) < n+vpslen {
|
||||||
|
err = ErrDecconfInvalid
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.VPS = append(self.VPS, b[n:n+vpslen])
|
||||||
|
n += vpslen
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b) < n+1 {
|
||||||
|
err = ErrDecconfInvalid
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
n++
|
||||||
|
n++
|
||||||
|
|
||||||
|
spscount := int(b[n])
|
||||||
|
n++
|
||||||
|
|
||||||
for i := 0; i < spscount; i++ {
|
for i := 0; i < spscount; i++ {
|
||||||
if len(b) < n+2 {
|
if len(b) < n+2 {
|
||||||
err = ErrDecconfInvalid
|
err = ErrDecconfInvalid
|
||||||
@ -557,10 +585,8 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) {
|
|||||||
n += spslen
|
n += spslen
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(b) < n+1 {
|
n++
|
||||||
err = ErrDecconfInvalid
|
n++
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ppscount := int(b[n])
|
ppscount := int(b[n])
|
||||||
n++
|
n++
|
||||||
@ -580,25 +606,6 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) {
|
|||||||
self.PPS = append(self.PPS, b[n:n+ppslen])
|
self.PPS = append(self.PPS, b[n:n+ppslen])
|
||||||
n += ppslen
|
n += ppslen
|
||||||
}
|
}
|
||||||
|
|
||||||
vpscount := int(b[n])
|
|
||||||
n++
|
|
||||||
|
|
||||||
for i := 0; i < vpscount; i++ {
|
|
||||||
if len(b) < n+2 {
|
|
||||||
err = ErrDecconfInvalid
|
|
||||||
return
|
|
||||||
}
|
|
||||||
vpslen := int(pio.U16BE(b[n:]))
|
|
||||||
n += 2
|
|
||||||
|
|
||||||
if len(b) < n+vpslen {
|
|
||||||
err = ErrDecconfInvalid
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self.VPS = append(self.VPS, b[n:n+vpslen])
|
|
||||||
n += vpslen
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/deepch/vdk/codec/aacparser"
|
"github.com/deepch/vdk/codec/aacparser"
|
||||||
"github.com/deepch/vdk/codec/fake"
|
"github.com/deepch/vdk/codec/fake"
|
||||||
"github.com/deepch/vdk/codec/h264parser"
|
"github.com/deepch/vdk/codec/h264parser"
|
||||||
|
"github.com/deepch/vdk/codec/h265parser"
|
||||||
"github.com/deepch/vdk/format/flv/flvio"
|
"github.com/deepch/vdk/format/flv/flvio"
|
||||||
"github.com/deepch/vdk/utils/bits/pio"
|
"github.com/deepch/vdk/utils/bits/pio"
|
||||||
)
|
)
|
||||||
@ -28,6 +29,8 @@ func NewMetadataByStreams(streams []av.CodecData) (metadata flvio.AMFMap, err er
|
|||||||
switch typ {
|
switch typ {
|
||||||
case av.H264:
|
case av.H264:
|
||||||
metadata["videocodecid"] = flvio.VIDEO_H264
|
metadata["videocodecid"] = flvio.VIDEO_H264
|
||||||
|
case av.H265:
|
||||||
|
metadata["videocodecid"] = flvio.VIDEO_H265
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("flv: metadata: unsupported video codecType=%v", stream.Type())
|
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 {
|
switch tag.AVCPacketType {
|
||||||
case flvio.AVC_SEQHDR:
|
case flvio.AVC_SEQHDR:
|
||||||
if !self.GotVideo {
|
if !self.GotVideo {
|
||||||
var stream h264parser.CodecData
|
var stream av.CodecData
|
||||||
if stream, err = h264parser.NewCodecDataFromAVCDecoderConfRecord(tag.Data); err != nil {
|
if stream, err = h264parser.NewCodecDataFromAVCDecoderConfRecord(tag.Data); err != nil {
|
||||||
err = fmt.Errorf("flv: h264 seqhdr invalid")
|
if stream, err = h265parser.NewCodecDataFromAVCDecoderConfRecord(tag.Data); err != nil {
|
||||||
return
|
err = fmt.Errorf("flv: h264 seqhdr invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.VideoStreamIdx = len(self.Streams)
|
self.VideoStreamIdx = len(self.Streams)
|
||||||
self.Streams = append(self.Streams, stream)
|
self.Streams = append(self.Streams, stream)
|
||||||
@ -222,7 +227,17 @@ func CodecDataToTag(stream av.CodecData) (_tag flvio.Tag, ok bool, err error) {
|
|||||||
}
|
}
|
||||||
ok = true
|
ok = true
|
||||||
_tag = tag
|
_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.NELLYMOSER:
|
||||||
case av.SPEEX:
|
case av.SPEEX:
|
||||||
|
|
||||||
@ -272,7 +287,19 @@ func PacketToTag(pkt av.Packet, stream av.CodecData) (tag flvio.Tag, timestamp i
|
|||||||
} else {
|
} else {
|
||||||
tag.FrameType = flvio.FRAME_INTER
|
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:
|
case av.AAC:
|
||||||
tag = flvio.Tag{
|
tag = flvio.Tag{
|
||||||
Type: flvio.TAG_AUDIO,
|
Type: flvio.TAG_AUDIO,
|
||||||
@ -336,7 +363,7 @@ func NewMuxer(w io.Writer) *Muxer {
|
|||||||
return NewMuxerWriteFlusher(bufio.NewWriterSize(w, pio.RecommendBufioSize))
|
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) {
|
func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) {
|
||||||
var flags uint8
|
var flags uint8
|
||||||
|
@ -59,6 +59,7 @@ const (
|
|||||||
FRAME_INTER = 2
|
FRAME_INTER = 2
|
||||||
|
|
||||||
VIDEO_H264 = 7
|
VIDEO_H264 = 7
|
||||||
|
VIDEO_H265 = 12
|
||||||
)
|
)
|
||||||
|
|
||||||
type Tag struct {
|
type Tag struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user