Merge branch 'AlexxIT:master' into onvif-client

This commit is contained in:
seydx
2025-04-09 17:10:07 +02:00
committed by GitHub
41 changed files with 1035 additions and 599 deletions

27
go.mod
View File

@@ -4,20 +4,20 @@ go 1.20
require ( require (
github.com/asticode/go-astits v1.13.0 github.com/asticode/go-astits v1.13.0
github.com/expr-lang/expr v1.16.9 github.com/expr-lang/expr v1.17.2
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3 github.com/gorilla/websocket v1.5.3
github.com/mattn/go-isatty v0.0.20 github.com/mattn/go-isatty v0.0.20
github.com/miekg/dns v1.1.63 github.com/miekg/dns v1.1.63
github.com/pion/ice/v2 v2.3.37 github.com/pion/ice/v4 v4.0.9
github.com/pion/interceptor v0.1.37 github.com/pion/interceptor v0.1.37
github.com/pion/rtcp v1.2.15 github.com/pion/rtcp v1.2.15
github.com/pion/rtp v1.8.11 github.com/pion/rtp v1.8.13
github.com/pion/sdp/v3 v3.0.10 github.com/pion/sdp/v3 v3.0.11
github.com/pion/srtp/v2 v2.0.20 github.com/pion/srtp/v3 v3.0.4
github.com/pion/stun v0.6.1 github.com/pion/stun/v3 v3.0.0
github.com/pion/webrtc/v3 v3.3.5 github.com/pion/webrtc/v4 v4.0.14
github.com/rs/zerolog v1.33.0 github.com/rs/zerolog v1.34.0
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1 github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1
github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
@@ -27,19 +27,18 @@ require (
) )
require ( require (
github.com/asticode/go-astikit v0.52.0 // indirect github.com/asticode/go-astikit v0.54.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/kr/pretty v0.3.1 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/pion/datachannel v1.5.10 // indirect github.com/pion/datachannel v1.5.10 // indirect
github.com/pion/dtls/v2 v2.2.12 // indirect github.com/pion/dtls/v3 v3.0.6 // indirect
github.com/pion/logging v0.2.3 // indirect github.com/pion/logging v0.2.3 // indirect
github.com/pion/mdns v0.0.12 // indirect github.com/pion/mdns/v2 v2.0.7 // indirect
github.com/pion/randutil v0.1.0 // indirect github.com/pion/randutil v0.1.0 // indirect
github.com/pion/sctp v1.8.36 // indirect github.com/pion/sctp v1.8.37 // indirect
github.com/pion/transport/v2 v2.2.10 // indirect
github.com/pion/transport/v3 v3.0.7 // indirect github.com/pion/transport/v3 v3.0.7 // indirect
github.com/pion/turn/v2 v2.1.6 // indirect github.com/pion/turn/v4 v4.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/wlynxg/anet v0.0.5 // indirect github.com/wlynxg/anet v0.0.5 // indirect
golang.org/x/mod v0.20.0 // indirect golang.org/x/mod v0.20.0 // indirect

127
go.sum
View File

@@ -1,6 +1,6 @@
github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0= github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0=
github.com/asticode/go-astikit v0.52.0 h1:kTl2XjgiVQhUl1H7kim7NhmTtCMwVBbPrXKqhQhbk8Y= github.com/asticode/go-astikit v0.54.0 h1:uq9eurgisdkYwJU9vSWIQaPH4MH0cac82sQH00kmSNQ=
github.com/asticode/go-astikit v0.52.0/go.mod h1:fV43j20UZYfXzP9oBn33udkvCvDvCDhzjVqoLFuuYZE= github.com/asticode/go-astikit v0.54.0/go.mod h1:fV43j20UZYfXzP9oBn33udkvCvDvCDhzjVqoLFuuYZE=
github.com/asticode/go-astits v1.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwfKZ1c= github.com/asticode/go-astits v1.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwfKZ1c=
github.com/asticode/go-astits v1.13.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI= github.com/asticode/go-astits v1.13.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
@@ -8,19 +8,15 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI= github.com/expr-lang/expr v1.17.2 h1:o0A99O/Px+/DTjEnQiodAgOIK9PPxL8DtXhBRKC+Iso=
github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= github.com/expr-lang/expr v1.17.2/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
@@ -34,47 +30,36 @@ github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= github.com/pion/dtls/v3 v3.0.6 h1:7Hkd8WhAJNbRgq9RgdNh1aaWlZlGpYTzdqjy9x9sK2E=
github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= github.com/pion/dtls/v3 v3.0.6/go.mod h1:iJxNQ3Uhn1NZWOMWlLxEEHAN5yX7GyPvvKw04v9bzYU=
github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= github.com/pion/ice/v4 v4.0.9 h1:VKgU4MwA2LUDVLq+WBkpEHTcAb8c5iCvFMECeuPOZNk=
github.com/pion/ice/v2 v2.3.37 h1:ObIdaNDu1rCo7hObhs34YSBcO7fjslJMZV0ux+uZWh0= github.com/pion/ice/v4 v4.0.9/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
github.com/pion/ice/v2 v2.3.37/go.mod h1:mBF7lnigdqgtB+YHkaY/Y6s6tsyRyo4u4rPGRuOjUBQ=
github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI= github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y= github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI= github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90= github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8= github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
github.com/pion/mdns v0.0.12/go.mod h1:VExJjv8to/6Wqm1FXK+Ii/Z9tsVk/F5sD/N70cnYFbk= github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= 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/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo= github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= github.com/pion/rtp v1.8.13 h1:8uSUPpjSL4OlwZI8Ygqu7+h2p9NPFB+yAZ461Xn5sNg=
github.com/pion/rtp v1.8.11 h1:17xjnY5WO5hgO6SD3/NTIUPvSFw/PbLsIJyz1r1yNIk= github.com/pion/rtp v1.8.13/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4=
github.com/pion/rtp v1.8.11/go.mod h1:8uMBJj32Pa1wwx8Fuv/AsFhn8jsgw+3rUC2PfoBZ8p4= github.com/pion/sctp v1.8.37 h1:ZDmGPtRPX9mKCiVXtMbTWybFw3z/hVKAZgU81wcOrqs=
github.com/pion/sctp v1.8.36 h1:owNudmnz1xmhfYje5L/FCav3V9wpPRePHle3Zi+P+M0= github.com/pion/sctp v1.8.37/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
github.com/pion/sctp v1.8.36/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= github.com/pion/sdp/v3 v3.0.11 h1:VhgVSopdsBKwhCFoyyPmT1fKMeV9nLMrEKxNOdy3IVI=
github.com/pion/sdp/v3 v3.0.10 h1:6MChLE/1xYB+CjumMw+gZ9ufp2DPApuVSnDT8t5MIgA= github.com/pion/sdp/v3 v3.0.11/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
github.com/pion/sdp/v3 v3.0.10/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E= github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
github.com/pion/srtp/v2 v2.0.20 h1:HNNny4s+OUmG280ETrCdgFndp4ufx3/uy85EawYEhTk= github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
github.com/pion/srtp/v2 v2.0.20/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA= github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0=
github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc= github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= github.com/pion/webrtc/v4 v4.0.14 h1:nyds/sFRR+HvmWoBa6wrL46sSfpArE0qR883MBW96lg=
github.com/pion/webrtc/v3 v3.3.5 h1:ZsSzaMz/i9nblPdiAkZoP+E6Kmjw+jnyq3bEmU3EtRg= github.com/pion/webrtc/v4 v4.0.14/go.mod h1:R3+qTnQTS03UzwDarYecgioNf7DYgTsldxnCXB821Kk=
github.com/pion/webrtc/v3 v3.3.5/go.mod h1:liNa+E1iwyzyXqNUwvoMRNQ10x8h8FOeJKL8RkIbamE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
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/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE= github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE=
@@ -82,96 +67,38 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
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/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1 h1:NVK+OqnavpyFmUiKfUMHrpvbCi2VFoWTrcpI7aDaJ2I= github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1 h1:NVK+OqnavpyFmUiKfUMHrpvbCi2VFoWTrcpI7aDaJ2I=
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA= github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f h1:1R9KdKjCNSd7F8iGTxIpoID9prlYH8nuNYKt0XvweHA= github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f h1:1R9KdKjCNSd7F8iGTxIpoID9prlYH8nuNYKt0XvweHA=
github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f/go.mod h1:vQhwQ4meQEDfahT5kd61wLAF5AAeh5ZPLVI4JJ/tYo8= github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f/go.mod h1:vQhwQ4meQEDfahT5kd61wLAF5AAeh5ZPLVI4JJ/tYo8=
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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tadglines/go-pkgs v0.0.0-20210623144937-b983b20f54f9 h1:aeN+ghOV0b2VCmKKO3gqnDQ8mLbpABZgRR2FVYx4ouI= github.com/tadglines/go-pkgs v0.0.0-20210623144937-b983b20f54f9 h1:aeN+ghOV0b2VCmKKO3gqnDQ8mLbpABZgRR2FVYx4ouI=
github.com/tadglines/go-pkgs v0.0.0-20210623144937-b983b20f54f9/go.mod h1:roo6cZ/uqpwKMuvPG0YmzI5+AmUiMWfjCBZpGXqbTxE= github.com/tadglines/go-pkgs v0.0.0-20210623144937-b983b20f54f9/go.mod h1:roo6cZ/uqpwKMuvPG0YmzI5+AmUiMWfjCBZpGXqbTxE=
github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -0,0 +1,10 @@
package eseecloud
import (
"github.com/AlexxIT/go2rtc/internal/streams"
"github.com/AlexxIT/go2rtc/pkg/eseecloud"
)
func Init() {
streams.HandleFunc("eseecloud", eseecloud.Dial)
}

View File

@@ -0,0 +1,10 @@
package flussonic
import (
"github.com/AlexxIT/go2rtc/internal/streams"
"github.com/AlexxIT/go2rtc/pkg/flussonic"
)
func Init() {
streams.HandleFunc("flussonic", flussonic.Dial)
}

View File

@@ -2,12 +2,9 @@ package ivideon
import ( import (
"github.com/AlexxIT/go2rtc/internal/streams" "github.com/AlexxIT/go2rtc/internal/streams"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/ivideon" "github.com/AlexxIT/go2rtc/pkg/ivideon"
) )
func Init() { func Init() {
streams.HandleFunc("ivideon", func(source string) (core.Producer, error) { streams.HandleFunc("ivideon", ivideon.Dial)
return ivideon.Dial(source)
})
} }

View File

@@ -8,7 +8,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
"github.com/AlexxIT/go2rtc/pkg/xnet" "github.com/AlexxIT/go2rtc/pkg/xnet"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
) )
type Address struct { type Address struct {

View File

@@ -15,7 +15,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
) )
// streamsHandler supports: // streamsHandler supports:

View File

@@ -10,6 +10,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
"github.com/pion/sdp/v3"
) )
// https://github.com/AlexxIT/go2rtc/issues/1600 // https://github.com/AlexxIT/go2rtc/issues/1600
@@ -27,7 +28,6 @@ func crealityClient(url string) (core.Producer, error) {
medias := []*core.Media{ medias := []*core.Media{
{Kind: core.KindVideo, Direction: core.DirectionRecvonly}, {Kind: core.KindVideo, Direction: core.DirectionRecvonly},
{Kind: core.KindAudio, Direction: core.DirectionRecvonly},
} }
// TODO: return webrtc.SessionDescription // TODO: return webrtc.SessionDescription
@@ -36,6 +36,8 @@ func crealityClient(url string) (core.Producer, error) {
return nil, err return nil, err
} }
log.Trace().Msgf("[webrtc] offer:\n%s", offer)
body, err := offerToB64(offer) body, err := offerToB64(offer)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -61,6 +63,12 @@ func crealityClient(url string) (core.Producer, error) {
return nil, err return nil, err
} }
log.Trace().Msgf("[webrtc] answer:\n%s", answer)
if answer, err = fixCrealitySDP(answer); err != nil {
return nil, err
}
if err = prod.SetAnswer(answer); err != nil { if err = prod.SetAnswer(answer); err != nil {
return nil, err return nil, err
} }
@@ -108,3 +116,37 @@ func answerFromB64(r io.Reader) (string, error) {
// string "v=0..." // string "v=0..."
return v["sdp"], nil return v["sdp"], nil
} }
func fixCrealitySDP(value string) (string, error) {
var sd sdp.SessionDescription
if err := sd.UnmarshalString(value); err != nil {
return "", err
}
md := sd.MediaDescriptions[0]
// important to skip first codec, because second codec will be used
skip := md.MediaName.Formats[0]
md.MediaName.Formats = md.MediaName.Formats[1:]
attrs := make([]sdp.Attribute, 0, len(md.Attributes))
for _, attr := range md.Attributes {
switch attr.Key {
case "fmtp", "rtpmap":
// important to skip fmtp with x-google, because this is second fmtp for same codec
// and pion library will fail parsing this SDP
if strings.HasPrefix(attr.Value, skip) || strings.Contains(attr.Value, "x-google") {
continue
}
}
attrs = append(attrs, attr)
}
md.Attributes = attrs
b, err := sd.Marshal()
if err != nil {
return "", err
}
return string(b), nil
}

