From 742b8fb01df17197de32082f2268b30abb2b3fb6 Mon Sep 17 00:00:00 2001 From: dexter <178529795@qq.com> Date: Tue, 22 Mar 2022 09:23:19 +0800 Subject: [PATCH] v4 first commit --- go.mod | 35 +++- go.sum | 132 +++++---------- io.go | 24 +++ main.go | 450 +++++++++++--------------------------------------- publisher.go | 78 +++++++++ subscriber.go | 85 ++++++++++ 6 files changed, 351 insertions(+), 453 deletions(-) create mode 100644 io.go create mode 100644 publisher.go create mode 100644 subscriber.go diff --git a/go.mod b/go.mod index 3dee6d8..a5c5926 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,31 @@ -module github.com/Monibuca/plugin-webrtc/v3 +module m7s.live/plugin/webrtc/v4 -go 1.13 +go 1.18 require ( - github.com/Monibuca/engine/v3 v3.4.5 - github.com/Monibuca/utils/v3 v3.0.5 - github.com/pion/interceptor v0.1.0 - github.com/pion/rtcp v1.2.8 - github.com/pion/rtp v1.7.4 - github.com/pion/webrtc/v3 v3.1.6 + github.com/pion/interceptor v0.1.10 + github.com/pion/rtcp v1.2.9 + github.com/pion/rtp v1.7.9 + github.com/pion/webrtc/v3 v3.1.25 +) + +require ( + github.com/google/uuid v1.3.0 // indirect + github.com/pion/datachannel v1.5.2 // indirect + github.com/pion/dtls/v2 v2.1.3 // indirect + github.com/pion/ice/v2 v2.2.2 // indirect + github.com/pion/logging v0.2.2 // indirect + github.com/pion/mdns v0.0.5 // indirect + github.com/pion/randutil v0.1.0 // indirect + github.com/pion/sctp v1.8.2 // indirect + github.com/pion/sdp/v3 v3.0.4 // indirect + github.com/pion/srtp/v2 v2.0.5 // indirect + github.com/pion/stun v0.3.5 // indirect + github.com/pion/transport v0.13.0 // indirect + github.com/pion/turn/v2 v2.0.8 // indirect + github.com/pion/udp v0.1.1 // indirect + golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 // indirect + golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect + golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/go.sum b/go.sum index b926bf8..01d69ba 100644 --- a/go.sum +++ b/go.sum @@ -1,28 +1,8 @@ -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= -github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/Monibuca/engine/v3 v3.4.5 h1:gPRsliBVC70EhKK7sJz/3LoNO7lfnXNC8uUaOIHZkUE= -github.com/Monibuca/engine/v3 v3.4.5/go.mod h1:Dik9pFxU9TFI5vj8Sv5QXZM+ooCs2fm9P7Uhe4yYNkQ= -github.com/Monibuca/utils/v3 v3.0.5 h1:w14x0HkWTbF4MmHbINLlOwe4VJNoSOeaQChMk5E/4es= -github.com/Monibuca/utils/v3 v3.0.5/go.mod h1:RpNS95gapWs6gimwh8Xn2x72FN5tO7Powabj7dTFyvE= -github.com/cnotch/apirouter v0.0.0-20200731232942-89e243a791f3/go.mod h1:5deJPLON/x/s2dLOQfuKS0lenhOIT4xX0pvtN/OEIuY= -github.com/cnotch/ipchub v1.1.0 h1:hH0lh2mU3AZXPiqMwA0pdtqrwo7PFIMRGush9OobMUs= -github.com/cnotch/ipchub v1.1.0/go.mod h1:2PbeBs2q2VxxTVCn1eYCDwpAWuVXbq1+N0FU7GimOH4= -github.com/cnotch/loader v0.0.0-20200405015128-d9d964d09439/go.mod h1:oWpDagHB6p+Kqqq7RoRZKyC4XAXft50hR8pbTxdbYYs= -github.com/cnotch/queue v0.0.0-20200326024423-6e88bdbf2ad4/go.mod h1:zOssjAlNusOxvtaqT+EMA+Iyi8rrtKr4/XfzN1Fgoeg= -github.com/cnotch/queue v0.0.0-20201224060551-4191569ce8f6/go.mod h1:zOssjAlNusOxvtaqT+EMA+Iyi8rrtKr4/XfzN1Fgoeg= -github.com/cnotch/scheduler v0.0.0-20200522024700-1d2da93eefc5/go.mod h1:F4GE3SZkJZ8an1Y0ZCqvSM3jeozNuKzoC67erG1PhIo= -github.com/cnotch/xlog v0.0.0-20201208005456-cfda439cd3a0/go.mod h1:RW9oHsR79ffl3sR3yMGgxYupMn2btzdtJUwoxFPUE5E= 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= -github.com/emitter-io/address v1.0.0/go.mod h1:GfZb5+S/o8694B1GMGK2imUYQyn2skszMvGNA5D84Ug= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/funny/slab v0.0.0-20180511031532-b1fad5e5d478 h1:Db9StoJ6RZN3YttC0Pm0I4Y5izITRYch3RMbT59BYN0= -github.com/funny/slab v0.0.0-20180511031532-b1fad5e5d478/go.mod h1:0j1+svBH8ABEIPdUP0AIg4qedsybnXGJBakCEw8cfoo= -github.com/funny/utest v0.0.0-20161029064919-43870a374500 h1:Z0r1CZnoIWFB/Uiwh1BU5FYmuFe6L5NPi6XWQEmsTRg= -github.com/funny/utest v0.0.0-20161029064919-43870a374500/go.mod h1:mUn39tBov9jKnTWV1RlOYoNzxdBFHiSzXWdY1FoNGGg= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= @@ -31,47 +11,35 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/kelindar/process v0.0.0-20170730150328-69a29e249ec3/go.mod h1:+lTCLnZFXOkqwD8sLPl6u4erAc0cP8wFegQHfipz7KE= -github.com/kelindar/rate v1.0.0/go.mod h1:AjT4G+hTItNwt30lucEGZIz8y7Uk5zPho6vurIZ+1Es= -github.com/kelindar/tcp v1.0.0/go.mod h1:JB5hj1cshLU60XrLij2BBxW3JQ4hOye8vqbyvuKb52k= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= -github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.1/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= -github.com/pion/datachannel v1.4.21 h1:3ZvhNyfmxsAqltQrApLPQMhSFNA+aT87RqyCq4OXmf0= -github.com/pion/datachannel v1.4.21/go.mod h1:oiNyP4gHx2DIwRzX/MFyH0Rz/Gz05OgBlayAI2hAWjg= -github.com/pion/dtls/v2 v2.0.9/go.mod h1:O0Wr7si/Zj5/EBFlDzDd6UtVxx25CE1r7XM7BQKYQho= -github.com/pion/dtls/v2 v2.0.10 h1:wgys7gPR1NMbWjmjJ3CW7lkUGaun8djgH8nahpNLnxI= -github.com/pion/dtls/v2 v2.0.10/go.mod h1:00OxfeCRWHShcqT9jx8pKKmBWuTt0NCZoVPCaC4VKvU= -github.com/pion/ice/v2 v2.1.13 h1:/YNYcIw56LT/whwuzkTnrprcRnapj2ZNqUsR0W8elmo= -github.com/pion/ice/v2 v2.1.13/go.mod h1:ovgYHUmwYLlRvcCLI67PnQ5YGe+upXZbGgllBDG/ktU= -github.com/pion/interceptor v0.1.0 h1:SlXKaDlEvSl7cr4j8fJykzVz4UdH+7UDtcvx+u01wLU= -github.com/pion/interceptor v0.1.0/go.mod h1:j5NIl3tJJPB3u8+Z2Xz8MZs/VV6rc+If9mXEKNuFmEM= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/pion/datachannel v1.5.2 h1:piB93s8LGmbECrpO84DnkIVWasRMk3IimbcXkTQLE6E= +github.com/pion/datachannel v1.5.2/go.mod h1:FTGQWaHrdCwIJ1rw6xBIfZVkslikjShim5yr05XFuCQ= +github.com/pion/dtls/v2 v2.1.3 h1:3UF7udADqous+M2R5Uo2q/YaP4EzUoWKdfX2oscCUio= +github.com/pion/dtls/v2 v2.1.3/go.mod h1:o6+WvyLDAlXF7YiPB/RlskRoeK+/JtuaZa5emwQcWus= +github.com/pion/ice/v2 v2.2.2 h1:UfmAslxZ0u0itVjA4x7aw7WeQIv22FdF8VjW9cM+74g= +github.com/pion/ice/v2 v2.2.2/go.mod h1:vLI7dFqxw8zMSb9J+ca74XU7JjLhddgfQB9+BbTydCo= +github.com/pion/interceptor v0.1.10 h1:DJ2GjMGm4XGIQgMJxuEpdaExdY/6RdngT7Uh4oVmquU= +github.com/pion/interceptor v0.1.10/go.mod h1:Lh3JSl/cbJ2wP8I3ccrjh1K/deRGRn3UlSPuOTiHb6U= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw= @@ -79,41 +47,35 @@ github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01 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/rtcp v1.2.6/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0= -github.com/pion/rtcp v1.2.8 h1:Cys8X6r0xxU65ESTmXkqr8eU1Q1Wx+lNkoZCUH4zD7E= -github.com/pion/rtcp v1.2.8/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= -github.com/pion/rtp v1.6.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= +github.com/pion/rtcp v1.2.9 h1:1ujStwg++IOLIEoOiIQ2s+qBuJ1VN81KW+9pMPsif+U= +github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= github.com/pion/rtp v1.7.0/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/rtp v1.7.2/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/rtp v1.7.4 h1:4dMbjb1SuynU5OpA3kz1zHK+u+eOCQjW3MAeVHf1ODA= github.com/pion/rtp v1.7.4/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/sctp v1.7.10/go.mod h1:EhpTUQu1/lcK3xI+eriS6/96fWetHGCvBi9MSsnaBN0= -github.com/pion/sctp v1.7.12 h1:GsatLufywVruXbZZT1CKg+Jr8ZTkwiPnmUC/oO9+uuY= -github.com/pion/sctp v1.7.12/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s= +github.com/pion/rtp v1.7.7/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= +github.com/pion/rtp v1.7.9 h1:17W5Mt2IM3MVfOh7yRfzXbbKXYzBZxV8eG4KKAy+0bg= +github.com/pion/rtp v1.7.9/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= +github.com/pion/sctp v1.8.0/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s= +github.com/pion/sctp v1.8.2 h1:yBBCIrUMJ4yFICL3RIvR4eh/H2BTTvlligmSTy+3kiA= +github.com/pion/sctp v1.8.2/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s= github.com/pion/sdp/v3 v3.0.4 h1:2Kf+dgrzJflNCSw3TV5v2VLeI0s/qkzy2r5jlR0wzf8= github.com/pion/sdp/v3 v3.0.4/go.mod h1:bNiSknmJE0HYBprTHXKPQ3+JjacTv5uap92ueJZKsRk= github.com/pion/srtp/v2 v2.0.5 h1:ks3wcTvIUE/GHndO3FAvROQ9opy0uLELpwHJaQ1yqhQ= github.com/pion/srtp/v2 v2.0.5/go.mod h1:8k6AJlal740mrZ6WYxc4Dg6qDqqhxoRG2GSjlUhDF0A= github.com/pion/stun v0.3.5 h1:uLUCBCkQby4S1cf6CGuR9QrVOKcvUwFeemaC865QHDg= github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA= -github.com/pion/transport v0.10.1/go.mod h1:PBis1stIILMiis0PewDw91WJeLJkyIMcEk+DwKOzf4A= github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= -github.com/pion/transport v0.12.3 h1:vdBfvfU/0Wq8kd2yhUMSDB/x+O4Z9MYVl2fJ5BT4JZw= github.com/pion/transport v0.12.3/go.mod h1:OViWW9SP2peE/HbwBvARicmAVnesphkNkCVZIWJ6q9A= -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/transport v0.13.0 h1:KWTA5ZrQogizzYwPEciGtHPLwpAjE91FgXnyu+Hv2uY= +github.com/pion/transport v0.13.0/go.mod h1:yxm9uXpK9bpBBWkITk13cLo1y5/ur5VQpG22ny6EP7g= +github.com/pion/turn/v2 v2.0.8 h1:KEstL92OUN3k5k8qxsXHpr7WWfrdp7iJZHx99ud8muw= +github.com/pion/turn/v2 v2.0.8/go.mod h1:+y7xl719J8bAEVpSXBXvTxStjJv3hbz9YFflvkpcGPw= github.com/pion/udp v0.1.1 h1:8UAPvyqmsxK8oOjloDk4wUt63TzFe9WEJkg5lChlj7o= github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= -github.com/pion/webrtc/v3 v3.1.6 h1:r6WQRayW2SyKTYeRl4vBUQ43XXp7RSwBJ9+tNQWI5zQ= -github.com/pion/webrtc/v3 v3.1.6/go.mod h1:tkwdWNYdZhc200hH/wPx6AtNo/rcTAM6MICA6dg1je8= -github.com/pixelbender/go-sdp v1.1.0/go.mod h1:6IBlz9+BrUHoFTea7gcp4S54khtOhjCW/nVDLhmZBAs= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pion/webrtc/v3 v3.1.25 h1:8bTa2lLI5rszkKCKVO6L9VlKhhmmwMXZ/beSWLwQK14= +github.com/pion/webrtc/v3 v3.1.25/go.mod h1:BA9hvF1mCu64w/to7nHrSNMxx+zMqVst990zA7xgfCM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/q191201771/naza v0.19.1 h1:4KLcxT2CHztO+7miPRtBG3FFgadSQYQw1gPPPKN7rnY= -github.com/q191201771/naza v0.19.1/go.mod h1:5LeGupZZFtYP1g/S203n9vXoUNVdlRnPIfM6rExjqt0= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518/go.mod h1:CKI4AZ4XmGV240rTHfO0hfE83S6/a3/Q1siZJ/vXf7A= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -123,54 +85,45 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 h1:71vQrMauZZhcTVK6KdYM+rklehEEwb3E+ZhaE5jrPrE= +golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211005001312-d4b1ae081e3b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI= -golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -185,13 +138,12 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/io.go b/io.go new file mode 100644 index 0000000..63c7137 --- /dev/null +++ b/io.go @@ -0,0 +1,24 @@ +package webrtc + +import ( + . "github.com/pion/webrtc/v3" +) + +type WebRTCIO struct { + *PeerConnection + SDP string +} + +func (IO *WebRTCIO) GetAnswer() (string, error) { + // Sets the LocalDescription, and starts our UDP listeners + answer, err := IO.CreateAnswer(nil) + if err != nil { + return "", err + } + gatherComplete := GatheringCompletePromise(IO.PeerConnection) + if err := IO.SetLocalDescription(answer); err != nil { + return "", err + } + <-gatherComplete + return IO.LocalDescription().SDP, nil +} diff --git a/main.go b/main.go index 6e0f65c..6b98ace 100644 --- a/main.go +++ b/main.go @@ -1,37 +1,19 @@ package webrtc import ( - "encoding/json" - "fmt" "io/ioutil" "net/http" "regexp" - "strings" - "sync" "time" - "unsafe" "github.com/pion/interceptor" - "github.com/pion/rtp" - "github.com/pion/rtp/codecs" - "github.com/Monibuca/engine/v3" - "github.com/Monibuca/plugin-webrtc/v3/webrtc" - - "github.com/Monibuca/utils/v3" - "github.com/pion/rtcp" . "github.com/pion/webrtc/v3" - "github.com/pion/webrtc/v3/pkg/media" + "m7s.live/engine/v4" + "m7s.live/engine/v4/config" + "m7s.live/plugin/webrtc/v4/webrtc" ) -var config = struct { - ICEServers []string - PublicIP []string - PortMin uint16 - PortMax uint16 - PLI time.Duration -}{nil, nil, 0, 0, 2000} - // }{[]string{ // "stun:stun.ekiga.net", // "stun:stun.ideasip.com", @@ -59,359 +41,117 @@ var config = struct { // port int // } var ( - playWaitList WaitList - reg_level = regexp.MustCompile("profile-level-id=(4.+f)") - api *API + reg_level = regexp.MustCompile("profile-level-id=(4.+f)") + api *API ) -type WaitList struct { - m map[string]*WebRTC - l sync.Mutex +type WebRTCConfig struct { + config.Publish + config.Subscribe + ICEServers []string + PublicIP []string + PortMin uint16 + PortMax uint16 + PLI time.Duration + m MediaEngine + s SettingEngine + api *API } -func (wl *WaitList) Set(k string, v *WebRTC) { - wl.l.Lock() - defer wl.l.Unlock() - if wl.m == nil { - wl.m = make(map[string]*WebRTC) - } - wl.m[k] = v -} -func (wl *WaitList) Get(k string) *WebRTC { - wl.l.Lock() - defer wl.l.Unlock() - defer delete(wl.m, k) - return wl.m[k] -} -func init() { - pc := engine.PluginConfig{ - Config: &config, - Name: "WebRTC", +func (conf *WebRTCConfig) OnEvent(event any) { + switch event.(type) { + case engine.FirstConfig: + webrtc.RegisterCodecs(&conf.m) + i := &interceptor.Registry{} + if len(conf.PublicIP) > 0 { + conf.s.SetNAT1To1IPs(conf.PublicIP, ICECandidateTypeHost) + } + if conf.PortMin > 0 && conf.PortMax > 0 { + conf.s.SetEphemeralUDPPortRange(conf.PortMin, conf.PortMax) + } + if len(conf.PublicIP) > 0 { + conf.s.SetNAT1To1IPs(conf.PublicIP, ICECandidateTypeHost) + } + conf.s.SetNetworkTypes([]NetworkType{NetworkTypeUDP4, NetworkTypeUDP6}) + if err := RegisterDefaultInterceptors(&conf.m, i); err != nil { + panic(err) + } + conf.api = NewAPI(WithMediaEngine(&conf.m), + WithInterceptorRegistry(i), WithSettingEngine(conf.s)) } - pc.Install(run) } -type WebRTC struct { - *PeerConnection -} - -func (rtc *WebRTC) Publish(streamPath string) bool { - if _, err := rtc.AddTransceiverFromKind(RTPCodecTypeVideo); err != nil { - if err != nil { - utils.Println("AddTransceiverFromKind video", err) - return false - } +func (conf *WebRTCConfig) API_play(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/sdp") + streamPath := r.URL.Query().Get("streamPath") + bytes, err := ioutil.ReadAll(r.Body) + var suber WebRTCSubscriber + suber.SDP = string(bytes) + if suber.PeerConnection, err = api.NewPeerConnection(Configuration{}); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return } - if _, err := rtc.AddTransceiverFromKind(RTPCodecTypeAudio); err != nil { - if err != nil { - utils.Println("AddTransceiverFromKind audio", err) - return false + suber.OnICECandidate(func(ice *ICECandidate) { + if ice != nil { + suber.Info(ice.ToJSON().Candidate) } + }) + if err = suber.SetRemoteDescription(SessionDescription{SDP: suber.SDP}); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return } - stream := &engine.Stream{ - Type: "WebRTC", - StreamPath: streamPath, + if err = plugin.Subscribe(streamPath, &suber); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return } - if stream.Publish() { - rtc.OnICEConnectionStateChange(func(connectionState ICEConnectionState) { - utils.Printf("%s Connection State has changed %s ", streamPath, connectionState.String()) - switch connectionState { - case ICEConnectionStateDisconnected, ICEConnectionStateFailed: - stream.Close() - } - }) - //f, _ := os.OpenFile("resource/live/rtc.h264", os.O_TRUNC|os.O_WRONLY, 0666) - rtc.OnTrack(func(track *TrackRemote, receiver *RTPReceiver) { - if codec := track.Codec(); track.Kind() == RTPCodecTypeAudio { - var at *engine.RTPAudio - switch codec.PayloadType { - case 8: - at = stream.NewRTPAudio(7) - at.SoundRate = 8000 - at.SoundSize = 16 - at.Channels = 1 - at.ExtraData = []byte{(at.CodecID << 4) | (1 << 1)} - case 0: - at = stream.NewRTPAudio(8) - at.SoundRate = 8000 - at.SoundSize = 16 - at.Channels = 1 - at.ExtraData = []byte{(at.CodecID << 4) | (1 << 1)} - default: - return - } - for { - b := make([]byte, 1460) - if i, _, err := track.Read(b); err == nil { - at.Push(b[:i]) - } else { - return - } - } - } else { - go func() { - ticker := time.NewTicker(time.Millisecond * config.PLI) - for { - select { - case <-ticker.C: - if rtcpErr := rtc.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}); rtcpErr != nil { - fmt.Println(rtcpErr) - } - case <-stream.Done(): - return - } - } - }() - vt := stream.NewRTPVideo(7) - for { - b := make([]byte, 1460) - if i, _, err := track.Read(b); err == nil { - vt.Push(b[:i]) - } else { - return - } - } - } - - }) + if sdp, err := suber.GetAnswer(); err == nil { + w.Write([]byte(sdp)) } else { - return false + http.Error(w, err.Error(), http.StatusBadRequest) } - return true } -func (rtc *WebRTC) GetAnswer() ([]byte, error) { - // Sets the LocalDescription, and starts our UDP listeners - answer, err := rtc.CreateAnswer(nil) - if err != nil { - return nil, err - } - gatherComplete := GatheringCompletePromise(rtc.PeerConnection) - if err := rtc.SetLocalDescription(answer); err != nil { - return nil, err + +func (conf *WebRTCConfig) API_publish(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/sdp") + streamPath := r.URL.Query().Get("streamPath") + bytes, err := ioutil.ReadAll(r.Body) + var puber WebRTCPublisher + puber.SDP = string(bytes) + if puber.PeerConnection, err = api.NewPeerConnection(Configuration{}); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return } - <-gatherComplete - if bytes, err := json.Marshal(rtc.LocalDescription()); err != nil { - utils.Println(err) - return bytes, err - } else { - return bytes, nil + puber.OnICECandidate(func(ice *ICECandidate) { + if ice != nil { + puber.Info(ice.ToJSON().Candidate) + } + }) + if _, err = puber.AddTransceiverFromKind(RTPCodecTypeVideo); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return } -} - -func run() { - var m MediaEngine - var s SettingEngine - //m.RegisterDefaultCodecs() - webrtc.RegisterCodecs(&m) - - i := &interceptor.Registry{} - if len(config.PublicIP) > 0 { - s.SetNAT1To1IPs(config.PublicIP, ICECandidateTypeHost) + if _, err = puber.AddTransceiverFromKind(RTPCodecTypeAudio); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return } - if config.PortMin > 0 && config.PortMax > 0 { - s.SetEphemeralUDPPortRange(config.PortMin, config.PortMax) + if err = plugin.Publish(streamPath, &puber); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return } - if len(config.PublicIP) > 0 { - s.SetNAT1To1IPs(config.PublicIP, ICECandidateTypeHost) + if err := puber.SetRemoteDescription(SessionDescription{SDP: puber.SDP}); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return } - s.SetNetworkTypes([]NetworkType{NetworkTypeUDP4, NetworkTypeUDP6}) - if err := RegisterDefaultInterceptors(&m, i); err != nil { - panic(err) + if answer, err := puber.GetAnswer(); err == nil { + w.Write([]byte(answer)) + } else { + http.Error(w, err.Error(), http.StatusBadRequest) + return } - api := NewAPI(WithMediaEngine(&m), - WithInterceptorRegistry(i), WithSettingEngine(s)) - http.HandleFunc("/api/webrtc/play", func(w http.ResponseWriter, r *http.Request) { - 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 { - utils.Println(err) - fmt.Fprintf(w, `{"errmsg":"%s"}`, err) - return - } - }() - if err != nil { - return - } - if err = json.Unmarshal(bytes, &offer); err != nil { - return - } - - if err = sub.Subscribe(streamPath); err != nil { - return - } - - if rtc.PeerConnection, err = api.NewPeerConnection(Configuration{}); err != nil { - return - } - rtc.OnICECandidate(func(ice *ICECandidate) { - if ice != nil { - utils.Println(ice.ToJSON().Candidate) - } - }) - if err = rtc.SetRemoteDescription(offer); err != nil { - return - } - vt := sub.WaitVideoTrack("h264") - at := sub.WaitAudioTrack("pcma", "pcmu") - var videoTrack *TrackLocalStaticRTP - var rtpSender *RTPSender - if vt != nil { - pli := "42001f" - pli = fmt.Sprintf("%x", vt.ExtraData.NALUs[0][1:4]) - if !strings.Contains(offer.SDP, pli) { - pli = reg_level.FindAllStringSubmatch(offer.SDP, -1)[0][1] - } - if videoTrack, err = NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeH264, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=" + pli}, "video", "m7s"); err != nil { - return - } - - rtpSender, err = rtc.AddTrack(videoTrack) - if err != nil { - return - } - var lastTimeStampV uint32 - - var vpacketer rtp.Packetizer - ssrc := uintptr(unsafe.Pointer(&sub)) - vpacketer = rtp.NewPacketizer(1200, 96, uint32(ssrc), &codecs.H264Payloader{}, rtp.NewFixedSequencer(1), 90000) - - sub.OnVideo = func(ts uint32, pack *engine.VideoPack) { - var s uint32 = 40 - if lastTimeStampV > 0 { - s = ts - lastTimeStampV - } - lastTimeStampV = ts - if pack.IDR { - for _, nalu := range vt.ExtraData.NALUs { - for _, packet := range vpacketer.Packetize(nalu, 0) { - err = videoTrack.WriteRTP(packet) - } - } - } - for naluIndex, nalu := range pack.NALUs { - var packets []*rtp.Packet - if naluIndex == len(pack.NALUs)-1 { - packets = vpacketer.Packetize(nalu, s) - } else { - packets = vpacketer.Packetize(nalu, 0) - } - for packIndex, packet := range packets { - packet.Marker = naluIndex == len(pack.NALUs)-1 && packIndex == len(packets)-1 - err = videoTrack.WriteRTP(packet) - } - } - } - go func() { - rtcpBuf := make([]byte, 1500) - for { - if n, _, rtcpErr := rtpSender.Read(rtcpBuf); rtcpErr != nil { - - return - } else { - if p, err := rtcp.Unmarshal(rtcpBuf[:n]); err == nil { - for _, pp := range p { - switch pp.(type) { - case *rtcp.PictureLossIndication: - - fmt.Println("PictureLossIndication") - } - } - } - } - } - }() - } - if at == nil { - engine.TriggerHook(engine.HOOK_REQUEST_TRANSAUDIO, &engine.TransCodeReq{ - Subscriber: &sub, - RequestCodec: "pcma", - }) - at = sub.WaitAudioTrack("pcma") - } - if at != nil { - var audioTrack *TrackLocalStaticSample - audioMimeType := MimeTypePCMA - if at.CodecID == 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(ts uint32, pack *engine.AudioPack) { - var s uint32 - if lastTimeStampA > 0 { - s = ts - lastTimeStampA - } - lastTimeStampA = ts - audioTrack.WriteSample(media.Sample{ - Data: pack.Raw, Duration: time.Millisecond * time.Duration(s), - }) - } - } - if bytes, err := rtc.GetAnswer(); err == nil { - w.Write(bytes) - rtc.OnConnectionStateChange(func(pcs PeerConnectionState) { - utils.Printf("%s Connection State has changed %s ", streamPath, pcs.String()) - switch pcs { - case PeerConnectionStateConnected: - if at != nil { - go sub.PlayAudio(at) - } - if vt != nil { - go sub.PlayVideo(vt) - } - case PeerConnectionStateDisconnected, PeerConnectionStateFailed: - sub.Close() - rtc.PeerConnection.Close() - } - }) - - } else { - return - } - }) +} - http.HandleFunc("/api/webrtc/publish", func(w http.ResponseWriter, r *http.Request) { - utils.CORS(w, r) - streamPath := r.URL.Query().Get("streamPath") - offer := SessionDescription{} - bytes, err := ioutil.ReadAll(r.Body) - err = json.Unmarshal(bytes, &offer) - if err != nil { - utils.Println(err) - return - } - rtc := new(WebRTC) - if rtc.PeerConnection, err = api.NewPeerConnection(Configuration{}); err != nil { - return - } - if rtc.Publish(streamPath) { - if err := rtc.SetRemoteDescription(offer); err != nil { - utils.Println(err) - return - } - if bytes, err = rtc.GetAnswer(); err == nil { - w.Write(bytes) - } else { - utils.Println("GetAnswer:", err) - w.Write([]byte(err.Error())) - return - } - } else { - w.Write([]byte("bad name")) - } - }) +var webrtcConfig = &WebRTCConfig{ + PLI: time.Second * 2, } + +var plugin = engine.InstallPlugin(webrtcConfig) diff --git a/publisher.go b/publisher.go new file mode 100644 index 0000000..d8ea90b --- /dev/null +++ b/publisher.go @@ -0,0 +1,78 @@ +package webrtc + +import ( + "fmt" + "time" + + "github.com/pion/rtcp" + . "github.com/pion/webrtc/v3" + . "m7s.live/engine/v4" + . "m7s.live/engine/v4/track" +) + +type WebRTCPublisher struct { + Publisher + WebRTCIO +} + +func (puber *WebRTCPublisher) OnEvent(event any) { + switch v := event.(type) { + case IPublisher: + puber.OnICEConnectionStateChange(func(connectionState ICEConnectionState) { + puber.Info("Connection State has changed:" + connectionState.String()) + switch connectionState { + case ICEConnectionStateDisconnected, ICEConnectionStateFailed: + puber.Stop() + } + }) + puber.OnTrack(func(track *TrackRemote, receiver *RTPReceiver) { + if codec := track.Codec(); track.Kind() == RTPCodecTypeAudio { + if puber.Equal(v) || puber.AudioTrack == nil { + switch codec.PayloadType { + case 8: + puber.AudioTrack = NewG711(puber.Stream, true) + case 0: + puber.AudioTrack = NewG711(puber.Stream, false) + default: + puber.AudioTrack = nil + return + } + } + for { + b := make([]byte, 1460) + if i, _, err := track.Read(b); err == nil { + puber.AudioTrack.WriteRTP(b[:i]) + } else { + return + } + } + } else { + go func() { + ticker := time.NewTicker(time.Millisecond * webrtcConfig.PLI) + for { + select { + case <-ticker.C: + if rtcpErr := puber.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}); rtcpErr != nil { + fmt.Println(rtcpErr) + } + case <-puber.Done(): + return + } + } + }() + if puber.Equal(v) { + puber.VideoTrack = NewH264(puber.Stream) + } + for { + b := make([]byte, 1460) + if i, _, err := track.Read(b); err == nil { + puber.VideoTrack.WriteRTP(b[:i]) + } else { + return + } + } + } + }) + } + puber.Publisher.OnEvent(event) +} diff --git a/subscriber.go b/subscriber.go new file mode 100644 index 0000000..77ed820 --- /dev/null +++ b/subscriber.go @@ -0,0 +1,85 @@ +package webrtc + +import ( + "fmt" + "strings" + + "github.com/pion/rtcp" + . "github.com/pion/webrtc/v3" + . "m7s.live/engine/v4" + "m7s.live/engine/v4/codec" + "m7s.live/engine/v4/track" +) + +type WebRTCSubscriber struct { + Subscriber + WebRTCIO + videoTrack *TrackLocalStaticRTP + audioTrack *TrackLocalStaticRTP +} + +func (suber *WebRTCSubscriber) OnEvent(event any) { + switch v := event.(type) { + case *track.Video: + if v.CodecID == codec.CodecID_H264 { + pli := "42001f" + pli = fmt.Sprintf("%x", v.GetDecoderConfiguration().Raw[0][1:4]) + if !strings.Contains(suber.SDP, pli) { + pli = reg_level.FindAllStringSubmatch(suber.SDP, -1)[0][1] + } + suber.videoTrack, _ = NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: MimeTypeH264, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=" + pli}, "video", "m7s") + rtpSender, _ := suber.PeerConnection.AddTrack(suber.videoTrack) + go func() { + rtcpBuf := make([]byte, 1500) + for { + if n, _, rtcpErr := rtpSender.Read(rtcpBuf); rtcpErr != nil { + + return + } else { + if p, err := rtcp.Unmarshal(rtcpBuf[:n]); err == nil { + for _, pp := range p { + switch pp.(type) { + case *rtcp.PictureLossIndication: + + fmt.Println("PictureLossIndication") + } + } + } + } + } + }() + suber.Subscriber.AddTrack(v) //接受这个track + } + case *track.Audio: + audioMimeType := MimeTypePCMA + if v.CodecID == codec.CodecID_PCMU { + audioMimeType = MimeTypePCMU + } + if v.CodecID == codec.CodecID_PCMA || v.CodecID == codec.CodecID_PCMU { + suber.audioTrack, _ = NewTrackLocalStaticRTP(RTPCodecCapability{MimeType: audioMimeType}, "audio", "m7s") + suber.PeerConnection.AddTrack(suber.audioTrack) + suber.Subscriber.AddTrack(v) //接受这个track + } + case *VideoFrame: + for _, p := range v.RTP { + suber.videoTrack.Write(p.Raw) + } + case *AudioFrame: + for _, p := range v.RTP { + suber.audioTrack.Write(p.Raw) + } + case ISubscriber: + suber.OnConnectionStateChange(func(pcs PeerConnectionState) { + suber.Info("Connection State has changed:" + pcs.String()) + switch pcs { + case PeerConnectionStateConnected: + go suber.PlayBlock(suber) + case PeerConnectionStateDisconnected, PeerConnectionStateFailed: + suber.Stop() + suber.PeerConnection.Close() + } + }) + default: + suber.Subscriber.OnEvent(event) + } +}