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
}
rbsp := nal2rbsp(sps[2:])
br := &bits.GolombBitReader{R: bytes.NewReader(rbsp)}
if _, err = br.ReadBits(4); err != nil {
return
}
spsMaxSubLayersMinus1, err := br.ReadBits(3)
if err != nil {
return
}
MbWidth uint if spsMaxSubLayersMinus1+1 > ctx.numTemporalLayers {
MbHeight uint ctx.numTemporalLayers = spsMaxSubLayersMinus1 + 1
}
if ctx.temporalIdNested, err = br.ReadBit(); err != nil {
return
}
if err = parsePTL(br, &ctx, spsMaxSubLayersMinus1); err != nil {
return
}
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 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
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
}
CropLeft uint var bdlm8 uint
CropRight uint if bdlm8, err = br.ReadExponentialGolombCode(); err != nil {
CropTop uint return
CropBottom uint }
ctx.bitDepthChromaMinus8 = uint(bdlm8)
var bdcm8 uint
if bdcm8, err = br.ReadExponentialGolombCode(); err != nil {
return
}
ctx.bitDepthChromaMinus8 = uint(bdcm8)
Width uint _, err = br.ReadExponentialGolombCode()
Height uint if err != nil {
return
}
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
}
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
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
if _, err = br.ReadExponentialGolombCode(); err != nil {
return
}
return
} }
func ParseSPS(data []byte) (self SPSInfo, err error) { func parsePTL(br *bits.GolombBitReader, ctx *SPSInfo, maxSubLayersMinus1 uint) error {
r := &bits.GolombBitReader{R: bytes.NewReader(data)} var err error
var ptl SPSInfo
if _, err = r.ReadBits(8); err != nil { if ptl.generalProfileSpace, err = br.ReadBits(2); err != nil {
return return err
} }
if ptl.generalTierFlag, err = br.ReadBit(); err != nil {
if self.ProfileIdc, err = r.ReadBits(8); err != nil { return err
return
} }
if ptl.generalProfileIDC, err = br.ReadBits(5); err != nil {
// constraint_set0_flag-constraint_set6_flag,reserved_zero_2bits return err
if _, err = r.ReadBits(8); err != nil {
return
} }
if ptl.generalProfileCompatibilityFlags, err = br.ReadBits32(32); err != nil {
// level_idc return err
if self.LevelIdc, err = r.ReadBits(8); err != nil {
return
} }
if ptl.generalConstraintIndicatorFlags, err = br.ReadBits64(48); err != nil {
// seq_parameter_set_id return err
if _, err = r.ReadExponentialGolombCode(); err != nil {
return
} }
if ptl.generalLevelIDC, err = br.ReadBits(8); err != nil {
if self.ProfileIdc == 100 || self.ProfileIdc == 110 || return err
self.ProfileIdc == 122 || self.ProfileIdc == 244 || }
self.ProfileIdc == 44 || self.ProfileIdc == 83 || updatePTL(ctx, &ptl)
self.ProfileIdc == 86 || self.ProfileIdc == 118 { if maxSubLayersMinus1 == 0 {
return nil
var chroma_format_idc uint }
if chroma_format_idc, err = r.ReadExponentialGolombCode(); err != nil { subLayerProfilePresentFlag := make([]uint, maxSubLayersMinus1)
return 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 {
if chroma_format_idc == 3 { return err
// residual_colour_transform_flag
if _, err = r.ReadBit(); err != nil {
return
}
} }
}
// bit_depth_luma_minus8 if maxSubLayersMinus1 > 0 {
if _, err = r.ReadExponentialGolombCode(); err != nil { for i := maxSubLayersMinus1; i < 8; i++ {
return if _, err = br.ReadBits(2); err != nil {
} return err
// bit_depth_chroma_minus8
if _, err = r.ReadExponentialGolombCode(); err != nil {
return
}
// qpprime_y_zero_transform_bypass_flag
if _, err = r.ReadBit(); err != nil {
return
}
var seq_scaling_matrix_present_flag uint
if seq_scaling_matrix_present_flag, err = r.ReadBit(); 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
}
}
}
} }
} }
} }
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
}
}
// log2_max_frame_num_minus4 if subLayerLevelPresentFlag[i] != 0 {
if _, err = r.ReadExponentialGolombCode(); err != nil { if _, err = br.ReadBits(8); err != nil {
return return err
}
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
} }
} }
} }
return nil
}
// max_num_ref_frames func updatePTL(ctx, ptl *SPSInfo) {
if _, err = r.ReadExponentialGolombCode(); err != nil { ctx.generalProfileSpace = ptl.generalProfileSpace
return
}
// gaps_in_frame_num_value_allowed_flag if ptl.generalTierFlag > ctx.generalTierFlag {
if _, err = r.ReadBit(); err != nil { ctx.generalLevelIDC = ptl.generalLevelIDC
return
}
if self.MbWidth, err = r.ReadExponentialGolombCode(); err != nil { ctx.generalTierFlag = ptl.generalTierFlag
return } else {
} if ptl.generalLevelIDC > ctx.generalLevelIDC {
self.MbWidth++ ctx.generalLevelIDC = ptl.generalLevelIDC
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
} }
} }
// direct_8x8_inference_flag if ptl.generalProfileIDC > ctx.generalProfileIDC {
if _, err = r.ReadBit(); err != nil { ctx.generalProfileIDC = ptl.generalProfileIDC
return
} }
var frame_cropping_flag uint ctx.generalProfileCompatibilityFlags &= ptl.generalProfileCompatibilityFlags
if frame_cropping_flag, err = r.ReadBit(); err != nil {
return
}
if frame_cropping_flag != 0 {
if self.CropLeft, err = r.ReadExponentialGolombCode(); err != nil {
return
}
if self.CropRight, err = r.ReadExponentialGolombCode(); err != nil {
return
}
if self.CropTop, err = r.ReadExponentialGolombCode(); err != nil {
return
}
if self.CropBottom, err = r.ReadExponentialGolombCode(); err != nil {
return
}
}
self.Width = (self.MbWidth * 16) - self.CropLeft*2 - self.CropRight*2 ctx.generalConstraintIndicatorFlags &= ptl.generalConstraintIndicatorFlags
self.Height = ((2 - frame_mbs_only_flag) * self.MbHeight * 16) - self.CropTop*2 - self.CropBottom*2 }
return 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 codecData, err := h264parser.NewCodecDataFromSPSAndPPS(i2.SpropParameterSets[0], i2.SpropParameterSets[1]); err == nil { if len(i2.SpropParameterSets) > 1 {
client.sps = i2.SpropParameterSets[0] if codecData, err := h264parser.NewCodecDataFromSPSAndPPS(i2.SpropParameterSets[0], i2.SpropParameterSets[1]); err == nil {
client.pps = i2.SpropParameterSets[1] client.sps = i2.SpropParameterSets[0]
client.CodecData = append(client.CodecData, codecData) client.pps = i2.SpropParameterSets[1]
client.videoIDX = int8(len(client.CodecData) - 1) client.CodecData = append(client.CodecData, codecData)
client.videoCodec = av.H264 }
} 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 { client.videoCodec = av.H264
if codecData, err := h265parser.NewCodecDataFromVPSAndSPSAndPPS(i2.SpropVPS, i2.SpropSPS, i2.SpropPPS); err == nil { } else if i2.Type == av.H265 {
client.vps = i2.SpropVPS if len(i2.SpropVPS) > 1 && len(i2.SpropSPS) > 1 && len(i2.SpropPPS) > 1 {
client.sps = i2.SpropSPS if codecData, err := h265parser.NewCodecDataFromVPSAndSPSAndPPS(i2.SpropVPS, i2.SpropSPS, i2.SpropPPS); err == nil {
client.pps = i2.SpropPPS client.vps = i2.SpropVPS
client.CodecData = append(client.CodecData, codecData) client.sps = i2.SpropSPS
client.videoIDX = int8(len(client.CodecData) - 1) client.pps = i2.SpropPPS
client.videoCodec = av.H265 client.CodecData = append(client.CodecData, codecData)
}
} 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 {