View File

@@ -12,7 +12,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
) )
type kinesisRequest struct { type kinesisRequest struct {

View File

@@ -12,7 +12,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/tcp" "github.com/AlexxIT/go2rtc/pkg/tcp"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
) )
// This package handles the Milestone WebRTC session lifecycle, including authentication, // This package handles the Milestone WebRTC session lifecycle, including authentication,

View File

@@ -9,7 +9,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
) )
func openIPCClient(rawURL string, query url.Values) (core.Producer, error) { func openIPCClient(rawURL string, query url.Values) (core.Producer, error) {

View File

@@ -13,7 +13,7 @@ import (
"github.com/AlexxIT/go2rtc/internal/streams" "github.com/AlexxIT/go2rtc/internal/streams"
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
) )
const MimeSDP = "application/sdp" const MimeSDP = "application/sdp"

View File

@@ -10,7 +10,7 @@ import (
"github.com/AlexxIT/go2rtc/internal/streams" "github.com/AlexxIT/go2rtc/internal/streams"
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
"github.com/rs/zerolog" "github.com/rs/zerolog"
) )

View File

@@ -2,10 +2,11 @@ package webrtc
import ( import (
"encoding/json" "encoding/json"
"strings"
"testing" "testing"
"github.com/AlexxIT/go2rtc/internal/api/ws" "github.com/AlexxIT/go2rtc/internal/api/ws"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -36,3 +37,37 @@ func TestWebRTCAPIv2(t *testing.T) {
require.Equal(t, "v=0\n...", offer.SDP) require.Equal(t, "v=0\n...", offer.SDP)
require.Equal(t, "stun:stun.l.google.com:19302", offer.ICEServers[0].URLs[0]) require.Equal(t, "stun:stun.l.google.com:19302", offer.ICEServers[0].URLs[0])
} }
func TestCrealitySDP(t *testing.T) {
sdp := `v=0
o=- 1495799811084970 1495799811084970 IN IP4 0.0.0.0
s=-
t=0 0
a=msid-semantic:WMS *
a=group:BUNDLE 0
m=video 9 UDP/TLS/RTP/SAVPF 96 98
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=fmtp:96 profile-level-id=42e01f;level-asymmetry-allowed=1
a=fmtp:98 profile-level-id=42e01f;packetization-mode=1;level-asymmetry-allowed=1
a=fmtp:98 x-google-max-bitrate=6000;x-google-min-bitrate=2000;x-google-start-bitrate=4000
a=rtpmap:96 H264/90000
a=rtpmap:98 H264/90000
a=ssrc:1 cname:pear
c=IN IP4 0.0.0.0
a=sendonly
a=mid:0
a=rtcp-mux
a=ice-ufrag:7AVa
a=ice-pwd:T+F/5y05Paw+mtG5Jrd8N3
a=ice-options:trickle
a=fingerprint:sha-256 A5:AB:C0:4E:29:5B:BD:3B:7D:88:24:6C:56:6B:2A:79:A3:76:99:35:57:75:AD:C8:5A:A6:34:20:88:1B:68:EF
a=setup:passive
a=candidate:1 1 UDP 2015363327 172.22.233.10 48929 typ host
a=candidate:2 1 TCP 1015021823 172.22.233.10 0 typ host tcptype active
a=candidate:3 1 TCP 1010827519 172.22.233.10 60677 typ host tcptype passive
`
sdp, err := fixCrealitySDP(sdp)
require.Nil(t, err)
require.False(t, strings.Contains(sdp, "x-google-max-bitrate"))
}

View File

@@ -9,9 +9,11 @@ import (
"github.com/AlexxIT/go2rtc/internal/doorbird" "github.com/AlexxIT/go2rtc/internal/doorbird"
"github.com/AlexxIT/go2rtc/internal/dvrip" "github.com/AlexxIT/go2rtc/internal/dvrip"
"github.com/AlexxIT/go2rtc/internal/echo" "github.com/AlexxIT/go2rtc/internal/echo"
"github.com/AlexxIT/go2rtc/internal/eseecloud"
"github.com/AlexxIT/go2rtc/internal/exec" "github.com/AlexxIT/go2rtc/internal/exec"
"github.com/AlexxIT/go2rtc/internal/expr" "github.com/AlexxIT/go2rtc/internal/expr"
"github.com/AlexxIT/go2rtc/internal/ffmpeg" "github.com/AlexxIT/go2rtc/internal/ffmpeg"
"github.com/AlexxIT/go2rtc/internal/flussonic"
"github.com/AlexxIT/go2rtc/internal/gopro" "github.com/AlexxIT/go2rtc/internal/gopro"
"github.com/AlexxIT/go2rtc/internal/hass" "github.com/AlexxIT/go2rtc/internal/hass"
"github.com/AlexxIT/go2rtc/internal/hls" "github.com/AlexxIT/go2rtc/internal/hls"
@@ -88,6 +90,8 @@ func main() {
gopro.Init() // gopro source gopro.Init() // gopro source
doorbird.Init() // doorbird source doorbird.Init() // doorbird source
v4l2.Init() // v4l2 source v4l2.Init() // v4l2 source
flussonic.Init()
eseecloud.Init()
// 6. Helper modules // 6. Helper modules

View File

@@ -89,6 +89,12 @@ func (r *Reader) ReadBits64(n byte) (res uint64) {
return return
} }
func (r *Reader) ReadFloat32() float64 {
i := r.ReadUint16()
f := r.ReadUint16()
return float64(i) + float64(f)/65536
}
func (r *Reader) ReadBytes(n int) (b []byte) { func (r *Reader) ReadBytes(n int) (b []byte) {
if r.bits == 0 { if r.bits == 0 {
if r.pos+n > len(r.buf) { if r.pos+n > len(r.buf) {

View File

@@ -97,13 +97,17 @@ func NewSender(media *Media, codec *Codec) *Sender {
buf: buf, buf: buf,
} }
s.Input = func(packet *Packet) { s.Input = func(packet *Packet) {
// writing to nil chan - OK, writing to closed chan - panic
s.mu.Lock() s.mu.Lock()
select { if s.buf != nil {
case s.buf <- packet: // unblocked write to channel
s.Bytes += len(packet.Payload) select {
s.Packets++ case s.buf <- packet:
default: s.Bytes += len(packet.Payload)
s.Packets++
default:
s.Drops++
}
} else {
s.Drops++ s.Drops++
} }
s.mu.Unlock() s.mu.Unlock()
@@ -139,13 +143,13 @@ func (s *Sender) Start() {
} }
s.done = make(chan struct{}) s.done = make(chan struct{})
go func() { // pass buf directly so that it's impossible for buf to be nil
// for range on nil chan is OK go func(buf chan *Packet) {
for packet := range s.buf { for packet := range buf {
s.Output(packet) s.Output(packet)
} }
close(s.done) close(s.done)
}() }(s.buf)
} }
func (s *Sender) Wait() { func (s *Sender) Wait() {

180
pkg/eseecloud/eseecloud.go Normal file
View File

@@ -0,0 +1,180 @@
package eseecloud
import (
"bytes"
"encoding/binary"
"errors"
"io"
"net/http"
"regexp"
"strings"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/h264/annexb"
"github.com/pion/rtp"
)
type Producer struct {
core.Connection
rd *core.ReadBuffer
videoPT, audioPT uint8
}
func Dial(rawURL string) (core.Producer, error) {
rawURL, _ = strings.CutPrefix(rawURL, "eseecloud")
res, err := http.Get("http" + rawURL)
if err != nil {
return nil, err
}
prod, err := Open(res.Body)
if err != nil {
return nil, err
}
if info, ok := prod.(core.Info); ok {
info.SetProtocol("http")
info.SetURL(rawURL)
}
return prod, nil
}
func Open(r io.Reader) (core.Producer, error) {
prod := &Producer{
Connection: core.Connection{
ID: core.NewID(),
FormatName: "eseecloud",
Transport: r,
},
rd: core.NewReadBuffer(r),
}
if err := prod.probe(); err != nil {
return nil, err
}
return prod, nil
}
func (p *Producer) probe() error {
b, err := p.rd.Peek(1024)
if err != nil {
return err
}
i := bytes.Index(b, []byte("\r\n\r\n"))
if i == -1 {
return io.EOF
}
b = make([]byte, i+4)
_, _ = p.rd.Read(b)
re := regexp.MustCompile(`m=(video|audio) (\d+) (\w+)/(\d+)\S*`)
for _, item := range re.FindAllStringSubmatch(string(b), 2) {
p.SDP += item[0] + "\n"
switch item[3] {
case "H264", "H265":
p.Medias = append(p.Medias, &core.Media{
Kind: core.KindVideo,
Direction: core.DirectionRecvonly,
Codecs: []*core.Codec{
{
Name: item[3],
ClockRate: 90000,
PayloadType: core.PayloadTypeRAW,
},
},
})
p.videoPT = byte(core.Atoi(item[2]))
case "G711":
p.Medias = append(p.Medias, &core.Media{
Kind: core.KindAudio,
Direction: core.DirectionRecvonly,
Codecs: []*core.Codec{
{
Name: core.CodecPCMA,
ClockRate: 8000,
},
},
})
p.audioPT = byte(core.Atoi(item[2]))
}
}
return nil
}
func (p *Producer) Start() error {
receivers := make(map[uint8]*core.Receiver)
for _, receiver := range p.Receivers {
switch receiver.Codec.Kind() {
case core.KindVideo:
receivers[p.videoPT] = receiver
case core.KindAudio:
receivers[p.audioPT] = receiver
}
}
for {
pkt, err := p.readPacket()
if err != nil {
return err
}
if recv := receivers[pkt.PayloadType]; recv != nil {
switch recv.Codec.Name {
case core.CodecH264, core.CodecH265:
// timestamp = seconds x 1000000
pkt = &rtp.Packet{
Header: rtp.Header{
Timestamp: uint32(uint64(pkt.Timestamp) * 90000 / 1000000),
},
Payload: annexb.EncodeToAVCC(pkt.Payload),
}
case core.CodecPCMA:
pkt = &rtp.Packet{
Header: rtp.Header{
Version: 2,
SequenceNumber: pkt.SequenceNumber,
Timestamp: uint32(uint64(pkt.Timestamp) * 8000 / 1000000),
},
Payload: pkt.Payload,
}
}
recv.WriteRTP(pkt)
}
}
}
func (p *Producer) readPacket() (*core.Packet, error) {
b := make([]byte, 8)
if _, err := io.ReadFull(p.rd, b); err != nil {
return nil, err
}
if b[0] != '$' {
return nil, errors.New("eseecloud: wrong start byte")
}
size := binary.BigEndian.Uint32(b[4:])
b = make([]byte, size)
if _, err := io.ReadFull(p.rd, b); err != nil {
return nil, err
}
pkt := &core.Packet{}
if err := pkt.Unmarshal(b); err != nil {
return nil, err
}
p.Recv += int(size)
return pkt, nil
}

176
pkg/flussonic/flussonic.go Normal file
View File

@@ -0,0 +1,176 @@
package flussonic
import (
"strings"
"github.com/AlexxIT/go2rtc/pkg/aac"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/h264"
"github.com/AlexxIT/go2rtc/pkg/iso"
"github.com/gorilla/websocket"
"github.com/pion/rtp"
)
type Producer struct {
core.Connection
conn *websocket.Conn
videoTrackID, audioTrackID uint32
videoTimeScale, audioTimeScale float32
}
func Dial(source string) (core.Producer, error) {
url, _ := strings.CutPrefix(source, "flussonic:")
conn, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
return nil, err
}
prod := &Producer{
Connection: core.Connection{
ID: core.NewID(),
FormatName: "flussonic",
Protocol: core.Before(url, ":"), // wss
RemoteAddr: conn.RemoteAddr().String(),
URL: url,
Transport: conn,
},
conn: conn,
}
if err = prod.probe(); err != nil {
_ = conn.Close()
return nil, err
}
return prod, nil
}
func (p *Producer) probe() error {
var init struct {
//Metadata struct {
// Tracks []struct {
// Width int `json:"width,omitempty"`
// Height int `json:"height,omitempty"`
// Fps int `json:"fps,omitempty"`
// Content string `json:"content"`
// TrackId string `json:"trackId"`
// Bitrate int `json:"bitrate"`
// } `json:"tracks"`
//} `json:"metadata"`
Tracks []struct {
Content string `json:"content"`
Id uint32 `json:"id"`
Payload []byte `json:"payload"`
} `json:"tracks"`
//Type string `json:"type"`
}
if err := p.conn.ReadJSON(&init); err != nil {
return err
}
var timeScale uint32
for _, track := range init.Tracks {
atoms, _ := iso.DecodeAtoms(track.Payload)
for _, atom := range atoms {
switch atom := atom.(type) {
case *iso.AtomMdhd:
timeScale = atom.TimeScale
case *iso.AtomVideo:
switch atom.Name {
case "avc1":
codec := h264.AVCCToCodec(atom.Config)
p.Medias = append(p.Medias, &core.Media{
Kind: core.KindVideo,
Direction: core.DirectionRecvonly,
Codecs: []*core.Codec{codec},
})
p.videoTrackID = track.Id
p.videoTimeScale = float32(codec.ClockRate) / float32(timeScale)
}
case *iso.AtomAudio:
switch atom.Name {
case "mp4a":
codec := aac.ConfigToCodec(atom.Config)
p.Medias = append(p.Medias, &core.Media{
Kind: core.KindAudio,
Direction: core.DirectionRecvonly,
Codecs: []*core.Codec{codec},
})
p.audioTrackID = track.Id
p.audioTimeScale = float32(codec.ClockRate) / float32(timeScale)
}
}
}
}
return nil
}
func (p *Producer) Start() error {
if err := p.conn.WriteMessage(websocket.TextMessage, []byte("resume")); err != nil {
return err
}
receivers := make(map[uint32]*core.Receiver)
timeScales := make(map[uint32]float32)
for _, receiver := range p.Receivers {
switch receiver.Codec.Kind() {
case core.KindVideo:
receivers[p.videoTrackID] = receiver
timeScales[p.videoTrackID] = p.videoTimeScale
case core.KindAudio:
receivers[p.audioTrackID] = receiver
timeScales[p.audioTrackID] = p.audioTimeScale
}
}
ch := make(chan []byte, 10)
defer close(ch)
go func() {
for b := range ch {
atoms, err := iso.DecodeAtoms(b)
if err != nil {
continue
}
var trackID uint32
var decodeTime uint64
for _, atom := range atoms {
switch atom := atom.(type) {
case *iso.AtomTfhd:
trackID = atom.TrackID
case *iso.AtomTfdt:
decodeTime = atom.DecodeTime
case *iso.AtomMdat:
b = atom.Data
}
}
if recv := receivers[trackID]; recv != nil {
timestamp := uint32(float32(decodeTime) * timeScales[trackID])
packet := &rtp.Packet{
Header: rtp.Header{Timestamp: timestamp},
Payload: b,
}
recv.WriteRTP(packet)
}
}
}()
for {
mType, b, err := p.conn.ReadMessage()
if err != nil {
return err
}
if mType == websocket.BinaryMessage {
p.Recv += len(b)
ch <- b
}
}
}

View File

@@ -6,7 +6,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
) )
type Client struct { type Client struct {

View File

@@ -1,6 +1,7 @@
package iso package iso
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"io" "io"
@@ -10,89 +11,192 @@ import (
type Atom struct { type Atom struct {
Name string Name string
Data []byte Data []byte
DecodeTime uint64
SamplesDuration []uint32
SamplesSize []uint32
} }
func DecodeAtoms(b []byte) ([]*Atom, error) { type AtomTkhd struct {
var atoms []*Atom TrackID uint32
for len(b) > 8 { }
size := binary.BigEndian.Uint32(b)
if uint32(len(b)) < size { type AtomMdhd struct {
return nil, io.EOF TimeScale uint32
}
type AtomVideo struct {
Name string
Config []byte
}
type AtomAudio struct {
Name string
Channels uint16
SampleRate uint32
Config []byte
}
type AtomMfhd struct {
Sequence uint32
}
type AtomMdat struct {
Data []byte
}
type AtomTfhd struct {
TrackID uint32
SampleDuration uint32
SampleSize uint32
SampleFlags uint32
}
type AtomTfdt struct {
DecodeTime uint64
}
type AtomTrun struct {
DataOffset uint32
FirstSampleFlags uint32
SamplesDuration []uint32
SamplesSize []uint32
SamplesFlags []uint32
SamplesCTS []uint32
}
func DecodeAtom(b []byte) (any, error) {
size := binary.BigEndian.Uint32(b)
if len(b) < int(size) {
return nil, io.EOF
}
name := string(b[4:8])
data := b[8:size]
switch name {
// useful containers
case Moov, MoovTrak, MoovTrakMdia, MoovTrakMdiaMinf, MoovTrakMdiaMinfStbl, Moof, MoofTraf:
return DecodeAtoms(data)
case MoovTrakTkhd:
return &AtomTkhd{TrackID: binary.BigEndian.Uint32(data[1+3+4+4:])}, nil
case MoovTrakMdiaMdhd:
return &AtomMdhd{TimeScale: binary.BigEndian.Uint32(data[1+3+4+4:])}, nil
case MoovTrakMdiaMinfStblStsd:
// support only 1 codec entry
if n := binary.BigEndian.Uint32(data[1+3:]); n == 1 {
return DecodeAtom(data[1+3+4:])
} }
name := string(b[4:8]) case "avc1", "hev1":
data := b[8:size] b = data[6+2+2+2+4+4+4+2+2+4+4+4+2+32+2+2:]
atom, err := DecodeAtom(b)
if err != nil {
return nil, err
}
if conf, ok := atom.(*Atom); ok {
return &AtomVideo{Name: name, Config: conf.Data}, nil
}
b = b[size:] case "mp4a":
atom := &AtomAudio{Name: name}
switch name { rd := bits.NewReader(data)
case Moof, MoofTraf: rd.ReadBytes(6 + 2 + 2 + 2 + 4) // skip
childs, err := DecodeAtoms(data) atom.Channels = rd.ReadUint16()
if err != nil { rd.ReadBytes(2 + 2 + 2) // skip
return nil, err atom.SampleRate = uint32(rd.ReadFloat32())
atom2, _ := DecodeAtom(rd.Left())
if conf, ok := atom2.(*Atom); ok {
_, b, _ = bytes.Cut(conf.Data, []byte{5, 0x80, 0x80, 0x80})
if n := len(b); n > 0 && n > 1+int(b[0]) {
atom.Config = b[1 : 1+b[0]]
} }
}
return atom, nil
case MoofMfhd:
return &AtomMfhd{Sequence: binary.BigEndian.Uint32(data[4:])}, nil
case MoofTrafTfhd:
rd := bits.NewReader(data)
_ = rd.ReadByte() // version
flags := rd.ReadUint24()
atom := &AtomTfhd{
TrackID: rd.ReadUint32(),
}
if flags&TfhdDefaultSampleDuration != 0 {
atom.SampleDuration = rd.ReadUint32()
}
if flags&TfhdDefaultSampleSize != 0 {
atom.SampleSize = rd.ReadUint32()
}
if flags&TfhdDefaultSampleFlags != 0 {
atom.SampleFlags = rd.ReadUint32() // skip
}
return atom, nil
case MoofTrafTfdt:
return &AtomTfdt{DecodeTime: binary.BigEndian.Uint64(data[4:])}, nil
case MoofTrafTrun:
rd := bits.NewReader(data)
_ = rd.ReadByte() // version
flags := rd.ReadUint24()
samples := rd.ReadUint32()
atom := &AtomTrun{}
if flags&TrunDataOffset != 0 {
atom.DataOffset = rd.ReadUint32()
}
if flags&TrunFirstSampleFlags != 0 {
atom.FirstSampleFlags = rd.ReadUint32()
}
for i := uint32(0); i < samples; i++ {
if flags&TrunSampleDuration != 0 {
atom.SamplesDuration = append(atom.SamplesDuration, rd.ReadUint32())
}
if flags&TrunSampleSize != 0 {
atom.SamplesSize = append(atom.SamplesSize, rd.ReadUint32())
}
if flags&TrunSampleFlags != 0 {
atom.SamplesFlags = append(atom.SamplesFlags, rd.ReadUint32())
}
if flags&TrunSampleCTS != 0 {
atom.SamplesCTS = append(atom.SamplesCTS, rd.ReadUint32())
}
}
return atom, nil
case Mdat:
return &AtomMdat{Data: data}, nil
}
return &Atom{Name: name, Data: data}, nil
}
func DecodeAtoms(b []byte) (atoms []any, err error) {
for len(b) > 0 {
atom, err := DecodeAtom(b)
if err != nil {
return nil, err
}
if childs, ok := atom.([]any); ok {
atoms = append(atoms, childs...) atoms = append(atoms, childs...)
} else {
case MoofMfhd, MoofTrafTfhd:
continue
case MoofTrafTfdt:
if len(data) < 8 {
return nil, io.EOF
}
dt := binary.BigEndian.Uint64(data[4:])
atoms = append(atoms, &Atom{Name: name, DecodeTime: dt})
case MoofTrafTrun:
rd := bits.NewReader(data)
_ = rd.ReadByte() // version
flags := rd.ReadUint24()
samples := rd.ReadUint32()
if flags&TrunDataOffset != 0 {
_ = rd.ReadUint32() // skip
}
if flags&TrunFirstSampleFlags != 0 {
_ = rd.ReadUint32() // skip
}
atom := &Atom{Name: name}
for i := uint32(0); i < samples; i++ {
if flags&TrunSampleDuration != 0 {
atom.SamplesDuration = append(atom.SamplesDuration, rd.ReadUint32())
}
if flags&TrunSampleSize != 0 {
atom.SamplesSize = append(atom.SamplesSize, rd.ReadUint32())
}
if flags&TrunSampleFlags != 0 {
_ = rd.ReadUint32() // skip
}
if flags&TrunSampleCTS != 0 {
_ = rd.ReadUint32() // skip
}
}
if rd.EOF {
return nil, io.EOF
}
atoms = append(atoms, atom) atoms = append(atoms, atom)
case Mdat:
atoms = append(atoms, &Atom{Name: name, Data: data})
default:
println("iso: unsupported atom: " + name)
} }
size := binary.BigEndian.Uint32(b)
b = b[size:]
} }
return atoms, nil return atoms, nil

View File

@@ -1,314 +0,0 @@
package ivideon
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"sync"
"time"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/h264"
"github.com/AlexxIT/go2rtc/pkg/iso"
"github.com/gorilla/websocket"
"github.com/pion/rtp"
)
type State byte
const (
StateNone State = iota
StateConn
StateHandle
)
// Deprecated: should be rewritten to core.Connection
type Client struct {
core.Listener
ID string
conn *websocket.Conn
medias []*core.Media
receiver *core.Receiver
msg *message
t0 time.Time
buffer chan []byte
state State
mu sync.Mutex
recv int
}
func Dial(source string) (*Client, error) {
id := strings.Replace(source[8:], "/", ":", 1)
client := &Client{ID: id}
if err := client.Dial(); err != nil {
return nil, err
}
return client, nil
}
func (c *Client) Dial() (err error) {
resp, err := http.Get(
"https://openapi-alpha.ivideon.com/cameras/" + c.ID +
"/live_stream?op=GET&access_token=public&q=2&" +
"video_codecs=h264&format=ws-fmp4",
)
data, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
var v liveResponse
if err = json.Unmarshal(data, &v); err != nil {
return err
}
if !v.Success {
return fmt.Errorf("wrong response: %s", data)
}
c.conn, _, err = websocket.DefaultDialer.Dial(v.Result.URL, nil)
if err != nil {
return err
}
if err = c.getTracks(); err != nil {
_ = c.conn.Close()
return err
}
c.state = StateConn
return nil
}
func (c *Client) Handle() error {
// add delay to the stream for smooth playing (not a best solution)
c.t0 = time.Now().Add(time.Second)
c.mu.Lock()
if c.state == StateConn {
c.buffer = make(chan []byte, 5)
c.state = StateHandle
// processing stream in separate thread for lower delay between packets
go c.worker(c.buffer)
}
c.mu.Unlock()
_, data, err := c.conn.ReadMessage()
if err != nil {
return err
}
if c.receiver != nil && c.receiver.ID == c.msg.Track {
c.mu.Lock()
if c.state == StateHandle {
c.buffer <- data
c.recv += len(data)
}
c.mu.Unlock()
}
// we have one unprocessed msg after getTracks
for {
_, data, err = c.conn.ReadMessage()
if err != nil {
return err
}
var msg message
if err = json.Unmarshal(data, &msg); err != nil {
return err
}
switch msg.Type {
case "stream-init":
continue
case "metadata":
continue
case "fragment":
_, data, err = c.conn.ReadMessage()
if err != nil {
return err
}
if c.receiver != nil && c.receiver.ID == msg.Track {
c.mu.Lock()
if c.state == StateHandle {
c.buffer <- data
c.recv += len(data)
}
c.mu.Unlock()
}
default:
return fmt.Errorf("wrong message type: %s", data)
}
}
}
func (c *Client) Close() error {
c.mu.Lock()
defer c.mu.Unlock()
switch c.state {
case StateNone:
return nil
case StateConn:
case StateHandle:
close(c.buffer)
}
c.state = StateNone
return c.conn.Close()
}
func (c *Client) getTracks() error {
for {
_, data, err := c.conn.ReadMessage()
if err != nil {
return err
}
var msg message
if err = json.Unmarshal(data, &msg); err != nil {
return err
}
switch msg.Type {
case "metadata":
continue
case "stream-init":
s := msg.CodecString
i := strings.IndexByte(s, '.')
if i > 0 {
s = s[:i]
}
switch s {
case "avc1": // avc1.4d0029
// skip multiple identical init
if c.receiver != nil {
continue
}
i = bytes.Index(msg.Data, []byte("avcC")) - 4
if i < 0 {
return fmt.Errorf("ivideon: wrong AVC: %s", msg.Data)
}
avccLen := binary.BigEndian.Uint32(msg.Data[i:])
data = msg.Data[i+8 : i+int(avccLen)]
codec := h264.ConfigToCodec(data)
media := &core.Media{
Kind: core.KindVideo,
Direction: core.DirectionRecvonly,
Codecs: []*core.Codec{codec},
}
c.medias = append(c.medias, media)
c.receiver = core.NewReceiver(media, codec)
c.receiver.ID = msg.TrackID
case "mp4a": // mp4a.40.2
}
case "fragment":
c.msg = &msg
return nil
default:
return fmt.Errorf("wrong message type: %s", data)
}
}
}
func (c *Client) worker(buffer chan []byte) {
for data := range buffer {
atoms, err := iso.DecodeAtoms(data)
if err != nil {
continue
}
var trun *iso.Atom
var ts uint32
for _, atom := range atoms {
switch atom.Name {
case iso.MoofTrafTrun:
trun = atom
case iso.MoofTrafTfdt:
ts = uint32(atom.DecodeTime)
case iso.Mdat:
data = atom.Data
}
}
if trun == nil || trun.SamplesDuration == nil || trun.SamplesSize == nil {
continue
}
for i := 0; i < len(trun.SamplesDuration); i++ {
duration := trun.SamplesDuration[i]
size := trun.SamplesSize[i]
// synchronize framerate for WebRTC and MSE
d := time.Duration(ts)*time.Millisecond - time.Since(c.t0)
if d < 0 {
d = time.Duration(duration) * time.Millisecond / 2
}
time.Sleep(d)
// can be SPS, PPS and IFrame in one packet
packet := &rtp.Packet{
// ivideon clockrate=1000, RTP clockrate=90000
Header: rtp.Header{Timestamp: ts * 90},
Payload: data[:size],
}
c.receiver.WriteRTP(packet)
data = data[size:]
ts += duration
}
}
}
type liveResponse struct {
Result struct {
URL string `json:"url"`
} `json:"result"`
Success bool `json:"success"`
}
type message struct {
Type string `json:"type"`
CodecString string `json:"codec_string"`
Data []byte `json:"data"`
TrackID byte `json:"track_id"`
Track byte `json:"track"`
StartTime float32 `json:"start_time"`
Duration float32 `json:"duration"`
IsKey bool `json:"is_key"`
DataOffset uint32 `json:"data_offset"`
}

187
pkg/ivideon/ivideon.go Normal file
View File

@@ -0,0 +1,187 @@
package ivideon
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"strings"
"time"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/mp4"
"github.com/gorilla/websocket"
)
type Producer struct {
core.Connection
conn *websocket.Conn
buf []byte
dem *mp4.Demuxer
}
func Dial(source string) (core.Producer, error) {
id := strings.Replace(source[8:], "/", ":", 1)
url, err := GetLiveStream(id)
if err != nil {
return nil, err
}
conn, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
return nil, err
}
prod := &Producer{
Connection: core.Connection{
ID: core.NewID(),
FormatName: "ivideon",
Protocol: core.Before(url, ":"), // wss
RemoteAddr: conn.RemoteAddr().String(),
Source: source,
URL: url,
Transport: conn,
},
conn: conn,
}
if err = prod.probe(); err != nil {
_ = conn.Close()
return nil, err
}
return prod, nil
}
func GetLiveStream(id string) (string, error) {
// &video_codecs=h264,h265&audio_codecs=aac,mp3,pcma,pcmu,none
resp, err := http.Get(
"https://openapi-alpha.ivideon.com/cameras/" + id +
"/live_stream?op=GET&access_token=public&q=2&video_codecs=h264&format=ws-fmp4",
)
if err != nil {
return "", err
}
var v struct {
Message string `json:"message"`
Result struct {
URL string `json:"url"`
} `json:"result"`
Success bool `json:"success"`
}
if err = json.NewDecoder(resp.Body).Decode(&v); err != nil {
return "", err
}
if !v.Success {
return "", fmt.Errorf("ivideon: can't get live_stream: " + v.Message)
}
return v.Result.URL, nil
}
func (p *Producer) Start() error {
receivers := make(map[uint32]*core.Receiver)
for _, receiver := range p.Receivers {
trackID := p.dem.GetTrackID(receiver.Codec)
receivers[trackID] = receiver
}
ch := make(chan []byte, 10)
defer close(ch)
ch <- p.buf
go func() {
// add delay to the stream for smooth playing (not a best solution)
t0 := time.Now()
for data := range ch {
trackID, packets := p.dem.Demux(data)
if receiver := receivers[trackID]; receiver != nil {
clockRate := time.Duration(receiver.Codec.ClockRate)
for _, packet := range packets {
// synchronize framerate for WebRTC and MSE
ts := time.Second * time.Duration(packet.Timestamp) / clockRate
d := ts - time.Since(t0)
if d < 0 {
d = 10 * time.Millisecond
}
time.Sleep(d)
receiver.WriteRTP(packet)
}
}
}
}()
for {
var msg message
if err := p.conn.ReadJSON(&msg); err != nil {
return err
}
switch msg.Type {
case "stream-init", "metadata":
continue
case "fragment":
_, b, err := p.conn.ReadMessage()
if err != nil {
return err
}
p.Recv += len(b)
ch <- b
default:
return errors.New("ivideon: wrong message type: " + msg.Type)
}
}
}
func (p *Producer) probe() (err error) {
p.dem = &mp4.Demuxer{}
for {
var msg message
if err = p.conn.ReadJSON(&msg); err != nil {
return err
}
switch msg.Type {
case "metadata":
continue
case "stream-init":
// it's difficult to maintain audio
if strings.HasPrefix(msg.CodecString, "avc1") {
medias := p.dem.Probe(msg.Data)
p.Medias = append(p.Medias, medias...)
}
case "fragment":
_, p.buf, err = p.conn.ReadMessage()
return
default:
return errors.New("ivideon: wrong message type: " + msg.Type)
}
}
}
type message struct {
Type string `json:"type"`
CodecString string `json:"codec_string"`
Data []byte `json:"data"`
//TrackID byte `json:"track_id"`
//Track byte `json:"track"`
//StartTime float32 `json:"start_time"`
//Duration float32 `json:"duration"`
//IsKey bool `json:"is_key"`
//DataOffset uint32 `json:"data_offset"`
}

View File

@@ -1,51 +0,0 @@
package ivideon
import (
"encoding/json"
"github.com/AlexxIT/go2rtc/pkg/core"
)
func (c *Client) GetMedias() []*core.Media {
return c.medias
}
func (c *Client) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, error) {
if c.receiver != nil {
return c.receiver, nil
}
return nil, core.ErrCantGetTrack
}
func (c *Client) Start() error {
err := c.Handle()
if c.buffer == nil {
return nil
}
return err
}
func (c *Client) Stop() error {
if c.receiver != nil {
c.receiver.Close()
}
return c.Close()
}
func (c *Client) MarshalJSON() ([]byte, error) {
info := &core.Connection{
ID: core.ID(c),
FormatName: "ivideon",
Protocol: "ws",
URL: c.ID,
Medias: c.medias,
Recv: c.recv,
}
if c.conn != nil {
info.RemoteAddr = c.conn.RemoteAddr().String()
}
if c.receiver != nil {
info.Receivers = []*core.Receiver{c.receiver}
}
return json.Marshal(info)
}

116
pkg/mp4/demuxer.go Normal file
View File

@@ -0,0 +1,116 @@
package mp4
import (
"github.com/AlexxIT/go2rtc/pkg/aac"
"github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/h264"
"github.com/AlexxIT/go2rtc/pkg/iso"
"github.com/pion/rtp"
)
type Demuxer struct {
codecs map[uint32]*core.Codec
timeScales map[uint32]float32
}
func (d *Demuxer) Probe(init []byte) (medias []*core.Media) {
var trackID, timeScale uint32
if d.codecs == nil {
d.codecs = make(map[uint32]*core.Codec)
d.timeScales = make(map[uint32]float32)
}
atoms, _ := iso.DecodeAtoms(init)
for _, atom := range atoms {
var codec *core.Codec
switch atom := atom.(type) {
case *iso.AtomTkhd:
trackID = atom.TrackID
case *iso.AtomMdhd:
timeScale = atom.TimeScale
case *iso.AtomVideo:
switch atom.Name {
case "avc1":
codec = h264.ConfigToCodec(atom.Config)
}
case *iso.AtomAudio:
switch atom.Name {
case "mp4a":
codec = aac.ConfigToCodec(atom.Config)
}
}
if codec != nil {
d.codecs[trackID] = codec
d.timeScales[trackID] = float32(codec.ClockRate) / float32(timeScale)
medias = append(medias, &core.Media{
Kind: codec.Kind(),
Direction: core.DirectionRecvonly,
Codecs: []*core.Codec{codec},
})
}
}
return
}
func (d *Demuxer) GetTrackID(codec *core.Codec) uint32 {
for trackID, c := range d.codecs {
if c == codec {
return trackID
}
}
return 0
}
func (d *Demuxer) Demux(data2 []byte) (trackID uint32, packets []*core.Packet) {
atoms, err := iso.DecodeAtoms(data2)
if err != nil {
return 0, nil
}
var ts uint32
var trun *iso.AtomTrun
var data []byte
for _, atom := range atoms {
switch atom := atom.(type) {
case *iso.AtomTfhd:
trackID = atom.TrackID
case *iso.AtomTfdt:
ts = uint32(atom.DecodeTime)
case *iso.AtomTrun:
trun = atom
case *iso.AtomMdat:
data = atom.Data
}
}
timeScale := d.timeScales[trackID]
if timeScale == 0 {
return 0, nil
}
n := len(trun.SamplesDuration)
packets = make([]*core.Packet, n)
for i := 0; i < n; i++ {
duration := trun.SamplesDuration[i]
size := trun.SamplesSize[i]
// can be SPS, PPS and IFrame in one packet
timestamp := uint32(float32(ts) * timeScale)
packets[i] = &rtp.Packet{
Header: rtp.Header{Timestamp: timestamp},
Payload: data[:size],
}
data = data[size:]
ts += duration
}
return
}

View File

@@ -8,7 +8,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/rtsp" "github.com/AlexxIT/go2rtc/pkg/rtsp"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
) )
type WebRTCClient struct { type WebRTCClient struct {

View File

@@ -12,7 +12,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
) )
type Client struct { type Client struct {
@@ -536,6 +536,6 @@ func (c *Client) MarshalJSON() ([]byte, error) {
if webrtcProd, ok := c.prod.(*webrtc.Conn); ok { if webrtcProd, ok := c.prod.(*webrtc.Conn); ok {
return webrtcProd.MarshalJSON() return webrtcProd.MarshalJSON()
} }
return json.Marshal(c.prod) return json.Marshal(c.prod)
} }

View File

@@ -15,7 +15,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/roborock/iot" "github.com/AlexxIT/go2rtc/pkg/roborock/iot"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
) )
// Deprecated: should be rewritten to core.Connection // Deprecated: should be rewritten to core.Connection

View File

@@ -6,7 +6,7 @@ import (
"github.com/pion/rtcp" "github.com/pion/rtcp"
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/pion/srtp/v2" "github.com/pion/srtp/v3"
) )
type Session struct { type Session struct {

View File

@@ -5,9 +5,9 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/xnet" "github.com/AlexxIT/go2rtc/pkg/xnet"
"github.com/pion/ice/v2" "github.com/pion/ice/v4"
"github.com/pion/interceptor" "github.com/pion/interceptor"
"github.com/pion/webrtc/v3" "github.com/pion/webrtc/v4"
) )
// ReceiveMTU = Ethernet MTU (1500) - IP Header (20) - UDP Header (8) // ReceiveMTU = Ethernet MTU (1500) - IP Header (20) - UDP Header (8)

View File

@@ -3,7 +3,7 @@ package webrtc
import ( import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/pion/sdp/v3" "github.com/pion/sdp/v3"
"github.com/pion/webrtc/v3" "github.com/pion/webrtc/v4"
) )
func (c *Conn) CreateOffer(medias []*core.Media) (string, error) { func (c *Conn) CreateOffer(medias []*core.Media) (string, error) {

View File

@@ -4,7 +4,7 @@ import (
"testing" "testing"
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/pion/webrtc/v3" "github.com/pion/webrtc/v4"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )

View File

@@ -9,7 +9,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/pion/rtcp" "github.com/pion/rtcp"
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/pion/webrtc/v3" "github.com/pion/webrtc/v4"
) )
type Conn struct { type Conn struct {

View File

@@ -11,10 +11,10 @@ import (
"time" "time"
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/pion/ice/v2" "github.com/pion/ice/v4"
"github.com/pion/sdp/v3" "github.com/pion/sdp/v3"
"github.com/pion/stun" "github.com/pion/stun/v3"
"github.com/pion/webrtc/v3" "github.com/pion/webrtc/v4"
) )
func UnmarshalMedias(descriptions []*sdp.MediaDescription) (medias []*core.Media) { func UnmarshalMedias(descriptions []*sdp.MediaDescription) (medias []*core.Media) {

View File

@@ -2,7 +2,7 @@ package webrtc
import ( import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/pion/webrtc/v3" "github.com/pion/webrtc/v4"
) )
func (c *Conn) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, error) { func (c *Conn) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, error) {

View File

@@ -3,7 +3,7 @@ package webrtc
import ( import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/pion/sdp/v3" "github.com/pion/sdp/v3"
"github.com/pion/webrtc/v3" "github.com/pion/webrtc/v4"
) )
func (c *Conn) SetOffer(offer string) (err error) { func (c *Conn) SetOffer(offer string) (err error) {

View File

@@ -4,7 +4,7 @@ import (
"sync" "sync"
"github.com/pion/rtp" "github.com/pion/rtp"
"github.com/pion/webrtc/v3" "github.com/pion/webrtc/v4"
) )
type Track struct { type Track struct {

View File

@@ -3,7 +3,7 @@ package webrtc
import ( import (
"testing" "testing"
"github.com/pion/webrtc/v3" "github.com/pion/webrtc/v4"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )

View File

@@ -9,7 +9,7 @@ import (
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/webrtc" "github.com/AlexxIT/go2rtc/pkg/webrtc"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
pion "github.com/pion/webrtc/v3" pion "github.com/pion/webrtc/v4"
) )
func NewClient(tracker, share, pwd string, pc *pion.PeerConnection) (*webrtc.Conn, error) { func NewClient(tracker, share, pwd string, pc *pion.PeerConnection) (*webrtc.Conn, error) {

View File

@@ -7,8 +7,12 @@ So we will set `go 1.20` (minimum version) inside `go.mod` file. And will use en
`win32` and `mac_amd64` binaries. All other binaries will use latest go version. `win32` and `mac_amd64` binaries. All other binaries will use latest go version.
``` ```
github.com/miekg/dns v1.1.63
golang.org/x/crypto v0.33.0 golang.org/x/crypto v0.33.0
golang.org/x/mod v0.20.0 // indirect golang.org/x/mod v0.20.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/tools v0.24.0 // indirect golang.org/x/tools v0.24.0 // indirect
``` ```

View File

@@ -21,34 +21,34 @@ go build -ldflags "-s -w" -trimpath && 7z a -mx9 -sdel %FILENAME% go2rtc.exe
@SET GOOS=linux @SET GOOS=linux
@SET GOARCH=amd64 @SET GOARCH=amd64
@SET FILENAME=go2rtc_linux_amd64 @SET FILENAME=go2rtc_linux_amd64
go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx %FILENAME% go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx --best --lzma %FILENAME%
@SET GOOS=linux @SET GOOS=linux
@SET GOARCH=386 @SET GOARCH=386
@SET FILENAME=go2rtc_linux_i386 @SET FILENAME=go2rtc_linux_i386
go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx %FILENAME% go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx --best --lzma %FILENAME%
@SET GOOS=linux @SET GOOS=linux
@SET GOARCH=arm64 @SET GOARCH=arm64
@SET FILENAME=go2rtc_linux_arm64 @SET FILENAME=go2rtc_linux_arm64
go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx %FILENAME% go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx --best --lzma %FILENAME%
@SET GOOS=linux @SET GOOS=linux
@SET GOARCH=arm @SET GOARCH=arm
@SET GOARM=7 @SET GOARM=7
@SET FILENAME=go2rtc_linux_arm @SET FILENAME=go2rtc_linux_arm
go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx %FILENAME% go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx --best --lzma %FILENAME%
@SET GOOS=linux @SET GOOS=linux
@SET GOARCH=arm @SET GOARCH=arm
@SET GOARM=6 @SET GOARM=6
@SET FILENAME=go2rtc_linux_armv6 @SET FILENAME=go2rtc_linux_armv6
go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx %FILENAME% go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx --best --lzma %FILENAME%
@SET GOOS=linux @SET GOOS=linux
@SET GOARCH=mipsle @SET GOARCH=mipsle
@SET FILENAME=go2rtc_linux_mipsel @SET FILENAME=go2rtc_linux_mipsel
go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx %FILENAME% go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx --best --lzma %FILENAME%
@SET GOTOOLCHAIN=go1.20.14 @SET GOTOOLCHAIN=go1.20.14
@SET GOOS=darwin @SET GOOS=darwin