From d4c0b2be7a00300ac44be9137b5ef14ebfbbc407 Mon Sep 17 00:00:00 2001 From: langhuihui <178529795@qq.com> Date: Sun, 14 Feb 2021 22:59:01 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=82=E9=85=8D3.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 6 +-- go.sum | 27 +++++----- main.go | 163 +++++++++++++++++++++++++++++--------------------------- 3 files changed, 99 insertions(+), 97 deletions(-) diff --git a/go.mod b/go.mod index d1a2db9..e2d39fd 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/Monibuca/plugin-webrtc/v3 go 1.13 require ( - github.com/Monibuca/engine/v3 v3.0.0-alpha3 - github.com/Monibuca/utils/v3 v3.0.0-alpha3 + github.com/Monibuca/engine/v3 v3.0.0-alpha4 + github.com/Monibuca/utils/v3 v3.0.0-alpha4 github.com/pion/rtcp v1.2.6 github.com/pion/rtp v1.6.2 - github.com/pion/webrtc/v3 v3.0.5 + github.com/pion/webrtc/v3 v3.0.8 ) diff --git a/go.sum b/go.sum index bf0c591..39128c0 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,9 @@ 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-alpha1 h1:WnUDkvEJUO7DIdt3EOZ3KbG0pOX9WeJKN0b3GwjpVfs= -github.com/Monibuca/engine/v3 v3.0.0-alpha1/go.mod h1:K5FB3wk+iS/nPc+NS4XwObYQV4gtF6klEwDxaVM0BsQ= -github.com/Monibuca/engine/v3 v3.0.0-alpha3 h1:NtFBMsu1nvEA09q64sW9xNzLdQ9RCKQXJlESM3GmGxU= -github.com/Monibuca/engine/v3 v3.0.0-alpha3/go.mod h1:K5FB3wk+iS/nPc+NS4XwObYQV4gtF6klEwDxaVM0BsQ= -github.com/Monibuca/utils/v3 v3.0.0-alpha3 h1:n4Sq7mS1Iz8oBj2BcV4sXgKbZgix0fFLvjAfXYoiXl0= -github.com/Monibuca/utils/v3 v3.0.0-alpha3/go.mod h1:3xYmhQbgAZBHLyIMteUCd1va+1z/xnd72B585mCaT3c= +github.com/Monibuca/engine/v3 v3.0.0-alpha4 h1:kAStDd1p9tlSQeNyAAmb7vrPL2UCz7LFTzw5LdbGxBI= +github.com/Monibuca/engine/v3 v3.0.0-alpha4/go.mod h1:V0/kfen6K5O/RLXHPsZj4DF/LboDZ0OqfeCfn35bWMo= +github.com/Monibuca/utils/v3 v3.0.0-alpha4 h1:pecYA89kWmtGOeY6R99d4T1epPJ1wc+jFrrJY13VD04= +github.com/Monibuca/utils/v3 v3.0.0-alpha4/go.mod h1:3xYmhQbgAZBHLyIMteUCd1va+1z/xnd72B585mCaT3c= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -30,8 +28,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= @@ -61,8 +57,8 @@ github.com/pion/datachannel v1.4.21 h1:3ZvhNyfmxsAqltQrApLPQMhSFNA+aT87RqyCq4OXm github.com/pion/datachannel v1.4.21/go.mod h1:oiNyP4gHx2DIwRzX/MFyH0Rz/Gz05OgBlayAI2hAWjg= github.com/pion/dtls/v2 v2.0.4 h1:WuUcqi6oYMu/noNTz92QrF1DaFj4eXbhQ6dzaaAwOiI= github.com/pion/dtls/v2 v2.0.4/go.mod h1:qAkFscX0ZHoI1E07RfYPoRw3manThveu+mlTDdOxoGI= -github.com/pion/ice/v2 v2.0.14 h1:FxXxauyykf89SWAtkQCfnHkno6G8+bhRkNguSh9zU+4= -github.com/pion/ice/v2 v2.0.14/go.mod h1:wqaUbOq5ObDNU5ox1hRsEst0rWfsKuH1zXjQFEWiZwM= +github.com/pion/dtls/v2 v2.0.5 h1:jgQJRK2IJ9eWQAcUEZN4M0tnCi5X/cERnxH9J8qOjR0= +github.com/pion/dtls/v2 v2.0.5/go.mod h1:QuDII+8FVvk9Dp5t5vYIMTo7hh7uBkra+8QIm7QGm10= github.com/pion/ice/v2 v2.0.15 h1:KZrwa2ciL9od8+TUVJiYTNsCW9J5lktBjGwW1MacEnQ= github.com/pion/ice/v2 v2.0.15/go.mod h1:ZIiVGevpgAxF/cXiIVmuIUtCb3Xs4gCzCbXB6+nFkSI= github.com/pion/interceptor v0.0.9 h1:fk5hTdyLO3KURQsf/+RjMpEm4NE3yeTY9Kh97b5BvwA= @@ -92,7 +88,6 @@ github.com/pion/transport v0.10.0 h1:9M12BSneJm6ggGhJyWpDveFOstJsTiQjkLf4M44rm80 github.com/pion/transport v0.10.0/go.mod h1:BnHnUipd0rZQyTVB2SBGojFHT9CBt5C5TcsJSQGkvSE= github.com/pion/transport v0.10.1 h1:2W+yJT+0mOQ160ThZYUx5Zp2skzshiNgxrNE9GUfhJM= github.com/pion/transport v0.10.1/go.mod h1:PBis1stIILMiis0PewDw91WJeLJkyIMcEk+DwKOzf4A= -github.com/pion/transport v0.12.0/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= github.com/pion/transport v0.12.1/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= github.com/pion/transport v0.12.2 h1:WYEjhloRHt1R86LhUKjC5y+P52Y11/QqEUalvtzVoys= github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= @@ -100,10 +95,8 @@ github.com/pion/turn/v2 v2.0.5 h1:iwMHqDfPEDEOFzwWKT56eFmh6DYC6o/+xnLAEzgISbA= github.com/pion/turn/v2 v2.0.5/go.mod h1:APg43CFyt/14Uy7heYUOGWdkem/Wu4PhCO/bjyrTqMw= github.com/pion/udp v0.1.0 h1:uGxQsNyrqG3GLINv36Ff60covYmfrLoxzwnCsIYspXI= github.com/pion/udp v0.1.0/go.mod h1:BPELIjbwE9PRbd/zxI/KYBnbo7B6+oA6YuEaNE8lths= -github.com/pion/webrtc/v3 v3.0.4 h1:Tiw3H9fpfcwkvaxonB+Gv1DG9tmgYBQaM1vBagDHP40= -github.com/pion/webrtc/v3 v3.0.4/go.mod h1:1TmFSLpPYFTFXFHPtoq9eGP1ASTa9LC6FBh7sUY8cd4= -github.com/pion/webrtc/v3 v3.0.5 h1:utennp7RwX+2mtyMzoOXE03IUIckiHBigjarRJZ2DqY= -github.com/pion/webrtc/v3 v3.0.5/go.mod h1:/EDCREM8y+JrJSkoCRHpoz//qtuBCOYV4E96vEK3bz0= +github.com/pion/webrtc/v3 v3.0.8 h1:Dgu/NZ6QAIvoNZU3qk/B35iPPx6TVHP506FfCE4SXCA= +github.com/pion/webrtc/v3 v3.0.8/go.mod h1:C5uzSMa9sGCtfVPLA+pB0eWoW/exZ0OV0KW7JJbkvp0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -122,6 +115,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnk golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -144,6 +139,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= @@ -154,6 +150,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/main.go b/main.go index 4f3b505..2abce8e 100644 --- a/main.go +++ b/main.go @@ -88,62 +88,8 @@ func init() { type WebRTC struct { engine.Publisher *PeerConnection - RemoteAddr string - audioTrack *TrackLocalStaticSample - videoTrack *TrackLocalStaticSample } -func (rtc *WebRTC) Play(streamPath string) bool { - var sub engine.Subscriber - sub.ID = rtc.RemoteAddr - sub.Type = "WebRTC" - var lastTimeStampV, lastTiimeStampA uint32 - onVideo := func(pack engine.VideoPack) { - var s uint32 - if lastTimeStampV > 0 { - s = pack.Timestamp - lastTimeStampV - } - lastTimeStampV = pack.Timestamp - if pack.NalType == codec.NALU_IDR_Picture { - rtc.videoTrack.WriteSample(media.Sample{ - Data: sub.VideoTracks[0].SPS, - }) - rtc.videoTrack.WriteSample(media.Sample{ - Data: sub.VideoTracks[0].PPS, - }) - } - rtc.videoTrack.WriteSample(media.Sample{ - Data: pack.Payload, - Duration: time.Millisecond * time.Duration(s), - }) - } - onAudio := func(pack engine.AudioPack) { - var s uint32 - if lastTiimeStampA > 0 { - s = pack.Timestamp - lastTiimeStampA - } - lastTiimeStampA = pack.Timestamp - rtc.audioTrack.WriteSample(media.Sample{ - Data: pack.Payload, Duration: time.Millisecond * time.Duration(s), - }) - } - rtc.OnICEConnectionStateChange(func(connectionState ICEConnectionState) { - utils.Printf("%s Connection State has changed %s ", streamPath, connectionState.String()) - switch connectionState { - case ICEConnectionStateDisconnected, ICEConnectionStateFailed: - sub.Close() - rtc.PeerConnection.Close() - case ICEConnectionStateConnected: - if err := sub.Subscribe(streamPath); err == nil { - go sub.VideoTracks[0].Play(sub.Context, onVideo) - if rtc.audioTrack != nil { - go sub.AudioTracks[0].Play(sub.Context, onAudio) - } - } - } - }) - return true -} func (rtc *WebRTC) Publish(streamPath string) bool { // rtc.m.RegisterCodec(NewRTPCodec(RTPCodecTypeVideo, // H264, @@ -211,9 +157,10 @@ func (rtc *WebRTC) Publish(streamPath string) bool { }() var etrack engine.Track if track.Kind() == RTPCodecTypeAudio { - etrack = rtc.AudioTracks[0] + //TODO: 判断音频格式 + etrack = rtc.AudioTracks["pcma"] } else { - etrack = rtc.VideoTracks[0] + etrack = rtc.VideoTracks["h264"] } var pack rtp.Packet b := make([]byte, 1460) @@ -262,19 +209,15 @@ func run() { m.RegisterDefaultCodecs() api = NewAPI(WithMediaEngine(&m), WithSettingEngine(s)) http.HandleFunc("/webrtc/play", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Access-Control-Allow-Credentials", "true") - origin := r.Header["Origin"] - if len(origin) == 0 { - w.Header().Set("Access-Control-Allow-Origin", "*") - } else { - w.Header().Set("Access-Control-Allow-Origin", origin[0]) - } - + utils.CORS(w, r) w.Header().Set("Content-Type", "application/json") streamPath := r.URL.Query().Get("streamPath") var offer SessionDescription var rtc WebRTC - + sub := engine.Subscriber{ + ID: r.RemoteAddr, + Type: "WebRTC", + } bytes, err := ioutil.ReadAll(r.Body) defer func() { if err != nil { @@ -282,7 +225,6 @@ func run() { fmt.Fprintf(w, `{"errmsg":"%s"}`, err) return } - rtc.Play(streamPath) }() if err != nil { return @@ -291,13 +233,8 @@ func run() { return } - pli := "42001f" - if stream := engine.FindStream(streamPath); stream != nil { - <-stream.VideoTracks[0].WaitFirst - pli = fmt.Sprintf("%x", stream.VideoTracks[0].SPS[1:4]) - } - if !strings.Contains(offer.SDP, pli) { - pli = reg_level.FindAllStringSubmatch(offer.SDP, -1)[0][1] + if err = sub.Subscribe(streamPath); err != nil { + return } if rtc.PeerConnection, err = api.NewPeerConnection(Configuration{}); err != nil { @@ -308,18 +245,87 @@ func run() { utils.Println(ice.ToJSON().Candidate) } }) - rtc.RemoteAddr = r.RemoteAddr if err = rtc.SetRemoteDescription(offer); err != nil { return } - if rtc.videoTrack, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: "video/h264", SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=" + pli}, "video", "m7s"); err != nil { - return + vt := sub.GetVideoTrack("h264") + if vt != nil { + pli := "42001f" + pli = fmt.Sprintf("%x", vt.SPS[1:4]) + if !strings.Contains(offer.SDP, pli) { + pli = reg_level.FindAllStringSubmatch(offer.SDP, -1)[0][1] + } + var videoTrack *TrackLocalStaticSample + if videoTrack, err = NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeH264, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=" + pli}, "video", "m7s"); err != nil { + return + } + if _, err = rtc.AddTrack(videoTrack); err != nil { + return + } + var lastTimeStampV uint32 + sub.OnVideo = func(pack engine.VideoPack) { + var s uint32 + if lastTimeStampV > 0 { + s = pack.Timestamp - lastTimeStampV + } + lastTimeStampV = pack.Timestamp + if pack.NalType == codec.NALU_IDR_Picture { + videoTrack.WriteSample(media.Sample{ + Data: vt.SPS, + }) + videoTrack.WriteSample(media.Sample{ + Data: vt.PPS, + }) + } + videoTrack.WriteSample(media.Sample{ + Data: pack.Payload, + Duration: time.Millisecond * time.Duration(s), + }) + } } - if _, err = rtc.AddTrack(rtc.videoTrack); err != nil { - return + at := sub.GetAudioTrack("pcma", "pcmu") + if at != nil { + var audioTrack *TrackLocalStaticSample + audioMimeType := MimeTypePCMA + if at.SoundFormat == 8 { + audioMimeType = MimeTypePCMU + } + if audioTrack, err = NewTrackLocalStaticSample(RTPCodecCapability{audioMimeType, 8000, 0, "", nil}, "audio", "m7s"); err != nil { + return + } + if _, err = rtc.AddTrack(audioTrack); err != nil { + return + } + var lastTimeStampA uint32 + sub.OnAudio = func(pack engine.AudioPack) { + var s uint32 + if lastTimeStampA > 0 { + s = pack.Timestamp - lastTimeStampA + } + lastTimeStampA = pack.Timestamp + audioTrack.WriteSample(media.Sample{ + Data: pack.Payload, Duration: time.Millisecond * time.Duration(s), + }) + } } + if bytes, err := rtc.GetAnswer(); err == nil { w.Write(bytes) + rtc.OnICEConnectionStateChange(func(connectionState ICEConnectionState) { + utils.Printf("%s Connection State has changed %s ", streamPath, connectionState.String()) + switch connectionState { + case ICEConnectionStateDisconnected, ICEConnectionStateFailed: + sub.Close() + rtc.PeerConnection.Close() + case ICEConnectionStateConnected: + if at != nil { + go sub.PlayAudio(sub.Context, at) + } + if vt != nil { + go sub.PlayVideo(sub.Context, vt) + } + } + }) } else { return } @@ -335,7 +341,6 @@ func run() { return } rtc := new(WebRTC) - rtc.RemoteAddr = r.RemoteAddr if rtc.Publish(streamPath) { if err := rtc.SetRemoteDescription(offer); err != nil { utils.Println(err)