From bd701f10fc2a240a762a62ebd3f379730a4a1db5 Mon Sep 17 00:00:00 2001 From: sergystepanov Date: Sun, 21 Feb 2021 13:51:44 +0300 Subject: [PATCH] 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 --- .github/workflows/build.yml | 5 +- .github/workflows/release.yml.disabled | 5 +- Dockerfile | 2 + README.md | 8 +- configs/config.yaml | 15 +++ go.mod | 24 ++-- go.sum | 66 +++++----- pkg/config/encoder/config.go | 12 ++ pkg/encoder/codec.go | 8 ++ pkg/encoder/h264/encoder.go | 95 ++++++++++++++ pkg/encoder/h264/options.go | 33 +++++ pkg/encoder/h264/x264.go | 120 ++++++++++++++++++ pkg/encoder/h264encoder/encoder.go | 115 ----------------- pkg/encoder/{vpx-encoder => vpx}/encoder.go | 8 +- pkg/encoder/{vpx-encoder => vpx}/msvc.h | 0 .../{vpx-encoder => vpx}/tools_common.c | 0 .../{vpx-encoder => vpx}/tools_common.h | 0 pkg/encoder/{vpx-encoder => vpx}/vpx_config.h | 0 pkg/util/codec.go | 11 +- pkg/webrtc/webrtc.go | 3 +- pkg/worker/handlers.go | 5 +- pkg/worker/internalhandlers.go | 8 +- pkg/worker/room/media.go | 20 ++- pkg/worker/room/media_test.go | 57 +++++++++ pkg/worker/room/room.go | 4 +- pkg/worker/room/room_test.go | 3 +- 26 files changed, 418 insertions(+), 209 deletions(-) create mode 100644 pkg/encoder/h264/encoder.go create mode 100644 pkg/encoder/h264/options.go create mode 100644 pkg/encoder/h264/x264.go delete mode 100644 pkg/encoder/h264encoder/encoder.go rename pkg/encoder/{vpx-encoder => vpx}/encoder.go (95%) rename pkg/encoder/{vpx-encoder => vpx}/msvc.h (100%) rename pkg/encoder/{vpx-encoder => vpx}/tools_common.c (100%) rename pkg/encoder/{vpx-encoder => vpx}/tools_common.h (100%) rename pkg/encoder/{vpx-encoder => vpx}/vpx_config.h (100%) create mode 100644 pkg/worker/room/media_test.go diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 52155096..b2839a2d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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 diff --git a/.github/workflows/release.yml.disabled b/.github/workflows/release.yml.disabled index af3e64ed..071f4e4b 100644 --- a/.github/workflows/release.yml.disabled +++ b/.github/workflows/release.yml.disabled @@ -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 diff --git a/Dockerfile b/Dockerfile index 8a7d8dbe..79dc7af2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 \ diff --git a/README.md b/README.md index 49b9a1ab..244e9c75 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/configs/config.yaml b/configs/config.yaml index 046a6040..660c3c5f 100644 --- a/configs/config.yaml +++ b/configs/config.yaml @@ -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 diff --git a/go.mod b/go.mod index 2a57d172..80e96cbb 100644 --- a/go.mod +++ b/go.mod @@ -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 ) diff --git a/go.sum b/go.sum index e50d9ed2..6a366b16 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/pkg/config/encoder/config.go b/pkg/config/encoder/config.go index 59afee6a..cc023022 100644 --- a/pkg/config/encoder/config.go +++ b/pkg/config/encoder/config.go @@ -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 } diff --git a/pkg/encoder/codec.go b/pkg/encoder/codec.go index 1120a265..e025fc68 100644 --- a/pkg/encoder/codec.go +++ b/pkg/encoder/codec.go @@ -6,3 +6,11 @@ const ( H264 VideoCodec = iota VPX ) + +func (v VideoCodec) String() string { + if v == H264 { + return "h264" + } else { + return "vpx" + } +} diff --git a/pkg/encoder/h264/encoder.go b/pkg/encoder/h264/encoder.go new file mode 100644 index 00000000..0b8896d1 --- /dev/null +++ b/pkg/encoder/h264/encoder.go @@ -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() } diff --git a/pkg/encoder/h264/options.go b/pkg/encoder/h264/options.go new file mode 100644 index 00000000..f14e475f --- /dev/null +++ b/pkg/encoder/h264/options.go @@ -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 } } diff --git a/pkg/encoder/h264/x264.go b/pkg/encoder/h264/x264.go new file mode 100644 index 00000000..dc87f272 --- /dev/null +++ b/pkg/encoder/h264/x264.go @@ -0,0 +1,120 @@ +package h264 + +// #include +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 +} diff --git a/pkg/encoder/h264encoder/encoder.go b/pkg/encoder/h264encoder/encoder.go deleted file mode 100644 index 4b956129..00000000 --- a/pkg/encoder/h264encoder/encoder.go +++ /dev/null @@ -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() -} diff --git a/pkg/encoder/vpx-encoder/encoder.go b/pkg/encoder/vpx/encoder.go similarity index 95% rename from pkg/encoder/vpx-encoder/encoder.go rename to pkg/encoder/vpx/encoder.go index 938e1754..50c70d67 100644 --- a/pkg/encoder/vpx-encoder/encoder.go +++ b/pkg/encoder/vpx/encoder.go @@ -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) } diff --git a/pkg/encoder/vpx-encoder/msvc.h b/pkg/encoder/vpx/msvc.h similarity index 100% rename from pkg/encoder/vpx-encoder/msvc.h rename to pkg/encoder/vpx/msvc.h diff --git a/pkg/encoder/vpx-encoder/tools_common.c b/pkg/encoder/vpx/tools_common.c similarity index 100% rename from pkg/encoder/vpx-encoder/tools_common.c rename to pkg/encoder/vpx/tools_common.c diff --git a/pkg/encoder/vpx-encoder/tools_common.h b/pkg/encoder/vpx/tools_common.h similarity index 100% rename from pkg/encoder/vpx-encoder/tools_common.h rename to pkg/encoder/vpx/tools_common.h diff --git a/pkg/encoder/vpx-encoder/vpx_config.h b/pkg/encoder/vpx/vpx_config.h similarity index 100% rename from pkg/encoder/vpx-encoder/vpx_config.h rename to pkg/encoder/vpx/vpx_config.h diff --git a/pkg/util/codec.go b/pkg/util/codec.go index ac850077..9d542694 100644 --- a/pkg/util/codec.go +++ b/pkg/util/codec.go @@ -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 -} diff --git a/pkg/webrtc/webrtc.go b/pkg/webrtc/webrtc.go index d0dff5b8..078648f7 100644 --- a/pkg/webrtc/webrtc.go +++ b/pkg/webrtc/webrtc.go @@ -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"} diff --git a/pkg/worker/handlers.go b/pkg/worker/handlers.go index 18ab6043..6e2edbd3 100644 --- a/pkg/worker/handlers.go +++ b/pkg/worker/handlers.go @@ -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 diff --git a/pkg/worker/internalhandlers.go b/pkg/worker/internalhandlers.go index 1822994d..fcfdfc3a 100644 --- a/pkg/worker/internalhandlers.go +++ b/pkg/worker/internalhandlers.go @@ -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 diff --git a/pkg/worker/room/media.go b/pkg/worker/room/media.go index 6fa363f7..53b2c1e9 100644 --- a/pkg/worker/room/media.go +++ b/pkg/worker/room/media.go @@ -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() { diff --git a/pkg/worker/room/media_test.go b/pkg/worker/room/media_test.go new file mode 100644 index 00000000..a577efcd --- /dev/null +++ b/pkg/worker/room/media_test.go @@ -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 +} diff --git a/pkg/worker/room/room.go b/pkg/worker/room/room.go index c20b6826..2c8850db 100644 --- a/pkg/worker/room/room.go +++ b/pkg/worker/room/room.go @@ -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() diff --git a/pkg/worker/room/room_test.go b/pkg/worker/room/room_test.go index 7f2eb831..d0e43082 100644 --- a/pkg/worker/room/room_test.go +++ b/pkg/worker/room/room_test.go @@ -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