h265 video mp4 support

This commit is contained in:
Andrey Semochkin 2021-02-09 04:27:04 +03:00
parent ae4ae47c04
commit 01cae17ec2
7 changed files with 320 additions and 250 deletions

View File

@ -2,6 +2,7 @@ package h265parser
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"github.com/deepch/vdk/av" "github.com/deepch/vdk/av"
@ -9,6 +10,32 @@ import (
"github.com/deepch/vdk/utils/bits/pio" "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 ( const (
NAL_UNIT_CODED_SLICE_TRAIL_N = 0 NAL_UNIT_CODED_SLICE_TRAIL_N = 0
NAL_UNIT_CODED_SLICE_TRAIL_R = 1 NAL_UNIT_CODED_SLICE_TRAIL_R = 1
@ -83,6 +110,11 @@ const (
MAX_SPS_COUNT = 32 MAX_SPS_COUNT = 32
) )
var (
ErrorH265IncorectUnitSize = errors.New("Invorect Unit Size")
ErrorH265IncorectUnitType = errors.New("Incorect Unit Type")
)
func IsDataNALU(b []byte) bool { func IsDataNALU(b []byte) bool {
typ := b[0] & 0x1f typ := b[0] & 0x1f
return typ >= 1 && typ <= 5 return typ >= 1 && typ <= 5
@ -128,7 +160,6 @@ func SplitNALUs(b []byte) (nalus [][]byte, typ int) {
return nalus, NALU_AVCC return nalus, NALU_AVCC
} }
} }
// is Annex B
if val3 == 1 || val4 == 1 { if val3 == 1 || val4 == 1 {
_val3 := val3 _val3 := val3
_val4 := val4 _val4 := val4
@ -175,212 +206,216 @@ func SplitNALUs(b []byte) (nalus [][]byte, typ int) {
return [][]byte{b}, NALU_RAW return [][]byte{b}, NALU_RAW
} }
type SPSInfo struct { func ParseSPS(sps []byte) (ctx SPSInfo, err error) {
ProfileIdc uint if len(sps) < 2 {
LevelIdc uint err = ErrorH265IncorectUnitSize
return
MbWidth uint
MbHeight uint
CropLeft uint
CropRight uint
CropTop uint
CropBottom uint
Width uint
Height uint
} }
rbsp := nal2rbsp(sps[2:])
func ParseSPS(data []byte) (self SPSInfo, err error) { br := &bits.GolombBitReader{R: bytes.NewReader(rbsp)}
r := &bits.GolombBitReader{R: bytes.NewReader(data)} if _, err = br.ReadBits(4); err != nil {
return
if _, err = r.ReadBits(8); err != nil { }
spsMaxSubLayersMinus1, err := br.ReadBits(3)
if err != nil {
return return
} }
if self.ProfileIdc, err = r.ReadBits(8); err != nil { if spsMaxSubLayersMinus1+1 > ctx.numTemporalLayers {
ctx.numTemporalLayers = spsMaxSubLayersMinus1 + 1
}
if ctx.temporalIdNested, err = br.ReadBit(); err != nil {
return return
} }
if err = parsePTL(br, &ctx, spsMaxSubLayersMinus1); err != nil {
// constraint_set0_flag-constraint_set6_flag,reserved_zero_2bits
if _, err = r.ReadBits(8); err != nil {
return return
} }
if _, err = br.ReadExponentialGolombCode(); err != nil {
// level_idc
if self.LevelIdc, err = r.ReadBits(8); err != nil {
return return
} }
var cf uint
// seq_parameter_set_id if cf, err = br.ReadExponentialGolombCode(); err != nil {
if _, err = r.ReadExponentialGolombCode(); err != nil {
return return
} }
ctx.chromaFormat = uint(cf)
if self.ProfileIdc == 100 || self.ProfileIdc == 110 || if ctx.chromaFormat == 3 {
self.ProfileIdc == 122 || self.ProfileIdc == 244 || if _, err = br.ReadBit(); err != nil {
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 {
return return
} }
}
if chroma_format_idc == 3 { if ctx.PicWidthInLumaSamples, err = br.ReadExponentialGolombCode(); err != nil {
// residual_colour_transform_flag return
if _, err = r.ReadBit(); err != nil { }
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
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return return
} }
} }
// bit_depth_luma_minus8 var bdlm8 uint
if _, err = r.ReadExponentialGolombCode(); err != nil { if bdlm8, err = br.ReadExponentialGolombCode(); err != nil {
return return
} }
// bit_depth_chroma_minus8 ctx.bitDepthChromaMinus8 = uint(bdlm8)
if _, err = r.ReadExponentialGolombCode(); err != nil { var bdcm8 uint
return if bdcm8, err = br.ReadExponentialGolombCode(); err != nil {
}
// qpprime_y_zero_transform_bypass_flag
if _, err = r.ReadBit(); err != nil {
return return
} }
ctx.bitDepthChromaMinus8 = uint(bdcm8)
var seq_scaling_matrix_present_flag uint _, err = br.ReadExponentialGolombCode()
if seq_scaling_matrix_present_flag, err = r.ReadBit(); err != nil { if err != nil {
return return
} }
spsSubLayerOrderingInfoPresentFlag, err := br.ReadBit()
if seq_scaling_matrix_present_flag != 0 { if err != nil {
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 return
} }
if seq_scaling_list_present_flag != 0 { var i uint
var sizeOfScalingList uint if spsSubLayerOrderingInfoPresentFlag != 0 {
if i < 6 { i = 0
sizeOfScalingList = 16
} else { } else {
sizeOfScalingList = 64 i = spsMaxSubLayersMinus1
} }
lastScale := uint(8) for ; i <= spsMaxSubLayersMinus1; i++ {
nextScale := uint(8) if _, err = br.ReadExponentialGolombCode(); err != nil {
for j := uint(0); j < sizeOfScalingList; j++ {
if nextScale != 0 {
var delta_scale uint
if delta_scale, err = r.ReadSE(); err != nil {
return return
} }
nextScale = (lastScale + delta_scale + 256) % 256 if _, err = br.ReadExponentialGolombCode(); err != nil {
}
if nextScale != 0 {
lastScale = nextScale
}
}
}
}
}
}
// log2_max_frame_num_minus4
if _, err = r.ReadExponentialGolombCode(); err != nil {
return return
} }
if _, err = br.ReadExponentialGolombCode(); err != nil {
var pic_order_cnt_type uint
if pic_order_cnt_type, err = r.ReadExponentialGolombCode(); 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 {
return
}
// offset_for_top_to_bottom_field
if _, err = r.ReadSE(); 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 {
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 {
return
}
// gaps_in_frame_num_value_allowed_flag
if _, err = r.ReadBit(); err != nil {
return
}
if self.MbWidth, err = r.ReadExponentialGolombCode(); err != nil {
return
}
self.MbWidth++
if self.MbHeight, err = r.ReadExponentialGolombCode(); err != nil {
return
}
self.MbHeight++
var frame_mbs_only_flag uint
if frame_mbs_only_flag, err = r.ReadBit(); err != nil {
return
}
if frame_mbs_only_flag == 0 {
// mb_adaptive_frame_field_flag
if _, err = r.ReadBit(); err != nil {
return return
} }
} }
// direct_8x8_inference_flag if _, err = br.ReadExponentialGolombCode(); err != nil {
if _, err = r.ReadBit(); err != nil { return
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
return return
} }
var frame_cropping_flag uint func parsePTL(br *bits.GolombBitReader, ctx *SPSInfo, maxSubLayersMinus1 uint) error {
if frame_cropping_flag, err = r.ReadBit(); err != nil { var err error
return var ptl SPSInfo
if ptl.generalProfileSpace, err = br.ReadBits(2); err != nil {
return err
} }
if frame_cropping_flag != 0 { if ptl.generalTierFlag, err = br.ReadBit(); err != nil {
if self.CropLeft, err = r.ReadExponentialGolombCode(); err != nil { return err
return
} }
if self.CropRight, err = r.ReadExponentialGolombCode(); err != nil { if ptl.generalProfileIDC, err = br.ReadBits(5); err != nil {
return return err
} }
if self.CropTop, err = r.ReadExponentialGolombCode(); err != nil { if ptl.generalProfileCompatibilityFlags, err = br.ReadBits32(32); err != nil {
return return err
} }
if self.CropBottom, err = r.ReadExponentialGolombCode(); err != nil { if ptl.generalConstraintIndicatorFlags, err = br.ReadBits64(48); err != nil {
return 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 subLayerLevelPresentFlag[i], err = br.ReadBit(); err != nil {
return err
}
}
if maxSubLayersMinus1 > 0 {
for i := maxSubLayersMinus1; i < 8; i++ {
if _, err = br.ReadBits(2); err != nil {
return err
}
}
}
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
} }
} }
self.Width = (self.MbWidth * 16) - self.CropLeft*2 - self.CropRight*2 if subLayerLevelPresentFlag[i] != 0 {
self.Height = ((2 - frame_mbs_only_flag) * self.MbHeight * 16) - self.CropTop*2 - self.CropBottom*2 if _, err = br.ReadBits(8); err != nil {
return err
}
}
}
return nil
}
return func updatePTL(ctx, ptl *SPSInfo) {
ctx.generalProfileSpace = ptl.generalProfileSpace
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 { 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) { func NewCodecDataFromVPSAndSPSAndPPS(vps, sps, pps []byte) (self CodecData, err error) {
recordinfo := AVCDecoderConfRecord{} recordinfo := AVCDecoderConfRecord{}
recordinfo.AVCProfileIndication = sps[1] recordinfo.AVCProfileIndication = sps[3]
recordinfo.ProfileCompatibility = sps[2] recordinfo.ProfileCompatibility = sps[4]
recordinfo.AVCLevelIndication = sps[3] recordinfo.AVCLevelIndication = sps[5]
recordinfo.SPS = [][]byte{sps} recordinfo.SPS = [][]byte{sps}
recordinfo.PPS = [][]byte{pps} recordinfo.PPS = [][]byte{pps}
recordinfo.VPS = [][]byte{vps} recordinfo.VPS = [][]byte{vps}
recordinfo.LengthSizeMinusOne = 3 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 { if self.SPSInfo, err = ParseSPS(sps); err != nil {
return return
} }
buf := make([]byte, recordinfo.Len())
recordinfo.Marshal(buf, self.SPSInfo)
self.RecordInfo = recordinfo
self.Record = buf
return return
} }
@ -480,14 +512,12 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) {
err = ErrDecconfInvalid err = ErrDecconfInvalid
return return
} }
self.AVCProfileIndication = b[1] self.AVCProfileIndication = b[1]
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) spscount := int(b[5] & 0x1f)
n += 6 n += 6
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
@ -550,55 +580,63 @@ func (self *AVCDecoderConfRecord) Unmarshal(b []byte) (n int, err error) {
} }
func (self AVCDecoderConfRecord) Len() (n int) { func (self AVCDecoderConfRecord) Len() (n int) {
n = 7 n = 23
for _, sps := range self.SPS { for _, sps := range self.SPS {
n += 2 + len(sps) n += 5 + len(sps)
} }
for _, pps := range self.PPS { for _, pps := range self.PPS {
n += 2 + len(pps) n += 5 + len(pps)
} }
for _, vps := range self.VPS { for _, vps := range self.VPS {
n += 2 + len(vps) n += 5 + len(vps)
} }
return return
} }
func (self AVCDecoderConfRecord) Marshal(b []byte) (n int) { func (self AVCDecoderConfRecord) Marshal(b []byte, si SPSInfo) (n int) {
b[0] = 1 b[0] = 1
b[1] = self.AVCProfileIndication b[1] = self.AVCProfileIndication
b[2] = self.ProfileCompatibility b[2] = self.ProfileCompatibility
b[3] = self.AVCLevelIndication b[3] = self.AVCLevelIndication
b[4] = self.LengthSizeMinusOne | 0xfc b[21] = 3
b[5] = uint8(len(self.SPS)) | 0xe0 b[22] = 3
n += 6 n += 23
b[n] = (self.VPS[0][0] >> 1) & 0x3f
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))
n++ n++
b[n] = byte(len(self.VPS) >> 8)
for _, pps := range self.PPS { n++
pio.PutU16BE(b[n:], uint16(len(pps))) b[n] = byte(len(self.VPS))
n += 2
copy(b[n:], pps)
n += len(pps)
}
b[n] = uint8(len(self.VPS))
n++ n++
for _, vps := range self.VPS { for _, vps := range self.VPS {
pio.PutU16BE(b[n:], uint16(len(vps))) pio.PutU16BE(b[n:], uint16(len(vps)))
n += 2 n += 2
copy(b[n:], vps) copy(b[n:], vps)
n += len(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] = (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)
}
return return
} }
@ -623,17 +661,13 @@ const (
) )
func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) { func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) {
if len(packet) <= 1 { if len(packet) <= 1 {
err = fmt.Errorf("h265parser: packet too short to parse slice header") err = fmt.Errorf("h265parser: packet too short to parse slice header")
return return
} }
nal_unit_type := packet[0] & 0x1f nal_unit_type := packet[0] & 0x1f
switch nal_unit_type { switch nal_unit_type {
case 1, 2, 5, 19: case 1, 2, 5, 19:
// slice_layer_without_partitioning_rbsp
// slice_data_partition_a_layer_rbsp
default: default:
err = fmt.Errorf("h265parser: nal_unit_type=%d has no slice header", nal_unit_type) 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:])} r := &bits.GolombBitReader{R: bytes.NewReader(packet[1:])}
// first_mb_in_slice
if _, err = r.ReadExponentialGolombCode(); err != nil { if _, err = r.ReadExponentialGolombCode(); err != nil {
return return
} }
// slice_type
var u uint var u uint
if u, err = r.ReadExponentialGolombCode(); err != nil { if u, err = r.ReadExponentialGolombCode(); err != nil {
return return
@ -664,6 +694,5 @@ func ParseSliceHeaderFromNALU(packet []byte) (sliceType SliceType, err error) {
err = fmt.Errorf("h265parser: slice_type=%d invalid", u) err = fmt.Errorf("h265parser: slice_type=%d invalid", u)
return return
} }
return return
} }

