mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-01-23 02:34:42 +00:00
Use modified x264 lib (#275)
* Use modified x264 lib * Add x264 system lib * Set x264 version 155 for Debian (Buster) * Add h264 config params * Set vp8 codec
This commit is contained in:
parent
b56069c96e
commit
bd701f10fc
26 changed files with 418 additions and 209 deletions
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
|
|
@ -32,12 +32,12 @@ jobs:
|
|||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y make pkg-config libvpx-dev libopus-dev libopusfile-dev libsdl2-dev libgl1-mesa-glx
|
||||
sudo apt-get install -y make pkg-config libvpx-dev libx264-dev libopus-dev libopusfile-dev libsdl2-dev libgl1-mesa-glx
|
||||
|
||||
- name: Get MacOS dev libraries and tools
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: |
|
||||
brew install libvpx pkg-config opus opusfile sdl2
|
||||
brew install pkg-config libvpx x264 opus opusfile sdl2
|
||||
|
||||
- name: Get Windows dev libraries and tools
|
||||
if: matrix.os == 'windows-latest'
|
||||
|
|
@ -51,6 +51,7 @@ jobs:
|
|||
mingw-w64-x86_64-pkg-config
|
||||
mingw-w64-x86_64-dlfcn
|
||||
mingw-w64-x86_64-libvpx
|
||||
mingw-w64-x86_64-x264-git
|
||||
mingw-w64-x86_64-opusfile
|
||||
mingw-w64-x86_64-SDL2
|
||||
|
||||
|
|
|
|||
5
.github/workflows/release.yml.disabled
vendored
5
.github/workflows/release.yml.disabled
vendored
|
|
@ -49,12 +49,12 @@ jobs:
|
|||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y make pkg-config libvpx-dev libopus-dev libopusfile-dev libsdl2-dev
|
||||
sudo apt-get install -y make pkg-config libvpx-dev libx264-dev libopus-dev libopusfile-dev libsdl2-dev
|
||||
|
||||
- name: Get MacOS dev libraries and tools
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: |
|
||||
brew install libvpx pkg-config opus opusfile sdl2
|
||||
brew install pkg-config libvpx x264 opus opusfile sdl2
|
||||
|
||||
- name: Get Windows dev libraries and tools
|
||||
if: matrix.os == 'windows-latest'
|
||||
|
|
@ -81,6 +81,7 @@ jobs:
|
|||
mingw-w64-x86_64-pkg-config
|
||||
mingw-w64-x86_64-dlfcn
|
||||
mingw-w64-x86_64-libvpx
|
||||
mingw-w64-x86_64-x264-git
|
||||
mingw-w64-x86_64-opusfile
|
||||
mingw-w64-x86_64-SDL2
|
||||
|
||||
|
|
|
|||
2
Dockerfile
vendored
2
Dockerfile
vendored
|
|
@ -11,6 +11,7 @@ RUN apt-get update && apt-get install -y \
|
|||
make \
|
||||
pkg-config \
|
||||
libvpx-dev \
|
||||
libx264-dev \
|
||||
libopus-dev \
|
||||
libopusfile-dev \
|
||||
libsdl2-dev \
|
||||
|
|
@ -32,6 +33,7 @@ WORKDIR /usr/local/share/cloud-game
|
|||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||
ca-certificates \
|
||||
libvpx5 \
|
||||
libx264-155 \
|
||||
libopus0 \
|
||||
libopusfile0 \
|
||||
libsdl2-2.0-0 \
|
||||
|
|
|
|||
8
README.md
vendored
8
README.md
vendored
|
|
@ -42,16 +42,16 @@ Install Golang https://golang.org/doc/install . Because the project uses GoModul
|
|||
|
||||
### Install Dependencies
|
||||
|
||||
* Install [libvpx](https://www.webmproject.org/code/), [libopus](http://opus-codec.org/), [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/), [sdl2](https://wiki.libsdl.org/Installation)
|
||||
* Install [libvpx](https://www.webmproject.org/code/), [libx264](https://www.videolan.org/developers/x264.html), [libopus](http://opus-codec.org/), [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/), [sdl2](https://wiki.libsdl.org/Installation)
|
||||
```
|
||||
# Ubuntu / Windows (WSL2)
|
||||
apt-get install -y make gcc pkg-config libvpx-dev libopus-dev libopusfile-dev libsdl2-dev
|
||||
apt-get install -y make gcc pkg-config libvpx-dev libx264-dev libopus-dev libopusfile-dev libsdl2-dev
|
||||
|
||||
# MacOS
|
||||
brew install libvpx pkg-config opus opusfile sdl2
|
||||
brew install pkg-config libvpx x264 opus opusfile sdl2
|
||||
|
||||
# Windows (MSYS2)
|
||||
pacman -Sy --noconfirm --needed git make mingw-w64-x86_64-{gcc,pkg-config,dlfcn,libvpx,opusfile,SDL2}
|
||||
pacman -Sy --noconfirm --needed git make mingw-w64-x86_64-{gcc,pkg-config,dlfcn,libvpx,x264-git,opusfile,SDL2}
|
||||
```
|
||||
|
||||
Because the coordinator and workers need to run simultaneously. Workers connect to the coordinator.
|
||||
|
|
|
|||
15
configs/config.yaml
vendored
15
configs/config.yaml
vendored
|
|
@ -150,6 +150,21 @@ encoder:
|
|||
# audio frame duration needed for WebRTC (Opus)
|
||||
frame: 20
|
||||
frequency: 48000
|
||||
video:
|
||||
# h264, vpx
|
||||
codec: vpx
|
||||
# see: https://trac.ffmpeg.org/wiki/Encode/H.264
|
||||
h264:
|
||||
# Constant Rate Factor (CRF) 0-51 (default: 23)
|
||||
crf: 17
|
||||
# ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo
|
||||
preset: veryfast
|
||||
# baseline, main, high, high10, high422, high444
|
||||
profile: main
|
||||
# film, animation, grain, stillimage, psnr, ssim, fastdecode, zerolatency
|
||||
tune: zerolatency
|
||||
# 0-3
|
||||
logLevel: 0
|
||||
# run without a game
|
||||
# (experimental)
|
||||
withoutGame: false
|
||||
|
|
|
|||
24
go.mod
vendored
24
go.mod
vendored
|
|
@ -3,12 +3,11 @@ module github.com/giongto35/cloud-game/v2
|
|||
go 1.13
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.75.0 // indirect
|
||||
cloud.google.com/go/storage v1.12.0
|
||||
cloud.google.com/go v0.77.0 // indirect
|
||||
cloud.google.com/go/storage v1.13.0
|
||||
github.com/cavaliercoder/grab v1.0.1-0.20201108051000-98a5bfe305ec
|
||||
github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/gen2brain/x264-go v0.0.0-20200605131102-0523307cbe23
|
||||
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7
|
||||
github.com/gofrs/flock v0.8.0
|
||||
github.com/gofrs/uuid v4.0.0+incompatible
|
||||
|
|
@ -19,26 +18,19 @@ require (
|
|||
github.com/kkyr/fig v0.2.0
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/pelletier/go-toml v1.8.1 // indirect
|
||||
github.com/pion/ice/v2 v2.0.15 // indirect
|
||||
github.com/pion/interceptor v0.0.9
|
||||
github.com/pion/rtp v1.6.2
|
||||
github.com/pion/webrtc/v3 v3.0.4
|
||||
github.com/pion/webrtc/v3 v3.0.8
|
||||
github.com/prometheus/client_golang v1.9.0
|
||||
github.com/prometheus/procfs v0.3.0 // indirect
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
github.com/sergystepanov/x264-go/v2 v2.0.0-20210211174636-21169c39dab5
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/veandco/go-sdl2 v0.4.5
|
||||
go.opencensus.io v0.22.6 // indirect
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||
golang.org/x/image v0.0.0-20201208152932-35266b937fa6
|
||||
golang.org/x/mod v0.4.1 // indirect
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013 // indirect
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect
|
||||
golang.org/x/text v0.3.5 // indirect
|
||||
golang.org/x/tools v0.1.0 // indirect
|
||||
google.golang.org/api v0.38.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506 // indirect
|
||||
google.golang.org/grpc v1.35.0 // indirect
|
||||
golang.org/x/image v0.0.0-20210216034530-4410531fe030
|
||||
golang.org/x/oauth2 v0.0.0-20210210192628-66670185b0cd // indirect
|
||||
golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65 // indirect
|
||||
gopkg.in/hraban/opus.v2 v2.0.0-20201025103112-d779bb1cc5a2
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
|
|
|||
66
go.sum
vendored
66
go.sum
vendored
|
|
@ -13,12 +13,12 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
|
|||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.66.0 h1:DZeAkuQGQqnm9Xv36SbMJEU8aFBz4wL04UpMWPWwjzg=
|
||||
cloud.google.com/go v0.66.0/go.mod h1:dgqGAjKCDxyhGTtC9dAREQGUJpkceNm1yt590Qno0Ko=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.75.0 h1:XgtDnVJRCPEUG21gjFiRPz4zI1Mjg16R+NYQjfmU4XY=
|
||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||
cloud.google.com/go v0.77.0 h1:qA5V5+uQf6Mgr+tmFI8UT3D/ELyhIYkPwNGao/3Y+sQ=
|
||||
cloud.google.com/go v0.77.0/go.mod h1:R8fYSLIilC247Iu8WS2OGHw1E/Ufn7Pd7HiDjTqiURs=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
|
|
@ -37,12 +37,13 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
|||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.12.0 h1:4y3gHptW1EHVtcPAVE0eBBlFuGqEejTTG3KdIE0lUX4=
|
||||
cloud.google.com/go/storage v1.12.0/go.mod h1:fFLk2dp2oAhDz8QFKwqrjdJvxSp/W2g7nillojlL5Ho=
|
||||
cloud.google.com/go/storage v1.13.0 h1:amPvhCOI+Hltp6rPu+62YdwhIrjf+34PKVAL4HwgYwk=
|
||||
cloud.google.com/go/storage v1.13.0/go.mod h1:pqFyBUK3zZqMIIU5+8NaZq6/Ma3ClgUg9Hv5jfuJnvo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
|
|
@ -114,8 +115,7 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
|
|||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/gen2brain/x264-go v0.0.0-20200605131102-0523307cbe23 h1:/bEJAMYC2kdJwLeemSoFiEir0ONJdBdK7sMdLMKBQHU=
|
||||
github.com/gen2brain/x264-go v0.0.0-20200605131102-0523307cbe23/go.mod h1:17kvfYQKi9/QHiKPeqmJW0YuDPZEgy72tSBVmweSyiE=
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw=
|
||||
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
|
||||
|
|
@ -201,10 +201,10 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
|
|||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200905233945-acf8798be1f7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||
|
|
@ -270,6 +270,7 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
|
|||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f/go.mod h1:f8GY5V3lRzakvEyr49P7hHRYoHtPr8zvj/7JodCoRzw=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kkyr/fig v0.2.0 h1:t/5yENaBw8ATXbQSWpPqwXLCn6wdhEi6jWXRfUgytZI=
|
||||
|
|
@ -284,6 +285,7 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
|
|
@ -354,8 +356,8 @@ github.com/pion/datachannel v1.4.21 h1:3ZvhNyfmxsAqltQrApLPQMhSFNA+aT87RqyCq4OXm
|
|||
github.com/pion/datachannel v1.4.21/go.mod h1:oiNyP4gHx2DIwRzX/MFyH0Rz/Gz05OgBlayAI2hAWjg=
|
||||
github.com/pion/dtls/v2 v2.0.4 h1:WuUcqi6oYMu/noNTz92QrF1DaFj4eXbhQ6dzaaAwOiI=
|
||||
github.com/pion/dtls/v2 v2.0.4/go.mod h1:qAkFscX0ZHoI1E07RfYPoRw3manThveu+mlTDdOxoGI=
|
||||
github.com/pion/ice/v2 v2.0.14 h1:FxXxauyykf89SWAtkQCfnHkno6G8+bhRkNguSh9zU+4=
|
||||
github.com/pion/ice/v2 v2.0.14/go.mod h1:wqaUbOq5ObDNU5ox1hRsEst0rWfsKuH1zXjQFEWiZwM=
|
||||
github.com/pion/dtls/v2 v2.0.5 h1:jgQJRK2IJ9eWQAcUEZN4M0tnCi5X/cERnxH9J8qOjR0=
|
||||
github.com/pion/dtls/v2 v2.0.5/go.mod h1:QuDII+8FVvk9Dp5t5vYIMTo7hh7uBkra+8QIm7QGm10=
|
||||
github.com/pion/ice/v2 v2.0.15 h1:KZrwa2ciL9od8+TUVJiYTNsCW9J5lktBjGwW1MacEnQ=
|
||||
github.com/pion/ice/v2 v2.0.15/go.mod h1:ZIiVGevpgAxF/cXiIVmuIUtCb3Xs4gCzCbXB6+nFkSI=
|
||||
github.com/pion/interceptor v0.0.9 h1:fk5hTdyLO3KURQsf/+RjMpEm4NE3yeTY9Kh97b5BvwA=
|
||||
|
|
@ -385,7 +387,6 @@ github.com/pion/transport v0.8.10/go.mod h1:tBmha/UCjpum5hqTWhfAEs3CO4/tHSg0MYRh
|
|||
github.com/pion/transport v0.10.0/go.mod h1:BnHnUipd0rZQyTVB2SBGojFHT9CBt5C5TcsJSQGkvSE=
|
||||
github.com/pion/transport v0.10.1 h1:2W+yJT+0mOQ160ThZYUx5Zp2skzshiNgxrNE9GUfhJM=
|
||||
github.com/pion/transport v0.10.1/go.mod h1:PBis1stIILMiis0PewDw91WJeLJkyIMcEk+DwKOzf4A=
|
||||
github.com/pion/transport v0.12.0/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
|
||||
github.com/pion/transport v0.12.1/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
|
||||
github.com/pion/transport v0.12.2 h1:WYEjhloRHt1R86LhUKjC5y+P52Y11/QqEUalvtzVoys=
|
||||
github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q=
|
||||
|
|
@ -393,8 +394,8 @@ github.com/pion/turn/v2 v2.0.5 h1:iwMHqDfPEDEOFzwWKT56eFmh6DYC6o/+xnLAEzgISbA=
|
|||
github.com/pion/turn/v2 v2.0.5/go.mod h1:APg43CFyt/14Uy7heYUOGWdkem/Wu4PhCO/bjyrTqMw=
|
||||
github.com/pion/udp v0.1.0 h1:uGxQsNyrqG3GLINv36Ff60covYmfrLoxzwnCsIYspXI=
|
||||
github.com/pion/udp v0.1.0/go.mod h1:BPELIjbwE9PRbd/zxI/KYBnbo7B6+oA6YuEaNE8lths=
|
||||
github.com/pion/webrtc/v3 v3.0.4 h1:Tiw3H9fpfcwkvaxonB+Gv1DG9tmgYBQaM1vBagDHP40=
|
||||
github.com/pion/webrtc/v3 v3.0.4/go.mod h1:1TmFSLpPYFTFXFHPtoq9eGP1ASTa9LC6FBh7sUY8cd4=
|
||||
github.com/pion/webrtc/v3 v3.0.8 h1:Dgu/NZ6QAIvoNZU3qk/B35iPPx6TVHP506FfCE4SXCA=
|
||||
github.com/pion/webrtc/v3 v3.0.8/go.mod h1:C5uzSMa9sGCtfVPLA+pB0eWoW/exZ0OV0KW7JJbkvp0=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
|
@ -434,8 +435,8 @@ github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFB
|
|||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.3.0 h1:Uehi/mxLK0eiUc0H0++5tpMGTexB8wZ598MIgU8VpDM=
|
||||
github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
|
|
@ -444,6 +445,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
|
|||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sergystepanov/x264-go/v2 v2.0.0-20210211174636-21169c39dab5 h1:M7Ck/uhuFxa7rTMcZcC7hCcdTVPJgAXbGwuK1D6mYro=
|
||||
github.com/sergystepanov/x264-go/v2 v2.0.0-20210211174636-21169c39dab5/go.mod h1:WfHP0dmR01K6NQeOyZf5oZdWvnlmSt/th1puDtIeJbI=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
|
|
@ -526,8 +529,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
|
|||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20201208152932-35266b937fa6 h1:nfeHNc1nAqecKCy2FCy4HY+soOOe5sDLJ/gZLbx6GYI=
|
||||
golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20210216034530-4410531fe030 h1:lP9pYkih3DUSC641giIXa2XqfTIbbbRr0w2EOTA7wHA=
|
||||
golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
|
|
@ -592,8 +595,6 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/
|
|||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/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-20201031054903-ff519b6c9102 h1:42cLlJJdEh+ySyeUUbEQ5bsTiq8voBeTuweGVkY6Puw=
|
||||
|
|
@ -617,8 +618,9 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
|
|||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5 h1:Lm4OryKCca1vehdsWogr9N4t7NfZxLbJoc/H0w4K4S4=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013 h1:55H5j7lotzuFCEOKDsMch+fRNUQ9DgtyHOUP31FNqKc=
|
||||
golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210210192628-66670185b0cd h1:2arJsLyTCJGek+eeptQ3z49Rqndm0f+zvvpwNIXWNIA=
|
||||
golang.org/x/oauth2 v0.0.0-20210210192628-66670185b0cd/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
@ -672,10 +674,10 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -683,6 +685,8 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65 h1:pTMjDVnP5eVRRlWO76rEWJ8JoC6Lf1CmyjPZXRiy2Sw=
|
||||
golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
@ -746,12 +750,7 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
|
|||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200828161849-5deb26317202/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20200915173823-2db8f0ff891c h1:AQsh/7arPVFDBraQa8x7GoVnwnGg1kM7J2ySI0kF5WU=
|
||||
golang.org/x/tools v0.0.0-20200915173823-2db8f0ff891c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266 h1:k7tVuG0g1JwmD3Jh8oAl1vQ1C3jb4Hi/dUl1wWDBJpQ=
|
||||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
|
|
@ -783,14 +782,13 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
|
|||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.31.0/go.mod h1:CL+9IBCa2WWU6gRuBWaKqGWLFFwbEUXkfeMkHLQWYWo=
|
||||
google.golang.org/api v0.32.0 h1:Le77IccnTqEa8ryp9wIpX5W3zYm7Gf9LhOp9PHcwFts=
|
||||
google.golang.org/api v0.32.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0 h1:l2Nfbl2GPXdWorv+dT2XfinX2jOOw4zv1VhLstx+6rE=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.38.0 h1:vDyWk6eup8eQAidaZ31sNWIn8tZEL8qpbtGkBD4ytQo=
|
||||
google.golang.org/api v0.38.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.40.0 h1:uWrpz12dpVPn7cojP82mk02XDgTJLDPc2KbVTxrWb4A=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
|
|
@ -832,17 +830,15 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
|
|||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200831141814-d751682dd103/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200914193844-75d14daec038/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200921151605-7abf4a1a14d5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506 h1:uLBY0yHDCj2PMQ98KWDSIDFwn9zK2zh+tgWtbvPPBjI=
|
||||
google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210203152818-3206188e46ba/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210212180131-e7f2df4ecc2d h1:Edhcm0CKDPLQIecHCp5Iz57Lo7MfT6zUFBAlocmOjcY=
|
||||
google.golang.org/genproto v0.0.0-20210212180131-e7f2df4ecc2d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
|
|
@ -862,8 +858,6 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
|
|||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0=
|
||||
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0 h1:raiipEjMOIC/TO2AvyTxP25XFdLxNIBwzDh3FM3XztI=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package encoder
|
|||
|
||||
type Encoder struct {
|
||||
Audio Audio
|
||||
Video Video
|
||||
WithoutGame bool
|
||||
}
|
||||
|
||||
|
|
@ -11,6 +12,17 @@ type Audio struct {
|
|||
Frequency int
|
||||
}
|
||||
|
||||
type Video struct {
|
||||
Codec string
|
||||
H264 struct {
|
||||
Crf uint8
|
||||
Preset string
|
||||
Profile string
|
||||
Tune string
|
||||
LogLevel int
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Audio) GetFrameDuration() int {
|
||||
return a.Frequency * a.Frame / 1000 * a.Channels
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,3 +6,11 @@ const (
|
|||
H264 VideoCodec = iota
|
||||
VPX
|
||||
)
|
||||
|
||||
func (v VideoCodec) String() string {
|
||||
if v == H264 {
|
||||
return "h264"
|
||||
} else {
|
||||
return "vpx"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
95
pkg/encoder/h264/encoder.go
Normal file
95
pkg/encoder/h264/encoder.go
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
package h264
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/util"
|
||||
)
|
||||
|
||||
// Encoder converts a yuvI420 image to h264 frame.
|
||||
type Encoder struct {
|
||||
Output chan encoder.OutFrame
|
||||
Input chan encoder.InFrame
|
||||
done chan struct{}
|
||||
|
||||
buf *bytes.Buffer
|
||||
enc *H264
|
||||
|
||||
// C
|
||||
width int
|
||||
height int
|
||||
fps int
|
||||
}
|
||||
|
||||
// NewEncoder creates h264 encoder
|
||||
func NewEncoder(width, height int, options ...Option) (encoder.Encoder, error) {
|
||||
enc := &Encoder{
|
||||
Output: make(chan encoder.OutFrame, 10),
|
||||
Input: make(chan encoder.InFrame, 2),
|
||||
done: make(chan struct{}),
|
||||
|
||||
buf: bytes.NewBuffer(make([]byte, 0)),
|
||||
width: width,
|
||||
height: height,
|
||||
}
|
||||
|
||||
if err := enc.init(options...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return enc, nil
|
||||
}
|
||||
|
||||
func (e *Encoder) init(options ...Option) error {
|
||||
enc, err := NewH264Encoder(e.buf, e.width, e.height, options...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
e.enc = enc
|
||||
|
||||
go e.startLooping()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) startLooping() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Println("Warn: Recovered panic in encoding ", r)
|
||||
log.Println(debug.Stack())
|
||||
}
|
||||
}()
|
||||
|
||||
size := int(float32(e.width*e.height) * 1.5)
|
||||
yuv := make([]byte, size, size)
|
||||
|
||||
for img := range e.Input {
|
||||
util.RgbaToYuvInplace(img.Image, yuv, e.width, e.height)
|
||||
err := e.enc.Encode(yuv)
|
||||
if err != nil {
|
||||
log.Println("err encoding ", img.Image, " using h264")
|
||||
}
|
||||
e.Output <- encoder.OutFrame{Data: e.buf.Bytes(), Timestamp: img.Timestamp}
|
||||
e.buf.Reset()
|
||||
}
|
||||
close(e.Output)
|
||||
close(e.done)
|
||||
}
|
||||
|
||||
// Release release memory and stop loop
|
||||
func (e *Encoder) release() {
|
||||
close(e.Input)
|
||||
<-e.done
|
||||
err := e.enc.Close()
|
||||
if err != nil {
|
||||
log.Println("Failed to close H264 encoder")
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) GetInputChan() chan encoder.InFrame { return e.Input }
|
||||
|
||||
func (e *Encoder) GetOutputChan() chan encoder.OutFrame { return e.Output }
|
||||
|
||||
func (e *Encoder) Stop() { e.release() }
|
||||
33
pkg/encoder/h264/options.go
Normal file
33
pkg/encoder/h264/options.go
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package h264
|
||||
|
||||
type Options struct {
|
||||
// Constant Rate Factor (CRF)
|
||||
// This method allows the encoder to attempt to achieve a certain output quality for the whole file
|
||||
// when output file size is of less importance.
|
||||
// The range of the CRF scale is 0–51, where 0 is lossless, 23 is the default, and 51 is worst quality possible.
|
||||
Crf uint8
|
||||
// film, animation, grain, stillimage, psnr, ssim, fastdecode, zerolatency.
|
||||
Tune string
|
||||
// ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo.
|
||||
Preset string
|
||||
// baseline, main, high, high10, high422, high444.
|
||||
Profile string
|
||||
LogLevel int32
|
||||
}
|
||||
|
||||
type Option func(*Options)
|
||||
|
||||
func WithOptions(arg Options) Option {
|
||||
return func(args *Options) {
|
||||
args.Crf = arg.Crf
|
||||
args.Tune = arg.Tune
|
||||
args.Preset = arg.Preset
|
||||
args.Profile = arg.Profile
|
||||
args.LogLevel = arg.LogLevel
|
||||
}
|
||||
}
|
||||
func Crf(arg uint8) Option { return func(args *Options) { args.Crf = arg } }
|
||||
func Tune(arg string) Option { return func(args *Options) { args.Tune = arg } }
|
||||
func Preset(arg string) Option { return func(args *Options) { args.Preset = arg } }
|
||||
func Profile(arg string) Option { return func(args *Options) { args.Profile = arg } }
|
||||
func LogLevel(arg int32) Option { return func(args *Options) { args.LogLevel = arg } }
|
||||
120
pkg/encoder/h264/x264.go
Normal file
120
pkg/encoder/h264/x264.go
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
package h264
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
x264 "github.com/sergystepanov/x264-go/v2/x264c/external"
|
||||
)
|
||||
|
||||
type H264 struct {
|
||||
ref *x264.T
|
||||
w io.Writer
|
||||
|
||||
width int32
|
||||
lumaSize int32
|
||||
chromaSize int32
|
||||
csp int32
|
||||
nnals int32
|
||||
nals []*x264.Nal
|
||||
|
||||
// keep monotonic pts to suppress warnings
|
||||
pts int64
|
||||
}
|
||||
|
||||
func NewH264Encoder(w io.Writer, width, height int, options ...Option) (encoder *H264, err error) {
|
||||
opts := &Options{
|
||||
Crf: 12,
|
||||
Tune: "zerolatency",
|
||||
Preset: "superfast",
|
||||
Profile: "baseline",
|
||||
}
|
||||
|
||||
for _, opt := range options {
|
||||
opt(opts)
|
||||
}
|
||||
|
||||
param := x264.Param{}
|
||||
if opts.Preset != "" && opts.Tune != "" {
|
||||
if x264.ParamDefaultPreset(¶m, opts.Preset, opts.Tune) < 0 {
|
||||
return nil, fmt.Errorf("x264: invalid preset/tune name")
|
||||
}
|
||||
} else {
|
||||
x264.ParamDefault(¶m)
|
||||
}
|
||||
|
||||
if opts.Profile != "" {
|
||||
if x264.ParamApplyProfile(¶m, opts.Profile) < 0 {
|
||||
return nil, fmt.Errorf("x264: invalid profile name")
|
||||
}
|
||||
}
|
||||
|
||||
// legacy encoder lacks of this param
|
||||
param.IBitdepth = 8
|
||||
param.ICsp = x264.CspI420
|
||||
param.IWidth = int32(width)
|
||||
param.IHeight = int32(height)
|
||||
param.ILogLevel = opts.LogLevel
|
||||
|
||||
param.Rc.IRcMethod = x264.RcCrf
|
||||
param.Rc.FRfConstant = float32(opts.Crf)
|
||||
|
||||
encoder = &H264{
|
||||
csp: param.ICsp,
|
||||
lumaSize: int32(width * height),
|
||||
chromaSize: int32(width*height) / 4,
|
||||
nals: make([]*x264.Nal, 1),
|
||||
w: w,
|
||||
width: int32(width),
|
||||
}
|
||||
|
||||
var picIn x264.Picture
|
||||
x264.PictureInit(&picIn)
|
||||
|
||||
if encoder.ref = x264.EncoderOpen(¶m); encoder.ref == nil {
|
||||
err = fmt.Errorf("x264: cannot open the encoder")
|
||||
return
|
||||
}
|
||||
|
||||
if ret := x264.EncoderHeaders(encoder.ref, encoder.nals, &encoder.nnals); ret > 0 {
|
||||
_, err = encoder.w.Write(C.GoBytes(encoder.nals[0].PPayload, C.int(ret)))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (e *H264) Encode(yuv []byte) (err error) {
|
||||
var picIn, picOut x264.Picture
|
||||
|
||||
picIn.Img.ICsp = e.csp
|
||||
picIn.Img.IPlane = 3
|
||||
picIn.Img.IStride[0] = e.width
|
||||
picIn.Img.IStride[1] = e.width / 2
|
||||
picIn.Img.IStride[2] = e.width / 2
|
||||
|
||||
picIn.Img.Plane[0] = C.CBytes(yuv[:e.lumaSize])
|
||||
picIn.Img.Plane[1] = C.CBytes(yuv[e.lumaSize : e.lumaSize+e.chromaSize])
|
||||
picIn.Img.Plane[2] = C.CBytes(yuv[e.lumaSize+e.chromaSize:])
|
||||
|
||||
picIn.IPts = e.pts
|
||||
e.pts++
|
||||
|
||||
defer func() {
|
||||
C.free(picIn.Img.Plane[0])
|
||||
C.free(picIn.Img.Plane[1])
|
||||
C.free(picIn.Img.Plane[2])
|
||||
}()
|
||||
|
||||
if ret := x264.EncoderEncode(e.ref, e.nals, &e.nnals, &picIn, &picOut); ret > 0 {
|
||||
_, err = e.w.Write(C.GoBytes(e.nals[0].PPayload, C.int(ret)))
|
||||
// ret should be equal to writer writes
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (e *H264) Close() error {
|
||||
x264.EncoderClose(e.ref)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
package h264encoder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/gen2brain/x264-go"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder"
|
||||
)
|
||||
|
||||
const chanSize = 2
|
||||
|
||||
// H264Encoder yuvI420 image to vp8 video
|
||||
type H264Encoder struct {
|
||||
Output chan encoder.OutFrame
|
||||
Input chan encoder.InFrame
|
||||
done chan struct{}
|
||||
|
||||
buf *bytes.Buffer
|
||||
enc *x264.Encoder
|
||||
|
||||
// C
|
||||
width int
|
||||
height int
|
||||
fps int
|
||||
}
|
||||
|
||||
// NewH264Encoder create h264 encoder
|
||||
func NewH264Encoder(width, height, fps int) (encoder.Encoder, error) {
|
||||
v := &H264Encoder{
|
||||
Output: make(chan encoder.OutFrame, 5*chanSize),
|
||||
Input: make(chan encoder.InFrame, chanSize),
|
||||
done: make(chan struct{}),
|
||||
|
||||
buf: bytes.NewBuffer(make([]byte, 0)),
|
||||
width: width,
|
||||
height: height,
|
||||
fps: fps,
|
||||
}
|
||||
|
||||
if err := v.init(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (v *H264Encoder) init() error {
|
||||
opts := &x264.Options{
|
||||
Width: v.width,
|
||||
Height: v.height,
|
||||
FrameRate: v.fps,
|
||||
Tune: "zerolatency",
|
||||
Preset: "veryfast",
|
||||
Profile: "baseline",
|
||||
//LogLevel: x264.LogDebug,
|
||||
}
|
||||
|
||||
enc, err := x264.NewEncoder(v.buf, opts)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
v.enc = enc
|
||||
|
||||
go v.startLooping()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *H264Encoder) startLooping() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Println("Warn: Recovered panic in encoding ", r)
|
||||
log.Println(debug.Stack())
|
||||
}
|
||||
}()
|
||||
|
||||
for img := range v.Input {
|
||||
err := v.enc.Encode(img.Image)
|
||||
if err != nil {
|
||||
log.Println("err encoding ", img.Image, " using h264")
|
||||
}
|
||||
v.Output <- encoder.OutFrame{Data: v.buf.Bytes(), Timestamp: img.Timestamp}
|
||||
v.buf.Reset()
|
||||
}
|
||||
close(v.Output)
|
||||
close(v.done)
|
||||
}
|
||||
|
||||
// Release release memory and stop loop
|
||||
func (v *H264Encoder) release() {
|
||||
close(v.Input)
|
||||
// Wait for loop to stop
|
||||
<-v.done
|
||||
log.Println("Releasing encoder")
|
||||
err := v.enc.Close()
|
||||
if err != nil {
|
||||
log.Println("Failed to close H264 encoder")
|
||||
}
|
||||
}
|
||||
|
||||
// GetInputChan returns input channel
|
||||
func (v *H264Encoder) GetInputChan() chan encoder.InFrame {
|
||||
return v.Input
|
||||
}
|
||||
|
||||
// GetInputChan returns output channel
|
||||
func (v *H264Encoder) GetOutputChan() chan encoder.OutFrame {
|
||||
return v.Output
|
||||
}
|
||||
|
||||
// GetDoneChan returns done channel
|
||||
func (v *H264Encoder) Stop() {
|
||||
v.release()
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package vpxencoder
|
||||
package vpx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
@ -61,8 +61,8 @@ type VpxEncoder struct {
|
|||
vpxCodexIter C.vpx_codec_iter_t
|
||||
}
|
||||
|
||||
// NewVpxEncoder create vp8 encoder
|
||||
func NewVpxEncoder(w, h, fps, bitrate, keyframe int) (encoder.Encoder, error) {
|
||||
// NewEncoder create vp8 encoder
|
||||
func NewEncoder(w, h, fps, bitrate, keyframe int) (encoder.Encoder, error) {
|
||||
v := &VpxEncoder{
|
||||
Output: make(chan encoder.OutFrame, 5*chanSize),
|
||||
Input: make(chan encoder.InFrame, chanSize),
|
||||
|
|
@ -161,9 +161,7 @@ func (v *VpxEncoder) startLooping() {
|
|||
// Release release memory and stop loop
|
||||
func (v *VpxEncoder) release() {
|
||||
close(v.Input)
|
||||
// Wait for loop to stop
|
||||
<-v.done
|
||||
log.Println("Releasing encoder")
|
||||
C.vpx_img_free(&v.vpxImage)
|
||||
C.vpx_codec_destroy(&v.vpxCodexCtx)
|
||||
}
|
||||
|
|
@ -4,13 +4,13 @@ package util
|
|||
import (
|
||||
"image"
|
||||
"unsafe"
|
||||
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder"
|
||||
)
|
||||
|
||||
// https://stackoverflow.com/questions/9465815/rgb-to-yuv420-algorithm-efficiency
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -O3
|
||||
|
||||
void rgba2yuv(void * destination, void * source, int width, int height, int stride) {
|
||||
const int image_size = width * height;
|
||||
unsigned char * rgba = source;
|
||||
|
|
@ -62,10 +62,3 @@ func RgbaToYuvInplace(rgba *image.RGBA, yuv []byte, width, height int) {
|
|||
stride := rgba.Stride - width*4
|
||||
C.rgba2yuv(unsafe.Pointer(&yuv[0]), unsafe.Pointer(&rgba.Pix[0]), C.int(width), C.int(height), C.int(stride))
|
||||
}
|
||||
|
||||
// GetVideoEncoder returns video encoder based on some qualification.
|
||||
// Actually Android is only supporting VP8 but H264 has better encoding performance
|
||||
// TODO: Better use useragent attribute from frontend
|
||||
func GetVideoEncoder(isMobile bool) encoder.VideoCodec {
|
||||
return encoder.VPX
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import (
|
|||
|
||||
webrtcConfig "github.com/giongto35/cloud-game/v2/pkg/config/webrtc"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/util"
|
||||
itc "github.com/giongto35/cloud-game/v2/pkg/webrtc/interceptor"
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/pion/interceptor"
|
||||
|
|
@ -127,7 +126,7 @@ func (w *WebRTC) StartClient(isMobile bool, iceCB OnIceCallback) (string, error)
|
|||
|
||||
// add video track
|
||||
var codec webrtc.RTPCodecCapability
|
||||
if util.GetVideoEncoder(isMobile) == encoder.H264 {
|
||||
if w.cfg.Encoder.Video.Codec == encoder.H264.String() {
|
||||
codec = webrtc.RTPCodecCapability{MimeType: "video/h264"}
|
||||
} else {
|
||||
codec = webrtc.RTPCodecCapability{MimeType: "video/vp8"}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/giongto35/cloud-game/v2/pkg/config/worker"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/cws/api"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/emulator/libretro/manager/remotehttp"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/environment"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/games"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/webrtc"
|
||||
|
|
@ -174,11 +173,11 @@ func (h *Handler) detachRoom(roomID string) {
|
|||
|
||||
// createNewRoom creates a new room
|
||||
// Return nil in case of room is existed
|
||||
func (h *Handler) createNewRoom(game games.GameMetadata, roomID string, videoCodec encoder.VideoCodec) *room.Room {
|
||||
func (h *Handler) createNewRoom(game games.GameMetadata, roomID string) *room.Room {
|
||||
// If the roomID doesn't have any running sessions (room was closed)
|
||||
// we spawn a new room
|
||||
if !h.isRoomBusy(roomID) {
|
||||
newRoom := room.NewRoom(roomID, game, videoCodec, h.onlineStorage, h.cfg)
|
||||
newRoom := room.NewRoom(roomID, game, h.onlineStorage, h.cfg)
|
||||
// TODO: Might have race condition (and it has (:)
|
||||
h.rooms[newRoom.ID] = newRoom
|
||||
return newRoom
|
||||
|
|
|
|||
|
|
@ -8,9 +8,7 @@ import (
|
|||
webrtcConfig "github.com/giongto35/cloud-game/v2/pkg/config/webrtc"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/cws"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/cws/api"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/games"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/util"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/webrtc"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/worker/room"
|
||||
)
|
||||
|
|
@ -144,7 +142,7 @@ func (h *Handler) handleGameStart() cws.PacketHandler {
|
|||
Path: startPacket.Path,
|
||||
}
|
||||
|
||||
room := h.startGameHandler(gameMeta, resp.RoomID, resp.PlayerIndex, peerconnection, util.GetVideoEncoder(false))
|
||||
room := h.startGameHandler(gameMeta, resp.RoomID, resp.PlayerIndex, peerconnection)
|
||||
session.RoomID = room.ID
|
||||
// TODO: can data race
|
||||
h.rooms[room.ID] = room
|
||||
|
|
@ -259,7 +257,7 @@ func (h *Handler) handleGameMultitap() cws.PacketHandler {
|
|||
}
|
||||
|
||||
// startGameHandler starts a game if roomID is given, if not create new room
|
||||
func (h *Handler) startGameHandler(game games.GameMetadata, existedRoomID string, playerIndex int, peerconnection *webrtc.WebRTC, videoCodec encoder.VideoCodec) *room.Room {
|
||||
func (h *Handler) startGameHandler(game games.GameMetadata, existedRoomID string, playerIndex int, peerconnection *webrtc.WebRTC) *room.Room {
|
||||
log.Printf("Loading game: %v\n", game.Name)
|
||||
// If we are connecting to coordinator, request corresponding serverID based on roomID
|
||||
// TODO: check if existedRoomID is in the current server
|
||||
|
|
@ -268,7 +266,7 @@ func (h *Handler) startGameHandler(game games.GameMetadata, existedRoomID string
|
|||
if room == nil {
|
||||
log.Println("Got Room from local ", room, " ID: ", existedRoomID)
|
||||
// Create new room and update player index
|
||||
room = h.createNewRoom(game, existedRoomID, videoCodec)
|
||||
room = h.createNewRoom(game, existedRoomID)
|
||||
room.UpdatePlayerIndex(peerconnection, playerIndex)
|
||||
|
||||
// Wait for done signal from room
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import (
|
|||
|
||||
encoderConfig "github.com/giongto35/cloud-game/v2/pkg/config/encoder"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder/h264encoder"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder/h264"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder/opus"
|
||||
vpxencoder "github.com/giongto35/cloud-game/v2/pkg/encoder/vpx-encoder"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder/vpx"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/webrtc"
|
||||
)
|
||||
|
||||
|
|
@ -68,15 +68,21 @@ func (r *Room) broadcastAudio(audio []byte) {
|
|||
}
|
||||
|
||||
// startVideo processes imageChannel images with an encoder (codec) then pushes the result to WebRTC.
|
||||
func (r *Room) startVideo(width, height int, videoCodec encoder.VideoCodec) {
|
||||
func (r *Room) startVideo(width, height int, video encoderConfig.Video) {
|
||||
var enc encoder.Encoder
|
||||
var err error
|
||||
|
||||
log.Println("Video Encoder: ", videoCodec)
|
||||
if videoCodec == encoder.H264 {
|
||||
enc, err = h264encoder.NewH264Encoder(width, height, 1)
|
||||
log.Println("Video codec:", video.Codec)
|
||||
if video.Codec == encoder.H264.String() {
|
||||
enc, err = h264.NewEncoder(width, height, h264.WithOptions(h264.Options{
|
||||
Crf: video.H264.Crf,
|
||||
Tune: video.H264.Tune,
|
||||
Preset: video.H264.Preset,
|
||||
Profile: video.H264.Profile,
|
||||
LogLevel: int32(video.H264.LogLevel),
|
||||
}))
|
||||
} else {
|
||||
enc, err = vpxencoder.NewVpxEncoder(width, height, 20, 1200, 5)
|
||||
enc, err = vpx.NewEncoder(width, height, 20, 1200, 5)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
|
|
|||
57
pkg/worker/room/media_test.go
Normal file
57
pkg/worker/room/media_test.go
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package room
|
||||
|
||||
import (
|
||||
"image"
|
||||
col "image/color"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder/h264"
|
||||
"github.com/giongto35/cloud-game/v2/pkg/encoder/vpx"
|
||||
)
|
||||
|
||||
func BenchmarkH264(b *testing.B) {
|
||||
benchmarkEncoder(1920, 1080, encoder.H264, b)
|
||||
}
|
||||
|
||||
func BenchmarkVP8(b *testing.B) {
|
||||
benchmarkEncoder(1920, 1080, encoder.VPX, b)
|
||||
}
|
||||
|
||||
func benchmarkEncoder(w, h int, codec encoder.VideoCodec, b *testing.B) {
|
||||
var enc encoder.Encoder
|
||||
|
||||
if codec == encoder.H264 {
|
||||
enc, _ = h264.NewEncoder(w, h)
|
||||
} else {
|
||||
enc, _ = vpx.NewEncoder(w, h, 20, 1200, 5)
|
||||
}
|
||||
defer enc.Stop()
|
||||
|
||||
in, out := enc.GetInputChan(), enc.GetOutputChan()
|
||||
|
||||
image1 := genTestImage(w, h, rand.New(rand.NewSource(int64(1))).Float32())
|
||||
image2 := genTestImage(w, h, rand.New(rand.NewSource(int64(2))).Float32())
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
im := image1
|
||||
if i%2 == 0 {
|
||||
im = image2
|
||||
}
|
||||
in <- encoder.InFrame{Image: im}
|
||||
<-out
|
||||
}
|
||||
}
|
||||
|
||||
func genTestImage(w, h int, seed float32) *image.RGBA {
|
||||
img := image.NewRGBA(image.Rectangle{Max: image.Point{X: w, Y: h}})
|
||||
for x := 0; x < w; x++ {
|
||||
for y := 0; y < h; y++ {
|
||||
var color col.Color
|
||||
color = col.RGBA{R: uint8(seed * 255), G: uint8(seed * 255), B: uint8(seed * 255), A: 0xff}
|
||||
img.Set(x, y, color)
|
||||
}
|
||||
}
|
||||
return img
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ func NewVideoImporter(roomID string) chan nanoarch.GameFrame {
|
|||
}
|
||||
|
||||
// NewRoom creates a new room
|
||||
func NewRoom(roomID string, game games.GameMetadata, videoCodec encoder.VideoCodec, onlineStorage *storage.Client, cfg worker.Config) *Room {
|
||||
func NewRoom(roomID string, game games.GameMetadata, onlineStorage *storage.Client, cfg worker.Config) *Room {
|
||||
if roomID == "" {
|
||||
roomID = generateRoomID(game.Name)
|
||||
}
|
||||
|
|
@ -211,7 +211,7 @@ func NewRoom(roomID string, game games.GameMetadata, videoCodec encoder.VideoCod
|
|||
room.director.SetViewport(encoderW, encoderH)
|
||||
|
||||
// Spawn video and audio encoding for webRTC
|
||||
go room.startVideo(encoderW, encoderH, videoCodec)
|
||||
go room.startVideo(encoderW, encoderH, cfg.Encoder.Video)
|
||||
go room.startAudio(gameMeta.AudioSampleRate, cfg.Encoder.Audio)
|
||||
go room.startVoice()
|
||||
room.director.Start()
|
||||
|
|
|
|||
|
|
@ -235,8 +235,9 @@ func getRoomMock(cfg roomMockConfig) roomMock {
|
|||
if err := coreManager.Sync(); err != nil {
|
||||
log.Printf("error: cores sync has failed, %v", err)
|
||||
}
|
||||
conf.Encoder.Video.Codec = cfg.codec.String()
|
||||
|
||||
room := NewRoom(cfg.roomName, cfg.game, cfg.codec, storage.NewInitClient(), conf)
|
||||
room := NewRoom(cfg.roomName, cfg.game, storage.NewInitClient(), conf)
|
||||
|
||||
// loop-wait the room initialization
|
||||
var init sync.WaitGroup
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue