mirror of
https://github.com/pion/mediadevices.git
synced 2025-09-27 12:52:20 +08:00
Compare commits
14 Commits
fork-merge
...
v0.3.5
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0d09f7f458 | ||
![]() |
e780bdc6f9 | ||
![]() |
ff18b21629 | ||
![]() |
eaf9ff42a8 | ||
![]() |
5ba49e03e7 | ||
![]() |
1250e06923 | ||
![]() |
651c847674 | ||
![]() |
3b2316081e | ||
![]() |
70261260cb | ||
![]() |
548cdac668 | ||
![]() |
79f9fc31f6 | ||
![]() |
1f92ea40da | ||
![]() |
4beb7e5a23 | ||
![]() |
9bb5755cd2 |
12
.github/workflows/ci.yaml
vendored
12
.github/workflows/ci.yaml
vendored
@@ -17,9 +17,9 @@ jobs:
|
|||||||
name: Linux Go ${{ matrix.go }}
|
name: Linux Go ${{ matrix.go }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go }}
|
go-version: ${{ matrix.go }}
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -43,9 +43,9 @@ jobs:
|
|||||||
name: Darwin Go ${{ matrix.go }}
|
name: Darwin Go ${{ matrix.go }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go }}
|
go-version: ${{ matrix.go }}
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@@ -62,9 +62,9 @@ jobs:
|
|||||||
name: Check Licenses
|
name: Check Licenses
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.16'
|
go-version: '1.16'
|
||||||
- name: Installing go-licenses
|
- name: Installing go-licenses
|
||||||
|
2
.github/workflows/renovate-go-mod-fix.yaml
vendored
2
.github/workflows/renovate-go-mod-fix.yaml
vendored
@@ -9,7 +9,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
- name: fix
|
- name: fix
|
||||||
|
8
go.mod
8
go.mod
@@ -3,13 +3,13 @@ module github.com/pion/mediadevices
|
|||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/blackjack/webcam v0.0.0-20200313125108-10ed912a8539
|
github.com/blackjack/webcam v0.0.0-20220329180758-ba064708e165
|
||||||
github.com/gen2brain/malgo v0.10.35
|
github.com/gen2brain/malgo v0.10.35
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329
|
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329
|
||||||
github.com/pion/logging v0.2.2
|
github.com/pion/logging v0.2.2
|
||||||
github.com/pion/rtp v1.7.4
|
github.com/pion/rtp v1.7.9
|
||||||
github.com/pion/webrtc/v3 v3.1.10
|
github.com/pion/webrtc/v3 v3.1.27
|
||||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
|
golang.org/x/image v0.0.0-20220321031419-a8550c1d254a
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
)
|
)
|
||||||
|
81
go.sum
81
go.sum
@@ -1,5 +1,5 @@
|
|||||||
github.com/blackjack/webcam v0.0.0-20200313125108-10ed912a8539 h1:1aIqYfg9s9RETAJHGfVKZW4ok0b22p4QTwk8MsdRtPs=
|
github.com/blackjack/webcam v0.0.0-20220329180758-ba064708e165 h1:QsIbRyO2tn5eSJZ/skuDqSTo0GWI5H4G1AT7Mm2H0Nw=
|
||||||
github.com/blackjack/webcam v0.0.0-20200313125108-10ed912a8539/go.mod h1:G0X+rEqYPWSq0dG8OMf8M446MtKytzpPjgS3HbdOJZ4=
|
github.com/blackjack/webcam v0.0.0-20220329180758-ba064708e165/go.mod h1:G0X+rEqYPWSq0dG8OMf8M446MtKytzpPjgS3HbdOJZ4=
|
||||||
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=
|
||||||
@@ -17,10 +17,12 @@ 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-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.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
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.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.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.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 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
@@ -40,19 +42,19 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI
|
|||||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
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.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
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/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.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.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg=
|
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 h1:piB93s8LGmbECrpO84DnkIVWasRMk3IimbcXkTQLE6E=
|
||||||
github.com/pion/datachannel v1.5.2/go.mod h1:FTGQWaHrdCwIJ1rw6xBIfZVkslikjShim5yr05XFuCQ=
|
github.com/pion/datachannel v1.5.2/go.mod h1:FTGQWaHrdCwIJ1rw6xBIfZVkslikjShim5yr05XFuCQ=
|
||||||
github.com/pion/dtls/v2 v2.0.9/go.mod h1:O0Wr7si/Zj5/EBFlDzDd6UtVxx25CE1r7XM7BQKYQho=
|
github.com/pion/dtls/v2 v2.1.3 h1:3UF7udADqous+M2R5Uo2q/YaP4EzUoWKdfX2oscCUio=
|
||||||
github.com/pion/dtls/v2 v2.0.10 h1:wgys7gPR1NMbWjmjJ3CW7lkUGaun8djgH8nahpNLnxI=
|
github.com/pion/dtls/v2 v2.1.3/go.mod h1:o6+WvyLDAlXF7YiPB/RlskRoeK+/JtuaZa5emwQcWus=
|
||||||
github.com/pion/dtls/v2 v2.0.10/go.mod h1:00OxfeCRWHShcqT9jx8pKKmBWuTt0NCZoVPCaC4VKvU=
|
github.com/pion/ice/v2 v2.2.2 h1:UfmAslxZ0u0itVjA4x7aw7WeQIv22FdF8VjW9cM+74g=
|
||||||
github.com/pion/ice/v2 v2.1.14 h1:nD9GZs3MiR1/dPa5EiMRMe8hLBG3/qqCdx/hTS2g8VE=
|
github.com/pion/ice/v2 v2.2.2/go.mod h1:vLI7dFqxw8zMSb9J+ca74XU7JjLhddgfQB9+BbTydCo=
|
||||||
github.com/pion/ice/v2 v2.1.14/go.mod h1:ovgYHUmwYLlRvcCLI67PnQ5YGe+upXZbGgllBDG/ktU=
|
github.com/pion/interceptor v0.1.10 h1:DJ2GjMGm4XGIQgMJxuEpdaExdY/6RdngT7Uh4oVmquU=
|
||||||
github.com/pion/interceptor v0.1.0 h1:SlXKaDlEvSl7cr4j8fJykzVz4UdH+7UDtcvx+u01wLU=
|
github.com/pion/interceptor v0.1.10/go.mod h1:Lh3JSl/cbJ2wP8I3ccrjh1K/deRGRn3UlSPuOTiHb6U=
|
||||||
github.com/pion/interceptor v0.1.0/go.mod h1:j5NIl3tJJPB3u8+Z2Xz8MZs/VV6rc+If9mXEKNuFmEM=
|
|
||||||
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
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/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||||
github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw=
|
github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw=
|
||||||
@@ -60,64 +62,62 @@ 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 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.6/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0=
|
github.com/pion/rtcp v1.2.6/go.mod h1:52rMNPWFsjr39z9B9MhnkqhPLoeHTv1aN63o/42bWE0=
|
||||||
github.com/pion/rtcp v1.2.8/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo=
|
|
||||||
github.com/pion/rtcp v1.2.9 h1:1ujStwg++IOLIEoOiIQ2s+qBuJ1VN81KW+9pMPsif+U=
|
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/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.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/rtp v1.7.4/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko=
|
||||||
github.com/pion/sctp v1.8.0 h1:6erMF2qmQwXr+0iB1lm0AUSmDr9LdmpaBzgSVAEgehw=
|
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.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 h1:2Kf+dgrzJflNCSw3TV5v2VLeI0s/qkzy2r5jlR0wzf8=
|
||||||
github.com/pion/sdp/v3 v3.0.4/go.mod h1:bNiSknmJE0HYBprTHXKPQ3+JjacTv5uap92ueJZKsRk=
|
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 h1:ks3wcTvIUE/GHndO3FAvROQ9opy0uLELpwHJaQ1yqhQ=
|
||||||
github.com/pion/srtp/v2 v2.0.5/go.mod h1:8k6AJlal740mrZ6WYxc4Dg6qDqqhxoRG2GSjlUhDF0A=
|
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 h1:uLUCBCkQby4S1cf6CGuR9QrVOKcvUwFeemaC865QHDg=
|
||||||
github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA=
|
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.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/transport v0.12.3/go.mod h1:OViWW9SP2peE/HbwBvARicmAVnesphkNkCVZIWJ6q9A=
|
||||||
github.com/pion/turn/v2 v2.0.5 h1:iwMHqDfPEDEOFzwWKT56eFmh6DYC6o/+xnLAEzgISbA=
|
github.com/pion/transport v0.13.0 h1:KWTA5ZrQogizzYwPEciGtHPLwpAjE91FgXnyu+Hv2uY=
|
||||||
github.com/pion/turn/v2 v2.0.5/go.mod h1:APg43CFyt/14Uy7heYUOGWdkem/Wu4PhCO/bjyrTqMw=
|
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 h1:8UAPvyqmsxK8oOjloDk4wUt63TzFe9WEJkg5lChlj7o=
|
||||||
github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M=
|
github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M=
|
||||||
github.com/pion/webrtc/v3 v3.1.10 h1:DO99F6/X1HrQho3LxTWHPjI3c388btBf56lR5UNRNNk=
|
github.com/pion/webrtc/v3 v3.1.27 h1:yQ6TuHKJR/vro3nLZMfPv+WGf7T1/4ItaQeuzIZLXs4=
|
||||||
github.com/pion/webrtc/v3 v3.1.10/go.mod h1:eL2HHZOvX+W+Q+lenuidTrWfMD9gG3aobtGcCqJ5G48=
|
github.com/pion/webrtc/v3 v3.1.27/go.mod h1:hdduI+Rx0cpGvva18j0gKy/Iak611WPyhUIXs5W/FuI=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||||
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/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
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=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
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-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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 h1:71vQrMauZZhcTVK6KdYM+rklehEEwb3E+ZhaE5jrPrE=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
|
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/image v0.0.0-20220321031419-a8550c1d254a h1:LnH9RNcpPv5Kzi15lXg42lYMPUf0x8CuPv1YnvBWZAg=
|
||||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
|
golang.org/x/image v0.0.0-20220321031419-a8550c1d254a/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
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-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-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-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-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-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-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-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-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211005001312-d4b1ae081e3b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI=
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
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-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-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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -132,15 +132,16 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-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-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-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-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
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-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.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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/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-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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
@@ -155,6 +156,8 @@ 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.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.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
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 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/pion/mediadevices/pkg/driver"
|
"github.com/pion/mediadevices/pkg/driver"
|
||||||
_ "github.com/pion/mediadevices/pkg/driver/audiotest"
|
_ "github.com/pion/mediadevices/pkg/driver/audiotest"
|
||||||
_ "github.com/pion/mediadevices/pkg/driver/videotest"
|
_ "github.com/pion/mediadevices/pkg/driver/videotest"
|
||||||
|
"github.com/pion/mediadevices/pkg/frame"
|
||||||
"github.com/pion/mediadevices/pkg/prop"
|
"github.com/pion/mediadevices/pkg/prop"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -97,20 +98,58 @@ func TestSelectBestDriverConstraintsResultIsSetProperly(t *testing.T) {
|
|||||||
t.Fatal("expect to get at least 1 property")
|
t.Fatal("expect to get at least 1 property")
|
||||||
}
|
}
|
||||||
expectedProp := driver.Properties()[0]
|
expectedProp := driver.Properties()[0]
|
||||||
// Since this is a continuous value, bestConstraints should be set with the value that user specified
|
|
||||||
expectedProp.FrameRate = 30.0
|
|
||||||
|
|
||||||
wantConstraints := MediaTrackConstraints{
|
// By reducing the value from the driver by a tiny amount, this property should be chosen.
|
||||||
MediaConstraints: prop.MediaConstraints{
|
|
||||||
VideoConstraints: prop.VideoConstraints{
|
|
||||||
// By reducing the width from the driver by a tiny amount, this property should be chosen.
|
|
||||||
// At the same time, we'll be able to find out if the return constraints will be properly set
|
// At the same time, we'll be able to find out if the return constraints will be properly set
|
||||||
// to the best constraints.
|
// to the best constraints.
|
||||||
Width: prop.Int(expectedProp.Width - 1),
|
cases := map[string]struct {
|
||||||
Height: prop.Int(expectedProp.Width),
|
width, height int
|
||||||
FrameFormat: prop.FrameFormat(expectedProp.FrameFormat),
|
frameFormat frame.Format
|
||||||
FrameRate: prop.Float(30.0),
|
frameRate float32
|
||||||
|
}{
|
||||||
|
"DifferentWidth": {
|
||||||
|
width: expectedProp.Width - 1,
|
||||||
|
height: expectedProp.Height,
|
||||||
|
frameFormat: expectedProp.FrameFormat,
|
||||||
|
frameRate: expectedProp.FrameRate,
|
||||||
},
|
},
|
||||||
|
"DifferentHeight": {
|
||||||
|
width: expectedProp.Width,
|
||||||
|
height: expectedProp.Height - 1,
|
||||||
|
frameFormat: expectedProp.FrameFormat,
|
||||||
|
frameRate: expectedProp.FrameRate,
|
||||||
|
},
|
||||||
|
"DifferentFrameFormat": {
|
||||||
|
width: expectedProp.Width,
|
||||||
|
height: expectedProp.Height,
|
||||||
|
frameFormat: frame.FormatI420,
|
||||||
|
frameRate: expectedProp.FrameRate,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, c := range cases {
|
||||||
|
c := c
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
var vc prop.VideoConstraints
|
||||||
|
|
||||||
|
if c.frameRate >= 0 {
|
||||||
|
vc = prop.VideoConstraints{
|
||||||
|
Width: prop.Int(c.width),
|
||||||
|
Height: prop.Int(c.height),
|
||||||
|
FrameFormat: prop.FrameFormat(c.frameFormat),
|
||||||
|
FrameRate: prop.Float(c.frameRate),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// do not specify the framerate
|
||||||
|
vc = prop.VideoConstraints{
|
||||||
|
Width: prop.Int(c.width),
|
||||||
|
Height: prop.Int(c.height),
|
||||||
|
FrameFormat: prop.FrameFormat(c.frameFormat),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wantConstraints := MediaTrackConstraints{
|
||||||
|
MediaConstraints: prop.MediaConstraints{
|
||||||
|
VideoConstraints: vc,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,4 +169,74 @@ func TestSelectBestDriverConstraintsResultIsSetProperly(t *testing.T) {
|
|||||||
s.FrameRate != expectedProp.FrameRate {
|
s.FrameRate != expectedProp.FrameRate {
|
||||||
t.Fatalf("failed to return best constraints\nexpected:\n%v\n\ngot:\n%v", expectedProp, bestConstraints.selectedMedia)
|
t.Fatalf("failed to return best constraints\nexpected:\n%v\n\ngot:\n%v", expectedProp, bestConstraints.selectedMedia)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSelectBestDriverConstraintsNoFit(t *testing.T) {
|
||||||
|
filterFn := driver.FilterVideoRecorder()
|
||||||
|
drivers := driver.GetManager().Query(filterFn)
|
||||||
|
if len(drivers) == 0 {
|
||||||
|
t.Fatal("expect to get at least 1 driver")
|
||||||
|
}
|
||||||
|
|
||||||
|
driver := drivers[0]
|
||||||
|
err := driver.Open()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expect to open driver successfully")
|
||||||
|
}
|
||||||
|
defer driver.Close()
|
||||||
|
|
||||||
|
if len(driver.Properties()) == 0 {
|
||||||
|
t.Fatal("expect to get at least 1 property")
|
||||||
|
}
|
||||||
|
expectedProp := driver.Properties()[0]
|
||||||
|
|
||||||
|
cases := map[string]struct {
|
||||||
|
width, height int
|
||||||
|
frameFormat frame.Format
|
||||||
|
frameRate float32
|
||||||
|
}{
|
||||||
|
"DifferentWidth": {
|
||||||
|
width: expectedProp.Width - 1,
|
||||||
|
height: expectedProp.Height,
|
||||||
|
frameFormat: expectedProp.FrameFormat,
|
||||||
|
frameRate: expectedProp.FrameRate,
|
||||||
|
},
|
||||||
|
"DifferentHeight": {
|
||||||
|
width: expectedProp.Width,
|
||||||
|
height: expectedProp.Height - 1,
|
||||||
|
frameFormat: expectedProp.FrameFormat,
|
||||||
|
frameRate: expectedProp.FrameRate,
|
||||||
|
},
|
||||||
|
"DifferentFrameFormat": {
|
||||||
|
width: expectedProp.Width,
|
||||||
|
height: expectedProp.Height,
|
||||||
|
frameFormat: frame.FormatI420,
|
||||||
|
frameRate: expectedProp.FrameRate,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, c := range cases {
|
||||||
|
c := c
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
wantConstraints := MediaTrackConstraints{
|
||||||
|
MediaConstraints: prop.MediaConstraints{
|
||||||
|
VideoConstraints: prop.VideoConstraints{
|
||||||
|
Width: prop.IntExact(c.width),
|
||||||
|
Height: prop.IntExact(c.height),
|
||||||
|
FrameFormat: prop.FrameFormatExact(c.frameFormat),
|
||||||
|
FrameRate: prop.FloatExact(c.frameRate),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err := selectBestDriver(filterFn, wantConstraints)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expect to not find a driver that fits the constraints")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@ package avfoundation
|
|||||||
// }
|
// }
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@@ -96,6 +97,8 @@ type ReadCloser struct {
|
|||||||
dataChan chan []byte
|
dataChan chan []byte
|
||||||
id handleID
|
id handleID
|
||||||
onClose func()
|
onClose func()
|
||||||
|
cancelCtx context.Context
|
||||||
|
cancelFunc func()
|
||||||
}
|
}
|
||||||
|
|
||||||
func newReadCloser(onClose func()) *ReadCloser {
|
func newReadCloser(onClose func()) *ReadCloser {
|
||||||
@@ -103,12 +106,22 @@ func newReadCloser(onClose func()) *ReadCloser {
|
|||||||
rc.dataChan = make(chan []byte, 1)
|
rc.dataChan = make(chan []byte, 1)
|
||||||
rc.onClose = onClose
|
rc.onClose = onClose
|
||||||
rc.id = register(rc.dataCb)
|
rc.id = register(rc.dataCb)
|
||||||
|
cancelCtx, cancelFunc := context.WithCancel(context.Background())
|
||||||
|
rc.cancelCtx = cancelCtx
|
||||||
|
rc.cancelFunc = cancelFunc
|
||||||
return &rc
|
return &rc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *ReadCloser) dataCb(data []byte) {
|
func (rc *ReadCloser) dataCb(data []byte) {
|
||||||
// TODO: add a policy for slow reader
|
// TODO: add a policy for slow reader
|
||||||
rc.dataChan <- data
|
if rc.cancelCtx.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-rc.cancelCtx.Done():
|
||||||
|
close(rc.dataChan)
|
||||||
|
case rc.dataChan <- data:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read reads raw data, the format is determined by the media type and property:
|
// Read reads raw data, the format is determined by the media type and property:
|
||||||
@@ -127,7 +140,7 @@ func (rc *ReadCloser) Close() {
|
|||||||
if rc.onClose != nil {
|
if rc.onClose != nil {
|
||||||
rc.onClose()
|
rc.onClose()
|
||||||
}
|
}
|
||||||
close(rc.dataChan)
|
rc.cancelFunc()
|
||||||
unregister(rc.id)
|
unregister(rc.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -81,16 +81,15 @@ Slice enc_encode(Encoder *e, Frame f, int *eresult) {
|
|||||||
Slice payload = {0};
|
Slice payload = {0};
|
||||||
|
|
||||||
if(e->force_key_frame == 1) {
|
if(e->force_key_frame == 1) {
|
||||||
info.eFrameType = videoFrameTypeI;
|
e->engine->ForceIntraFrame(true);
|
||||||
e->force_key_frame = 0;
|
e->force_key_frame = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pic.iPicWidth = f.width;
|
pic.iPicWidth = f.width;
|
||||||
pic.iPicHeight = f.height;
|
pic.iPicHeight = f.height;
|
||||||
pic.iColorFormat = videoFormatI420;
|
pic.iColorFormat = videoFormatI420;
|
||||||
// We always received I420 format
|
pic.iStride[0] = f.ystride;
|
||||||
pic.iStride[0] = pic.iPicWidth;
|
pic.iStride[1] = pic.iStride[2] = f.cstride;
|
||||||
pic.iStride[1] = pic.iStride[2] = pic.iPicWidth / 2;
|
|
||||||
pic.pData[0] = (unsigned char *)f.y;
|
pic.pData[0] = (unsigned char *)f.y;
|
||||||
pic.pData[1] = (unsigned char *)f.u;
|
pic.pData[1] = (unsigned char *)f.u;
|
||||||
pic.pData[2] = (unsigned char *)f.v;
|
pic.pData[2] = (unsigned char *)f.v;
|
||||||
|
@@ -12,6 +12,8 @@ typedef struct Slice {
|
|||||||
|
|
||||||
typedef struct Frame {
|
typedef struct Frame {
|
||||||
void *y, *u, *v;
|
void *y, *u, *v;
|
||||||
|
int ystride;
|
||||||
|
int cstride;
|
||||||
int height;
|
int height;
|
||||||
int width;
|
int width;
|
||||||
} Frame;
|
} Frame;
|
||||||
|
@@ -68,6 +68,8 @@ func (e *encoder) Read() ([]byte, func(), error) {
|
|||||||
y: unsafe.Pointer(&yuvImg.Y[0]),
|
y: unsafe.Pointer(&yuvImg.Y[0]),
|
||||||
u: unsafe.Pointer(&yuvImg.Cb[0]),
|
u: unsafe.Pointer(&yuvImg.Cb[0]),
|
||||||
v: unsafe.Pointer(&yuvImg.Cr[0]),
|
v: unsafe.Pointer(&yuvImg.Cr[0]),
|
||||||
|
ystride: C.int(yuvImg.YStride),
|
||||||
|
cstride: C.int(yuvImg.CStride),
|
||||||
height: C.int(bounds.Max.Y - bounds.Min.Y),
|
height: C.int(bounds.Max.Y - bounds.Min.Y),
|
||||||
width: C.int(bounds.Max.X - bounds.Min.X),
|
width: C.int(bounds.Max.X - bounds.Min.X),
|
||||||
}, &rv)
|
}, &rv)
|
||||||
|
@@ -18,6 +18,7 @@ typedef struct Encoder {
|
|||||||
x264_t *h;
|
x264_t *h;
|
||||||
x264_picture_t pic_in;
|
x264_picture_t pic_in;
|
||||||
x264_param_t param;
|
x264_param_t param;
|
||||||
|
int force_key_frame;
|
||||||
} Encoder;
|
} Encoder;
|
||||||
|
|
||||||
Encoder *enc_new(x264_param_t param, char *preset, int *rc) {
|
Encoder *enc_new(x264_param_t param, char *preset, int *rc) {
|
||||||
@@ -85,8 +86,14 @@ Slice enc_encode(Encoder *e, uint8_t *y, uint8_t *cb, uint8_t *cr, int *rc) {
|
|||||||
e->pic_in.img.plane[0] = y;
|
e->pic_in.img.plane[0] = y;
|
||||||
e->pic_in.img.plane[1] = cb;
|
e->pic_in.img.plane[1] = cb;
|
||||||
e->pic_in.img.plane[2] = cr;
|
e->pic_in.img.plane[2] = cr;
|
||||||
|
if (e->force_key_frame) {
|
||||||
|
e->pic_in.i_type = X264_TYPE_IDR;
|
||||||
|
} else {
|
||||||
|
e->pic_in.i_type = X264_TYPE_AUTO;
|
||||||
|
}
|
||||||
|
|
||||||
int frame_size = x264_encoder_encode(e->h, &nal, &i_nal, &e->pic_in, &pic_out);
|
int frame_size = x264_encoder_encode(e->h, &nal, &i_nal, &e->pic_in, &pic_out);
|
||||||
|
e->force_key_frame = 0;
|
||||||
Slice s = {.data_len = frame_size};
|
Slice s = {.data_len = frame_size};
|
||||||
if (frame_size <= 0) {
|
if (frame_size <= 0) {
|
||||||
*rc = ERR_ENCODE;
|
*rc = ERR_ENCODE;
|
||||||
|
@@ -129,7 +129,8 @@ func (e *encoder) SetBitRate(b int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *encoder) ForceKeyFrame() error {
|
func (e *encoder) ForceKeyFrame() error {
|
||||||
panic("ForceKeyFrame is not implemented")
|
e.engine.force_key_frame = C.int(1)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *encoder) Close() error {
|
func (e *encoder) Close() error {
|
||||||
|
@@ -13,6 +13,7 @@ import (
|
|||||||
type camera struct {
|
type camera struct {
|
||||||
device avfoundation.Device
|
device avfoundation.Device
|
||||||
session *avfoundation.Session
|
session *avfoundation.Session
|
||||||
|
rcClose func()
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -43,6 +44,9 @@ func (cam *camera) Open() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cam *camera) Close() error {
|
func (cam *camera) Close() error {
|
||||||
|
if cam.rcClose != nil {
|
||||||
|
cam.rcClose()
|
||||||
|
}
|
||||||
return cam.session.Close()
|
return cam.session.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,6 +60,7 @@ func (cam *camera) VideoRecord(property prop.Media) (video.Reader, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
cam.rcClose = rc.Close
|
||||||
r := video.ReaderFunc(func() (image.Image, func(), error) {
|
r := video.ReaderFunc(func() (image.Image, func(), error) {
|
||||||
frame, _, err := rc.Read()
|
frame, _, err := rc.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -179,6 +179,13 @@ func (c *camera) VideoRecord(p prop.Media) (video.Reader, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.FrameRate > 0 {
|
||||||
|
err = c.cam.SetFramerate(float32(p.FrameRate))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := c.cam.StartStreaming(); err != nil {
|
if err := c.cam.StartStreaming(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -47,10 +47,6 @@ func (d *dummy) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *dummy) VideoRecord(p prop.Media) (video.Reader, error) {
|
func (d *dummy) VideoRecord(p prop.Media) (video.Reader, error) {
|
||||||
if p.FrameRate == 0 {
|
|
||||||
p.FrameRate = 30
|
|
||||||
}
|
|
||||||
|
|
||||||
colors := [][3]byte{
|
colors := [][3]byte{
|
||||||
{235, 128, 128},
|
{235, 128, 128},
|
||||||
{210, 16, 146},
|
{210, 16, 146},
|
||||||
@@ -143,6 +139,7 @@ func (d dummy) Properties() []prop.Media {
|
|||||||
Width: 640,
|
Width: 640,
|
||||||
Height: 480,
|
Height: 480,
|
||||||
FrameFormat: frame.FormatYUYV,
|
FrameFormat: frame.FormatYUYV,
|
||||||
|
FrameRate: 30,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,25 @@ type Encoding interface {
|
|||||||
// the proper data.
|
// the proper data.
|
||||||
Read(*ClientConn, *Rectangle, io.Reader) (Encoding, error)
|
Read(*ClientConn, *Rectangle, io.Reader) (Encoding, error)
|
||||||
}
|
}
|
||||||
|
type CursorEncoding struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*CursorEncoding) Type() int32 {
|
||||||
|
return -239
|
||||||
|
}
|
||||||
|
func (*CursorEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) {
|
||||||
|
size := int(rect.Height) * int(rect.Width) * int(c.PixelFormat.BPP) / 8
|
||||||
|
pixelBytes := make([]uint8, size)
|
||||||
|
if _, err := io.ReadFull(r, pixelBytes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
mask := ((int(rect.Width) + 7) / 8) * int(rect.Height)
|
||||||
|
maskBytes := make([]uint8, mask)
|
||||||
|
if _, err := io.ReadFull(r, maskBytes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &CursorEncoding{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// RawEncoding is raw pixel data sent by the server.
|
// RawEncoding is raw pixel data sent by the server.
|
||||||
//
|
//
|
||||||
@@ -32,6 +51,7 @@ func (*RawEncoding) Type() int32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (*RawEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) {
|
func (*RawEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) {
|
||||||
|
//fmt.Println("RawEncoding")
|
||||||
bytesPerPixel := c.PixelFormat.BPP / 8
|
bytesPerPixel := c.PixelFormat.BPP / 8
|
||||||
pixelBytes := make([]uint8, bytesPerPixel)
|
pixelBytes := make([]uint8, bytesPerPixel)
|
||||||
|
|
||||||
@@ -41,7 +61,7 @@ func (*RawEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding,
|
|||||||
}
|
}
|
||||||
|
|
||||||
colors := make([]Color, int(rect.Height)*int(rect.Width))
|
colors := make([]Color, int(rect.Height)*int(rect.Width))
|
||||||
rawPixels:=make([]uint32,int(rect.Height)*int(rect.Width))
|
rawPixels := make([]uint32, int(rect.Height)*int(rect.Width))
|
||||||
for y := uint16(0); y < rect.Height; y++ {
|
for y := uint16(0); y < rect.Height; y++ {
|
||||||
for x := uint16(0); x < rect.Width; x++ {
|
for x := uint16(0); x < rect.Width; x++ {
|
||||||
if _, err := io.ReadFull(r, pixelBytes); err != nil {
|
if _, err := io.ReadFull(r, pixelBytes); err != nil {
|
||||||
@@ -62,22 +82,28 @@ func (*RawEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding,
|
|||||||
color.R = uint16((rawPixel >> c.PixelFormat.RedShift) & uint32(c.PixelFormat.RedMax))
|
color.R = uint16((rawPixel >> c.PixelFormat.RedShift) & uint32(c.PixelFormat.RedMax))
|
||||||
color.G = uint16((rawPixel >> c.PixelFormat.GreenShift) & uint32(c.PixelFormat.GreenMax))
|
color.G = uint16((rawPixel >> c.PixelFormat.GreenShift) & uint32(c.PixelFormat.GreenMax))
|
||||||
color.B = uint16((rawPixel >> c.PixelFormat.BlueShift) & uint32(c.PixelFormat.BlueMax))
|
color.B = uint16((rawPixel >> c.PixelFormat.BlueShift) & uint32(c.PixelFormat.BlueMax))
|
||||||
|
if c.PixelFormat.BPP == 16 {
|
||||||
|
color.B = color.B<<3 | color.B>>2
|
||||||
|
color.G = color.G<<2 | color.G>>2
|
||||||
|
color.R = color.R<<3 | color.R>>2
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*color = c.ColorMap[rawPixel]
|
*color = c.ColorMap[rawPixel]
|
||||||
}
|
}
|
||||||
rawPixels[int(y)*int(rect.Width)+int(x)]=uint32(color.B)<<16 | uint32(color.G)<<8 | uint32(color.R)
|
rawPixels[int(y)*int(rect.Width)+int(x)] = uint32(0xff)<<24 | uint32(color.B)<<16 | uint32(color.G)<<8 | uint32(color.R)
|
||||||
//fmt.Printf("%x %x",rawPixel,rawPixels[int(y)*int(rect.Width)+int(x)])
|
//fmt.Printf("%x %x",rawPixel,rawPixels[int(y)*int(rect.Width)+int(x)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &RawEncoding{colors,rawPixels}, nil
|
return &RawEncoding{colors, rawPixels}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ZlibEncoding is raw pixel data sent by the server compressed by Zlib.
|
// ZlibEncoding is raw pixel data sent by the server compressed by Zlib.
|
||||||
//
|
//
|
||||||
// A single Zlib stream is created. There is only a single header for a framebuffer request response.
|
// A single Zlib stream is created. There is only a single header for a framebuffer request response.
|
||||||
type ZlibEncoding struct {
|
type ZlibEncoding struct {
|
||||||
Colors []Color
|
Colors []Color
|
||||||
RawPixel[] uint32
|
RawPixel []uint32
|
||||||
ZStream *bytes.Buffer
|
ZStream *bytes.Buffer
|
||||||
ZReader io.ReadCloser
|
ZReader io.ReadCloser
|
||||||
}
|
}
|
||||||
@@ -87,6 +113,7 @@ func (*ZlibEncoding) Type() int32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ze *ZlibEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) {
|
func (ze *ZlibEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) {
|
||||||
|
//fmt.Println("ZlibEncoding")
|
||||||
bytesPerPixel := c.PixelFormat.BPP / 8
|
bytesPerPixel := c.PixelFormat.BPP / 8
|
||||||
pixelBytes := make([]uint8, bytesPerPixel)
|
pixelBytes := make([]uint8, bytesPerPixel)
|
||||||
|
|
||||||
@@ -98,7 +125,6 @@ func (ze *ZlibEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encod
|
|||||||
// Format
|
// Format
|
||||||
// 4 bytes | uint32 | length
|
// 4 bytes | uint32 | length
|
||||||
// 'length' bytes | []byte | zlibData
|
// 'length' bytes | []byte | zlibData
|
||||||
|
|
||||||
// Read zlib length
|
// Read zlib length
|
||||||
var zipLength uint32
|
var zipLength uint32
|
||||||
err := binary.Read(r, binary.BigEndian, &zipLength)
|
err := binary.Read(r, binary.BigEndian, &zipLength)
|
||||||
@@ -146,7 +172,7 @@ func (ze *ZlibEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encod
|
|||||||
colorReader := bytes.NewReader(colorBytes)
|
colorReader := bytes.NewReader(colorBytes)
|
||||||
|
|
||||||
colors := make([]Color, int(rect.Height)*int(rect.Width))
|
colors := make([]Color, int(rect.Height)*int(rect.Width))
|
||||||
rawPixels:=make([]uint32,int(rect.Height)*int(rect.Width))
|
rawPixels := make([]uint32, int(rect.Height)*int(rect.Width))
|
||||||
for y := uint16(0); y < rect.Height; y++ {
|
for y := uint16(0); y < rect.Height; y++ {
|
||||||
for x := uint16(0); x < rect.Width; x++ {
|
for x := uint16(0); x < rect.Width; x++ {
|
||||||
if _, err := io.ReadFull(colorReader, pixelBytes); err != nil {
|
if _, err := io.ReadFull(colorReader, pixelBytes); err != nil {
|
||||||
@@ -167,14 +193,19 @@ func (ze *ZlibEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encod
|
|||||||
color.R = uint16((rawPixel >> c.PixelFormat.RedShift) & uint32(c.PixelFormat.RedMax))
|
color.R = uint16((rawPixel >> c.PixelFormat.RedShift) & uint32(c.PixelFormat.RedMax))
|
||||||
color.G = uint16((rawPixel >> c.PixelFormat.GreenShift) & uint32(c.PixelFormat.GreenMax))
|
color.G = uint16((rawPixel >> c.PixelFormat.GreenShift) & uint32(c.PixelFormat.GreenMax))
|
||||||
color.B = uint16((rawPixel >> c.PixelFormat.BlueShift) & uint32(c.PixelFormat.BlueMax))
|
color.B = uint16((rawPixel >> c.PixelFormat.BlueShift) & uint32(c.PixelFormat.BlueMax))
|
||||||
|
if c.PixelFormat.BPP == 16 {
|
||||||
|
color.B = color.B<<3 | color.B>>2
|
||||||
|
color.G = color.G<<2 | color.G>>2
|
||||||
|
color.R = color.R<<3 | color.R>>2
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*color = c.ColorMap[rawPixel]
|
*color = c.ColorMap[rawPixel]
|
||||||
}
|
}
|
||||||
rawPixels[int(y)*int(rect.Width)+int(x)]=uint32(color.B)<<16 | uint32(color.G)<<8 | uint32(color.R)
|
rawPixels[int(y)*int(rect.Width)+int(x)] = uint32(0xff)<<24 | uint32(color.B)<<16 | uint32(color.G)<<8 | uint32(color.R)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ZlibEncoding{Colors: colors,RawPixel: rawPixels}, nil
|
return &ZlibEncoding{Colors: colors, RawPixel: rawPixels}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ze *ZlibEncoding) Close() {
|
func (ze *ZlibEncoding) Close() {
|
||||||
|
@@ -5,13 +5,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pion/mediadevices/pkg/driver/vncdriver/vnc"
|
|
||||||
"image"
|
"image"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pion/mediadevices/pkg/driver/vncdriver/vnc"
|
||||||
|
|
||||||
"github.com/pion/mediadevices/pkg/frame"
|
"github.com/pion/mediadevices/pkg/frame"
|
||||||
"github.com/pion/mediadevices/pkg/io/video"
|
"github.com/pion/mediadevices/pkg/io/video"
|
||||||
"github.com/pion/mediadevices/pkg/prop"
|
"github.com/pion/mediadevices/pkg/prop"
|
||||||
@@ -32,12 +33,12 @@ func NewVnc(vncAddr string) *vncDevice {
|
|||||||
return &vncDevice{vncAddr: vncAddr}
|
return &vncDevice{vncAddr: vncAddr}
|
||||||
}
|
}
|
||||||
func (d *vncDevice) PointerEvent(mask uint8, x, y uint16) {
|
func (d *vncDevice) PointerEvent(mask uint8, x, y uint16) {
|
||||||
if d.vClient!=nil{
|
if d.vClient != nil {
|
||||||
d.vClient.PointerEvent(vnc.ButtonMask(mask), x, y)
|
d.vClient.PointerEvent(vnc.ButtonMask(mask), x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (d *vncDevice) KeyEvent(keysym uint32, down bool) {
|
func (d *vncDevice) KeyEvent(keysym uint32, down bool) {
|
||||||
if d.vClient!=nil {
|
if d.vClient != nil {
|
||||||
d.vClient.KeyEvent(keysym, down)
|
d.vClient.KeyEvent(keysym, down)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,7 +50,10 @@ func (d *vncDevice) Open() error {
|
|||||||
d.closed = ctx.Done()
|
d.closed = ctx.Done()
|
||||||
d.cancel = cancel
|
d.cancel = cancel
|
||||||
msg := make(chan vnc.ServerMessage, 1)
|
msg := make(chan vnc.ServerMessage, 1)
|
||||||
|
//auth:=new(vnc.PasswordAuth)
|
||||||
|
//auth.Password="####"
|
||||||
conf := vnc.ClientConfig{
|
conf := vnc.ClientConfig{
|
||||||
|
//Auth: []vnc.ClientAuth{auth},
|
||||||
ServerMessageCh: msg,
|
ServerMessageCh: msg,
|
||||||
Exclusive: false,
|
Exclusive: false,
|
||||||
}
|
}
|
||||||
@@ -66,6 +70,7 @@ func (d *vncDevice) Open() error {
|
|||||||
d.vClient.SetEncodings([]vnc.Encoding{
|
d.vClient.SetEncodings([]vnc.Encoding{
|
||||||
&vnc.ZlibEncoding{},
|
&vnc.ZlibEncoding{},
|
||||||
&vnc.RawEncoding{},
|
&vnc.RawEncoding{},
|
||||||
|
&vnc.CursorEncoding{},
|
||||||
})
|
})
|
||||||
d.w = int(d.vClient.FrameBufferWidth)
|
d.w = int(d.vClient.FrameBufferWidth)
|
||||||
d.h = int(d.vClient.FrameBufferHeight)
|
d.h = int(d.vClient.FrameBufferHeight)
|
||||||
@@ -89,6 +94,9 @@ func (d *vncDevice) Open() error {
|
|||||||
for _, rect := range t.Rectangles {
|
for _, rect := range t.Rectangles {
|
||||||
var pix []uint32
|
var pix []uint32
|
||||||
switch t := rect.Enc.(type) {
|
switch t := rect.Enc.(type) {
|
||||||
|
case *vnc.CursorEncoding:
|
||||||
|
//ignore remote cursor messages
|
||||||
|
continue
|
||||||
case *vnc.RawEncoding:
|
case *vnc.RawEncoding:
|
||||||
pix = t.RawPixel
|
pix = t.RawPixel
|
||||||
case *vnc.ZlibEncoding:
|
case *vnc.ZlibEncoding:
|
||||||
@@ -97,19 +105,16 @@ func (d *vncDevice) Open() error {
|
|||||||
for y := int(rect.Y); y < int(rect.Height+rect.Y); y++ {
|
for y := int(rect.Y); y < int(rect.Height+rect.Y); y++ {
|
||||||
for x := int(rect.X); x < int(rect.Width+rect.X); x++ {
|
for x := int(rect.X); x < int(rect.Width+rect.X); x++ {
|
||||||
binary.LittleEndian.PutUint32(d.rawPixel[(y*d.w+x)*4:], pix[(y-int(rect.Y))*int(rect.Width)+(x-int(rect.X))])
|
binary.LittleEndian.PutUint32(d.rawPixel[(y*d.w+x)*4:], pix[(y-int(rect.Y))*int(rect.Width)+(x-int(rect.X))])
|
||||||
//BigEndian
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//time.Sleep(33 * time.Millisecond)
|
|
||||||
d.vClient.FramebufferUpdateRequest(true, 0, 0, uint16(d.w), uint16(d.h))
|
d.vClient.FramebufferUpdateRequest(true, 0, 0, uint16(d.w), uint16(d.h))
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
|
||||||
}
|
}
|
||||||
case <-time.After(10 * time.Second):
|
case <-time.After(10 * time.Second):
|
||||||
//fmt.Println("Timeout FramebufferUpdate")
|
|
||||||
if d.vClient.FramebufferUpdateRequest(true, 0, 0, uint16(d.w), uint16(d.h)) != nil {
|
if d.vClient.FramebufferUpdateRequest(true, 0, 0, uint16(d.w), uint16(d.h)) != nil {
|
||||||
d.cancel()
|
d.cancel()
|
||||||
return
|
return
|
||||||
@@ -137,13 +142,12 @@ func (d *vncDevice) Close() error {
|
|||||||
|
|
||||||
func (d *vncDevice) VideoRecord(p prop.Media) (video.Reader, error) {
|
func (d *vncDevice) VideoRecord(p prop.Media) (video.Reader, error) {
|
||||||
if p.FrameRate == 0 {
|
if p.FrameRate == 0 {
|
||||||
p.FrameRate = 15
|
p.FrameRate = 30
|
||||||
}
|
}
|
||||||
|
|
||||||
tick := time.NewTicker(time.Duration(float32(time.Second) / p.FrameRate))
|
tick := time.NewTicker(time.Duration(float32(time.Second) / p.FrameRate))
|
||||||
d.tick = tick
|
d.tick = tick
|
||||||
closed := d.closed
|
closed := d.closed
|
||||||
pixs := make([]byte, d.h*d.w*4)
|
|
||||||
r := video.ReaderFunc(func() (image.Image, func(), error) {
|
r := video.ReaderFunc(func() (image.Image, func(), error) {
|
||||||
select {
|
select {
|
||||||
case <-closed:
|
case <-closed:
|
||||||
@@ -153,9 +157,8 @@ func (d *vncDevice) VideoRecord(p prop.Media) (video.Reader, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
<-tick.C
|
<-tick.C
|
||||||
copy(pixs, d.rawPixel)
|
|
||||||
return &image.RGBA{
|
return &image.RGBA{
|
||||||
Pix: pixs,
|
Pix: d.rawPixel,
|
||||||
Stride: 4,
|
Stride: 4,
|
||||||
Rect: image.Rect(0, 0, d.w, d.h),
|
Rect: image.Rect(0, 0, d.w, d.h),
|
||||||
}, func() {}, nil
|
}, func() {}, nil
|
||||||
|
@@ -109,7 +109,7 @@ func Scale(width, height int, scaler Scaler) TransformFunc {
|
|||||||
yDy := rect.Dy()
|
yDy := rect.Dy()
|
||||||
cRect := fixedRect(rect, i1.SubsampleRatio)
|
cRect := fixedRect(rect, i1.SubsampleRatio)
|
||||||
cDx := cRect.Dx()
|
cDx := cRect.Dx()
|
||||||
cDy := cRect.Dx()
|
cDy := cRect.Dy()
|
||||||
yLen := yDx * yDy
|
yLen := yDx * yDy
|
||||||
cLen := cDx * cDy
|
cLen := cDx * cDy
|
||||||
if len(imgDst.Y) < yLen {
|
if len(imgDst.Y) < yLen {
|
||||||
|
@@ -36,6 +36,32 @@ func TestScale(t *testing.T) {
|
|||||||
Rect: image.Rect(0, 0, 2, 2),
|
Rect: image.Rect(0, 0, 2, 2),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"RGBASameSize": {
|
||||||
|
src: &image.RGBA{
|
||||||
|
Pix: []uint8{
|
||||||
|
// R G B A | R G B A | R G B A | R G B A
|
||||||
|
0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF,
|
||||||
|
0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF,
|
||||||
|
0x00, 0x40, 0x00, 0xFF, 0x00, 0x40, 0x00, 0xFF, 0x00, 0x00, 0x60, 0xFF, 0x00, 0x00, 0x60, 0xFF,
|
||||||
|
0x00, 0x40, 0x00, 0xFF, 0x00, 0x40, 0x00, 0xFF, 0x00, 0x00, 0x60, 0xFF, 0x00, 0x00, 0x60, 0xFF,
|
||||||
|
},
|
||||||
|
Stride: 16,
|
||||||
|
Rect: image.Rect(0, 0, 4, 4),
|
||||||
|
},
|
||||||
|
width: 4,
|
||||||
|
height: 4,
|
||||||
|
expected: &image.RGBA{
|
||||||
|
Pix: []uint8{
|
||||||
|
// R G B A | R G B A | R G B A | R G B A
|
||||||
|
0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF,
|
||||||
|
0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF,
|
||||||
|
0x00, 0x40, 0x00, 0xFF, 0x00, 0x40, 0x00, 0xFF, 0x00, 0x00, 0x60, 0xFF, 0x00, 0x00, 0x60, 0xFF,
|
||||||
|
0x00, 0x40, 0x00, 0xFF, 0x00, 0x40, 0x00, 0xFF, 0x00, 0x00, 0x60, 0xFF, 0x00, 0x00, 0x60, 0xFF,
|
||||||
|
},
|
||||||
|
Stride: 16,
|
||||||
|
Rect: image.Rect(0, 0, 4, 4),
|
||||||
|
},
|
||||||
|
},
|
||||||
"I444": {
|
"I444": {
|
||||||
src: &image.YCbCr{
|
src: &image.YCbCr{
|
||||||
SubsampleRatio: image.YCbCrSubsampleRatio444,
|
SubsampleRatio: image.YCbCrSubsampleRatio444,
|
||||||
@@ -91,6 +117,70 @@ func TestScale(t *testing.T) {
|
|||||||
Rect: image.Rect(0, 0, 3, 3),
|
Rect: image.Rect(0, 0, 3, 3),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"I444SameSize": {
|
||||||
|
src: &image.YCbCr{
|
||||||
|
SubsampleRatio: image.YCbCrSubsampleRatio444,
|
||||||
|
Y: []uint8{
|
||||||
|
0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
|
||||||
|
},
|
||||||
|
Cb: []uint8{
|
||||||
|
0x20, 0x20, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x20, 0x20, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
},
|
||||||
|
Cr: []uint8{
|
||||||
|
0xE0, 0xE0, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0xE0, 0xE0, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x40, 0x40, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x40, 0x40, 0x80, 0x80,
|
||||||
|
},
|
||||||
|
YStride: 6,
|
||||||
|
CStride: 6,
|
||||||
|
Rect: image.Rect(0, 0, 6, 6),
|
||||||
|
},
|
||||||
|
width: 6,
|
||||||
|
height: 6,
|
||||||
|
expected: &image.YCbCr{
|
||||||
|
SubsampleRatio: image.YCbCrSubsampleRatio444,
|
||||||
|
Y: []uint8{
|
||||||
|
0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
|
||||||
|
},
|
||||||
|
Cb: []uint8{
|
||||||
|
0x20, 0x20, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x20, 0x20, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
},
|
||||||
|
Cr: []uint8{
|
||||||
|
0xE0, 0xE0, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0xE0, 0xE0, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x40, 0x40, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x40, 0x40, 0x80, 0x80,
|
||||||
|
},
|
||||||
|
YStride: 6,
|
||||||
|
CStride: 6,
|
||||||
|
Rect: image.Rect(0, 0, 6, 6),
|
||||||
|
},
|
||||||
|
},
|
||||||
"I422": {
|
"I422": {
|
||||||
src: &image.YCbCr{
|
src: &image.YCbCr{
|
||||||
SubsampleRatio: image.YCbCrSubsampleRatio422,
|
SubsampleRatio: image.YCbCrSubsampleRatio422,
|
||||||
@@ -155,6 +245,82 @@ func TestScale(t *testing.T) {
|
|||||||
Rect: image.Rect(0, 0, 4, 4),
|
Rect: image.Rect(0, 0, 4, 4),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"I422SameSize": {
|
||||||
|
src: &image.YCbCr{
|
||||||
|
SubsampleRatio: image.YCbCrSubsampleRatio422,
|
||||||
|
Y: []uint8{
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
},
|
||||||
|
Cb: []uint8{
|
||||||
|
0x20, 0x20, 0x80, 0x80,
|
||||||
|
0x20, 0x20, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0,
|
||||||
|
},
|
||||||
|
Cr: []uint8{
|
||||||
|
0xE0, 0xE0, 0x80, 0x80,
|
||||||
|
0xE0, 0xE0, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40,
|
||||||
|
},
|
||||||
|
YStride: 8,
|
||||||
|
CStride: 4,
|
||||||
|
Rect: image.Rect(0, 0, 8, 8),
|
||||||
|
},
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
expected: &image.YCbCr{
|
||||||
|
SubsampleRatio: image.YCbCrSubsampleRatio422,
|
||||||
|
Y: []uint8{
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
},
|
||||||
|
Cb: []uint8{
|
||||||
|
0x20, 0x20, 0x80, 0x80,
|
||||||
|
0x20, 0x20, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0,
|
||||||
|
},
|
||||||
|
Cr: []uint8{
|
||||||
|
0xE0, 0xE0, 0x80, 0x80,
|
||||||
|
0xE0, 0xE0, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0x80, 0x80,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40,
|
||||||
|
},
|
||||||
|
YStride: 8,
|
||||||
|
CStride: 4,
|
||||||
|
Rect: image.Rect(0, 0, 8, 8),
|
||||||
|
},
|
||||||
|
},
|
||||||
"I420": {
|
"I420": {
|
||||||
src: &image.YCbCr{
|
src: &image.YCbCr{
|
||||||
SubsampleRatio: image.YCbCrSubsampleRatio420,
|
SubsampleRatio: image.YCbCrSubsampleRatio420,
|
||||||
@@ -207,6 +373,118 @@ func TestScale(t *testing.T) {
|
|||||||
Rect: image.Rect(0, 0, 4, 4),
|
Rect: image.Rect(0, 0, 4, 4),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"I420SameSize": {
|
||||||
|
src: &image.YCbCr{
|
||||||
|
SubsampleRatio: image.YCbCrSubsampleRatio420,
|
||||||
|
Y: []uint8{
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
},
|
||||||
|
Cb: []uint8{
|
||||||
|
0x20, 0x20, 0x80, 0x80,
|
||||||
|
0x20, 0x20, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0,
|
||||||
|
},
|
||||||
|
Cr: []uint8{
|
||||||
|
0xE0, 0xE0, 0x80, 0x80,
|
||||||
|
0xE0, 0xE0, 0x80, 0x80,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40,
|
||||||
|
},
|
||||||
|
YStride: 8,
|
||||||
|
CStride: 4,
|
||||||
|
Rect: image.Rect(0, 0, 8, 8),
|
||||||
|
},
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
expected: &image.YCbCr{
|
||||||
|
SubsampleRatio: image.YCbCrSubsampleRatio420,
|
||||||
|
Y: []uint8{
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
},
|
||||||
|
Cb: []uint8{
|
||||||
|
0x20, 0x20, 0x80, 0x80,
|
||||||
|
0x20, 0x20, 0x80, 0x80,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0,
|
||||||
|
},
|
||||||
|
Cr: []uint8{
|
||||||
|
0xE0, 0xE0, 0x80, 0x80,
|
||||||
|
0xE0, 0xE0, 0x80, 0x80,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40,
|
||||||
|
},
|
||||||
|
YStride: 8,
|
||||||
|
CStride: 4,
|
||||||
|
Rect: image.Rect(0, 0, 8, 8),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"I420NonSquareImage": {
|
||||||
|
src: &image.YCbCr{
|
||||||
|
SubsampleRatio: image.YCbCrSubsampleRatio420,
|
||||||
|
Y: []uint8{
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x10, 0x10,
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x10, 0x10,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
},
|
||||||
|
Cb: []uint8{
|
||||||
|
0x20, 0x20, 0x80, 0x80, 0x50, 0x50,
|
||||||
|
0x20, 0x20, 0x80, 0x80, 0x50, 0x50,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0, 0x30, 0x30,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0, 0x30, 0x30,
|
||||||
|
},
|
||||||
|
Cr: []uint8{
|
||||||
|
0xE0, 0xE0, 0x80, 0x80, 0xB0, 0xB0,
|
||||||
|
0xE0, 0xE0, 0x80, 0x80, 0xB0, 0xB0,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40, 0xC0, 0xC0,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40, 0xC0, 0xC0,
|
||||||
|
},
|
||||||
|
YStride: 12,
|
||||||
|
CStride: 6,
|
||||||
|
Rect: image.Rect(0, 0, 12, 8),
|
||||||
|
},
|
||||||
|
width: 6,
|
||||||
|
height: 4,
|
||||||
|
expected: &image.YCbCr{
|
||||||
|
SubsampleRatio: image.YCbCrSubsampleRatio420,
|
||||||
|
Y: []uint8{
|
||||||
|
0xF0, 0x10, 0x00, 0x00, 0xF0, 0x10,
|
||||||
|
0x00, 0x00, 0x40, 0x00, 0x40, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x80, 0x30, 0x00, 0x30, 0x00,
|
||||||
|
},
|
||||||
|
Cb: []uint8{
|
||||||
|
0x20, 0x80, 0x50,
|
||||||
|
0x80, 0xE0, 0x30,
|
||||||
|
},
|
||||||
|
Cr: []uint8{
|
||||||
|
0xE0, 0x80, 0xB0,
|
||||||
|
0xF0, 0x40, 0xC0,
|
||||||
|
},
|
||||||
|
YStride: 6,
|
||||||
|
CStride: 3,
|
||||||
|
Rect: image.Rect(0, 0, 6, 4),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for name, algo := range scalerTestAlgos {
|
for name, algo := range scalerTestAlgos {
|
||||||
algo := algo
|
algo := algo
|
||||||
@@ -247,6 +525,100 @@ func TestScale(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestScaleFastBoxSampling(t *testing.T) {
|
||||||
|
cases := map[string]struct {
|
||||||
|
src image.Image
|
||||||
|
width, height int
|
||||||
|
expected image.Image
|
||||||
|
}{
|
||||||
|
"I420NonSquareImage": {
|
||||||
|
src: &image.YCbCr{
|
||||||
|
SubsampleRatio: image.YCbCrSubsampleRatio420,
|
||||||
|
Y: []uint8{
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x10, 0x10,
|
||||||
|
0xF0, 0xF0, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x10, 0x10,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x80, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
},
|
||||||
|
Cb: []uint8{
|
||||||
|
0x20, 0x20, 0x80, 0x80, 0x50, 0x50,
|
||||||
|
0x20, 0x20, 0x80, 0x80, 0x50, 0x50,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0, 0x30, 0x30,
|
||||||
|
0x80, 0x80, 0xE0, 0xE0, 0x30, 0x30,
|
||||||
|
},
|
||||||
|
Cr: []uint8{
|
||||||
|
0xE0, 0xE0, 0x80, 0x80, 0xB0, 0xB0,
|
||||||
|
0xE0, 0xE0, 0x80, 0x80, 0xB0, 0xB0,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40, 0xC0, 0xC0,
|
||||||
|
0xF0, 0xF0, 0x40, 0x40, 0xC0, 0xC0,
|
||||||
|
},
|
||||||
|
YStride: 12,
|
||||||
|
CStride: 6,
|
||||||
|
Rect: image.Rect(0, 0, 12, 8),
|
||||||
|
},
|
||||||
|
width: 6,
|
||||||
|
height: 4,
|
||||||
|
expected: &image.YCbCr{
|
||||||
|
SubsampleRatio: image.YCbCrSubsampleRatio420,
|
||||||
|
Y: []uint8{
|
||||||
|
0xF0, 0x80, 0x08, 0x00, 0x78, 0x80,
|
||||||
|
0x08, 0x00, 0x20, 0x20, 0x20, 0x20,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x40, 0x58, 0x18, 0x18, 0x18,
|
||||||
|
},
|
||||||
|
Cb: []uint8{
|
||||||
|
0x20, 0x50, 0x68,
|
||||||
|
0x68, 0xB0, 0x88,
|
||||||
|
},
|
||||||
|
Cr: []uint8{
|
||||||
|
0xE0, 0xB0, 0x98,
|
||||||
|
0xD0, 0x98, 0x80,
|
||||||
|
},
|
||||||
|
YStride: 6,
|
||||||
|
CStride: 3,
|
||||||
|
Rect: image.Rect(0, 0, 6, 4),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, c := range cases {
|
||||||
|
c := c
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
trans := Scale(c.width, c.height, ScalerFastBoxSampling)
|
||||||
|
r := trans(ReaderFunc(func() (image.Image, func(), error) {
|
||||||
|
return c.src, func() {}, nil
|
||||||
|
}))
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
out, _, err := r.Read()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(c.expected, out) {
|
||||||
|
t.Errorf("Expected output image:\n%v\ngot:\n%v\nrepeat: %d", c.expected, out, i)
|
||||||
|
}
|
||||||
|
// Destroy output contents
|
||||||
|
switch v := out.(type) {
|
||||||
|
case *image.RGBA:
|
||||||
|
v.Stride = 10
|
||||||
|
v.Pix = v.Pix[:1]
|
||||||
|
v.Rect.Max.X = 1
|
||||||
|
case *image.YCbCr:
|
||||||
|
v.YStride = 10
|
||||||
|
v.CStride = 100
|
||||||
|
v.Y = v.Y[:1]
|
||||||
|
v.Cb = v.Cb[:2]
|
||||||
|
v.Cr = v.Cr[:1]
|
||||||
|
v.Rect.Max.X = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkScale(b *testing.B) {
|
func BenchmarkScale(b *testing.B) {
|
||||||
for name, algo := range scalerBenchAlgos {
|
for name, algo := range scalerBenchAlgos {
|
||||||
algo := algo
|
algo := algo
|
||||||
|
@@ -29,7 +29,7 @@ void fastBoxSampling(
|
|||||||
const int sw, const int sh, const int sstride,
|
const int sw, const int sh, const int sstride,
|
||||||
uint32_t* tmp)
|
uint32_t* tmp)
|
||||||
{
|
{
|
||||||
memset(tmp, 0, dw * dh * ch);
|
memset(tmp, 0, dw * dh * ch * sizeof(tmp[0]));
|
||||||
|
|
||||||
for (int sy = 0; sy < sh; sy++)
|
for (int sy = 0; sy < sh; sy++)
|
||||||
{
|
{
|
||||||
|
@@ -30,10 +30,18 @@ func (p *rgbLikeYCbCr) At(x, y int) color.Color {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *rgbLikeYCbCr) Set(x, y int, c color.Color) {
|
func (p *rgbLikeYCbCr) Set(x, y int, c color.Color) {
|
||||||
rgb := c.(*color.RGBA64)
|
switch v := c.(type) {
|
||||||
p.y.SetGray(x, y, color.Gray{uint8(rgb.R / 0x100)})
|
case color.RGBA:
|
||||||
|
p.y.SetGray(x, y, color.Gray{v.R})
|
||||||
if (image.Point{x, y}.In(p.cb.Rect)) {
|
if (image.Point{x, y}.In(p.cb.Rect)) {
|
||||||
p.cb.SetGray(x, y, color.Gray{uint8(rgb.G / 0x100)})
|
p.cb.SetGray(x, y, color.Gray{v.G})
|
||||||
p.cr.SetGray(x, y, color.Gray{uint8(rgb.B / 0x100)})
|
p.cr.SetGray(x, y, color.Gray{v.B})
|
||||||
|
}
|
||||||
|
case *color.RGBA64:
|
||||||
|
p.y.SetGray(x, y, color.Gray{uint8(v.R / 0x100)})
|
||||||
|
if (image.Point{x, y}.In(p.cb.Rect)) {
|
||||||
|
p.cb.SetGray(x, y, color.Gray{uint8(v.G / 0x100)})
|
||||||
|
p.cr.SetGray(x, y, color.Gray{uint8(v.B / 0x100)})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -145,13 +145,17 @@ func (p *MediaConstraints) FitnessDistance(o Media) (float64, bool) {
|
|||||||
cmps.add(p.Width, o.Width)
|
cmps.add(p.Width, o.Width)
|
||||||
cmps.add(p.Height, o.Height)
|
cmps.add(p.Height, o.Height)
|
||||||
cmps.add(p.FrameFormat, o.FrameFormat)
|
cmps.add(p.FrameFormat, o.FrameFormat)
|
||||||
|
// The next line is comment out for now to not include framerate in the fitness function.
|
||||||
|
// As camera.Properties does not have access to the list of available framerate at the moment,
|
||||||
|
// no driver can be matched with a framerate constraint.
|
||||||
|
// Note this also affect screen caputre as screen.Properties does not fill in the Framerate field.
|
||||||
|
// cmps.add(p.FrameRate, o.FrameRate)
|
||||||
cmps.add(p.SampleRate, o.SampleRate)
|
cmps.add(p.SampleRate, o.SampleRate)
|
||||||
cmps.add(p.Latency, o.Latency)
|
cmps.add(p.Latency, o.Latency)
|
||||||
cmps.add(p.ChannelCount, o.ChannelCount)
|
cmps.add(p.ChannelCount, o.ChannelCount)
|
||||||
cmps.add(p.IsBigEndian, o.IsBigEndian)
|
cmps.add(p.IsBigEndian, o.IsBigEndian)
|
||||||
cmps.add(p.IsFloat, o.IsFloat)
|
cmps.add(p.IsFloat, o.IsFloat)
|
||||||
cmps.add(p.IsInterleaved, o.IsInterleaved)
|
cmps.add(p.IsInterleaved, o.IsInterleaved)
|
||||||
|
|
||||||
return cmps.fitnessDistance()
|
return cmps.fitnessDistance()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user