View File

@ -181,6 +181,7 @@ func (self *Stream) fillTrackAtom() (err error) {
} else if self.Type() == av.H265 { } else if self.Type() == av.H265 {
codec := self.CodecData.(h265parser.CodecData) codec := self.CodecData.(h265parser.CodecData)
width, height := codec.Width(), codec.Height() width, height := codec.Width(), codec.Height()
self.sample.SampleDesc.HV1Desc = &mp4io.HV1Desc{ self.sample.SampleDesc.HV1Desc = &mp4io.HV1Desc{
DataRefIdx: 1, DataRefIdx: 1,
HorizontalResolution: 72, HorizontalResolution: 72,
@ -192,6 +193,7 @@ func (self *Stream) fillTrackAtom() (err error) {
ColorTableId: -1, ColorTableId: -1,
Conf: &mp4io.HV1Conf{Data: codec.AVCDecoderConfRecordBytes()}, Conf: &mp4io.HV1Conf{Data: codec.AVCDecoderConfRecordBytes()},
} }
self.trackAtom.Media.Handler = &mp4io.HandlerRefer{ self.trackAtom.Media.Handler = &mp4io.HandlerRefer{
SubType: [4]byte{'v', 'i', 'd', 'e'}, 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}, 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, Flags: 0x000001,
} }
self.codecString = fmt.Sprintf("hvc1.%02X%02X%02X", codec.RecordInfo.AVCProfileIndication, codec.RecordInfo.ProfileCompatibility, codec.RecordInfo.AVCLevelIndication) self.codecString = fmt.Sprintf("hvc1.%02X%02X%02X", codec.RecordInfo.AVCProfileIndication, codec.RecordInfo.ProfileCompatibility, codec.RecordInfo.AVCLevelIndication)
} else if self.Type() == av.AAC { } else if self.Type() == av.AAC {
codec := self.CodecData.(aacparser.CodecData) codec := self.CodecData.(aacparser.CodecData)
self.sample.SampleDesc.MP4ADesc = &mp4io.MP4ADesc{ 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) { func (element *Stream) writePacketV2(pkt av.Packet, rawdur time.Duration, maxFrames int) (bool, []byte, error) {
//pkt.Data = pkt.Data[4:]
trackID := pkt.Idx + 1 trackID := pkt.Idx + 1
if element.sampleIndex == 0 { if element.sampleIndex == 0 {
element.moof.Header = &mp4fio.MovieFragHeader{Seqnum: uint32(element.muxer.fragmentIndex + 1)} element.moof.Header = &mp4fio.MovieFragHeader{Seqnum: uint32(element.muxer.fragmentIndex + 1)}

View File

@ -142,26 +142,33 @@ func Dial(options RTSPClientOptions) (*RTSPClient, error) {
return nil, err return nil, err
} }
if i2.AVType == VIDEO { if i2.AVType == VIDEO {
if i2.Type == av.H264 && len(i2.SpropParameterSets) > 1 { if i2.Type == av.H264 {
if len(i2.SpropParameterSets) > 1 {
if codecData, err := h264parser.NewCodecDataFromSPSAndPPS(i2.SpropParameterSets[0], i2.SpropParameterSets[1]); err == nil { if codecData, err := h264parser.NewCodecDataFromSPSAndPPS(i2.SpropParameterSets[0], i2.SpropParameterSets[1]); err == nil {
client.sps = i2.SpropParameterSets[0] client.sps = i2.SpropParameterSets[0]
client.pps = i2.SpropParameterSets[1] client.pps = i2.SpropParameterSets[1]
client.CodecData = append(client.CodecData, codecData) client.CodecData = append(client.CodecData, codecData)
client.videoIDX = int8(len(client.CodecData) - 1)
client.videoCodec = av.H264
} }
} else if i2.Type == av.H265 && len(i2.SpropVPS) > 1 && len(i2.SpropSPS) > 1 && len(i2.SpropPPS) > 1 { } else {
client.CodecData = append(client.CodecData, h264parser.CodecData{})
}
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 { if codecData, err := h265parser.NewCodecDataFromVPSAndSPSAndPPS(i2.SpropVPS, i2.SpropSPS, i2.SpropPPS); err == nil {
client.vps = i2.SpropVPS client.vps = i2.SpropVPS
client.sps = i2.SpropSPS client.sps = i2.SpropSPS
client.pps = i2.SpropPPS client.pps = i2.SpropPPS
client.CodecData = append(client.CodecData, codecData) client.CodecData = append(client.CodecData, codecData)
client.videoIDX = int8(len(client.CodecData) - 1)
client.videoCodec = av.H265
} }
} else {
client.CodecData = append(client.CodecData, h265parser.CodecData{})
}
client.videoCodec = av.H265
} else { } else {
client.Println("SDP Video Codec Type Not Supported", i2.Type) client.Println("SDP Video Codec Type Not Supported", i2.Type)
} }
client.videoIDX = int8(len(client.CodecData) - 1)
client.videoID = ch client.videoID = ch
} }
if i2.AVType == AUDIO { if i2.AVType == AUDIO {
@ -552,7 +559,7 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) {
Data: append(binSize(len(nal)), nal...), Data: append(binSize(len(nal)), nal...),
CompositionTime: time.Duration(1) * time.Millisecond, CompositionTime: time.Duration(1) * time.Millisecond,
Idx: client.videoIDX, 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, Duration: time.Duration(float32(timestamp-client.PreVideoTS)/90) * time.Millisecond,
Time: time.Duration(timestamp/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) client.CodecUpdatePPS(nal)
case h265parser.NAL_UNIT_UNSPECIFIED_49: case h265parser.NAL_UNIT_UNSPECIFIED_49:
se := nal[2] >> 6 se := nal[2] >> 6
naluType = nal[2] & 0x3f naluType := nal[2] & 0x3f
if se == 2 { if se == 2 {
client.BufferRtpPacket.Truncate(0) client.BufferRtpPacket.Truncate(0)
client.BufferRtpPacket.Reset() 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 := make([]byte, 2)
r[1] = nal[1] r[1] = nal[1]
r[0] = (nal[0] & 0x81) | (naluType << 1) r[0] = (nal[0] & 0x81) | (naluType << 1)
client.BufferRtpPacket.Write(nal[3:]) client.BufferRtpPacket.Write(nal[3:])
} else if se == 1 { } else if se == 1 {
client.BufferRtpPacket.Write(nal[3:]) 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{ 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, CompositionTime: time.Duration(1) * time.Millisecond,
Idx: client.videoIDX, Idx: client.videoIDX,
IsKeyFrame: naluType == h265parser.NAL_UNIT_CODED_SLICE_IDR_W_RADL, 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:]) client.BufferRtpPacket.Write(nal[3:])
} }
default: default:
//log.Println("???", naluType) client.Println("Unsupported Nal", naluType)
} }
} else if client.videoCodec == av.H264 { } else if client.videoCodec == av.H264 {
naluType := nal[0] & 0x1f naluType := nal[0] & 0x1f
switch { switch {

View File

@ -195,6 +195,9 @@ func (element *Muxer) WritePacket(pkt av.Packet) (err error) {
} }
if tmp, ok := element.streams[pkt.Idx]; ok { if tmp, ok := element.streams[pkt.Idx]; ok {
element.StreamACK.Reset(10 * time.Second) element.StreamACK.Reset(10 * time.Second)
if len(pkt.Data) < 5 {
return nil
}
switch tmp.codec.Type() { switch tmp.codec.Type() {
case av.H264: case av.H264:
codec := tmp.codec.(h264parser.CodecData) codec := tmp.codec.(h264parser.CodecData)

1
go.mod
View File

@ -5,4 +5,5 @@ go 1.14
require ( require (
github.com/pion/webrtc/v2 v2.2.23 // indirect github.com/pion/webrtc/v2 v2.2.23 // indirect
github.com/pion/webrtc/v3 v3.0.1 // indirect github.com/pion/webrtc/v3 v3.0.1 // indirect
github.com/q191201771/lal v0.19.1 // indirect
) )

4
go.sum
View File

@ -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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/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/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/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=

View File

@ -33,6 +33,30 @@ func (self *GolombBitReader) ReadBits(n int) (res uint, err error) {
return 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) { func (self *GolombBitReader) ReadExponentialGolombCode() (res uint, err error) {
i := 0 i := 0
for { for {