From cc7b89992259376ce222bfededcda95ed4a9d436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=AE=87=E7=BF=94?= <11123448@vivo.xyz> Date: Wed, 23 Jun 2021 15:57:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96track=E8=AE=BE=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client.go | 17 ++------------ go.sum | 11 --------- main.go | 63 ++++++++++++++++++++++++++++++++------------------- sdp-parser.go | 23 ++++++++++--------- session.go | 17 ++------------ 5 files changed, 56 insertions(+), 75 deletions(-) diff --git a/client.go b/client.go index 6bd7854..b22af5c 100644 --- a/client.go +++ b/client.go @@ -218,14 +218,7 @@ func (client *RTSP) requestStream() (err error) { } switch t { case "video": - if len(sdpInfo.SpropParameterSets) > 1 { - client.RtpVideo = client.NewRTPVideo(7) - client.RtpVideo.PushNalu(VideoPack{NALUs: sdpInfo.SpropParameterSets}) - } else if client.VSdp.Codec == "H264" { - client.RtpVideo = client.NewRTPVideo(7) - } else if client.VSdp.Codec == "H265" { - client.RtpVideo = client.NewRTPVideo(12) - } + client.setVideoTrack() if client.TransType == TRANS_TYPE_TCP { headers["Transport"] = fmt.Sprintf("RTP/AVP/TCP;unicast;interleaved=%d-%d", client.vRTPChannel, client.vRTPControlChannel) } else { @@ -238,13 +231,7 @@ func (client *RTSP) requestStream() (err error) { client.Conn.timeout = 0 // UDP ignore timeout } case "audio": - client.RtpAudio = client.NewRTPAudio(0) - at := client.RtpAudio.AudioTrack - if len(client.ASdp.Control) > 0 { - at.SetASC(client.ASdp.Config) - } else { - client.setAudioFormat(at) - } + client.setAudioTrack() if client.TransType == TRANS_TYPE_TCP { headers["Transport"] = fmt.Sprintf("RTP/AVP/TCP;unicast;interleaved=%d-%d", client.aRTPChannel, client.aRTPControlChannel) } else { diff --git a/go.sum b/go.sum index 1bd5728..0d699d0 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,7 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Monibuca/engine/v3 v3.0.0-alpha6 h1:USZa+JDVJd13rb9wmX06ZxjRCrqYTAPe5wVD+0IODEE= -github.com/Monibuca/engine/v3 v3.0.0-alpha6/go.mod h1:V0/kfen6K5O/RLXHPsZj4DF/LboDZ0OqfeCfn35bWMo= -github.com/Monibuca/engine/v3 v3.0.0-beta3 h1:/co+L2qCRZUq55S0LtYpY9xzOJiUUG3VGytYGFf1RD4= -github.com/Monibuca/engine/v3 v3.0.0-beta3/go.mod h1:SMgnlwih4pBA/HkTLjKXZFYkv3ukRzFjv65CARRLVIk= github.com/Monibuca/engine/v3 v3.0.0-beta5 h1:b27ZQDfvf5dBMZbCSIUXItUwVIFs95fpkAV4xjN7BNE= github.com/Monibuca/engine/v3 v3.0.0-beta5/go.mod h1:SMgnlwih4pBA/HkTLjKXZFYkv3ukRzFjv65CARRLVIk= -github.com/Monibuca/utils/v3 v3.0.0-alpha4/go.mod h1:3xYmhQbgAZBHLyIMteUCd1va+1z/xnd72B585mCaT3c= -github.com/Monibuca/utils/v3 v3.0.0-alpha5 h1:IOyW/KJSRdRg+TPcgwkHLBynqfNQOV6p3iP7LgXEMFc= -github.com/Monibuca/utils/v3 v3.0.0-alpha5/go.mod h1:3xYmhQbgAZBHLyIMteUCd1va+1z/xnd72B585mCaT3c= github.com/Monibuca/utils/v3 v3.0.0-beta h1:z4p/BSH5J9Ja/gwoDmj1RyN+b0q28Nmn/fqXiwq2hGY= github.com/Monibuca/utils/v3 v3.0.0-beta/go.mod h1:mQYP/OMox1tkWP6Qut7pBfARr1TXSRkK662dexQl6kI= github.com/funny/slab v0.0.0-20180511031532-b1fad5e5d478 h1:Db9StoJ6RZN3YttC0Pm0I4Y5izITRYch3RMbT59BYN0= @@ -23,8 +16,6 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtp v1.6.2 h1:iGBerLX6JiDjB9NXuaPzHyxHFG9JsIEdgwTC0lp5n/U= -github.com/pion/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= github.com/pion/rtp v1.6.5 h1:o2cZf8OascA5HF/b0PAbTxRKvOWxTQxWYt7SlToxFGI= github.com/pion/rtp v1.6.5/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -37,7 +28,5 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVs golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43 h1:SgQ6LNaYJU0JIuEHv9+s6EbhSCwYeAf5Yvj6lpYlqAE= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210611083646-a4fc73990273 h1:faDu4veV+8pcThn4fewv6TVlNCezafGoC1gM/mxQLbQ= golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/main.go b/main.go index 1bd2a74..8903b54 100644 --- a/main.go +++ b/main.go @@ -141,13 +141,11 @@ type RTSP struct { Type SessionType TransType TransType - SDPMap map[string]*SDPInfo - nonce string - closeOld bool - ASdp *SDPInfo - VSdp *SDPInfo - aacsent bool - Timeout int + SDPMap map[string]*SDPInfo + nonce string + ASdp *SDPInfo + VSdp *SDPInfo + Timeout int //tcp channels aRTPChannel int aRTPControlChannel int @@ -162,23 +160,42 @@ type RTSP struct { RtpVideo *RTPVideo } -func (rtsp *RTSP) setAudioFormat(at *AudioTrack) { - switch rtsp.ASdp.Codec { - case "aac": - at.CodecID = 10 - case "pcma": - at.CodecID = 7 - at.SoundRate = rtsp.ASdp.TimeScale - at.SoundSize = 16 - case "pcmu": - at.CodecID = 8 - at.SoundRate = rtsp.ASdp.TimeScale - at.SoundSize = 16 - default: - Printf("rtsp audio codec not support:%s", rtsp.ASdp.Codec) - return +func (rtsp *RTSP) setVideoTrack() { + if rtsp.VSdp.Codec == "H264" { + rtsp.RtpVideo = rtsp.NewRTPVideo(7) + if len(rtsp.VSdp.SpropParameterSets) > 1 { + rtsp.RtpVideo.PushNalu(VideoPack{NALUs: rtsp.VSdp.SpropParameterSets}) + } + } else if rtsp.VSdp.Codec == "H265" { + rtsp.RtpVideo = rtsp.NewRTPVideo(12) + if len(rtsp.VSdp.VPS) > 0 { + rtsp.RtpVideo.PushNalu(VideoPack{NALUs: [][]byte{rtsp.VSdp.VPS, rtsp.ASdp.SPS, rtsp.ASdp.PPS}}) + } } - rtsp.AudioTracks.AddTrack(rtsp.ASdp.Codec, at) +} +func (rtsp *RTSP) setAudioTrack() { + var at *RTPAudio + if len(rtsp.ASdp.Control) > 0 { + at = rtsp.NewRTPAudio(0) + at.SetASC(rtsp.ASdp.Config) + } else { + switch rtsp.ASdp.Codec { + case "AAC": + at = rtsp.NewRTPAudio(10) + case "PCMA": + at = rtsp.NewRTPAudio(7) + at.SoundRate = rtsp.ASdp.TimeScale + at.SoundSize = 16 + case "PCMU": + at = rtsp.NewRTPAudio(8) + at.SoundRate = rtsp.ASdp.TimeScale + at.SoundSize = 16 + default: + Printf("rtsp audio codec not support:%s", rtsp.ASdp.Codec) + return + } + } + rtsp.RtpAudio = at } type RTSPClientInfo struct { diff --git a/sdp-parser.go b/sdp-parser.go index 0d55245..0aea15f 100644 --- a/sdp-parser.go +++ b/sdp-parser.go @@ -15,6 +15,9 @@ type SDPInfo struct { Rtpmap int Config []byte SpropParameterSets [][]byte + VPS []byte + PPS []byte + SPS []byte PayloadType int SizeLength int IndexLength int @@ -54,18 +57,10 @@ func ParseSDP(sdpRaw string) map[string]*SDPInfo { } keyval = strings.Split(field, "/") if len(keyval) >= 2 { - key := keyval[0] - switch key { - case "PCMA": - info.Codec = "pcma" - case "PCMU": - info.Codec = "pcmu" + info.Codec = keyval[0] + switch info.Codec { case "MPEG4-GENERIC": - info.Codec = "aac" - case "H264": - info.Codec = "h264" - case "H265": - info.Codec = "h265" + info.Codec = "AAC" } if i, err := strconv.Atoi(keyval[1]); err == nil { info.TimeScale = i @@ -85,6 +80,12 @@ func ParseSDP(sdpRaw string) map[string]*SDPInfo { info.SizeLength, _ = strconv.Atoi(val) case "indexlength": info.IndexLength, _ = strconv.Atoi(val) + case "sprop-vps": + info.VPS, _ = base64.StdEncoding.DecodeString(field) + case "sprop-sps": + info.SPS, _ = base64.StdEncoding.DecodeString(field) + case "sprop-pps": + info.PPS, _ = base64.StdEncoding.DecodeString(field) case "sprop-parameter-sets": fields := strings.Split(val, ",") for _, field := range fields { diff --git a/session.go b/session.go index 979df72..3958585 100644 --- a/session.go +++ b/session.go @@ -341,24 +341,11 @@ func (session *RTSP) handleRequest(req *Request) { session.Stream = stream if session.Publish() { if session.ASdp, session.HasAudio = session.SDPMap["audio"]; session.HasAudio { - session.RtpAudio = stream.NewRTPAudio(0) - at := session.RtpAudio.AudioTrack - if len(session.ASdp.Control) > 0 { - at.SetASC(session.ASdp.Config) - } else { - session.setAudioFormat(at) - } + session.setAudioTrack() Printf("audio codec[%s]\n", session.ASdp.Codec) } if session.VSdp, session.HasVideo = session.SDPMap["video"]; session.HasVideo { - if len(session.VSdp.SpropParameterSets) > 1 { - session.RtpVideo = stream.NewRTPVideo(7) - session.RtpVideo.PushNalu(VideoPack{NALUs: session.VSdp.SpropParameterSets}) - } else if session.VSdp.Codec == "H264" { - session.RtpVideo = stream.NewRTPVideo(7) - } else if session.VSdp.Codec == "H265" { - session.RtpVideo = stream.NewRTPVideo(12) - } + session.setVideoTrack() Printf("video codec[%s]\n", session.VSdp.Codec) } session.Stream.Type = "RTSP"