From 01abed7b340f679d06c8fe2654b40c9b27c00f61 Mon Sep 17 00:00:00 2001 From: joestarzxh Date: Mon, 9 May 2022 12:24:43 +0800 Subject: [PATCH] =?UTF-8?q?[feat]gb=20ps=E9=9F=B3=E9=A2=91=E9=83=A8?= =?UTF-8?q?=E5=88=86=E5=85=88=E5=8A=A0=E4=BA=BA=E7=BC=93=E5=AD=98=E5=90=8E?= =?UTF-8?q?=E5=86=8D=E6=A0=B9=E6=8D=AE=E6=97=B6=E9=97=B4=E6=88=B3=E6=9D=A5?= =?UTF-8?q?=E5=9B=9E=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/gb28181/unpack.go | 31 +++++++++++------ pkg/gb28181/unpack_test.go | 69 ++++++++++++++++++++++++++++++++------ 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/pkg/gb28181/unpack.go b/pkg/gb28181/unpack.go index 66da276..75563f4 100644 --- a/pkg/gb28181/unpack.go +++ b/pkg/gb28181/unpack.go @@ -77,6 +77,7 @@ type PsUnpacker struct { preAudioDts uint64 videoBuf []byte + audioBuf []byte onAudio onAudioFn onVideo onVideoFn @@ -137,6 +138,7 @@ func (p *PsUnpacker) FeedRtpBody(rtpBody []byte, rtpTimestamp uint32) { // Table 2-35 - Program Stream map // // TODO(chef): [fix] 有些没做有效长度判断 + firstVideoPack := false for p.buf.Len() != 0 { rb := p.buf.Bytes() i := 0 @@ -155,6 +157,7 @@ func (p *PsUnpacker) FeedRtpBody(rtpBody []byte, rtpTimestamp uint32) { l := int(rb[i] & 0x7) i += 1 + l p.buf.Skip(i) + firstVideoPack = true case psPackStartCodeSystemHeader: nazalog.Debugf("-----system header-----") // skip @@ -250,18 +253,24 @@ func (p *PsUnpacker) FeedRtpBody(rtpBody []byte, rtpTimestamp uint32) { if dts == 0 { dts = pts } - p.preAudioPts = pts - p.preAudioDts = dts - if p.videoStreamType == StreamTypeAAC { + if p.audioStreamType == StreamTypeAAC { nazalog.Debugf("audio code=%d, length=%d, ptsDtsFlag=%d, phdl=%d, pts=%d, dts=%d,type=%d", code, length, ptsDtsFlag, phdl, pts, dts, p.audioStreamType) - if p.onAudio != nil { - p.onAudio(rb[i:i+length-3-phdl], int64(dts), int64(pts)) + if p.preAudioPts != 0 { + if p.preAudioPts != pts { + if p.onAudio != nil { + p.onAudio(p.audioBuf, int64(p.preAudioDts), int64(p.preAudioPts)) + } + p.audioBuf = nil + } } + p.audioBuf = append(p.audioBuf, rb[i:i+length-3-phdl]...) } + p.preAudioPts = pts + p.preAudioDts = dts } else { if pts == 0 { - if p.videoBuf == nil { + if firstVideoPack { pts = uint64(rtpTimestamp) } else { pts = p.preVideoPts @@ -358,7 +367,7 @@ func (p *PsUnpacker) findNextNaluStartPos(buf []byte, index int) (startPos int, if p.videoStreamType == StreamTypeH265 { nalType := (buf[i+pos] >> 1) & 0x3f if bufLen > i+pos+2 { - if hevcNalu(nalType, buf[i+pos:]) { + if isHevcNalu(nalType, buf[i+pos:]) { startPos = i + pos - leading - 1 return } @@ -366,7 +375,7 @@ func (p *PsUnpacker) findNextNaluStartPos(buf []byte, index int) (startPos int, } else { nalType := buf[i+pos] & 0x1f if bufLen > i+pos+1 { - if avcNalu(nalType, buf[i+pos:]) { + if isAvcNalu(nalType, buf[i+pos:]) { startPos = i + pos - leading - 1 return } @@ -401,7 +410,7 @@ func (p *PsUnpacker) findNaluStartPos(buf []byte) (pos int, leading int) { return } -func avcNalu(nalType byte, nalu []byte) bool { +func isAvcNalu(nalType byte, nalu []byte) bool { switch nalType { case avc.NaluTypeSlice: fallthrough @@ -428,8 +437,8 @@ func avcNalu(nalType byte, nalu []byte) bool { } return false } -func hevcNalu(nalType byte, nalu []byte) bool { - nuhLayerId := ((nalType & 0x01) << 5) | ((nalu[1] >> 3) & 0x1F) +func isHevcNalu(nalType byte, nalu []byte) bool { + nuhLayerId := (nalType & 0x01 << 5) | (nalu[1] >> 3 & 0x1F) if nalType == hevc.NaluTypeVps || nalType == hevc.NaluTypeSps || nalType == hevc.NaluTypePps || diff --git a/pkg/gb28181/unpack_test.go b/pkg/gb28181/unpack_test.go index b6b81d4..98fc2a4 100644 --- a/pkg/gb28181/unpack_test.go +++ b/pkg/gb28181/unpack_test.go @@ -6,19 +6,19 @@ // // Author: Chef (191201771@qq.com) -package gb28181_test +package gb28181 import ( "bytes" "encoding/hex" "fmt" - "github.com/q191201771/lal/pkg/avc" - "github.com/q191201771/lal/pkg/gb28181" - "github.com/q191201771/naza/pkg/nazabytes" - "github.com/q191201771/naza/pkg/nazalog" "io/ioutil" "os" "testing" + + "github.com/q191201771/lal/pkg/avc" + "github.com/q191201771/naza/pkg/nazabytes" + "github.com/q191201771/naza/pkg/nazalog" ) var goldenRtpList = []string{ @@ -66,7 +66,7 @@ var goldenRtpList = []string{ } func TestPsUnpacker(t *testing.T) { - unpacker := gb28181.NewPsUnpacker().WithCallbackFunc(nil, func(payload []byte, dts int64, pts int64) { + unpacker := NewPsUnpacker().WithCallbackFunc(nil, func(payload []byte, dts int64, pts int64) { }) @@ -74,7 +74,54 @@ func TestPsUnpacker(t *testing.T) { nazalog.Debugf("%d", i) b, _ := hex.DecodeString(item) nazalog.Debugf("%s", hex.Dump(nazabytes.Prefix(b, 128))) - unpacker.FeedRtpPacket(b) + unpacker.FeedRtpPacket(b, 0) + } +} + +var avcNalu = []byte{ + 0x00, 0x00, 0x00, + 0x01, 0x64, 0x00, 0x20, 0xFF, + 0xE1, 0x00, 0x19, + 0x67, 0x64, 0x00, 0x20, 0xAC, 0xD9, 0x40, 0xC0, 0x29, 0xB0, 0x11, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x32, 0x0F, 0x18, 0x31, 0x96, + 0x01, 0x00, 0x05, + 0x68, 0xEB, 0xEC, 0xB2, 0x2C, + 0x00, 0x00, 0x00, 0x00, + 0x01, 0x09, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x01, 0x65, 0x01, + 0x00, 0x00, + 0x01, 0x41, 0x03, +} +var hevcNalu = []byte{ + 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, + 0x0c, 0x01, 0xff, 0xff, + 0x01, + 0x60, 0x00, 0x00, 0x03, 0x00, + 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x3f, + 0xba, 0x02, 0x40, + 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, + 0x01, + 0x01, + 0x60, 0x00, 0x00, 0x03, 0x00, + 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x3f, + 0xa0, 0x05, 0x02, 0x01, 0x71, 0xf2, 0xe5, 0xba, 0x4a, 0x4c, 0x2f, 0x01, 0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x0f, 0x08, + 0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc0, 0x73, 0xc1, 0x89, + 0x00, 0x00, 0x01, 0x26, 0x01, 0x83, +} + +func TestFindNaluStartPos(t *testing.T) { + unpacker := NewPsUnpacker().WithCallbackFunc(nil, func(payload []byte, dts int64, pts int64) { + + }) + findPos := 0 + startPos, leading := unpacker.findNaluStartPos(avcNalu) + nazalog.Debugf("find pos=%d,start pos=%d,leading=%d", findPos+startPos, startPos, leading) + for startPos > 0 { + findPos += startPos + startPos, leading = unpacker.findNaluStartPos(avcNalu[findPos:]) + nazalog.Debugf("find pos=%d,start pos=%d,leading=%d", findPos+startPos, startPos, leading) } } @@ -96,7 +143,7 @@ func test1() { defer fp.Close() waitingSps := true - unpacker := gb28181.NewPsUnpacker().WithCallbackFunc(nil, func(payload []byte, dts int64, pts int64) { + unpacker := NewPsUnpacker().WithCallbackFunc(nil, func(payload []byte, dts int64, pts int64) { nazalog.Debugf("onVideo. length=%d", len(payload)) if waitingSps { if avc.ParseNaluType(payload[4]) == avc.NaluTypeSps { @@ -107,7 +154,7 @@ func test1() { } _, _ = fp.Write(payload) }) - unpacker.FeedRtpBody(b) + unpacker.FeedRtpBody(b, 0) } func test2() { @@ -119,7 +166,7 @@ func test2() { nazalog.Assert(nil, err) defer fp.Close() - unpacker := gb28181.NewPsUnpacker().WithCallbackFunc(nil, func(payload []byte, dts int64, pts int64) { + unpacker := NewPsUnpacker().WithCallbackFunc(nil, func(payload []byte, dts int64, pts int64) { nazalog.Debugf("onVideo. length=%d", len(payload)) _, _ = fp.Write(payload) }) @@ -136,6 +183,6 @@ func test2() { b = bytes.Join(bytes.Split(b, []byte{'\n'}), nil) b = bytes.Join(bytes.Split(b, []byte{' '}), nil) nazalog.Debugf("%s", hex.Dump(b)) - unpacker.FeedRtpPacket(b) + unpacker.FeedRtpPacket(b, 0) } }